in java/fury-core/src/main/java/org/apache/fury/resolver/FieldResolver.java [226:341]
public FieldResolver(
Fury fury,
Class<?> type,
boolean ignoreCollectionType,
List<ClassField> allFields,
Set<String> duplicatedFields) {
this.cls = type;
this.fury = fury;
this.refResolver = fury.getRefResolver();
this.classResolver = fury.getClassResolver();
this.duplicatedFields = duplicatedFields;
this.numFields = allFields.size();
this.minPrimitiveClassId =
classResolver.getRegisteredClassId(TypeUtils.getSortedPrimitiveClasses().get(0));
this.maxPrimitiveClassId =
classResolver.getRegisteredClassId(TypeUtils.getSortedPrimitiveClasses().get(8));
intSerializer = (PrimitiveSerializers.IntSerializer) classResolver.getSerializer(int.class);
longSerializer = (PrimitiveSerializers.LongSerializer) classResolver.getSerializer(long.class);
classInfoHolder = classResolver.nilClassInfoHolder();
// Using `comparingLong` to avoid overflow in f1.getEncodedFieldInfo() -
// f2.getEncodedFieldInfo().
Comparator<FieldInfo> fieldInfoComparator =
Comparator.comparingLong(FieldInfo::getEncodedFieldInfo);
SortedSet<FieldInfo> embedTypes4FieldsSet = new TreeSet<>(fieldInfoComparator);
SortedSet<FieldInfo> embedTypes9FieldsSet = new TreeSet<>(fieldInfoComparator);
SortedSet<FieldInfo> embedTypesHashFieldsSet = new TreeSet<>(fieldInfoComparator);
SortedSet<FieldInfo> separateTypesHashFieldsSet = new TreeSet<>(fieldInfoComparator);
Preconditions.checkState(maxPrimitiveClassId < MAX_EMBED_CLASS_ID);
for (ClassField classField : allFields) {
String fieldName = classField.getName();
Class<?> fieldType = classField.getType();
if (duplicatedFields.contains(fieldName)) {
fieldName = classField.getDeclaringClass().getName() + "#" + fieldName;
}
int fieldNameLen = encodingBytesLength(fieldName);
Short classId = classResolver.getRegisteredClassId(fieldType);
// try to encode 6 bit for a char if field name is ascii.
// then 7 byte can encode 9 char, remains 2 bits can be used as flag bits or just left.
if (ReflectionUtils.isMonomorphic(fieldType)
&& classId != null
&& classId < MAX_EMBED_CLASS_ID) {
if (fieldNameLen <= 3 && classId <= 63) { // at most 4 chars
// little-endian reversed bits: 24 bits field name + 6 bits class id + bit `1 0`.
int encodedFieldInfo = (int) encodeFieldNameAsLong(fieldName);
encodedFieldInfo = encodedFieldInfo << 8 | classId.byteValue() << 2 | EMBED_TYPES_4_FLAG;
FieldInfo fieldInfo =
new FieldInfo(
fury,
fieldName,
fieldType,
classField.getField(),
FieldTypes.OBJECT,
EMBED_TYPES_4,
encodedFieldInfo,
classId);
embedTypes4FieldsSet.add(fieldInfo);
} else if (fieldNameLen <= 7) { // at most 9 chars
// little-endian reversed bits: 54bits field name + 7 bits class id + bit `1 1 0`.
long encodedFieldInfo = encodeFieldNameAsLong(fieldName);
encodedFieldInfo = encodedFieldInfo << 10 | (classId << 3) | EMBED_TYPES_9_FLAG;
FieldInfo fieldInfo =
new FieldInfo(
fury,
fieldName,
fieldType,
classField.getField(),
FieldTypes.OBJECT,
EMBED_TYPES_9,
encodedFieldInfo,
classId);
embedTypes9FieldsSet.add(fieldInfo);
} else {
// Truncate 7-bytes of MurmurHash3 128 bits hash.
// Truncate is OK, see docs in org.apache.commons.codec.digest.MurmurHash3
// little-endian: bit `1 1 1` + 7 bits class id + 54bits field name hash.
long encodedFieldInfo = computeStringHash(fieldName);
encodedFieldInfo = encodedFieldInfo << 10 | classId << 3 | EMBED_TYPES_HASH_FLAG;
FieldInfo fieldInfo =
new FieldInfo(
fury,
fieldName,
fieldType,
classField.getField(),
FieldTypes.OBJECT,
EMBED_TYPES_HASH,
encodedFieldInfo,
classId);
embedTypesHashFieldsSet.add(fieldInfo);
}
} else { // write field name and class info separately.
// bit `0 0` + field name(62 bits MurmurHash3 hash) + fieldType + ref info + n-bytes class
// name/id
long encodedFieldInfo = computeStringHash(fieldName) << 2;
FieldInfo fieldInfo =
FieldInfo.of(
fury,
fieldName,
fieldType,
classField.getField(),
SEPARATE_TYPES_HASH,
encodedFieldInfo,
ignoreCollectionType);
separateTypesHashFieldsSet.add(fieldInfo);
}
}
embedTypes4Fields = embedTypes4FieldsSet.toArray(new FieldInfo[0]);
embedTypes9Fields = embedTypes9FieldsSet.toArray(new FieldInfo[0]);
embedTypesHashFields = embedTypesHashFieldsSet.toArray(new FieldInfo[0]);
separateTypesHashFields = separateTypesHashFieldsSet.toArray(new FieldInfo[0]);
Preconditions.checkArgument(
embedTypes4Fields.length
+ embedTypes9Fields.length
+ embedTypesHashFields.length
+ separateTypesHashFields.length
== allFields.size());
}