Implementing Towards Better PEP/Serialization
David Ryan
david at livemedia.com.au
Sat Dec 12 04:06:54 UTC 2020
On Sat, Dec 12, 2020 at 9:32 AM Brian Goetz <brian.goetz at oracle.com> wrote:
>
> >
> > My base test case has been the following:
> >
> > public class Point {
> > private final float latitude; private final float longitude;
> > @Data
> > public Point(float latitude, float longitude) { this.latitude =
> > latitude; this.longitude = longitude; }
> > public float latitude() {return latitude; }
> > public float longitude() { return longitude; }
> > }
>
> Does this mean that you infer that, from the constructor argument list,
> that the serialized form for Point is (lat, long), and you use the ctor
> as the deserializer? How do you extract the state -- do you match the
> parameter names with getter names, or with field names, or what?
>
>
There are a few options and fallbacks to resolve state extraction and
construction of the object. In this case, I'm using byte code analysis [1],
which matches the parameter and field with the getter. It then uses the
getter name to generate the name of the component field. In cases where
byte code analysis doesn't work, it can fall back to requiring the @Field
annotation (e.g. [2]). Another fallback would be to use parameter names if
the compile flag is set, but that isn't implemented yet and I'll probably
avoid adding it. All access is via declared interfaces using getters for
serialization and ctor for deserializer (ie no direct field
reading/writing).
One of the jobs of the PEP library is to create the field meta data and
method handle constructor that accepts all fields. For instance, the test
case that has two immutable fields and one mutable field [3] still ends up
with a method handle that takes three arguments. The method handle creates
the object through the two argument constructor and then calls the setter
on the third field. Jumping through method handle hoops at [4].
Another interesting example is [5] which has a constructor:
ImmutableAtom(SimpleEnum enumCount, String str, boolean bool, Optional<
String> optional);
The PEP library creates a MethodHandle with (String, String, boolean,
String):ImmutableAtom as it treats both SimpleEnum and Optional as atomic
values that need to go through other translation before calling the
constructor. Similar translation occurs on the getters. This way the
serialization library doesn't need to know about Enums or Optional.
The previous question I had regarding what to do if there's an empty
constructor available was resolved by offering both the parameterised
method handle and the empty method handle as part of the PepDataClass
interface. The serialization library can decide what type of code to
generate for serialization based on the available interface. There's
interpreted language generators for each type [6], however, this part of
code needs more work.
Regards,
David.
[1]
https://github.com/litterat/litterat/blob/main/litterat-pep/src/main/java/io/litterat/pep/describe/ImmutableFinder.java
[2]
https://github.com/litterat/litterat/blob/main/litterat-pep-test/src/main/java/io/litterat/pep/test/ComplexImmutableTest.java
[3]
https://github.com/litterat/litterat/blob/main/litterat-pep-test/src/main/java/io/litterat/pep/test/data/MixedImmutable.java
[4]
https://github.com/litterat/litterat/blob/main/litterat-pep/src/main/java/io/litterat/pep/describe/DefaultResolver.java#L586
[5]
https://github.com/litterat/litterat/blob/main/litterat-pep-test/src/main/java/io/litterat/pep/test/data/ImmutableAtom.java
[6]
https://github.com/litterat/litterat/blob/main/litterat-xpl/src/main/java/io/litterat/xpl/resolve/SchemaResolver.java#L174
More information about the amber-dev
mailing list