Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ public SerializedArrayClass(final ClassDesc classDesc, final Serialized classLoa
this.componentType = Assert.checkNotNullParam("componentType", componentType);
}

@Override
final String computeName() {
return descriptorString().replace('/', '.');
}

/**
* {@return the class descriptor of the array's component type (not {@code null})}
* For multi-dimensional arrays, this is itself a {@code SerializedArrayClass}.
Expand Down
15 changes: 6 additions & 9 deletions serial/src/main/java/io/smallrye/serial/SerializedClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.lang.constant.ClassDesc;

import io.smallrye.common.constraint.Assert;
import io.smallrye.serial.impl.Util;

/**
* The serialized representation of a {@link Class}.
Expand Down Expand Up @@ -52,7 +51,7 @@ public String descriptorString() {
* {@return the name of the serialized class in {@link Class#getName()} format (not {@code null})}
* The name is lazily computed from the {@linkplain #descriptor() class descriptor} and cached.
*/
public String name() {
public final String name() {
String n = name;
if (n == null) {
name = n = computeName();
Expand All @@ -62,15 +61,13 @@ public String name() {

/**
* Compute the {@link Class#getName()}-format name from the stored class descriptor.
* Subclasses with non-reference-type descriptors override this method.
*
* @return the computed name (not {@code null})
*/
private String computeName() {
String computeName() {
String desc = classDesc.descriptorString();
char typeCode = desc.charAt(0);
return switch (typeCode) {
case '[' -> desc.replace('/', '.');
case 'L' -> desc.substring(1, desc.length() - 1).replace('/', '.');
default -> Util.primitiveTypeName(typeCode);
};
return desc.substring(1, desc.length() - 1).replace('/', '.');
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.lang.constant.ClassDesc;

import io.smallrye.serial.impl.Primitive;
import io.smallrye.serial.impl.Util;

/**
* The serialized representation of a primitive type or {@code void}.
* <p>
Expand Down Expand Up @@ -43,6 +46,11 @@ private SerializedPrimitiveClass(final ClassDesc classDesc) {
super(classDesc, SerializedKnownClassLoader.forBootClassLoader());
}

@Override
final String computeName() {
return Util.primitiveTypeName(descriptorString().charAt(0));
}

/**
* Return the singleton for the given primitive class descriptor.
*
Expand All @@ -63,17 +71,10 @@ public static SerializedPrimitiveClass of(ClassDesc classDesc) {
* @throws IllegalArgumentException if the type code is not a recognized primitive type code
*/
public static SerializedPrimitiveClass of(char typeCode) {
return switch (typeCode) {
case 'Z' -> BOOLEAN;
case 'B' -> BYTE;
case 'C' -> CHAR;
case 'S' -> SHORT;
case 'I' -> INT;
case 'J' -> LONG;
case 'F' -> FLOAT;
case 'D' -> DOUBLE;
case 'V' -> VOID;
default -> throw new IllegalArgumentException("Not a primitive type code: " + typeCode);
};
Primitive prim = Primitive.forTypeCode(typeCode);
if (prim == null) {
throw new IllegalArgumentException("Not a primitive type code: " + typeCode);
}
return prim.serializedClass();
}
}
32 changes: 22 additions & 10 deletions serial/src/main/java/io/smallrye/serial/impl/Primitive.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,48 @@
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;

import io.smallrye.serial.SerializedPrimitiveClass;

/**
* The primitive types of the Java language, with associated metadata
* for serialization operations.
*/
public enum Primitive {
/** The {@code boolean} type. */
BOOLEAN('Z', "boolean", 1, 1, ConstantDescs.CD_boolean),
BOOLEAN('Z', "boolean", 1, 1, ConstantDescs.CD_boolean, SerializedPrimitiveClass.BOOLEAN),
/** The {@code byte} type. */
BYTE('B', "byte", 1, 1, ConstantDescs.CD_byte),
BYTE('B', "byte", 1, 1, ConstantDescs.CD_byte, SerializedPrimitiveClass.BYTE),
/** The {@code char} type. */
CHAR('C', "char", 2, 1, ConstantDescs.CD_char),
CHAR('C', "char", 2, 1, ConstantDescs.CD_char, SerializedPrimitiveClass.CHAR),
/** The {@code short} type. */
SHORT('S', "short", 2, 1, ConstantDescs.CD_short),
SHORT('S', "short", 2, 1, ConstantDescs.CD_short, SerializedPrimitiveClass.SHORT),
/** The {@code int} type. */
INT('I', "int", 4, 1, ConstantDescs.CD_int),
INT('I', "int", 4, 1, ConstantDescs.CD_int, SerializedPrimitiveClass.INT),
/** The {@code long} type. */
LONG('J', "long", 8, 2, ConstantDescs.CD_long),
LONG('J', "long", 8, 2, ConstantDescs.CD_long, SerializedPrimitiveClass.LONG),
/** The {@code float} type. */
FLOAT('F', "float", 4, 1, ConstantDescs.CD_float),
FLOAT('F', "float", 4, 1, ConstantDescs.CD_float, SerializedPrimitiveClass.FLOAT),
/** The {@code double} type. */
DOUBLE('D', "double", 8, 2, ConstantDescs.CD_double),
DOUBLE('D', "double", 8, 2, ConstantDescs.CD_double, SerializedPrimitiveClass.DOUBLE),
/** The {@code void} type. */
VOID('V', "void", 0, 0, ConstantDescs.CD_void),
VOID('V', "void", 0, 0, ConstantDescs.CD_void, SerializedPrimitiveClass.VOID),
;

private final char typeCode;
private final String typeName;
private final int byteSize;
private final int slotSize;
private final ClassDesc classDesc;
private final SerializedPrimitiveClass serializedClass;

Primitive(char typeCode, String typeName, int byteSize, int slotSize, ClassDesc classDesc) {
Primitive(char typeCode, String typeName, int byteSize, int slotSize, ClassDesc classDesc,
final SerializedPrimitiveClass serializedClass) {
this.typeCode = typeCode;
this.typeName = typeName;
this.byteSize = byteSize;
this.slotSize = slotSize;
this.classDesc = classDesc;
this.serializedClass = serializedClass;
}

/**
Expand Down Expand Up @@ -120,4 +125,11 @@ public static Primitive forClassDesc(ClassDesc classDesc) {
public static Primitive forClass(Class<?> type) {
return forClassDesc(Util.classDesc(type));
}

/**
* {@return the serialized primitive class for this primitive type}
*/
public SerializedPrimitiveClass serializedClass() {
return serializedClass;
}
}
166 changes: 166 additions & 0 deletions serial/src/test/java/io/smallrye/serial/ClassNameTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package io.smallrye.serial;

import static org.junit.jupiter.api.Assertions.*;

import java.io.IOException;

import org.junit.jupiter.api.Test;

/**
* Tests that {@link SerializedClass#name()} matches {@link Class#getName()} for
* all class descriptor types: primitives, arrays, regular classes, and nested types.
*/
class ClassNameTest {

private final SerialContext ctx = SerialContext.builder().addDefaultProviders().build();
private final Serializer ser = ctx.createSerializer();

// ---- Primitive types ----

@Test
void booleanName() {
assertEquals(boolean.class.getName(), SerializedPrimitiveClass.BOOLEAN.name());
}

@Test
void byteName() {
assertEquals(byte.class.getName(), SerializedPrimitiveClass.BYTE.name());
}

@Test
void charName() {
assertEquals(char.class.getName(), SerializedPrimitiveClass.CHAR.name());
}

@Test
void shortName() {
assertEquals(short.class.getName(), SerializedPrimitiveClass.SHORT.name());
}

@Test
void intName() {
assertEquals(int.class.getName(), SerializedPrimitiveClass.INT.name());
}

@Test
void longName() {
assertEquals(long.class.getName(), SerializedPrimitiveClass.LONG.name());
}

@Test
void floatName() {
assertEquals(float.class.getName(), SerializedPrimitiveClass.FLOAT.name());
}

@Test
void doubleName() {
assertEquals(double.class.getName(), SerializedPrimitiveClass.DOUBLE.name());
}

@Test
void voidName() {
assertEquals(void.class.getName(), SerializedPrimitiveClass.VOID.name());
}

// ---- Primitive array types ----

@Test
void booleanArrayName() {
assertEquals(boolean[].class.getName(), SerializedArrayClass.BOOLEAN_ARRAY.name());
}

@Test
void byteArrayName() {
assertEquals(byte[].class.getName(), SerializedArrayClass.BYTE_ARRAY.name());
}

@Test
void charArrayName() {
assertEquals(char[].class.getName(), SerializedArrayClass.CHAR_ARRAY.name());
}

@Test
void shortArrayName() {
assertEquals(short[].class.getName(), SerializedArrayClass.SHORT_ARRAY.name());
}

@Test
void intArrayName() {
assertEquals(int[].class.getName(), SerializedArrayClass.INT_ARRAY.name());
}

@Test
void longArrayName() {
assertEquals(long[].class.getName(), SerializedArrayClass.LONG_ARRAY.name());
}

@Test
void floatArrayName() {
assertEquals(float[].class.getName(), SerializedArrayClass.FLOAT_ARRAY.name());
}

@Test
void doubleArrayName() {
assertEquals(double[].class.getName(), SerializedArrayClass.DOUBLE_ARRAY.name());
}

// ---- Object array types ----

@Test
void stringArrayName() throws IOException {
Serialized s = ser.serialize(String[].class);
assertInstanceOf(SerializedArrayClass.class, s);
assertEquals(String[].class.getName(), ((SerializedClass) s).name());
}

@Test
void nestedObjectArrayName() throws IOException {
Serialized s = ser.serialize(String[][].class);
assertInstanceOf(SerializedArrayClass.class, s);
assertEquals(String[][].class.getName(), ((SerializedClass) s).name());
}

@Test
void intMultiDimArrayName() throws IOException {
Serialized s = ser.serialize(int[][].class);
assertInstanceOf(SerializedArrayClass.class, s);
assertEquals(int[][].class.getName(), ((SerializedClass) s).name());
}

// ---- Reference types ----

@Test
void regularClassName() throws IOException {
Serialized s = ser.serialize(String.class);
assertInstanceOf(SerializedClass.class, s);
assertEquals(String.class.getName(), ((SerializedClass) s).name());
}

@Test
void innerClassName() throws IOException {
Serialized s = ser.serialize(java.util.Map.Entry.class);
assertInstanceOf(SerializedClass.class, s);
assertEquals(java.util.Map.Entry.class.getName(), ((SerializedClass) s).name());
}

@Test
void serializableClassName() throws IOException {
Serialized s = ser.serialize(java.util.ArrayList.class);
assertInstanceOf(SerializedSerializableClass.class, s);
assertEquals(java.util.ArrayList.class.getName(), ((SerializedClass) s).name());
}

@Test
void enumClassName() throws IOException {
Serialized s = ser.serialize(Thread.State.class);
assertInstanceOf(SerializedEnumClass.class, s);
assertEquals(Thread.State.class.getName(), ((SerializedClass) s).name());
}

@Test
void nonSerializableClassName() throws IOException {
Serialized s = ser.serialize(Thread.class);
assertInstanceOf(SerializedNonSerializableClass.class, s);
assertEquals(Thread.class.getName(), ((SerializedClass) s).name());
}
}
Loading