diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp index bc1aa4cd5e..c657a74761 100644 --- a/staticlibs/Android.bp +++ b/staticlibs/Android.bp @@ -178,6 +178,7 @@ java_library { java_library { name: "net-utils-device-common-struct-base", srcs: [ + "device/com/android/net/module/util/LegacyStruct.java", "device/com/android/net/module/util/Struct.java", ], sdk_version: "module_current", @@ -688,6 +689,7 @@ filegroup { "device/com/android/net/module/util/BpfUtils.java", "device/com/android/net/module/util/IBpfMap.java", "device/com/android/net/module/util/JniUtil.java", + "device/com/android/net/module/util/LegacyStruct.java", "device/com/android/net/module/util/SingleWriterBpfMap.java", "device/com/android/net/module/util/Struct.java", "device/com/android/net/module/util/TcUtils.java", diff --git a/staticlibs/device/com/android/net/module/util/LegacyStruct.java b/staticlibs/device/com/android/net/module/util/LegacyStruct.java new file mode 100644 index 0000000000..2f20677c77 --- /dev/null +++ b/staticlibs/device/com/android/net/module/util/LegacyStruct.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.net.module.util; + +import java.nio.ByteOrder; + +/** + * LegacyStruct is solely used for providing access to the deprecated writeToBytes(ByteOrder) + * method. + * + * The goal is to slowly move all Struct classes to defining the ByteOrder directly on the field (by + * virtue of using the BE int types) after which LegacyStruct can be deleted. + */ +public class LegacyStruct extends Struct { + /** A wrapper around {@code Struct#legacyWriteToBytes} */ + public final byte[] writeToBytes(final ByteOrder order) { + return legacyWriteToBytes(order); + + } +} diff --git a/staticlibs/device/com/android/net/module/util/Struct.java b/staticlibs/device/com/android/net/module/util/Struct.java index 76c97f0883..006642b26f 100644 --- a/staticlibs/device/com/android/net/module/util/Struct.java +++ b/staticlibs/device/com/android/net/module/util/Struct.java @@ -706,9 +706,12 @@ public class Struct { /** * Convert the parsed Struct subclass object to byte array. * + * WARNING: Structs should use byteorder annotations on the field, rather than using + * legacyWriteToBytes. This method will be deleted in the future. + * * @param order indicate ByteBuffer is outputted as little-endian or big-endian. */ - public final byte[] writeToBytes(final ByteOrder order) { + protected final byte[] legacyWriteToBytes(final ByteOrder order) { final FieldInfo[] fieldInfos = getClassFieldInfo(this.getClass()); final byte[] output = new byte[getSizeInternal(fieldInfos)]; final ByteBuffer buffer = ByteBuffer.wrap(output); @@ -719,7 +722,7 @@ public class Struct { /** Convert the parsed Struct subclass object to byte array with native order. */ public final byte[] writeToBytes() { - return writeToBytes(ByteOrder.nativeOrder()); + return legacyWriteToBytes(ByteOrder.nativeOrder()); } @Override @@ -788,7 +791,7 @@ public class Struct { } /** A simple Struct which only contains a bool field. */ - public static class Bool extends Struct { + public static class Bool extends LegacyStruct { @Struct.Field(order = 0, type = Struct.Type.Bool) public final boolean val; diff --git a/staticlibs/device/com/android/net/module/util/structs/FragmentHeader.java b/staticlibs/device/com/android/net/module/util/structs/FragmentHeader.java index 3da6a385d3..eb853992a2 100644 --- a/staticlibs/device/com/android/net/module/util/structs/FragmentHeader.java +++ b/staticlibs/device/com/android/net/module/util/structs/FragmentHeader.java @@ -16,7 +16,7 @@ package com.android.net.module.util.structs; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -31,7 +31,7 @@ import com.android.net.module.util.Struct.Type; * | Identification | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -public class FragmentHeader extends Struct { +public class FragmentHeader extends LegacyStruct { @Field(order = 0, type = Type.U8) public final short nextHeader; @Field(order = 1, type = Type.S8) diff --git a/staticlibs/device/com/android/net/module/util/structs/IaAddressOption.java b/staticlibs/device/com/android/net/module/util/structs/IaAddressOption.java index 7368d4fd1c..ab02c358ea 100644 --- a/staticlibs/device/com/android/net/module/util/structs/IaAddressOption.java +++ b/staticlibs/device/com/android/net/module/util/structs/IaAddressOption.java @@ -18,7 +18,7 @@ package com.android.net.module.util.structs; import static com.android.net.module.util.NetworkStackConstants.DHCP6_OPTION_IA_ADDR; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -49,7 +49,7 @@ import java.nio.ByteOrder; * . . * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -public class IaAddressOption extends Struct { +public class IaAddressOption extends LegacyStruct { public static final int LENGTH = 24; // option length excluding IAaddr-options @Field(order = 0, type = Type.S16) diff --git a/staticlibs/device/com/android/net/module/util/structs/IaPdOption.java b/staticlibs/device/com/android/net/module/util/structs/IaPdOption.java index dbf79dcbaf..6934ae2f15 100644 --- a/staticlibs/device/com/android/net/module/util/structs/IaPdOption.java +++ b/staticlibs/device/com/android/net/module/util/structs/IaPdOption.java @@ -18,7 +18,7 @@ package com.android.net.module.util.structs; import static com.android.net.module.util.NetworkStackConstants.DHCP6_OPTION_IA_PD; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -46,7 +46,7 @@ import java.nio.ByteOrder; * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ -public class IaPdOption extends Struct { +public class IaPdOption extends LegacyStruct { public static final int LENGTH = 12; // option length excluding IA_PD options @Field(order = 0, type = Type.S16) diff --git a/staticlibs/device/com/android/net/module/util/structs/IaPrefixOption.java b/staticlibs/device/com/android/net/module/util/structs/IaPrefixOption.java index b0f19e207d..e30ac1aebe 100644 --- a/staticlibs/device/com/android/net/module/util/structs/IaPrefixOption.java +++ b/staticlibs/device/com/android/net/module/util/structs/IaPrefixOption.java @@ -21,7 +21,7 @@ import static com.android.net.module.util.NetworkStackConstants.DHCP6_OPTION_IAP import android.net.IpPrefix; import android.util.Log; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Computed; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -58,7 +58,7 @@ import java.nio.ByteOrder; * . . * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -public class IaPrefixOption extends Struct { +public class IaPrefixOption extends LegacyStruct { private static final String TAG = IaPrefixOption.class.getSimpleName(); public static final int LENGTH = 25; // option length excluding IAprefix-options diff --git a/staticlibs/device/com/android/net/module/util/structs/LlaOption.java b/staticlibs/device/com/android/net/module/util/structs/LlaOption.java index fbaccabcca..4ee40bfd78 100644 --- a/staticlibs/device/com/android/net/module/util/structs/LlaOption.java +++ b/staticlibs/device/com/android/net/module/util/structs/LlaOption.java @@ -18,7 +18,7 @@ package com.android.net.module.util.structs; import android.net.MacAddress; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -34,7 +34,7 @@ import java.nio.ByteOrder; * | Type | Length | Link-Layer Address ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -public class LlaOption extends Struct { +public class LlaOption extends LegacyStruct { @Field(order = 0, type = Type.S8) public final byte type; @Field(order = 1, type = Type.S8) diff --git a/staticlibs/device/com/android/net/module/util/structs/MtuOption.java b/staticlibs/device/com/android/net/module/util/structs/MtuOption.java index 34bc21c140..b3fba682f8 100644 --- a/staticlibs/device/com/android/net/module/util/structs/MtuOption.java +++ b/staticlibs/device/com/android/net/module/util/structs/MtuOption.java @@ -18,7 +18,7 @@ package com.android.net.module.util.structs; import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_MTU; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -36,7 +36,7 @@ import java.nio.ByteOrder; * | MTU | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -public class MtuOption extends Struct { +public class MtuOption extends LegacyStruct { @Field(order = 0, type = Type.S8) public final byte type; @Field(order = 1, type = Type.S8) diff --git a/staticlibs/device/com/android/net/module/util/structs/NaHeader.java b/staticlibs/device/com/android/net/module/util/structs/NaHeader.java index 90c078e8c6..dc0fd186c3 100644 --- a/staticlibs/device/com/android/net/module/util/structs/NaHeader.java +++ b/staticlibs/device/com/android/net/module/util/structs/NaHeader.java @@ -16,7 +16,7 @@ package com.android.net.module.util.structs; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -44,7 +44,7 @@ import java.net.Inet6Address; * | Options ... * +-+-+-+-+-+-+-+-+-+-+-+- */ -public class NaHeader extends Struct { +public class NaHeader extends LegacyStruct { @Field(order = 0, type = Type.S32) public int flags; // Router flag, Solicited flag, Override flag and 29 Reserved bits. @Field(order = 1, type = Type.Ipv6Address) diff --git a/staticlibs/device/com/android/net/module/util/structs/NsHeader.java b/staticlibs/device/com/android/net/module/util/structs/NsHeader.java index 2e8b77ba11..eb9aee085b 100644 --- a/staticlibs/device/com/android/net/module/util/structs/NsHeader.java +++ b/staticlibs/device/com/android/net/module/util/structs/NsHeader.java @@ -16,7 +16,7 @@ package com.android.net.module.util.structs; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -44,7 +44,7 @@ import java.net.Inet6Address; * | Options ... * +-+-+-+-+-+-+-+-+-+-+-+- */ -public class NsHeader extends Struct { +public class NsHeader extends LegacyStruct { @Field(order = 0, type = Type.S32) public int reserved; // 32 Reserved bits. @Field(order = 1, type = Type.Ipv6Address) diff --git a/staticlibs/device/com/android/net/module/util/structs/PrefixInformationOption.java b/staticlibs/device/com/android/net/module/util/structs/PrefixInformationOption.java index bbbe5713fb..b8fbe5fff5 100644 --- a/staticlibs/device/com/android/net/module/util/structs/PrefixInformationOption.java +++ b/staticlibs/device/com/android/net/module/util/structs/PrefixInformationOption.java @@ -23,7 +23,7 @@ import android.net.IpPrefix; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Computed; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -57,7 +57,7 @@ import java.nio.ByteOrder; * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -public class PrefixInformationOption extends Struct { +public class PrefixInformationOption extends LegacyStruct { @Field(order = 0, type = Type.S8) public final byte type; @Field(order = 1, type = Type.S8) diff --git a/staticlibs/device/com/android/net/module/util/structs/RaHeader.java b/staticlibs/device/com/android/net/module/util/structs/RaHeader.java index 31a5cb76fc..3a168d5a89 100644 --- a/staticlibs/device/com/android/net/module/util/structs/RaHeader.java +++ b/staticlibs/device/com/android/net/module/util/structs/RaHeader.java @@ -16,7 +16,7 @@ package com.android.net.module.util.structs; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -38,7 +38,7 @@ import com.android.net.module.util.Struct.Type; * | Options ... * +-+-+-+-+-+-+-+-+-+-+-+- */ -public class RaHeader extends Struct { +public class RaHeader extends LegacyStruct { @Field(order = 0, type = Type.S8) public final byte hopLimit; // "Managed address configuration", "Other configuration" bits, and 6 reserved bits diff --git a/staticlibs/device/com/android/net/module/util/structs/RouteInformationOption.java b/staticlibs/device/com/android/net/module/util/structs/RouteInformationOption.java index 49bafedbed..36cb4844a9 100644 --- a/staticlibs/device/com/android/net/module/util/structs/RouteInformationOption.java +++ b/staticlibs/device/com/android/net/module/util/structs/RouteInformationOption.java @@ -22,7 +22,7 @@ import android.net.IpPrefix; import androidx.annotation.NonNull; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -44,7 +44,7 @@ import java.nio.ByteOrder; * . . * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ -public class RouteInformationOption extends Struct { +public class RouteInformationOption extends LegacyStruct { public enum Preference { HIGH((byte) 0x1), MEDIUM((byte) 0x0), diff --git a/staticlibs/device/com/android/net/module/util/structs/RsHeader.java b/staticlibs/device/com/android/net/module/util/structs/RsHeader.java index 0b51ff25fd..fe50976111 100644 --- a/staticlibs/device/com/android/net/module/util/structs/RsHeader.java +++ b/staticlibs/device/com/android/net/module/util/structs/RsHeader.java @@ -16,7 +16,7 @@ package com.android.net.module.util.structs; -import com.android.net.module.util.Struct; +import com.android.net.module.util.LegacyStruct; import com.android.net.module.util.Struct.Field; import com.android.net.module.util.Struct.Type; @@ -34,7 +34,7 @@ import com.android.net.module.util.Struct.Type; * | Options ... * +-+-+-+-+-+-+-+-+-+-+-+- */ -public class RsHeader extends Struct { +public class RsHeader extends LegacyStruct { @Field(order = 0, type = Type.S32) public final int reserved; diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java index c5a922643c..8958c1d4e0 100644 --- a/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java +++ b/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java @@ -123,8 +123,7 @@ public class StructTest { assertEquals(0, msg.mIcmpCode); assertEquals(16, Struct.getSize(HeaderMsgWithConstructor.class)); - assertArrayEquals(toByteBuffer(HDR_EMPTY).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); + assertArrayEquals(toByteBuffer(HDR_EMPTY).array(), msg.writeToBytes()); } @Test @@ -184,8 +183,7 @@ public class StructTest { assertEquals(0, msg.mIcmpCode); assertEquals(16, Struct.getSize(HeaderMsgWithoutConstructor.class)); - assertArrayEquals(toByteBuffer(HDR_EMPTY).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); + assertArrayEquals(toByteBuffer(HDR_EMPTY).array(), msg.writeToBytes()); } public static class HeaderMessage { @@ -255,8 +253,7 @@ public class StructTest { assertEquals(9151314442816847871L, msg.mUBE63); assertEquals(22, Struct.getSize(NetworkOrderMessage.class)); - assertArrayEquals(toByteBuffer(NETWORK_ORDER_MSG).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); + assertArrayEquals(toByteBuffer(NETWORK_ORDER_MSG).array(), msg.writeToBytes()); } public static class UnsignedDataMessage extends Struct { @@ -296,8 +293,7 @@ public class StructTest { assertEquals(-1L, msg.mLU64); assertEquals(31, Struct.getSize(UnsignedDataMessage.class)); - assertArrayEquals(toByteBuffer(UNSIGNED_DATA).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); + assertArrayEquals(toByteBuffer(UNSIGNED_DATA).array(), msg.writeToBytes()); } public static class U64DataMessage extends Struct { @@ -336,11 +332,10 @@ public class StructTest { assertEquals(new BigInteger("0"), msg.mZero); assertEquals(24, Struct.getSize(SmallValueBigInteger.class)); - assertArrayEquals(toByteBuffer(SMALL_VALUE_BIGINTEGER).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); + assertArrayEquals(toByteBuffer(SMALL_VALUE_BIGINTEGER).array(), msg.writeToBytes()); } - public static class SignedDataMessage extends Struct { + public static class SignedDataMessage extends LegacyStruct { @Field(order = 0, type = Type.S8) public final byte mS8; @Field(order = 1, type = Type.S16) @@ -368,8 +363,7 @@ public class StructTest { assertEquals(9223372036854775807L, msg.mS64); assertEquals(15, Struct.getSize(SignedDataMessage.class)); - assertArrayEquals(toByteBuffer(SIGNED_DATA).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); + assertArrayEquals(toByteBuffer(SIGNED_DATA).array(), msg.writeToBytes()); } @Test @@ -382,8 +376,7 @@ public class StructTest { assertEquals(-9223372036854775807L, msg.mS64); assertEquals(15, Struct.getSize(SignedDataMessage.class)); - assertArrayEquals(toByteBuffer(SIGNED_NEGATIVE_DATA).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); + assertArrayEquals(toByteBuffer(SIGNED_NEGATIVE_DATA).array(), msg.writeToBytes()); } public static class HeaderMessageWithDuplicateOrder extends Struct { @@ -489,8 +482,7 @@ public class StructTest { assertTrue(prefix.equals(new IpPrefix("2001:db8:3:4:5:6::/96"))); assertEquals(14, Struct.getSize(PrefixMessage.class)); - assertArrayEquals(toByteBuffer(OPT_PREF64).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); + assertArrayEquals(toByteBuffer(OPT_PREF64).array(), msg.writeToBytes()); } public static class PrefixMessageWithZeroLengthArray extends Struct { @@ -581,8 +573,7 @@ public class StructTest { assertEquals(0, msg.mIcmpCode); assertEquals(16, Struct.getSize(HeaderMsgWithStaticConstant.class)); - assertArrayEquals(toByteBuffer(HDR_EMPTY).array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); + assertArrayEquals(toByteBuffer(HDR_EMPTY).array(), msg.writeToBytes()); } public static class MismatchedConstructor extends Struct { @@ -622,8 +613,7 @@ public class StructTest { assertEquals(30806 /* 0x7856 */, msg.mInt2); assertEquals(4, Struct.getSize(ClassWithTwoConstructors.class)); - assertArrayEquals(toByteBuffer("1234" + "5678").array(), - msg.writeToBytes(ByteOrder.LITTLE_ENDIAN)); + assertArrayEquals(toByteBuffer("1234" + "5678").array(), msg.writeToBytes()); } @Test @@ -669,7 +659,7 @@ public class StructTest { } } - public static class BigEndianDataMessage extends Struct { + public static class BigEndianDataMessage extends LegacyStruct { @Field(order = 0, type = Type.S32) public int mInt1; @Field(order = 1, type = Type.S32) public int mInt2; @Field(order = 2, type = Type.UBE16) public int mInt3; @@ -724,7 +714,7 @@ public class StructTest { assertEquals(12, Struct.getSize(MacAddressMessage.class)); assertArrayEquals(toByteBuffer("001122334455" + "ffffffffffff").array(), - msg.writeToBytes(ByteOrder.BIG_ENDIAN)); + msg.writeToBytes()); } public static class BadMacAddressType extends Struct { @@ -748,11 +738,6 @@ public class StructTest { SignedDataMessage.class, ByteOrder.BIG_ENDIAN); assertArrayEquals(toByteBuffer(SIGNED_DATA).array(), bigEndianMsg.writeToBytes(ByteOrder.BIG_ENDIAN)); - - final SignedDataMessage nativeOrderMsg = ByteOrder.nativeOrder().equals( - ByteOrder.LITTLE_ENDIAN) ? littleEndianMsg : bigEndianMsg; - assertArrayEquals(toByteBuffer(SIGNED_DATA).array(), - nativeOrderMsg.writeToBytes()); } @Test @@ -786,7 +771,7 @@ public class StructTest { assertEquals(20, Struct.getSize(IpAddressMessage.class)); assertArrayEquals(toByteBuffer("c0a86401" + "20010db8000300040005000600070008").array(), - msg.writeToBytes(ByteOrder.BIG_ENDIAN)); + msg.writeToBytes()); } @Test @@ -823,7 +808,7 @@ public class StructTest { "00000000000000000000ffffc0a86401", InetAddressMessage.class, ByteOrder.BIG_ENDIAN); assertEquals(TEST_IPV4_ADDRESS, msg.ipAddress); assertArrayEquals(toByteBuffer("00000000000000000000ffffc0a86401").array(), - msg.writeToBytes(ByteOrder.BIG_ENDIAN)); + msg.writeToBytes()); } @Test public void testV6AddressInIpAddress() { @@ -831,10 +816,10 @@ public class StructTest { "20010db8000300040005000600070008", InetAddressMessage.class, ByteOrder.BIG_ENDIAN); assertEquals(TEST_IPV6_ADDRESS, msg.ipAddress); assertArrayEquals(toByteBuffer("20010db8000300040005000600070008").array(), - msg.writeToBytes(ByteOrder.BIG_ENDIAN)); + msg.writeToBytes()); } - public static class FullTypeMessage extends Struct { + public static class FullTypeMessage extends LegacyStruct { @Field(order = 0, type = Type.U8) public final short u8; @Field(order = 1, type = Type.U16) public final int u16; @Field(order = 2, type = Type.U32) public final long u32;