From 4e5b4348e036cf7b0d9fec7c21c2fe8c52e69c39 Mon Sep 17 00:00:00 2001 From: Jun Luo <4catcode@gmail.com> Date: Fri, 17 Apr 2026 15:38:37 +0800 Subject: [PATCH 1/2] docs: improve xdr generator javadocs --- xdr-generator/generator/generator.rb | 13 +++ .../templates/XdrDataInputStream.erb | 9 ++ .../templates/XdrDataOutputStream.erb | 24 ++++++ .../generator/templates/XdrElement.erb | 81 ++++++++++++++++++ .../generator/templates/XdrString.erb | 85 +++++++++++++++++++ .../templates/XdrUnsignedHyperInteger.erb | 68 +++++++++++++++ .../templates/XdrUnsignedInteger.erb | 67 +++++++++++++++ .../block_comments/XdrDataInputStream.java | 9 ++ .../block_comments/XdrDataOutputStream.java | 24 ++++++ .../snapshots/block_comments/XdrElement.java | 81 ++++++++++++++++++ .../snapshots/block_comments/XdrString.java | 85 +++++++++++++++++++ .../XdrUnsignedHyperInteger.java | 68 +++++++++++++++ .../block_comments/XdrUnsignedInteger.java | 67 +++++++++++++++ .../test/snapshots/const/TestArray.java | 6 ++ .../test/snapshots/const/TestArray2.java | 6 ++ .../snapshots/const/XdrDataInputStream.java | 9 ++ .../snapshots/const/XdrDataOutputStream.java | 24 ++++++ .../test/snapshots/const/XdrElement.java | 81 ++++++++++++++++++ .../test/snapshots/const/XdrString.java | 85 +++++++++++++++++++ .../const/XdrUnsignedHyperInteger.java | 68 +++++++++++++++ .../snapshots/const/XdrUnsignedInteger.java | 67 +++++++++++++++ .../snapshots/enum/XdrDataInputStream.java | 9 ++ .../snapshots/enum/XdrDataOutputStream.java | 24 ++++++ .../test/snapshots/enum/XdrElement.java | 81 ++++++++++++++++++ .../test/snapshots/enum/XdrString.java | 85 +++++++++++++++++++ .../enum/XdrUnsignedHyperInteger.java | 68 +++++++++++++++ .../snapshots/enum/XdrUnsignedInteger.java | 67 +++++++++++++++ xdr-generator/test/snapshots/nesting/Foo.java | 6 ++ .../test/snapshots/nesting/MyUnion.java | 36 ++++++++ .../snapshots/nesting/XdrDataInputStream.java | 9 ++ .../nesting/XdrDataOutputStream.java | 24 ++++++ .../test/snapshots/nesting/XdrElement.java | 81 ++++++++++++++++++ .../test/snapshots/nesting/XdrString.java | 85 +++++++++++++++++++ .../nesting/XdrUnsignedHyperInteger.java | 68 +++++++++++++++ .../snapshots/nesting/XdrUnsignedInteger.java | 67 +++++++++++++++ .../test/snapshots/optional/Arr.java | 6 ++ .../test/snapshots/optional/HasOptions.java | 18 ++++ .../optional/XdrDataInputStream.java | 9 ++ .../optional/XdrDataOutputStream.java | 24 ++++++ .../test/snapshots/optional/XdrElement.java | 81 ++++++++++++++++++ .../test/snapshots/optional/XdrString.java | 85 +++++++++++++++++++ .../optional/XdrUnsignedHyperInteger.java | 68 +++++++++++++++ .../optional/XdrUnsignedInteger.java | 67 +++++++++++++++ .../test/snapshots/struct/Int64.java | 6 ++ .../test/snapshots/struct/MyStruct.java | 30 +++++++ .../snapshots/struct/XdrDataInputStream.java | 9 ++ .../snapshots/struct/XdrDataOutputStream.java | 24 ++++++ .../test/snapshots/struct/XdrElement.java | 81 ++++++++++++++++++ .../test/snapshots/struct/XdrString.java | 85 +++++++++++++++++++ .../struct/XdrUnsignedHyperInteger.java | 68 +++++++++++++++ .../snapshots/struct/XdrUnsignedInteger.java | 67 +++++++++++++++ .../test/snapshots/test/HasStuff.java | 6 ++ xdr-generator/test/snapshots/test/Hash.java | 6 ++ .../test/snapshots/test/Hashes1.java | 6 ++ .../test/snapshots/test/Hashes2.java | 6 ++ .../test/snapshots/test/Hashes3.java | 6 ++ xdr-generator/test/snapshots/test/Int1.java | 6 ++ xdr-generator/test/snapshots/test/Int2.java | 6 ++ xdr-generator/test/snapshots/test/Int3.java | 6 ++ xdr-generator/test/snapshots/test/Int4.java | 6 ++ .../test/snapshots/test/LotsOfMyStructs.java | 6 ++ .../test/snapshots/test/MyStruct.java | 42 +++++++++ xdr-generator/test/snapshots/test/Nester.java | 36 ++++++++ .../test/snapshots/test/OptHash1.java | 6 ++ .../test/snapshots/test/OptHash2.java | 6 ++ xdr-generator/test/snapshots/test/Str.java | 6 ++ xdr-generator/test/snapshots/test/Str2.java | 6 ++ .../test/snapshots/test/Uint512.java | 6 ++ .../test/snapshots/test/Uint513.java | 6 ++ .../test/snapshots/test/Uint514.java | 6 ++ .../snapshots/test/XdrDataInputStream.java | 9 ++ .../snapshots/test/XdrDataOutputStream.java | 24 ++++++ .../test/snapshots/test/XdrElement.java | 81 ++++++++++++++++++ .../test/snapshots/test/XdrString.java | 85 +++++++++++++++++++ .../test/XdrUnsignedHyperInteger.java | 68 +++++++++++++++ .../snapshots/test/XdrUnsignedInteger.java | 67 +++++++++++++++ xdr-generator/test/snapshots/union/Error.java | 6 ++ .../test/snapshots/union/IntUnion.java | 18 ++++ .../test/snapshots/union/IntUnion2.java | 6 ++ xdr-generator/test/snapshots/union/Multi.java | 6 ++ .../test/snapshots/union/MyUnion.java | 18 ++++ .../snapshots/union/XdrDataInputStream.java | 9 ++ .../snapshots/union/XdrDataOutputStream.java | 24 ++++++ .../test/snapshots/union/XdrElement.java | 81 ++++++++++++++++++ .../test/snapshots/union/XdrString.java | 85 +++++++++++++++++++ .../union/XdrUnsignedHyperInteger.java | 68 +++++++++++++++ .../snapshots/union/XdrUnsignedInteger.java | 67 +++++++++++++++ 87 files changed, 3367 insertions(+) diff --git a/xdr-generator/generator/generator.rb b/xdr-generator/generator/generator.rb index 899fcefff..f3ede62af 100644 --- a/xdr-generator/generator/generator.rb +++ b/xdr-generator/generator/generator.rb @@ -327,6 +327,7 @@ def render_enum_json(enum, out) def render_struct(struct, out) struct.members.each do |m| + render_field_javadoc(out, m.name) out.puts "private #{decl_string(m.declaration)} #{m.name};" end @@ -416,6 +417,7 @@ def render_struct_json(struct, out) # ============================================================================ def render_typedef(typedef, out) + render_field_javadoc(out, typedef.name) out.puts "private #{decl_string typedef.declaration} #{typedef.name};" out.puts "public void encode(XdrDataOutputStream stream) throws IOException {" out.indent do @@ -486,9 +488,11 @@ def render_typedef_json(typedef, out) # ============================================================================ def render_union(union, out) + render_field_javadoc(out, "discriminant") out.puts "private #{type_string union.discriminant.type} discriminant;" union.arms.each do |arm| next if arm.void? + render_field_javadoc(out, arm.name) out.puts "private #{decl_string(arm.declaration)} #{arm.name};" end out.break @@ -809,6 +813,15 @@ def render_source_comment(out, defn) out.puts " */" end + def render_field_javadoc(out, field_name) + out.puts "/**" + out.puts " * Value of the {@code #{field_name}} field." + out.puts " *" + out.puts " * @param #{field_name} the {@code #{field_name}} field value" + out.puts " * @return the {@code #{field_name}} field value" + out.puts " */" + end + def render_base64(return_type, out) out.puts <<-EOS.strip_heredoc public static #{return_type} fromXdrBase64(String xdr) throws IOException { diff --git a/xdr-generator/generator/templates/XdrDataInputStream.erb b/xdr-generator/generator/templates/XdrDataInputStream.erb index 1975f8402..20e5505c6 100644 --- a/xdr-generator/generator/templates/XdrDataInputStream.erb +++ b/xdr-generator/generator/templates/XdrDataInputStream.erb @@ -7,6 +7,7 @@ import java.io.InputStream; import java.nio.charset.Charset; import lombok.Setter; +/** XDR-aware input stream with padding handling and decode safety checks. */ public class XdrDataInputStream extends DataInputStream { /** Default maximum decoding depth to prevent stack overflow from deeply nested structures. */ @@ -19,6 +20,8 @@ public class XdrDataInputStream extends DataInputStream { * Maximum input length, -1 if unknown. * This is used to validate that the declared size of variable-length * arrays/opaques doesn't exceed the remaining input length, preventing DoS attacks. + * + * @param maxInputLen the maximum input length, or -1 if unknown */ @Setter private int maxInputLen = -1; @@ -69,6 +72,8 @@ public class XdrDataInputStream extends DataInputStream { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded integer array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public int[] readIntArray() throws IOException { @@ -88,6 +93,8 @@ public class XdrDataInputStream extends DataInputStream { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded float array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public float[] readFloatArray() throws IOException { @@ -107,6 +114,8 @@ public class XdrDataInputStream extends DataInputStream { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded double array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public double[] readDoubleArray() throws IOException { diff --git a/xdr-generator/generator/templates/XdrDataOutputStream.erb b/xdr-generator/generator/templates/XdrDataOutputStream.erb index 6069833a9..6150dbd4d 100644 --- a/xdr-generator/generator/templates/XdrDataOutputStream.erb +++ b/xdr-generator/generator/templates/XdrDataOutputStream.erb @@ -5,15 +5,27 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; +/** XDR-aware output stream that writes variable-length values with the required padding. */ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; + /** + * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * + * @param out the specified output stream + */ public XdrDataOutputStream(OutputStream out) { super(new XdrOutputStream(out)); mOut = (XdrOutputStream) super.out; } + /** + * Writes an XDR variable-length array of integers. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeIntArray(int[] a) throws IOException { writeInt(a.length); writeIntArray(a, a.length); @@ -25,6 +37,12 @@ public class XdrDataOutputStream extends DataOutputStream { } } + /** + * Writes an XDR variable-length array of floats. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeFloatArray(float[] a) throws IOException { writeInt(a.length); writeFloatArray(a, a.length); @@ -36,6 +54,12 @@ public class XdrDataOutputStream extends DataOutputStream { } } + /** + * Writes an XDR variable-length array of doubles. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeDoubleArray(double[] a) throws IOException { writeInt(a.length); writeDoubleArray(a, a.length); diff --git a/xdr-generator/generator/templates/XdrElement.erb b/xdr-generator/generator/templates/XdrElement.erb index d8970f7be..95fe33e17 100644 --- a/xdr-generator/generator/templates/XdrElement.erb +++ b/xdr-generator/generator/templates/XdrElement.erb @@ -16,6 +16,7 @@ import org.stellar.sdk.Base64Factory; /** Common parent interface for all generated classes. */ public interface XdrElement { + /** Shared Gson instance used by generated XDR classes for JSON serialization. */ Gson gson = new GsonBuilder() .disableHtmlEscaping() @@ -23,12 +24,30 @@ public interface XdrElement { .setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) .create(); + /** + * Encodes this value to XDR and writes it to the provided stream. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ void encode(XdrDataOutputStream stream) throws IOException; + /** + * Encodes this value to XDR and returns the base64-encoded result. + * + * @return the base64-encoded XDR representation + * @throws IOException if an I/O error occurs while encoding the value + */ default String toXdrBase64() throws IOException { return Base64Factory.getInstance().encodeToString(toXdrByteArray()); } + /** + * Encodes this value to XDR and returns the raw bytes. + * + * @return the raw XDR byte representation + * @throws IOException if an I/O error occurs while encoding the value + */ default byte[] toXdrByteArray() throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); @@ -36,8 +55,19 @@ public interface XdrElement { return byteArrayOutputStream.toByteArray(); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ String toJson(); + /** + * Returns the lowercase hexadecimal representation of a byte array. + * + * @param bytes the bytes to encode + * @return the lowercase hexadecimal representation + */ static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { @@ -46,6 +76,13 @@ public interface XdrElement { return sb.toString(); } + /** + * Decodes a hexadecimal string into bytes. + * + * @param hex the hexadecimal string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input length is odd or contains non-hex characters + */ static byte[] hexToBytes(String hex) { if (hex.length() % 2 != 0) { throw new IllegalArgumentException("Hex string must have an even length"); @@ -63,6 +100,12 @@ public interface XdrElement { return data; } + /** + * Converts a byte array to an escaped ASCII string suitable for JSON serialization. + * + * @param data the bytes to encode + * @return the escaped ASCII representation + */ static String bytesToEscapedAscii(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { @@ -95,6 +138,13 @@ public interface XdrElement { return sb.toString(); } + /** + * Decodes an escaped ASCII string produced by {@link #bytesToEscapedAscii(byte[])}. + * + * @param s the escaped ASCII string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input contains invalid escape sequences or characters + */ static byte[] escapedAsciiToBytes(String s) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; @@ -155,6 +205,13 @@ public interface XdrElement { return out.toByteArray(); } + /** + * Converts a JSON scalar into a Java {@code long}. + * + * @param json the JSON value to convert + * @return the converted {@code long} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static long jsonToLong(Object json) { if (json instanceof String) { return Long.parseLong((String) json); @@ -168,6 +225,13 @@ public interface XdrElement { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a JSON scalar into a {@link BigInteger}. + * + * @param json the JSON value to convert + * @return the converted {@link BigInteger} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static BigInteger jsonToBigInteger(Object json) { if (json instanceof String) { return new BigInteger((String) json); @@ -181,6 +245,14 @@ public interface XdrElement { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a Java array into a JSON array using the provided mapper. + * + * @param array the array to convert + * @param mapper maps each element index to a JSON-compatible value + * @param the Java element type + * @return the converted JSON array + */ @SuppressWarnings("unchecked") static List arrayToJsonArray(T[] array, IntFunction mapper) { List list = new ArrayList<>(array.length); @@ -190,6 +262,15 @@ public interface XdrElement { return list; } + /** + * Converts a JSON array into a Java array using the provided mapper. + * + * @param list the JSON array to convert + * @param clazz the Java array component type + * @param mapper maps each JSON value to the target Java type + * @param the Java element type + * @return the converted Java array + */ @SuppressWarnings("unchecked") static T[] jsonArrayToArray(List list, Class clazz, Function mapper) { T[] array = (T[]) Array.newInstance(clazz, list.size()); diff --git a/xdr-generator/generator/templates/XdrString.erb b/xdr-generator/generator/templates/XdrString.erb index 7f5c5c542..b2740624b 100644 --- a/xdr-generator/generator/templates/XdrString.erb +++ b/xdr-generator/generator/templates/XdrString.erb @@ -6,24 +6,55 @@ import java.nio.charset.StandardCharsets; import lombok.Value; import org.stellar.sdk.Base64Factory; +/** Represents XDR string data. */ @Value public class XdrString implements XdrElement { + /** + * Raw bytes of the XDR string value. + * + * @return the encoded string bytes + */ byte[] bytes; + /** + * Creates an {@link XdrString} from raw bytes. + * + * @param bytes the string bytes + */ public XdrString(byte[] bytes) { this.bytes = bytes; } + /** + * Creates an {@link XdrString} from UTF-8 text. + * + * @param text the text value + */ public XdrString(String text) { this.bytes = text.getBytes(StandardCharsets.UTF_8); } + /** + * Encodes this string to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(this.bytes.length); stream.write(this.bytes, 0, this.bytes.length); } + /** + * Decodes an {@link XdrString} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxSize) throws IOException { // maxDepth is intentionally not checked - XdrString is a leaf type with no recursive decoding int size = stream.readInt(); @@ -42,19 +73,50 @@ public class XdrString implements XdrElement { return new XdrString(bytes); } + /** + * Decodes an {@link XdrString} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxSize) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr, int maxSize) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr) throws IOException { return fromXdrBase64(xdr, Integer.MAX_VALUE); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -62,6 +124,13 @@ public class XdrString implements XdrElement { return decode(xdrDataInputStream, maxSize); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -69,6 +138,11 @@ public class XdrString implements XdrElement { return decode(xdrDataInputStream, Integer.MAX_VALUE); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this string + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -78,6 +152,12 @@ public class XdrString implements XdrElement { return XdrElement.bytesToEscapedAscii(this.bytes); } + /** + * Parses an {@link XdrString} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrString}, or {@code null} if the input is {@code null} + */ public static XdrString fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -92,6 +172,11 @@ public class XdrString implements XdrElement { return new XdrString(XdrElement.escapedAsciiToBytes((String) json)); } + /** + * Returns this value decoded as a UTF-8 string. + * + * @return the UTF-8 string representation + */ @Override public String toString() { return new String(bytes, StandardCharsets.UTF_8); diff --git a/xdr-generator/generator/templates/XdrUnsignedHyperInteger.erb b/xdr-generator/generator/templates/XdrUnsignedHyperInteger.erb index 318c918aa..b7fa49e02 100644 --- a/xdr-generator/generator/templates/XdrUnsignedHyperInteger.erb +++ b/xdr-generator/generator/templates/XdrUnsignedHyperInteger.erb @@ -15,10 +15,24 @@ import org.stellar.sdk.Base64Factory; */ @Value public class XdrUnsignedHyperInteger implements XdrElement { + /** Largest value representable by XDR unsigned hyper integer. */ public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615"); + /** Smallest value representable by XDR unsigned hyper integer. */ public static final BigInteger MIN_VALUE = BigInteger.ZERO; + + /** + * Numeric value stored by this XDR unsigned hyper integer. + * + * @return the unsigned 64-bit value + */ BigInteger number; + /** + * Creates an {@link XdrUnsignedHyperInteger} from a {@link BigInteger}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedHyperInteger(BigInteger number) { if (number.compareTo(MIN_VALUE) < 0 || number.compareTo(MAX_VALUE) > 0) { throw new IllegalArgumentException("number must be between 0 and 2^64 - 1 inclusive"); @@ -26,6 +40,12 @@ public class XdrUnsignedHyperInteger implements XdrElement { this.number = number; } + /** + * Creates an {@link XdrUnsignedHyperInteger} from a non-negative {@link Long}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedHyperInteger(Long number) { if (number < 0) { throw new IllegalArgumentException( @@ -34,11 +54,25 @@ public class XdrUnsignedHyperInteger implements XdrElement { this.number = BigInteger.valueOf(number); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.write(getBytes()); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedHyperInteger is a leaf type with no recursive decoding byte[] bytes = new byte[8]; @@ -47,6 +81,14 @@ public class XdrUnsignedHyperInteger implements XdrElement { return new XdrUnsignedHyperInteger(uint64); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream using the default maximum + * depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } @@ -61,6 +103,11 @@ public class XdrUnsignedHyperInteger implements XdrElement { return paddedBytes; } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -70,6 +117,13 @@ public class XdrUnsignedHyperInteger implements XdrElement { return this.number.toString(); } + /** + * Parses an {@link XdrUnsignedHyperInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedHyperInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedHyperInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -81,11 +135,25 @@ public class XdrUnsignedHyperInteger implements XdrElement { return new XdrUnsignedHyperInteger(XdrElement.jsonToBigInteger(json)); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/generator/templates/XdrUnsignedInteger.erb b/xdr-generator/generator/templates/XdrUnsignedInteger.erb index 1f45c33e7..2a0b08a92 100644 --- a/xdr-generator/generator/templates/XdrUnsignedInteger.erb +++ b/xdr-generator/generator/templates/XdrUnsignedInteger.erb @@ -14,10 +14,24 @@ import org.stellar.sdk.Base64Factory; */ @Value public class XdrUnsignedInteger implements XdrElement { + /** Largest value representable by XDR unsigned integer. */ public static final long MAX_VALUE = (1L << 32) - 1; + /** Smallest value representable by XDR unsigned integer. */ public static final long MIN_VALUE = 0; + + /** + * Numeric value stored by this XDR unsigned integer. + * + * @return the unsigned 32-bit value as a {@link Long} + */ Long number; + /** + * Creates an {@link XdrUnsignedInteger} from a {@link Long}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedInteger(Long number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive"); @@ -25,6 +39,12 @@ public class XdrUnsignedInteger implements XdrElement { this.number = number; } + /** + * Creates an {@link XdrUnsignedInteger} from a non-negative {@link Integer}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedInteger(Integer number) { if (number < 0) { throw new IllegalArgumentException( @@ -33,6 +53,14 @@ public class XdrUnsignedInteger implements XdrElement { this.number = number.longValue(); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedInteger is a leaf type with no recursive decoding int intValue = stream.readInt(); @@ -40,15 +68,33 @@ public class XdrUnsignedInteger implements XdrElement { return new XdrUnsignedInteger(uint32Value); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(number.intValue()); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -58,6 +104,13 @@ public class XdrUnsignedInteger implements XdrElement { return this.number; } + /** + * Parses an {@link XdrUnsignedInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -69,11 +122,25 @@ public class XdrUnsignedInteger implements XdrElement { return new XdrUnsignedInteger(XdrElement.jsonToLong(json)); } + /** + * Decodes an {@link XdrUnsignedInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/block_comments/XdrDataInputStream.java b/xdr-generator/test/snapshots/block_comments/XdrDataInputStream.java index 0dd3098d9..2491769a6 100644 --- a/xdr-generator/test/snapshots/block_comments/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/block_comments/XdrDataInputStream.java @@ -7,6 +7,7 @@ import java.nio.charset.Charset; import lombok.Setter; +/** XDR-aware input stream with padding handling and decode safety checks. */ public class XdrDataInputStream extends DataInputStream { /** Default maximum decoding depth to prevent stack overflow from deeply nested structures. */ @@ -19,6 +20,8 @@ public class XdrDataInputStream extends DataInputStream { * Maximum input length, -1 if unknown. * This is used to validate that the declared size of variable-length * arrays/opaques doesn't exceed the remaining input length, preventing DoS attacks. + * + * @param maxInputLen the maximum input length, or -1 if unknown */ @Setter private int maxInputLen = -1; @@ -69,6 +72,8 @@ public boolean readXdrBoolean() throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded integer array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public int[] readIntArray() throws IOException { @@ -88,6 +93,8 @@ private int[] readIntArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded float array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public float[] readFloatArray() throws IOException { @@ -107,6 +114,8 @@ private float[] readFloatArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded double array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public double[] readDoubleArray() throws IOException { diff --git a/xdr-generator/test/snapshots/block_comments/XdrDataOutputStream.java b/xdr-generator/test/snapshots/block_comments/XdrDataOutputStream.java index 9bb857a64..d5d8cda41 100644 --- a/xdr-generator/test/snapshots/block_comments/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/block_comments/XdrDataOutputStream.java @@ -5,15 +5,27 @@ import java.io.OutputStream; import java.nio.charset.Charset; +/** XDR-aware output stream that writes variable-length values with the required padding. */ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; + /** + * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * + * @param out the specified output stream + */ public XdrDataOutputStream(OutputStream out) { super(new XdrOutputStream(out)); mOut = (XdrOutputStream) super.out; } + /** + * Writes an XDR variable-length array of integers. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeIntArray(int[] a) throws IOException { writeInt(a.length); writeIntArray(a, a.length); @@ -25,6 +37,12 @@ private void writeIntArray(int[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of floats. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeFloatArray(float[] a) throws IOException { writeInt(a.length); writeFloatArray(a, a.length); @@ -36,6 +54,12 @@ private void writeFloatArray(float[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of doubles. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeDoubleArray(double[] a) throws IOException { writeInt(a.length); writeDoubleArray(a, a.length); diff --git a/xdr-generator/test/snapshots/block_comments/XdrElement.java b/xdr-generator/test/snapshots/block_comments/XdrElement.java index ef8f9efd6..99e832356 100644 --- a/xdr-generator/test/snapshots/block_comments/XdrElement.java +++ b/xdr-generator/test/snapshots/block_comments/XdrElement.java @@ -16,6 +16,7 @@ /** Common parent interface for all generated classes. */ public interface XdrElement { + /** Shared Gson instance used by generated XDR classes for JSON serialization. */ Gson gson = new GsonBuilder() .disableHtmlEscaping() @@ -23,12 +24,30 @@ public interface XdrElement { .setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) .create(); + /** + * Encodes this value to XDR and writes it to the provided stream. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ void encode(XdrDataOutputStream stream) throws IOException; + /** + * Encodes this value to XDR and returns the base64-encoded result. + * + * @return the base64-encoded XDR representation + * @throws IOException if an I/O error occurs while encoding the value + */ default String toXdrBase64() throws IOException { return Base64Factory.getInstance().encodeToString(toXdrByteArray()); } + /** + * Encodes this value to XDR and returns the raw bytes. + * + * @return the raw XDR byte representation + * @throws IOException if an I/O error occurs while encoding the value + */ default byte[] toXdrByteArray() throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); @@ -36,8 +55,19 @@ default byte[] toXdrByteArray() throws IOException { return byteArrayOutputStream.toByteArray(); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ String toJson(); + /** + * Returns the lowercase hexadecimal representation of a byte array. + * + * @param bytes the bytes to encode + * @return the lowercase hexadecimal representation + */ static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { @@ -46,6 +76,13 @@ static String bytesToHex(byte[] bytes) { return sb.toString(); } + /** + * Decodes a hexadecimal string into bytes. + * + * @param hex the hexadecimal string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input length is odd or contains non-hex characters + */ static byte[] hexToBytes(String hex) { if (hex.length() % 2 != 0) { throw new IllegalArgumentException("Hex string must have an even length"); @@ -63,6 +100,12 @@ static byte[] hexToBytes(String hex) { return data; } + /** + * Converts a byte array to an escaped ASCII string suitable for JSON serialization. + * + * @param data the bytes to encode + * @return the escaped ASCII representation + */ static String bytesToEscapedAscii(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { @@ -95,6 +138,13 @@ static String bytesToEscapedAscii(byte[] data) { return sb.toString(); } + /** + * Decodes an escaped ASCII string produced by {@link #bytesToEscapedAscii(byte[])}. + * + * @param s the escaped ASCII string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input contains invalid escape sequences or characters + */ static byte[] escapedAsciiToBytes(String s) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; @@ -155,6 +205,13 @@ static byte[] escapedAsciiToBytes(String s) { return out.toByteArray(); } + /** + * Converts a JSON scalar into a Java {@code long}. + * + * @param json the JSON value to convert + * @return the converted {@code long} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static long jsonToLong(Object json) { if (json instanceof String) { return Long.parseLong((String) json); @@ -168,6 +225,13 @@ static long jsonToLong(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a JSON scalar into a {@link BigInteger}. + * + * @param json the JSON value to convert + * @return the converted {@link BigInteger} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static BigInteger jsonToBigInteger(Object json) { if (json instanceof String) { return new BigInteger((String) json); @@ -181,6 +245,14 @@ static BigInteger jsonToBigInteger(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a Java array into a JSON array using the provided mapper. + * + * @param array the array to convert + * @param mapper maps each element index to a JSON-compatible value + * @param the Java element type + * @return the converted JSON array + */ @SuppressWarnings("unchecked") static List arrayToJsonArray(T[] array, IntFunction mapper) { List list = new ArrayList<>(array.length); @@ -190,6 +262,15 @@ static List arrayToJsonArray(T[] array, IntFunction mapper) return list; } + /** + * Converts a JSON array into a Java array using the provided mapper. + * + * @param list the JSON array to convert + * @param clazz the Java array component type + * @param mapper maps each JSON value to the target Java type + * @param the Java element type + * @return the converted Java array + */ @SuppressWarnings("unchecked") static T[] jsonArrayToArray(List list, Class clazz, Function mapper) { T[] array = (T[]) Array.newInstance(clazz, list.size()); diff --git a/xdr-generator/test/snapshots/block_comments/XdrString.java b/xdr-generator/test/snapshots/block_comments/XdrString.java index e50113cfa..269f7b9d3 100644 --- a/xdr-generator/test/snapshots/block_comments/XdrString.java +++ b/xdr-generator/test/snapshots/block_comments/XdrString.java @@ -6,24 +6,55 @@ import lombok.Value; import org.stellar.sdk.Base64Factory; +/** Represents XDR string data. */ @Value public class XdrString implements XdrElement { + /** + * Raw bytes of the XDR string value. + * + * @return the encoded string bytes + */ byte[] bytes; + /** + * Creates an {@link XdrString} from raw bytes. + * + * @param bytes the string bytes + */ public XdrString(byte[] bytes) { this.bytes = bytes; } + /** + * Creates an {@link XdrString} from UTF-8 text. + * + * @param text the text value + */ public XdrString(String text) { this.bytes = text.getBytes(StandardCharsets.UTF_8); } + /** + * Encodes this string to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(this.bytes.length); stream.write(this.bytes, 0, this.bytes.length); } + /** + * Decodes an {@link XdrString} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxSize) throws IOException { // maxDepth is intentionally not checked - XdrString is a leaf type with no recursive decoding int size = stream.readInt(); @@ -42,19 +73,50 @@ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxS return new XdrString(bytes); } + /** + * Decodes an {@link XdrString} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxSize) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr, int maxSize) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr) throws IOException { return fromXdrBase64(xdr, Integer.MAX_VALUE); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -62,6 +124,13 @@ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOExcep return decode(xdrDataInputStream, maxSize); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -69,6 +138,11 @@ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { return decode(xdrDataInputStream, Integer.MAX_VALUE); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this string + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -78,6 +152,12 @@ Object toJsonObject() { return XdrElement.bytesToEscapedAscii(this.bytes); } + /** + * Parses an {@link XdrString} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrString}, or {@code null} if the input is {@code null} + */ public static XdrString fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -92,6 +172,11 @@ static XdrString fromJsonObject(Object json) { return new XdrString(XdrElement.escapedAsciiToBytes((String) json)); } + /** + * Returns this value decoded as a UTF-8 string. + * + * @return the UTF-8 string representation + */ @Override public String toString() { return new String(bytes, StandardCharsets.UTF_8); diff --git a/xdr-generator/test/snapshots/block_comments/XdrUnsignedHyperInteger.java b/xdr-generator/test/snapshots/block_comments/XdrUnsignedHyperInteger.java index e5237302c..58ff42684 100644 --- a/xdr-generator/test/snapshots/block_comments/XdrUnsignedHyperInteger.java +++ b/xdr-generator/test/snapshots/block_comments/XdrUnsignedHyperInteger.java @@ -15,10 +15,24 @@ */ @Value public class XdrUnsignedHyperInteger implements XdrElement { + /** Largest value representable by XDR unsigned hyper integer. */ public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615"); + /** Smallest value representable by XDR unsigned hyper integer. */ public static final BigInteger MIN_VALUE = BigInteger.ZERO; + + /** + * Numeric value stored by this XDR unsigned hyper integer. + * + * @return the unsigned 64-bit value + */ BigInteger number; + /** + * Creates an {@link XdrUnsignedHyperInteger} from a {@link BigInteger}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedHyperInteger(BigInteger number) { if (number.compareTo(MIN_VALUE) < 0 || number.compareTo(MAX_VALUE) > 0) { throw new IllegalArgumentException("number must be between 0 and 2^64 - 1 inclusive"); @@ -26,6 +40,12 @@ public XdrUnsignedHyperInteger(BigInteger number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedHyperInteger} from a non-negative {@link Long}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedHyperInteger(Long number) { if (number < 0) { throw new IllegalArgumentException( @@ -34,11 +54,25 @@ public XdrUnsignedHyperInteger(Long number) { this.number = BigInteger.valueOf(number); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.write(getBytes()); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedHyperInteger is a leaf type with no recursive decoding byte[] bytes = new byte[8]; @@ -47,6 +81,14 @@ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxD return new XdrUnsignedHyperInteger(uint64); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream using the default maximum + * depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } @@ -61,6 +103,11 @@ private byte[] getBytes() { return paddedBytes; } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -70,6 +117,13 @@ Object toJsonObject() { return this.number.toString(); } + /** + * Parses an {@link XdrUnsignedHyperInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedHyperInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedHyperInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -81,11 +135,25 @@ static XdrUnsignedHyperInteger fromJsonObject(Object json) { return new XdrUnsignedHyperInteger(XdrElement.jsonToBigInteger(json)); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/block_comments/XdrUnsignedInteger.java b/xdr-generator/test/snapshots/block_comments/XdrUnsignedInteger.java index 522554bc0..f0686a651 100644 --- a/xdr-generator/test/snapshots/block_comments/XdrUnsignedInteger.java +++ b/xdr-generator/test/snapshots/block_comments/XdrUnsignedInteger.java @@ -14,10 +14,24 @@ */ @Value public class XdrUnsignedInteger implements XdrElement { + /** Largest value representable by XDR unsigned integer. */ public static final long MAX_VALUE = (1L << 32) - 1; + /** Smallest value representable by XDR unsigned integer. */ public static final long MIN_VALUE = 0; + + /** + * Numeric value stored by this XDR unsigned integer. + * + * @return the unsigned 32-bit value as a {@link Long} + */ Long number; + /** + * Creates an {@link XdrUnsignedInteger} from a {@link Long}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedInteger(Long number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive"); @@ -25,6 +39,12 @@ public XdrUnsignedInteger(Long number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedInteger} from a non-negative {@link Integer}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedInteger(Integer number) { if (number < 0) { throw new IllegalArgumentException( @@ -33,6 +53,14 @@ public XdrUnsignedInteger(Integer number) { this.number = number.longValue(); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedInteger is a leaf type with no recursive decoding int intValue = stream.readInt(); @@ -40,15 +68,33 @@ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) return new XdrUnsignedInteger(uint32Value); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(number.intValue()); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -58,6 +104,13 @@ Object toJsonObject() { return this.number; } + /** + * Parses an {@link XdrUnsignedInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -69,11 +122,25 @@ static XdrUnsignedInteger fromJsonObject(Object json) { return new XdrUnsignedInteger(XdrElement.jsonToLong(json)); } + /** + * Decodes an {@link XdrUnsignedInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/const/TestArray.java b/xdr-generator/test/snapshots/const/TestArray.java index 494893125..7c07c8e5c 100644 --- a/xdr-generator/test/snapshots/const/TestArray.java +++ b/xdr-generator/test/snapshots/const/TestArray.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class TestArray implements XdrElement { + /** + * Value of the {@code TestArray} field. + * + * @param TestArray the {@code TestArray} field value + * @return the {@code TestArray} field value + */ private Integer[] TestArray; public void encode(XdrDataOutputStream stream) throws IOException { int TestArraySize = getTestArray().length; diff --git a/xdr-generator/test/snapshots/const/TestArray2.java b/xdr-generator/test/snapshots/const/TestArray2.java index a93bac3b5..4e15cd672 100644 --- a/xdr-generator/test/snapshots/const/TestArray2.java +++ b/xdr-generator/test/snapshots/const/TestArray2.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class TestArray2 implements XdrElement { + /** + * Value of the {@code TestArray2} field. + * + * @param TestArray2 the {@code TestArray2} field value + * @return the {@code TestArray2} field value + */ private Integer[] TestArray2; public void encode(XdrDataOutputStream stream) throws IOException { int TestArray2Size = getTestArray2().length; diff --git a/xdr-generator/test/snapshots/const/XdrDataInputStream.java b/xdr-generator/test/snapshots/const/XdrDataInputStream.java index 0dd3098d9..2491769a6 100644 --- a/xdr-generator/test/snapshots/const/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/const/XdrDataInputStream.java @@ -7,6 +7,7 @@ import java.nio.charset.Charset; import lombok.Setter; +/** XDR-aware input stream with padding handling and decode safety checks. */ public class XdrDataInputStream extends DataInputStream { /** Default maximum decoding depth to prevent stack overflow from deeply nested structures. */ @@ -19,6 +20,8 @@ public class XdrDataInputStream extends DataInputStream { * Maximum input length, -1 if unknown. * This is used to validate that the declared size of variable-length * arrays/opaques doesn't exceed the remaining input length, preventing DoS attacks. + * + * @param maxInputLen the maximum input length, or -1 if unknown */ @Setter private int maxInputLen = -1; @@ -69,6 +72,8 @@ public boolean readXdrBoolean() throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded integer array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public int[] readIntArray() throws IOException { @@ -88,6 +93,8 @@ private int[] readIntArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded float array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public float[] readFloatArray() throws IOException { @@ -107,6 +114,8 @@ private float[] readFloatArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded double array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public double[] readDoubleArray() throws IOException { diff --git a/xdr-generator/test/snapshots/const/XdrDataOutputStream.java b/xdr-generator/test/snapshots/const/XdrDataOutputStream.java index 9bb857a64..d5d8cda41 100644 --- a/xdr-generator/test/snapshots/const/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/const/XdrDataOutputStream.java @@ -5,15 +5,27 @@ import java.io.OutputStream; import java.nio.charset.Charset; +/** XDR-aware output stream that writes variable-length values with the required padding. */ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; + /** + * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * + * @param out the specified output stream + */ public XdrDataOutputStream(OutputStream out) { super(new XdrOutputStream(out)); mOut = (XdrOutputStream) super.out; } + /** + * Writes an XDR variable-length array of integers. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeIntArray(int[] a) throws IOException { writeInt(a.length); writeIntArray(a, a.length); @@ -25,6 +37,12 @@ private void writeIntArray(int[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of floats. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeFloatArray(float[] a) throws IOException { writeInt(a.length); writeFloatArray(a, a.length); @@ -36,6 +54,12 @@ private void writeFloatArray(float[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of doubles. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeDoubleArray(double[] a) throws IOException { writeInt(a.length); writeDoubleArray(a, a.length); diff --git a/xdr-generator/test/snapshots/const/XdrElement.java b/xdr-generator/test/snapshots/const/XdrElement.java index ef8f9efd6..99e832356 100644 --- a/xdr-generator/test/snapshots/const/XdrElement.java +++ b/xdr-generator/test/snapshots/const/XdrElement.java @@ -16,6 +16,7 @@ /** Common parent interface for all generated classes. */ public interface XdrElement { + /** Shared Gson instance used by generated XDR classes for JSON serialization. */ Gson gson = new GsonBuilder() .disableHtmlEscaping() @@ -23,12 +24,30 @@ public interface XdrElement { .setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) .create(); + /** + * Encodes this value to XDR and writes it to the provided stream. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ void encode(XdrDataOutputStream stream) throws IOException; + /** + * Encodes this value to XDR and returns the base64-encoded result. + * + * @return the base64-encoded XDR representation + * @throws IOException if an I/O error occurs while encoding the value + */ default String toXdrBase64() throws IOException { return Base64Factory.getInstance().encodeToString(toXdrByteArray()); } + /** + * Encodes this value to XDR and returns the raw bytes. + * + * @return the raw XDR byte representation + * @throws IOException if an I/O error occurs while encoding the value + */ default byte[] toXdrByteArray() throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); @@ -36,8 +55,19 @@ default byte[] toXdrByteArray() throws IOException { return byteArrayOutputStream.toByteArray(); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ String toJson(); + /** + * Returns the lowercase hexadecimal representation of a byte array. + * + * @param bytes the bytes to encode + * @return the lowercase hexadecimal representation + */ static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { @@ -46,6 +76,13 @@ static String bytesToHex(byte[] bytes) { return sb.toString(); } + /** + * Decodes a hexadecimal string into bytes. + * + * @param hex the hexadecimal string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input length is odd or contains non-hex characters + */ static byte[] hexToBytes(String hex) { if (hex.length() % 2 != 0) { throw new IllegalArgumentException("Hex string must have an even length"); @@ -63,6 +100,12 @@ static byte[] hexToBytes(String hex) { return data; } + /** + * Converts a byte array to an escaped ASCII string suitable for JSON serialization. + * + * @param data the bytes to encode + * @return the escaped ASCII representation + */ static String bytesToEscapedAscii(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { @@ -95,6 +138,13 @@ static String bytesToEscapedAscii(byte[] data) { return sb.toString(); } + /** + * Decodes an escaped ASCII string produced by {@link #bytesToEscapedAscii(byte[])}. + * + * @param s the escaped ASCII string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input contains invalid escape sequences or characters + */ static byte[] escapedAsciiToBytes(String s) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; @@ -155,6 +205,13 @@ static byte[] escapedAsciiToBytes(String s) { return out.toByteArray(); } + /** + * Converts a JSON scalar into a Java {@code long}. + * + * @param json the JSON value to convert + * @return the converted {@code long} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static long jsonToLong(Object json) { if (json instanceof String) { return Long.parseLong((String) json); @@ -168,6 +225,13 @@ static long jsonToLong(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a JSON scalar into a {@link BigInteger}. + * + * @param json the JSON value to convert + * @return the converted {@link BigInteger} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static BigInteger jsonToBigInteger(Object json) { if (json instanceof String) { return new BigInteger((String) json); @@ -181,6 +245,14 @@ static BigInteger jsonToBigInteger(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a Java array into a JSON array using the provided mapper. + * + * @param array the array to convert + * @param mapper maps each element index to a JSON-compatible value + * @param the Java element type + * @return the converted JSON array + */ @SuppressWarnings("unchecked") static List arrayToJsonArray(T[] array, IntFunction mapper) { List list = new ArrayList<>(array.length); @@ -190,6 +262,15 @@ static List arrayToJsonArray(T[] array, IntFunction mapper) return list; } + /** + * Converts a JSON array into a Java array using the provided mapper. + * + * @param list the JSON array to convert + * @param clazz the Java array component type + * @param mapper maps each JSON value to the target Java type + * @param the Java element type + * @return the converted Java array + */ @SuppressWarnings("unchecked") static T[] jsonArrayToArray(List list, Class clazz, Function mapper) { T[] array = (T[]) Array.newInstance(clazz, list.size()); diff --git a/xdr-generator/test/snapshots/const/XdrString.java b/xdr-generator/test/snapshots/const/XdrString.java index e50113cfa..269f7b9d3 100644 --- a/xdr-generator/test/snapshots/const/XdrString.java +++ b/xdr-generator/test/snapshots/const/XdrString.java @@ -6,24 +6,55 @@ import lombok.Value; import org.stellar.sdk.Base64Factory; +/** Represents XDR string data. */ @Value public class XdrString implements XdrElement { + /** + * Raw bytes of the XDR string value. + * + * @return the encoded string bytes + */ byte[] bytes; + /** + * Creates an {@link XdrString} from raw bytes. + * + * @param bytes the string bytes + */ public XdrString(byte[] bytes) { this.bytes = bytes; } + /** + * Creates an {@link XdrString} from UTF-8 text. + * + * @param text the text value + */ public XdrString(String text) { this.bytes = text.getBytes(StandardCharsets.UTF_8); } + /** + * Encodes this string to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(this.bytes.length); stream.write(this.bytes, 0, this.bytes.length); } + /** + * Decodes an {@link XdrString} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxSize) throws IOException { // maxDepth is intentionally not checked - XdrString is a leaf type with no recursive decoding int size = stream.readInt(); @@ -42,19 +73,50 @@ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxS return new XdrString(bytes); } + /** + * Decodes an {@link XdrString} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxSize) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr, int maxSize) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr) throws IOException { return fromXdrBase64(xdr, Integer.MAX_VALUE); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -62,6 +124,13 @@ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOExcep return decode(xdrDataInputStream, maxSize); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -69,6 +138,11 @@ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { return decode(xdrDataInputStream, Integer.MAX_VALUE); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this string + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -78,6 +152,12 @@ Object toJsonObject() { return XdrElement.bytesToEscapedAscii(this.bytes); } + /** + * Parses an {@link XdrString} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrString}, or {@code null} if the input is {@code null} + */ public static XdrString fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -92,6 +172,11 @@ static XdrString fromJsonObject(Object json) { return new XdrString(XdrElement.escapedAsciiToBytes((String) json)); } + /** + * Returns this value decoded as a UTF-8 string. + * + * @return the UTF-8 string representation + */ @Override public String toString() { return new String(bytes, StandardCharsets.UTF_8); diff --git a/xdr-generator/test/snapshots/const/XdrUnsignedHyperInteger.java b/xdr-generator/test/snapshots/const/XdrUnsignedHyperInteger.java index e5237302c..58ff42684 100644 --- a/xdr-generator/test/snapshots/const/XdrUnsignedHyperInteger.java +++ b/xdr-generator/test/snapshots/const/XdrUnsignedHyperInteger.java @@ -15,10 +15,24 @@ */ @Value public class XdrUnsignedHyperInteger implements XdrElement { + /** Largest value representable by XDR unsigned hyper integer. */ public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615"); + /** Smallest value representable by XDR unsigned hyper integer. */ public static final BigInteger MIN_VALUE = BigInteger.ZERO; + + /** + * Numeric value stored by this XDR unsigned hyper integer. + * + * @return the unsigned 64-bit value + */ BigInteger number; + /** + * Creates an {@link XdrUnsignedHyperInteger} from a {@link BigInteger}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedHyperInteger(BigInteger number) { if (number.compareTo(MIN_VALUE) < 0 || number.compareTo(MAX_VALUE) > 0) { throw new IllegalArgumentException("number must be between 0 and 2^64 - 1 inclusive"); @@ -26,6 +40,12 @@ public XdrUnsignedHyperInteger(BigInteger number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedHyperInteger} from a non-negative {@link Long}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedHyperInteger(Long number) { if (number < 0) { throw new IllegalArgumentException( @@ -34,11 +54,25 @@ public XdrUnsignedHyperInteger(Long number) { this.number = BigInteger.valueOf(number); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.write(getBytes()); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedHyperInteger is a leaf type with no recursive decoding byte[] bytes = new byte[8]; @@ -47,6 +81,14 @@ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxD return new XdrUnsignedHyperInteger(uint64); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream using the default maximum + * depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } @@ -61,6 +103,11 @@ private byte[] getBytes() { return paddedBytes; } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -70,6 +117,13 @@ Object toJsonObject() { return this.number.toString(); } + /** + * Parses an {@link XdrUnsignedHyperInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedHyperInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedHyperInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -81,11 +135,25 @@ static XdrUnsignedHyperInteger fromJsonObject(Object json) { return new XdrUnsignedHyperInteger(XdrElement.jsonToBigInteger(json)); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/const/XdrUnsignedInteger.java b/xdr-generator/test/snapshots/const/XdrUnsignedInteger.java index 522554bc0..f0686a651 100644 --- a/xdr-generator/test/snapshots/const/XdrUnsignedInteger.java +++ b/xdr-generator/test/snapshots/const/XdrUnsignedInteger.java @@ -14,10 +14,24 @@ */ @Value public class XdrUnsignedInteger implements XdrElement { + /** Largest value representable by XDR unsigned integer. */ public static final long MAX_VALUE = (1L << 32) - 1; + /** Smallest value representable by XDR unsigned integer. */ public static final long MIN_VALUE = 0; + + /** + * Numeric value stored by this XDR unsigned integer. + * + * @return the unsigned 32-bit value as a {@link Long} + */ Long number; + /** + * Creates an {@link XdrUnsignedInteger} from a {@link Long}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedInteger(Long number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive"); @@ -25,6 +39,12 @@ public XdrUnsignedInteger(Long number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedInteger} from a non-negative {@link Integer}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedInteger(Integer number) { if (number < 0) { throw new IllegalArgumentException( @@ -33,6 +53,14 @@ public XdrUnsignedInteger(Integer number) { this.number = number.longValue(); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedInteger is a leaf type with no recursive decoding int intValue = stream.readInt(); @@ -40,15 +68,33 @@ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) return new XdrUnsignedInteger(uint32Value); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(number.intValue()); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -58,6 +104,13 @@ Object toJsonObject() { return this.number; } + /** + * Parses an {@link XdrUnsignedInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -69,11 +122,25 @@ static XdrUnsignedInteger fromJsonObject(Object json) { return new XdrUnsignedInteger(XdrElement.jsonToLong(json)); } + /** + * Decodes an {@link XdrUnsignedInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/enum/XdrDataInputStream.java b/xdr-generator/test/snapshots/enum/XdrDataInputStream.java index 0dd3098d9..2491769a6 100644 --- a/xdr-generator/test/snapshots/enum/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/enum/XdrDataInputStream.java @@ -7,6 +7,7 @@ import java.nio.charset.Charset; import lombok.Setter; +/** XDR-aware input stream with padding handling and decode safety checks. */ public class XdrDataInputStream extends DataInputStream { /** Default maximum decoding depth to prevent stack overflow from deeply nested structures. */ @@ -19,6 +20,8 @@ public class XdrDataInputStream extends DataInputStream { * Maximum input length, -1 if unknown. * This is used to validate that the declared size of variable-length * arrays/opaques doesn't exceed the remaining input length, preventing DoS attacks. + * + * @param maxInputLen the maximum input length, or -1 if unknown */ @Setter private int maxInputLen = -1; @@ -69,6 +72,8 @@ public boolean readXdrBoolean() throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded integer array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public int[] readIntArray() throws IOException { @@ -88,6 +93,8 @@ private int[] readIntArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded float array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public float[] readFloatArray() throws IOException { @@ -107,6 +114,8 @@ private float[] readFloatArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded double array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public double[] readDoubleArray() throws IOException { diff --git a/xdr-generator/test/snapshots/enum/XdrDataOutputStream.java b/xdr-generator/test/snapshots/enum/XdrDataOutputStream.java index 9bb857a64..d5d8cda41 100644 --- a/xdr-generator/test/snapshots/enum/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/enum/XdrDataOutputStream.java @@ -5,15 +5,27 @@ import java.io.OutputStream; import java.nio.charset.Charset; +/** XDR-aware output stream that writes variable-length values with the required padding. */ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; + /** + * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * + * @param out the specified output stream + */ public XdrDataOutputStream(OutputStream out) { super(new XdrOutputStream(out)); mOut = (XdrOutputStream) super.out; } + /** + * Writes an XDR variable-length array of integers. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeIntArray(int[] a) throws IOException { writeInt(a.length); writeIntArray(a, a.length); @@ -25,6 +37,12 @@ private void writeIntArray(int[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of floats. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeFloatArray(float[] a) throws IOException { writeInt(a.length); writeFloatArray(a, a.length); @@ -36,6 +54,12 @@ private void writeFloatArray(float[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of doubles. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeDoubleArray(double[] a) throws IOException { writeInt(a.length); writeDoubleArray(a, a.length); diff --git a/xdr-generator/test/snapshots/enum/XdrElement.java b/xdr-generator/test/snapshots/enum/XdrElement.java index ef8f9efd6..99e832356 100644 --- a/xdr-generator/test/snapshots/enum/XdrElement.java +++ b/xdr-generator/test/snapshots/enum/XdrElement.java @@ -16,6 +16,7 @@ /** Common parent interface for all generated classes. */ public interface XdrElement { + /** Shared Gson instance used by generated XDR classes for JSON serialization. */ Gson gson = new GsonBuilder() .disableHtmlEscaping() @@ -23,12 +24,30 @@ public interface XdrElement { .setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) .create(); + /** + * Encodes this value to XDR and writes it to the provided stream. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ void encode(XdrDataOutputStream stream) throws IOException; + /** + * Encodes this value to XDR and returns the base64-encoded result. + * + * @return the base64-encoded XDR representation + * @throws IOException if an I/O error occurs while encoding the value + */ default String toXdrBase64() throws IOException { return Base64Factory.getInstance().encodeToString(toXdrByteArray()); } + /** + * Encodes this value to XDR and returns the raw bytes. + * + * @return the raw XDR byte representation + * @throws IOException if an I/O error occurs while encoding the value + */ default byte[] toXdrByteArray() throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); @@ -36,8 +55,19 @@ default byte[] toXdrByteArray() throws IOException { return byteArrayOutputStream.toByteArray(); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ String toJson(); + /** + * Returns the lowercase hexadecimal representation of a byte array. + * + * @param bytes the bytes to encode + * @return the lowercase hexadecimal representation + */ static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { @@ -46,6 +76,13 @@ static String bytesToHex(byte[] bytes) { return sb.toString(); } + /** + * Decodes a hexadecimal string into bytes. + * + * @param hex the hexadecimal string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input length is odd or contains non-hex characters + */ static byte[] hexToBytes(String hex) { if (hex.length() % 2 != 0) { throw new IllegalArgumentException("Hex string must have an even length"); @@ -63,6 +100,12 @@ static byte[] hexToBytes(String hex) { return data; } + /** + * Converts a byte array to an escaped ASCII string suitable for JSON serialization. + * + * @param data the bytes to encode + * @return the escaped ASCII representation + */ static String bytesToEscapedAscii(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { @@ -95,6 +138,13 @@ static String bytesToEscapedAscii(byte[] data) { return sb.toString(); } + /** + * Decodes an escaped ASCII string produced by {@link #bytesToEscapedAscii(byte[])}. + * + * @param s the escaped ASCII string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input contains invalid escape sequences or characters + */ static byte[] escapedAsciiToBytes(String s) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; @@ -155,6 +205,13 @@ static byte[] escapedAsciiToBytes(String s) { return out.toByteArray(); } + /** + * Converts a JSON scalar into a Java {@code long}. + * + * @param json the JSON value to convert + * @return the converted {@code long} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static long jsonToLong(Object json) { if (json instanceof String) { return Long.parseLong((String) json); @@ -168,6 +225,13 @@ static long jsonToLong(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a JSON scalar into a {@link BigInteger}. + * + * @param json the JSON value to convert + * @return the converted {@link BigInteger} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static BigInteger jsonToBigInteger(Object json) { if (json instanceof String) { return new BigInteger((String) json); @@ -181,6 +245,14 @@ static BigInteger jsonToBigInteger(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a Java array into a JSON array using the provided mapper. + * + * @param array the array to convert + * @param mapper maps each element index to a JSON-compatible value + * @param the Java element type + * @return the converted JSON array + */ @SuppressWarnings("unchecked") static List arrayToJsonArray(T[] array, IntFunction mapper) { List list = new ArrayList<>(array.length); @@ -190,6 +262,15 @@ static List arrayToJsonArray(T[] array, IntFunction mapper) return list; } + /** + * Converts a JSON array into a Java array using the provided mapper. + * + * @param list the JSON array to convert + * @param clazz the Java array component type + * @param mapper maps each JSON value to the target Java type + * @param the Java element type + * @return the converted Java array + */ @SuppressWarnings("unchecked") static T[] jsonArrayToArray(List list, Class clazz, Function mapper) { T[] array = (T[]) Array.newInstance(clazz, list.size()); diff --git a/xdr-generator/test/snapshots/enum/XdrString.java b/xdr-generator/test/snapshots/enum/XdrString.java index e50113cfa..269f7b9d3 100644 --- a/xdr-generator/test/snapshots/enum/XdrString.java +++ b/xdr-generator/test/snapshots/enum/XdrString.java @@ -6,24 +6,55 @@ import lombok.Value; import org.stellar.sdk.Base64Factory; +/** Represents XDR string data. */ @Value public class XdrString implements XdrElement { + /** + * Raw bytes of the XDR string value. + * + * @return the encoded string bytes + */ byte[] bytes; + /** + * Creates an {@link XdrString} from raw bytes. + * + * @param bytes the string bytes + */ public XdrString(byte[] bytes) { this.bytes = bytes; } + /** + * Creates an {@link XdrString} from UTF-8 text. + * + * @param text the text value + */ public XdrString(String text) { this.bytes = text.getBytes(StandardCharsets.UTF_8); } + /** + * Encodes this string to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(this.bytes.length); stream.write(this.bytes, 0, this.bytes.length); } + /** + * Decodes an {@link XdrString} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxSize) throws IOException { // maxDepth is intentionally not checked - XdrString is a leaf type with no recursive decoding int size = stream.readInt(); @@ -42,19 +73,50 @@ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxS return new XdrString(bytes); } + /** + * Decodes an {@link XdrString} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxSize) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr, int maxSize) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr) throws IOException { return fromXdrBase64(xdr, Integer.MAX_VALUE); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -62,6 +124,13 @@ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOExcep return decode(xdrDataInputStream, maxSize); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -69,6 +138,11 @@ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { return decode(xdrDataInputStream, Integer.MAX_VALUE); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this string + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -78,6 +152,12 @@ Object toJsonObject() { return XdrElement.bytesToEscapedAscii(this.bytes); } + /** + * Parses an {@link XdrString} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrString}, or {@code null} if the input is {@code null} + */ public static XdrString fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -92,6 +172,11 @@ static XdrString fromJsonObject(Object json) { return new XdrString(XdrElement.escapedAsciiToBytes((String) json)); } + /** + * Returns this value decoded as a UTF-8 string. + * + * @return the UTF-8 string representation + */ @Override public String toString() { return new String(bytes, StandardCharsets.UTF_8); diff --git a/xdr-generator/test/snapshots/enum/XdrUnsignedHyperInteger.java b/xdr-generator/test/snapshots/enum/XdrUnsignedHyperInteger.java index e5237302c..58ff42684 100644 --- a/xdr-generator/test/snapshots/enum/XdrUnsignedHyperInteger.java +++ b/xdr-generator/test/snapshots/enum/XdrUnsignedHyperInteger.java @@ -15,10 +15,24 @@ */ @Value public class XdrUnsignedHyperInteger implements XdrElement { + /** Largest value representable by XDR unsigned hyper integer. */ public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615"); + /** Smallest value representable by XDR unsigned hyper integer. */ public static final BigInteger MIN_VALUE = BigInteger.ZERO; + + /** + * Numeric value stored by this XDR unsigned hyper integer. + * + * @return the unsigned 64-bit value + */ BigInteger number; + /** + * Creates an {@link XdrUnsignedHyperInteger} from a {@link BigInteger}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedHyperInteger(BigInteger number) { if (number.compareTo(MIN_VALUE) < 0 || number.compareTo(MAX_VALUE) > 0) { throw new IllegalArgumentException("number must be between 0 and 2^64 - 1 inclusive"); @@ -26,6 +40,12 @@ public XdrUnsignedHyperInteger(BigInteger number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedHyperInteger} from a non-negative {@link Long}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedHyperInteger(Long number) { if (number < 0) { throw new IllegalArgumentException( @@ -34,11 +54,25 @@ public XdrUnsignedHyperInteger(Long number) { this.number = BigInteger.valueOf(number); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.write(getBytes()); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedHyperInteger is a leaf type with no recursive decoding byte[] bytes = new byte[8]; @@ -47,6 +81,14 @@ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxD return new XdrUnsignedHyperInteger(uint64); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream using the default maximum + * depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } @@ -61,6 +103,11 @@ private byte[] getBytes() { return paddedBytes; } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -70,6 +117,13 @@ Object toJsonObject() { return this.number.toString(); } + /** + * Parses an {@link XdrUnsignedHyperInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedHyperInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedHyperInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -81,11 +135,25 @@ static XdrUnsignedHyperInteger fromJsonObject(Object json) { return new XdrUnsignedHyperInteger(XdrElement.jsonToBigInteger(json)); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/enum/XdrUnsignedInteger.java b/xdr-generator/test/snapshots/enum/XdrUnsignedInteger.java index 522554bc0..f0686a651 100644 --- a/xdr-generator/test/snapshots/enum/XdrUnsignedInteger.java +++ b/xdr-generator/test/snapshots/enum/XdrUnsignedInteger.java @@ -14,10 +14,24 @@ */ @Value public class XdrUnsignedInteger implements XdrElement { + /** Largest value representable by XDR unsigned integer. */ public static final long MAX_VALUE = (1L << 32) - 1; + /** Smallest value representable by XDR unsigned integer. */ public static final long MIN_VALUE = 0; + + /** + * Numeric value stored by this XDR unsigned integer. + * + * @return the unsigned 32-bit value as a {@link Long} + */ Long number; + /** + * Creates an {@link XdrUnsignedInteger} from a {@link Long}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedInteger(Long number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive"); @@ -25,6 +39,12 @@ public XdrUnsignedInteger(Long number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedInteger} from a non-negative {@link Integer}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedInteger(Integer number) { if (number < 0) { throw new IllegalArgumentException( @@ -33,6 +53,14 @@ public XdrUnsignedInteger(Integer number) { this.number = number.longValue(); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedInteger is a leaf type with no recursive decoding int intValue = stream.readInt(); @@ -40,15 +68,33 @@ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) return new XdrUnsignedInteger(uint32Value); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(number.intValue()); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -58,6 +104,13 @@ Object toJsonObject() { return this.number; } + /** + * Parses an {@link XdrUnsignedInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -69,11 +122,25 @@ static XdrUnsignedInteger fromJsonObject(Object json) { return new XdrUnsignedInteger(XdrElement.jsonToLong(json)); } + /** + * Decodes an {@link XdrUnsignedInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/nesting/Foo.java b/xdr-generator/test/snapshots/nesting/Foo.java index 5d676376d..5498c4f98 100644 --- a/xdr-generator/test/snapshots/nesting/Foo.java +++ b/xdr-generator/test/snapshots/nesting/Foo.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Foo implements XdrElement { + /** + * Value of the {@code Foo} field. + * + * @param Foo the {@code Foo} field value + * @return the {@code Foo} field value + */ private Integer Foo; public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(Foo); diff --git a/xdr-generator/test/snapshots/nesting/MyUnion.java b/xdr-generator/test/snapshots/nesting/MyUnion.java index 124a8dd91..a47708cf1 100644 --- a/xdr-generator/test/snapshots/nesting/MyUnion.java +++ b/xdr-generator/test/snapshots/nesting/MyUnion.java @@ -43,8 +43,26 @@ @AllArgsConstructor @Builder(toBuilder = true) public class MyUnion implements XdrElement { + /** + * Value of the {@code discriminant} field. + * + * @param discriminant the {@code discriminant} field value + * @return the {@code discriminant} field value + */ private UnionKey discriminant; + /** + * Value of the {@code one} field. + * + * @param one the {@code one} field value + * @return the {@code one} field value + */ private MyUnionOne one; + /** + * Value of the {@code two} field. + * + * @param two the {@code two} field value + * @return the {@code two} field value + */ private MyUnionTwo two; public void encode(XdrDataOutputStream stream) throws IOException { @@ -169,6 +187,12 @@ static MyUnion fromJsonObject(Object json) { @AllArgsConstructor @Builder(toBuilder = true) public static class MyUnionOne implements XdrElement { + /** + * Value of the {@code someInt} field. + * + * @param someInt the {@code someInt} field value + * @return the {@code someInt} field value + */ private Integer someInt; public void encode(XdrDataOutputStream stream) throws IOException{ stream.writeInt(someInt); @@ -232,7 +256,19 @@ static MyUnionOne fromJsonObject(Object json) { @AllArgsConstructor @Builder(toBuilder = true) public static class MyUnionTwo implements XdrElement { + /** + * Value of the {@code someInt} field. + * + * @param someInt the {@code someInt} field value + * @return the {@code someInt} field value + */ private Integer someInt; + /** + * Value of the {@code foo} field. + * + * @param foo the {@code foo} field value + * @return the {@code foo} field value + */ private Foo foo; public void encode(XdrDataOutputStream stream) throws IOException{ stream.writeInt(someInt); diff --git a/xdr-generator/test/snapshots/nesting/XdrDataInputStream.java b/xdr-generator/test/snapshots/nesting/XdrDataInputStream.java index 0dd3098d9..2491769a6 100644 --- a/xdr-generator/test/snapshots/nesting/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/nesting/XdrDataInputStream.java @@ -7,6 +7,7 @@ import java.nio.charset.Charset; import lombok.Setter; +/** XDR-aware input stream with padding handling and decode safety checks. */ public class XdrDataInputStream extends DataInputStream { /** Default maximum decoding depth to prevent stack overflow from deeply nested structures. */ @@ -19,6 +20,8 @@ public class XdrDataInputStream extends DataInputStream { * Maximum input length, -1 if unknown. * This is used to validate that the declared size of variable-length * arrays/opaques doesn't exceed the remaining input length, preventing DoS attacks. + * + * @param maxInputLen the maximum input length, or -1 if unknown */ @Setter private int maxInputLen = -1; @@ -69,6 +72,8 @@ public boolean readXdrBoolean() throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded integer array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public int[] readIntArray() throws IOException { @@ -88,6 +93,8 @@ private int[] readIntArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded float array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public float[] readFloatArray() throws IOException { @@ -107,6 +114,8 @@ private float[] readFloatArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded double array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public double[] readDoubleArray() throws IOException { diff --git a/xdr-generator/test/snapshots/nesting/XdrDataOutputStream.java b/xdr-generator/test/snapshots/nesting/XdrDataOutputStream.java index 9bb857a64..d5d8cda41 100644 --- a/xdr-generator/test/snapshots/nesting/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/nesting/XdrDataOutputStream.java @@ -5,15 +5,27 @@ import java.io.OutputStream; import java.nio.charset.Charset; +/** XDR-aware output stream that writes variable-length values with the required padding. */ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; + /** + * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * + * @param out the specified output stream + */ public XdrDataOutputStream(OutputStream out) { super(new XdrOutputStream(out)); mOut = (XdrOutputStream) super.out; } + /** + * Writes an XDR variable-length array of integers. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeIntArray(int[] a) throws IOException { writeInt(a.length); writeIntArray(a, a.length); @@ -25,6 +37,12 @@ private void writeIntArray(int[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of floats. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeFloatArray(float[] a) throws IOException { writeInt(a.length); writeFloatArray(a, a.length); @@ -36,6 +54,12 @@ private void writeFloatArray(float[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of doubles. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeDoubleArray(double[] a) throws IOException { writeInt(a.length); writeDoubleArray(a, a.length); diff --git a/xdr-generator/test/snapshots/nesting/XdrElement.java b/xdr-generator/test/snapshots/nesting/XdrElement.java index ef8f9efd6..99e832356 100644 --- a/xdr-generator/test/snapshots/nesting/XdrElement.java +++ b/xdr-generator/test/snapshots/nesting/XdrElement.java @@ -16,6 +16,7 @@ /** Common parent interface for all generated classes. */ public interface XdrElement { + /** Shared Gson instance used by generated XDR classes for JSON serialization. */ Gson gson = new GsonBuilder() .disableHtmlEscaping() @@ -23,12 +24,30 @@ public interface XdrElement { .setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) .create(); + /** + * Encodes this value to XDR and writes it to the provided stream. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ void encode(XdrDataOutputStream stream) throws IOException; + /** + * Encodes this value to XDR and returns the base64-encoded result. + * + * @return the base64-encoded XDR representation + * @throws IOException if an I/O error occurs while encoding the value + */ default String toXdrBase64() throws IOException { return Base64Factory.getInstance().encodeToString(toXdrByteArray()); } + /** + * Encodes this value to XDR and returns the raw bytes. + * + * @return the raw XDR byte representation + * @throws IOException if an I/O error occurs while encoding the value + */ default byte[] toXdrByteArray() throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); @@ -36,8 +55,19 @@ default byte[] toXdrByteArray() throws IOException { return byteArrayOutputStream.toByteArray(); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ String toJson(); + /** + * Returns the lowercase hexadecimal representation of a byte array. + * + * @param bytes the bytes to encode + * @return the lowercase hexadecimal representation + */ static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { @@ -46,6 +76,13 @@ static String bytesToHex(byte[] bytes) { return sb.toString(); } + /** + * Decodes a hexadecimal string into bytes. + * + * @param hex the hexadecimal string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input length is odd or contains non-hex characters + */ static byte[] hexToBytes(String hex) { if (hex.length() % 2 != 0) { throw new IllegalArgumentException("Hex string must have an even length"); @@ -63,6 +100,12 @@ static byte[] hexToBytes(String hex) { return data; } + /** + * Converts a byte array to an escaped ASCII string suitable for JSON serialization. + * + * @param data the bytes to encode + * @return the escaped ASCII representation + */ static String bytesToEscapedAscii(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { @@ -95,6 +138,13 @@ static String bytesToEscapedAscii(byte[] data) { return sb.toString(); } + /** + * Decodes an escaped ASCII string produced by {@link #bytesToEscapedAscii(byte[])}. + * + * @param s the escaped ASCII string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input contains invalid escape sequences or characters + */ static byte[] escapedAsciiToBytes(String s) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; @@ -155,6 +205,13 @@ static byte[] escapedAsciiToBytes(String s) { return out.toByteArray(); } + /** + * Converts a JSON scalar into a Java {@code long}. + * + * @param json the JSON value to convert + * @return the converted {@code long} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static long jsonToLong(Object json) { if (json instanceof String) { return Long.parseLong((String) json); @@ -168,6 +225,13 @@ static long jsonToLong(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a JSON scalar into a {@link BigInteger}. + * + * @param json the JSON value to convert + * @return the converted {@link BigInteger} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static BigInteger jsonToBigInteger(Object json) { if (json instanceof String) { return new BigInteger((String) json); @@ -181,6 +245,14 @@ static BigInteger jsonToBigInteger(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a Java array into a JSON array using the provided mapper. + * + * @param array the array to convert + * @param mapper maps each element index to a JSON-compatible value + * @param the Java element type + * @return the converted JSON array + */ @SuppressWarnings("unchecked") static List arrayToJsonArray(T[] array, IntFunction mapper) { List list = new ArrayList<>(array.length); @@ -190,6 +262,15 @@ static List arrayToJsonArray(T[] array, IntFunction mapper) return list; } + /** + * Converts a JSON array into a Java array using the provided mapper. + * + * @param list the JSON array to convert + * @param clazz the Java array component type + * @param mapper maps each JSON value to the target Java type + * @param the Java element type + * @return the converted Java array + */ @SuppressWarnings("unchecked") static T[] jsonArrayToArray(List list, Class clazz, Function mapper) { T[] array = (T[]) Array.newInstance(clazz, list.size()); diff --git a/xdr-generator/test/snapshots/nesting/XdrString.java b/xdr-generator/test/snapshots/nesting/XdrString.java index e50113cfa..269f7b9d3 100644 --- a/xdr-generator/test/snapshots/nesting/XdrString.java +++ b/xdr-generator/test/snapshots/nesting/XdrString.java @@ -6,24 +6,55 @@ import lombok.Value; import org.stellar.sdk.Base64Factory; +/** Represents XDR string data. */ @Value public class XdrString implements XdrElement { + /** + * Raw bytes of the XDR string value. + * + * @return the encoded string bytes + */ byte[] bytes; + /** + * Creates an {@link XdrString} from raw bytes. + * + * @param bytes the string bytes + */ public XdrString(byte[] bytes) { this.bytes = bytes; } + /** + * Creates an {@link XdrString} from UTF-8 text. + * + * @param text the text value + */ public XdrString(String text) { this.bytes = text.getBytes(StandardCharsets.UTF_8); } + /** + * Encodes this string to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(this.bytes.length); stream.write(this.bytes, 0, this.bytes.length); } + /** + * Decodes an {@link XdrString} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxSize) throws IOException { // maxDepth is intentionally not checked - XdrString is a leaf type with no recursive decoding int size = stream.readInt(); @@ -42,19 +73,50 @@ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxS return new XdrString(bytes); } + /** + * Decodes an {@link XdrString} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxSize) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr, int maxSize) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr) throws IOException { return fromXdrBase64(xdr, Integer.MAX_VALUE); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -62,6 +124,13 @@ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOExcep return decode(xdrDataInputStream, maxSize); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -69,6 +138,11 @@ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { return decode(xdrDataInputStream, Integer.MAX_VALUE); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this string + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -78,6 +152,12 @@ Object toJsonObject() { return XdrElement.bytesToEscapedAscii(this.bytes); } + /** + * Parses an {@link XdrString} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrString}, or {@code null} if the input is {@code null} + */ public static XdrString fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -92,6 +172,11 @@ static XdrString fromJsonObject(Object json) { return new XdrString(XdrElement.escapedAsciiToBytes((String) json)); } + /** + * Returns this value decoded as a UTF-8 string. + * + * @return the UTF-8 string representation + */ @Override public String toString() { return new String(bytes, StandardCharsets.UTF_8); diff --git a/xdr-generator/test/snapshots/nesting/XdrUnsignedHyperInteger.java b/xdr-generator/test/snapshots/nesting/XdrUnsignedHyperInteger.java index e5237302c..58ff42684 100644 --- a/xdr-generator/test/snapshots/nesting/XdrUnsignedHyperInteger.java +++ b/xdr-generator/test/snapshots/nesting/XdrUnsignedHyperInteger.java @@ -15,10 +15,24 @@ */ @Value public class XdrUnsignedHyperInteger implements XdrElement { + /** Largest value representable by XDR unsigned hyper integer. */ public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615"); + /** Smallest value representable by XDR unsigned hyper integer. */ public static final BigInteger MIN_VALUE = BigInteger.ZERO; + + /** + * Numeric value stored by this XDR unsigned hyper integer. + * + * @return the unsigned 64-bit value + */ BigInteger number; + /** + * Creates an {@link XdrUnsignedHyperInteger} from a {@link BigInteger}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedHyperInteger(BigInteger number) { if (number.compareTo(MIN_VALUE) < 0 || number.compareTo(MAX_VALUE) > 0) { throw new IllegalArgumentException("number must be between 0 and 2^64 - 1 inclusive"); @@ -26,6 +40,12 @@ public XdrUnsignedHyperInteger(BigInteger number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedHyperInteger} from a non-negative {@link Long}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedHyperInteger(Long number) { if (number < 0) { throw new IllegalArgumentException( @@ -34,11 +54,25 @@ public XdrUnsignedHyperInteger(Long number) { this.number = BigInteger.valueOf(number); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.write(getBytes()); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedHyperInteger is a leaf type with no recursive decoding byte[] bytes = new byte[8]; @@ -47,6 +81,14 @@ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxD return new XdrUnsignedHyperInteger(uint64); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream using the default maximum + * depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } @@ -61,6 +103,11 @@ private byte[] getBytes() { return paddedBytes; } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -70,6 +117,13 @@ Object toJsonObject() { return this.number.toString(); } + /** + * Parses an {@link XdrUnsignedHyperInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedHyperInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedHyperInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -81,11 +135,25 @@ static XdrUnsignedHyperInteger fromJsonObject(Object json) { return new XdrUnsignedHyperInteger(XdrElement.jsonToBigInteger(json)); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/nesting/XdrUnsignedInteger.java b/xdr-generator/test/snapshots/nesting/XdrUnsignedInteger.java index 522554bc0..f0686a651 100644 --- a/xdr-generator/test/snapshots/nesting/XdrUnsignedInteger.java +++ b/xdr-generator/test/snapshots/nesting/XdrUnsignedInteger.java @@ -14,10 +14,24 @@ */ @Value public class XdrUnsignedInteger implements XdrElement { + /** Largest value representable by XDR unsigned integer. */ public static final long MAX_VALUE = (1L << 32) - 1; + /** Smallest value representable by XDR unsigned integer. */ public static final long MIN_VALUE = 0; + + /** + * Numeric value stored by this XDR unsigned integer. + * + * @return the unsigned 32-bit value as a {@link Long} + */ Long number; + /** + * Creates an {@link XdrUnsignedInteger} from a {@link Long}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedInteger(Long number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive"); @@ -25,6 +39,12 @@ public XdrUnsignedInteger(Long number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedInteger} from a non-negative {@link Integer}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedInteger(Integer number) { if (number < 0) { throw new IllegalArgumentException( @@ -33,6 +53,14 @@ public XdrUnsignedInteger(Integer number) { this.number = number.longValue(); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedInteger is a leaf type with no recursive decoding int intValue = stream.readInt(); @@ -40,15 +68,33 @@ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) return new XdrUnsignedInteger(uint32Value); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(number.intValue()); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -58,6 +104,13 @@ Object toJsonObject() { return this.number; } + /** + * Parses an {@link XdrUnsignedInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -69,11 +122,25 @@ static XdrUnsignedInteger fromJsonObject(Object json) { return new XdrUnsignedInteger(XdrElement.jsonToLong(json)); } + /** + * Decodes an {@link XdrUnsignedInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/optional/Arr.java b/xdr-generator/test/snapshots/optional/Arr.java index 45ddcec15..2ad24ba34 100644 --- a/xdr-generator/test/snapshots/optional/Arr.java +++ b/xdr-generator/test/snapshots/optional/Arr.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Arr implements XdrElement { + /** + * Value of the {@code Arr} field. + * + * @param Arr the {@code Arr} field value + * @return the {@code Arr} field value + */ private Integer[] Arr; public void encode(XdrDataOutputStream stream) throws IOException { int ArrSize = getArr().length; diff --git a/xdr-generator/test/snapshots/optional/HasOptions.java b/xdr-generator/test/snapshots/optional/HasOptions.java index 394b6e9bb..cfd9a153e 100644 --- a/xdr-generator/test/snapshots/optional/HasOptions.java +++ b/xdr-generator/test/snapshots/optional/HasOptions.java @@ -33,8 +33,26 @@ @AllArgsConstructor @Builder(toBuilder = true) public class HasOptions implements XdrElement { + /** + * Value of the {@code firstOption} field. + * + * @param firstOption the {@code firstOption} field value + * @return the {@code firstOption} field value + */ private Integer firstOption; + /** + * Value of the {@code secondOption} field. + * + * @param secondOption the {@code secondOption} field value + * @return the {@code secondOption} field value + */ private Integer secondOption; + /** + * Value of the {@code thirdOption} field. + * + * @param thirdOption the {@code thirdOption} field value + * @return the {@code thirdOption} field value + */ private Arr thirdOption; public void encode(XdrDataOutputStream stream) throws IOException{ if (firstOption != null) { diff --git a/xdr-generator/test/snapshots/optional/XdrDataInputStream.java b/xdr-generator/test/snapshots/optional/XdrDataInputStream.java index 0dd3098d9..2491769a6 100644 --- a/xdr-generator/test/snapshots/optional/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/optional/XdrDataInputStream.java @@ -7,6 +7,7 @@ import java.nio.charset.Charset; import lombok.Setter; +/** XDR-aware input stream with padding handling and decode safety checks. */ public class XdrDataInputStream extends DataInputStream { /** Default maximum decoding depth to prevent stack overflow from deeply nested structures. */ @@ -19,6 +20,8 @@ public class XdrDataInputStream extends DataInputStream { * Maximum input length, -1 if unknown. * This is used to validate that the declared size of variable-length * arrays/opaques doesn't exceed the remaining input length, preventing DoS attacks. + * + * @param maxInputLen the maximum input length, or -1 if unknown */ @Setter private int maxInputLen = -1; @@ -69,6 +72,8 @@ public boolean readXdrBoolean() throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded integer array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public int[] readIntArray() throws IOException { @@ -88,6 +93,8 @@ private int[] readIntArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded float array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public float[] readFloatArray() throws IOException { @@ -107,6 +114,8 @@ private float[] readFloatArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded double array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public double[] readDoubleArray() throws IOException { diff --git a/xdr-generator/test/snapshots/optional/XdrDataOutputStream.java b/xdr-generator/test/snapshots/optional/XdrDataOutputStream.java index 9bb857a64..d5d8cda41 100644 --- a/xdr-generator/test/snapshots/optional/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/optional/XdrDataOutputStream.java @@ -5,15 +5,27 @@ import java.io.OutputStream; import java.nio.charset.Charset; +/** XDR-aware output stream that writes variable-length values with the required padding. */ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; + /** + * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * + * @param out the specified output stream + */ public XdrDataOutputStream(OutputStream out) { super(new XdrOutputStream(out)); mOut = (XdrOutputStream) super.out; } + /** + * Writes an XDR variable-length array of integers. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeIntArray(int[] a) throws IOException { writeInt(a.length); writeIntArray(a, a.length); @@ -25,6 +37,12 @@ private void writeIntArray(int[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of floats. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeFloatArray(float[] a) throws IOException { writeInt(a.length); writeFloatArray(a, a.length); @@ -36,6 +54,12 @@ private void writeFloatArray(float[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of doubles. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeDoubleArray(double[] a) throws IOException { writeInt(a.length); writeDoubleArray(a, a.length); diff --git a/xdr-generator/test/snapshots/optional/XdrElement.java b/xdr-generator/test/snapshots/optional/XdrElement.java index ef8f9efd6..99e832356 100644 --- a/xdr-generator/test/snapshots/optional/XdrElement.java +++ b/xdr-generator/test/snapshots/optional/XdrElement.java @@ -16,6 +16,7 @@ /** Common parent interface for all generated classes. */ public interface XdrElement { + /** Shared Gson instance used by generated XDR classes for JSON serialization. */ Gson gson = new GsonBuilder() .disableHtmlEscaping() @@ -23,12 +24,30 @@ public interface XdrElement { .setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) .create(); + /** + * Encodes this value to XDR and writes it to the provided stream. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ void encode(XdrDataOutputStream stream) throws IOException; + /** + * Encodes this value to XDR and returns the base64-encoded result. + * + * @return the base64-encoded XDR representation + * @throws IOException if an I/O error occurs while encoding the value + */ default String toXdrBase64() throws IOException { return Base64Factory.getInstance().encodeToString(toXdrByteArray()); } + /** + * Encodes this value to XDR and returns the raw bytes. + * + * @return the raw XDR byte representation + * @throws IOException if an I/O error occurs while encoding the value + */ default byte[] toXdrByteArray() throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); @@ -36,8 +55,19 @@ default byte[] toXdrByteArray() throws IOException { return byteArrayOutputStream.toByteArray(); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ String toJson(); + /** + * Returns the lowercase hexadecimal representation of a byte array. + * + * @param bytes the bytes to encode + * @return the lowercase hexadecimal representation + */ static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { @@ -46,6 +76,13 @@ static String bytesToHex(byte[] bytes) { return sb.toString(); } + /** + * Decodes a hexadecimal string into bytes. + * + * @param hex the hexadecimal string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input length is odd or contains non-hex characters + */ static byte[] hexToBytes(String hex) { if (hex.length() % 2 != 0) { throw new IllegalArgumentException("Hex string must have an even length"); @@ -63,6 +100,12 @@ static byte[] hexToBytes(String hex) { return data; } + /** + * Converts a byte array to an escaped ASCII string suitable for JSON serialization. + * + * @param data the bytes to encode + * @return the escaped ASCII representation + */ static String bytesToEscapedAscii(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { @@ -95,6 +138,13 @@ static String bytesToEscapedAscii(byte[] data) { return sb.toString(); } + /** + * Decodes an escaped ASCII string produced by {@link #bytesToEscapedAscii(byte[])}. + * + * @param s the escaped ASCII string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input contains invalid escape sequences or characters + */ static byte[] escapedAsciiToBytes(String s) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; @@ -155,6 +205,13 @@ static byte[] escapedAsciiToBytes(String s) { return out.toByteArray(); } + /** + * Converts a JSON scalar into a Java {@code long}. + * + * @param json the JSON value to convert + * @return the converted {@code long} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static long jsonToLong(Object json) { if (json instanceof String) { return Long.parseLong((String) json); @@ -168,6 +225,13 @@ static long jsonToLong(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a JSON scalar into a {@link BigInteger}. + * + * @param json the JSON value to convert + * @return the converted {@link BigInteger} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static BigInteger jsonToBigInteger(Object json) { if (json instanceof String) { return new BigInteger((String) json); @@ -181,6 +245,14 @@ static BigInteger jsonToBigInteger(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a Java array into a JSON array using the provided mapper. + * + * @param array the array to convert + * @param mapper maps each element index to a JSON-compatible value + * @param the Java element type + * @return the converted JSON array + */ @SuppressWarnings("unchecked") static List arrayToJsonArray(T[] array, IntFunction mapper) { List list = new ArrayList<>(array.length); @@ -190,6 +262,15 @@ static List arrayToJsonArray(T[] array, IntFunction mapper) return list; } + /** + * Converts a JSON array into a Java array using the provided mapper. + * + * @param list the JSON array to convert + * @param clazz the Java array component type + * @param mapper maps each JSON value to the target Java type + * @param the Java element type + * @return the converted Java array + */ @SuppressWarnings("unchecked") static T[] jsonArrayToArray(List list, Class clazz, Function mapper) { T[] array = (T[]) Array.newInstance(clazz, list.size()); diff --git a/xdr-generator/test/snapshots/optional/XdrString.java b/xdr-generator/test/snapshots/optional/XdrString.java index e50113cfa..269f7b9d3 100644 --- a/xdr-generator/test/snapshots/optional/XdrString.java +++ b/xdr-generator/test/snapshots/optional/XdrString.java @@ -6,24 +6,55 @@ import lombok.Value; import org.stellar.sdk.Base64Factory; +/** Represents XDR string data. */ @Value public class XdrString implements XdrElement { + /** + * Raw bytes of the XDR string value. + * + * @return the encoded string bytes + */ byte[] bytes; + /** + * Creates an {@link XdrString} from raw bytes. + * + * @param bytes the string bytes + */ public XdrString(byte[] bytes) { this.bytes = bytes; } + /** + * Creates an {@link XdrString} from UTF-8 text. + * + * @param text the text value + */ public XdrString(String text) { this.bytes = text.getBytes(StandardCharsets.UTF_8); } + /** + * Encodes this string to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(this.bytes.length); stream.write(this.bytes, 0, this.bytes.length); } + /** + * Decodes an {@link XdrString} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxSize) throws IOException { // maxDepth is intentionally not checked - XdrString is a leaf type with no recursive decoding int size = stream.readInt(); @@ -42,19 +73,50 @@ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxS return new XdrString(bytes); } + /** + * Decodes an {@link XdrString} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxSize) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr, int maxSize) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr) throws IOException { return fromXdrBase64(xdr, Integer.MAX_VALUE); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -62,6 +124,13 @@ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOExcep return decode(xdrDataInputStream, maxSize); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -69,6 +138,11 @@ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { return decode(xdrDataInputStream, Integer.MAX_VALUE); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this string + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -78,6 +152,12 @@ Object toJsonObject() { return XdrElement.bytesToEscapedAscii(this.bytes); } + /** + * Parses an {@link XdrString} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrString}, or {@code null} if the input is {@code null} + */ public static XdrString fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -92,6 +172,11 @@ static XdrString fromJsonObject(Object json) { return new XdrString(XdrElement.escapedAsciiToBytes((String) json)); } + /** + * Returns this value decoded as a UTF-8 string. + * + * @return the UTF-8 string representation + */ @Override public String toString() { return new String(bytes, StandardCharsets.UTF_8); diff --git a/xdr-generator/test/snapshots/optional/XdrUnsignedHyperInteger.java b/xdr-generator/test/snapshots/optional/XdrUnsignedHyperInteger.java index e5237302c..58ff42684 100644 --- a/xdr-generator/test/snapshots/optional/XdrUnsignedHyperInteger.java +++ b/xdr-generator/test/snapshots/optional/XdrUnsignedHyperInteger.java @@ -15,10 +15,24 @@ */ @Value public class XdrUnsignedHyperInteger implements XdrElement { + /** Largest value representable by XDR unsigned hyper integer. */ public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615"); + /** Smallest value representable by XDR unsigned hyper integer. */ public static final BigInteger MIN_VALUE = BigInteger.ZERO; + + /** + * Numeric value stored by this XDR unsigned hyper integer. + * + * @return the unsigned 64-bit value + */ BigInteger number; + /** + * Creates an {@link XdrUnsignedHyperInteger} from a {@link BigInteger}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedHyperInteger(BigInteger number) { if (number.compareTo(MIN_VALUE) < 0 || number.compareTo(MAX_VALUE) > 0) { throw new IllegalArgumentException("number must be between 0 and 2^64 - 1 inclusive"); @@ -26,6 +40,12 @@ public XdrUnsignedHyperInteger(BigInteger number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedHyperInteger} from a non-negative {@link Long}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedHyperInteger(Long number) { if (number < 0) { throw new IllegalArgumentException( @@ -34,11 +54,25 @@ public XdrUnsignedHyperInteger(Long number) { this.number = BigInteger.valueOf(number); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.write(getBytes()); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedHyperInteger is a leaf type with no recursive decoding byte[] bytes = new byte[8]; @@ -47,6 +81,14 @@ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxD return new XdrUnsignedHyperInteger(uint64); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream using the default maximum + * depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } @@ -61,6 +103,11 @@ private byte[] getBytes() { return paddedBytes; } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -70,6 +117,13 @@ Object toJsonObject() { return this.number.toString(); } + /** + * Parses an {@link XdrUnsignedHyperInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedHyperInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedHyperInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -81,11 +135,25 @@ static XdrUnsignedHyperInteger fromJsonObject(Object json) { return new XdrUnsignedHyperInteger(XdrElement.jsonToBigInteger(json)); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/optional/XdrUnsignedInteger.java b/xdr-generator/test/snapshots/optional/XdrUnsignedInteger.java index 522554bc0..f0686a651 100644 --- a/xdr-generator/test/snapshots/optional/XdrUnsignedInteger.java +++ b/xdr-generator/test/snapshots/optional/XdrUnsignedInteger.java @@ -14,10 +14,24 @@ */ @Value public class XdrUnsignedInteger implements XdrElement { + /** Largest value representable by XDR unsigned integer. */ public static final long MAX_VALUE = (1L << 32) - 1; + /** Smallest value representable by XDR unsigned integer. */ public static final long MIN_VALUE = 0; + + /** + * Numeric value stored by this XDR unsigned integer. + * + * @return the unsigned 32-bit value as a {@link Long} + */ Long number; + /** + * Creates an {@link XdrUnsignedInteger} from a {@link Long}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedInteger(Long number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive"); @@ -25,6 +39,12 @@ public XdrUnsignedInteger(Long number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedInteger} from a non-negative {@link Integer}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedInteger(Integer number) { if (number < 0) { throw new IllegalArgumentException( @@ -33,6 +53,14 @@ public XdrUnsignedInteger(Integer number) { this.number = number.longValue(); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedInteger is a leaf type with no recursive decoding int intValue = stream.readInt(); @@ -40,15 +68,33 @@ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) return new XdrUnsignedInteger(uint32Value); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(number.intValue()); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -58,6 +104,13 @@ Object toJsonObject() { return this.number; } + /** + * Parses an {@link XdrUnsignedInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -69,11 +122,25 @@ static XdrUnsignedInteger fromJsonObject(Object json) { return new XdrUnsignedInteger(XdrElement.jsonToLong(json)); } + /** + * Decodes an {@link XdrUnsignedInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/struct/Int64.java b/xdr-generator/test/snapshots/struct/Int64.java index 96957b659..ba14bd1e5 100644 --- a/xdr-generator/test/snapshots/struct/Int64.java +++ b/xdr-generator/test/snapshots/struct/Int64.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Int64 implements XdrElement { + /** + * Value of the {@code int64} field. + * + * @param int64 the {@code int64} field value + * @return the {@code int64} field value + */ private Long int64; public void encode(XdrDataOutputStream stream) throws IOException { stream.writeLong(int64); diff --git a/xdr-generator/test/snapshots/struct/MyStruct.java b/xdr-generator/test/snapshots/struct/MyStruct.java index d7474d7eb..a78886caf 100644 --- a/xdr-generator/test/snapshots/struct/MyStruct.java +++ b/xdr-generator/test/snapshots/struct/MyStruct.java @@ -35,10 +35,40 @@ @AllArgsConstructor @Builder(toBuilder = true) public class MyStruct implements XdrElement { + /** + * Value of the {@code someInt} field. + * + * @param someInt the {@code someInt} field value + * @return the {@code someInt} field value + */ private Integer someInt; + /** + * Value of the {@code aBigInt} field. + * + * @param aBigInt the {@code aBigInt} field value + * @return the {@code aBigInt} field value + */ private Int64 aBigInt; + /** + * Value of the {@code someOpaque} field. + * + * @param someOpaque the {@code someOpaque} field value + * @return the {@code someOpaque} field value + */ private byte[] someOpaque; + /** + * Value of the {@code someString} field. + * + * @param someString the {@code someString} field value + * @return the {@code someString} field value + */ private XdrString someString; + /** + * Value of the {@code maxString} field. + * + * @param maxString the {@code maxString} field value + * @return the {@code maxString} field value + */ private XdrString maxString; public void encode(XdrDataOutputStream stream) throws IOException{ stream.writeInt(someInt); diff --git a/xdr-generator/test/snapshots/struct/XdrDataInputStream.java b/xdr-generator/test/snapshots/struct/XdrDataInputStream.java index 0dd3098d9..2491769a6 100644 --- a/xdr-generator/test/snapshots/struct/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/struct/XdrDataInputStream.java @@ -7,6 +7,7 @@ import java.nio.charset.Charset; import lombok.Setter; +/** XDR-aware input stream with padding handling and decode safety checks. */ public class XdrDataInputStream extends DataInputStream { /** Default maximum decoding depth to prevent stack overflow from deeply nested structures. */ @@ -19,6 +20,8 @@ public class XdrDataInputStream extends DataInputStream { * Maximum input length, -1 if unknown. * This is used to validate that the declared size of variable-length * arrays/opaques doesn't exceed the remaining input length, preventing DoS attacks. + * + * @param maxInputLen the maximum input length, or -1 if unknown */ @Setter private int maxInputLen = -1; @@ -69,6 +72,8 @@ public boolean readXdrBoolean() throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded integer array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public int[] readIntArray() throws IOException { @@ -88,6 +93,8 @@ private int[] readIntArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded float array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public float[] readFloatArray() throws IOException { @@ -107,6 +114,8 @@ private float[] readFloatArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded double array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public double[] readDoubleArray() throws IOException { diff --git a/xdr-generator/test/snapshots/struct/XdrDataOutputStream.java b/xdr-generator/test/snapshots/struct/XdrDataOutputStream.java index 9bb857a64..d5d8cda41 100644 --- a/xdr-generator/test/snapshots/struct/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/struct/XdrDataOutputStream.java @@ -5,15 +5,27 @@ import java.io.OutputStream; import java.nio.charset.Charset; +/** XDR-aware output stream that writes variable-length values with the required padding. */ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; + /** + * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * + * @param out the specified output stream + */ public XdrDataOutputStream(OutputStream out) { super(new XdrOutputStream(out)); mOut = (XdrOutputStream) super.out; } + /** + * Writes an XDR variable-length array of integers. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeIntArray(int[] a) throws IOException { writeInt(a.length); writeIntArray(a, a.length); @@ -25,6 +37,12 @@ private void writeIntArray(int[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of floats. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeFloatArray(float[] a) throws IOException { writeInt(a.length); writeFloatArray(a, a.length); @@ -36,6 +54,12 @@ private void writeFloatArray(float[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of doubles. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeDoubleArray(double[] a) throws IOException { writeInt(a.length); writeDoubleArray(a, a.length); diff --git a/xdr-generator/test/snapshots/struct/XdrElement.java b/xdr-generator/test/snapshots/struct/XdrElement.java index ef8f9efd6..99e832356 100644 --- a/xdr-generator/test/snapshots/struct/XdrElement.java +++ b/xdr-generator/test/snapshots/struct/XdrElement.java @@ -16,6 +16,7 @@ /** Common parent interface for all generated classes. */ public interface XdrElement { + /** Shared Gson instance used by generated XDR classes for JSON serialization. */ Gson gson = new GsonBuilder() .disableHtmlEscaping() @@ -23,12 +24,30 @@ public interface XdrElement { .setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) .create(); + /** + * Encodes this value to XDR and writes it to the provided stream. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ void encode(XdrDataOutputStream stream) throws IOException; + /** + * Encodes this value to XDR and returns the base64-encoded result. + * + * @return the base64-encoded XDR representation + * @throws IOException if an I/O error occurs while encoding the value + */ default String toXdrBase64() throws IOException { return Base64Factory.getInstance().encodeToString(toXdrByteArray()); } + /** + * Encodes this value to XDR and returns the raw bytes. + * + * @return the raw XDR byte representation + * @throws IOException if an I/O error occurs while encoding the value + */ default byte[] toXdrByteArray() throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); @@ -36,8 +55,19 @@ default byte[] toXdrByteArray() throws IOException { return byteArrayOutputStream.toByteArray(); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ String toJson(); + /** + * Returns the lowercase hexadecimal representation of a byte array. + * + * @param bytes the bytes to encode + * @return the lowercase hexadecimal representation + */ static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { @@ -46,6 +76,13 @@ static String bytesToHex(byte[] bytes) { return sb.toString(); } + /** + * Decodes a hexadecimal string into bytes. + * + * @param hex the hexadecimal string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input length is odd or contains non-hex characters + */ static byte[] hexToBytes(String hex) { if (hex.length() % 2 != 0) { throw new IllegalArgumentException("Hex string must have an even length"); @@ -63,6 +100,12 @@ static byte[] hexToBytes(String hex) { return data; } + /** + * Converts a byte array to an escaped ASCII string suitable for JSON serialization. + * + * @param data the bytes to encode + * @return the escaped ASCII representation + */ static String bytesToEscapedAscii(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { @@ -95,6 +138,13 @@ static String bytesToEscapedAscii(byte[] data) { return sb.toString(); } + /** + * Decodes an escaped ASCII string produced by {@link #bytesToEscapedAscii(byte[])}. + * + * @param s the escaped ASCII string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input contains invalid escape sequences or characters + */ static byte[] escapedAsciiToBytes(String s) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; @@ -155,6 +205,13 @@ static byte[] escapedAsciiToBytes(String s) { return out.toByteArray(); } + /** + * Converts a JSON scalar into a Java {@code long}. + * + * @param json the JSON value to convert + * @return the converted {@code long} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static long jsonToLong(Object json) { if (json instanceof String) { return Long.parseLong((String) json); @@ -168,6 +225,13 @@ static long jsonToLong(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a JSON scalar into a {@link BigInteger}. + * + * @param json the JSON value to convert + * @return the converted {@link BigInteger} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static BigInteger jsonToBigInteger(Object json) { if (json instanceof String) { return new BigInteger((String) json); @@ -181,6 +245,14 @@ static BigInteger jsonToBigInteger(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a Java array into a JSON array using the provided mapper. + * + * @param array the array to convert + * @param mapper maps each element index to a JSON-compatible value + * @param the Java element type + * @return the converted JSON array + */ @SuppressWarnings("unchecked") static List arrayToJsonArray(T[] array, IntFunction mapper) { List list = new ArrayList<>(array.length); @@ -190,6 +262,15 @@ static List arrayToJsonArray(T[] array, IntFunction mapper) return list; } + /** + * Converts a JSON array into a Java array using the provided mapper. + * + * @param list the JSON array to convert + * @param clazz the Java array component type + * @param mapper maps each JSON value to the target Java type + * @param the Java element type + * @return the converted Java array + */ @SuppressWarnings("unchecked") static T[] jsonArrayToArray(List list, Class clazz, Function mapper) { T[] array = (T[]) Array.newInstance(clazz, list.size()); diff --git a/xdr-generator/test/snapshots/struct/XdrString.java b/xdr-generator/test/snapshots/struct/XdrString.java index e50113cfa..269f7b9d3 100644 --- a/xdr-generator/test/snapshots/struct/XdrString.java +++ b/xdr-generator/test/snapshots/struct/XdrString.java @@ -6,24 +6,55 @@ import lombok.Value; import org.stellar.sdk.Base64Factory; +/** Represents XDR string data. */ @Value public class XdrString implements XdrElement { + /** + * Raw bytes of the XDR string value. + * + * @return the encoded string bytes + */ byte[] bytes; + /** + * Creates an {@link XdrString} from raw bytes. + * + * @param bytes the string bytes + */ public XdrString(byte[] bytes) { this.bytes = bytes; } + /** + * Creates an {@link XdrString} from UTF-8 text. + * + * @param text the text value + */ public XdrString(String text) { this.bytes = text.getBytes(StandardCharsets.UTF_8); } + /** + * Encodes this string to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(this.bytes.length); stream.write(this.bytes, 0, this.bytes.length); } + /** + * Decodes an {@link XdrString} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxSize) throws IOException { // maxDepth is intentionally not checked - XdrString is a leaf type with no recursive decoding int size = stream.readInt(); @@ -42,19 +73,50 @@ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxS return new XdrString(bytes); } + /** + * Decodes an {@link XdrString} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxSize) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr, int maxSize) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr) throws IOException { return fromXdrBase64(xdr, Integer.MAX_VALUE); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -62,6 +124,13 @@ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOExcep return decode(xdrDataInputStream, maxSize); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -69,6 +138,11 @@ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { return decode(xdrDataInputStream, Integer.MAX_VALUE); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this string + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -78,6 +152,12 @@ Object toJsonObject() { return XdrElement.bytesToEscapedAscii(this.bytes); } + /** + * Parses an {@link XdrString} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrString}, or {@code null} if the input is {@code null} + */ public static XdrString fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -92,6 +172,11 @@ static XdrString fromJsonObject(Object json) { return new XdrString(XdrElement.escapedAsciiToBytes((String) json)); } + /** + * Returns this value decoded as a UTF-8 string. + * + * @return the UTF-8 string representation + */ @Override public String toString() { return new String(bytes, StandardCharsets.UTF_8); diff --git a/xdr-generator/test/snapshots/struct/XdrUnsignedHyperInteger.java b/xdr-generator/test/snapshots/struct/XdrUnsignedHyperInteger.java index e5237302c..58ff42684 100644 --- a/xdr-generator/test/snapshots/struct/XdrUnsignedHyperInteger.java +++ b/xdr-generator/test/snapshots/struct/XdrUnsignedHyperInteger.java @@ -15,10 +15,24 @@ */ @Value public class XdrUnsignedHyperInteger implements XdrElement { + /** Largest value representable by XDR unsigned hyper integer. */ public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615"); + /** Smallest value representable by XDR unsigned hyper integer. */ public static final BigInteger MIN_VALUE = BigInteger.ZERO; + + /** + * Numeric value stored by this XDR unsigned hyper integer. + * + * @return the unsigned 64-bit value + */ BigInteger number; + /** + * Creates an {@link XdrUnsignedHyperInteger} from a {@link BigInteger}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedHyperInteger(BigInteger number) { if (number.compareTo(MIN_VALUE) < 0 || number.compareTo(MAX_VALUE) > 0) { throw new IllegalArgumentException("number must be between 0 and 2^64 - 1 inclusive"); @@ -26,6 +40,12 @@ public XdrUnsignedHyperInteger(BigInteger number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedHyperInteger} from a non-negative {@link Long}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedHyperInteger(Long number) { if (number < 0) { throw new IllegalArgumentException( @@ -34,11 +54,25 @@ public XdrUnsignedHyperInteger(Long number) { this.number = BigInteger.valueOf(number); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.write(getBytes()); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedHyperInteger is a leaf type with no recursive decoding byte[] bytes = new byte[8]; @@ -47,6 +81,14 @@ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxD return new XdrUnsignedHyperInteger(uint64); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream using the default maximum + * depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } @@ -61,6 +103,11 @@ private byte[] getBytes() { return paddedBytes; } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -70,6 +117,13 @@ Object toJsonObject() { return this.number.toString(); } + /** + * Parses an {@link XdrUnsignedHyperInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedHyperInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedHyperInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -81,11 +135,25 @@ static XdrUnsignedHyperInteger fromJsonObject(Object json) { return new XdrUnsignedHyperInteger(XdrElement.jsonToBigInteger(json)); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/struct/XdrUnsignedInteger.java b/xdr-generator/test/snapshots/struct/XdrUnsignedInteger.java index 522554bc0..f0686a651 100644 --- a/xdr-generator/test/snapshots/struct/XdrUnsignedInteger.java +++ b/xdr-generator/test/snapshots/struct/XdrUnsignedInteger.java @@ -14,10 +14,24 @@ */ @Value public class XdrUnsignedInteger implements XdrElement { + /** Largest value representable by XDR unsigned integer. */ public static final long MAX_VALUE = (1L << 32) - 1; + /** Smallest value representable by XDR unsigned integer. */ public static final long MIN_VALUE = 0; + + /** + * Numeric value stored by this XDR unsigned integer. + * + * @return the unsigned 32-bit value as a {@link Long} + */ Long number; + /** + * Creates an {@link XdrUnsignedInteger} from a {@link Long}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedInteger(Long number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive"); @@ -25,6 +39,12 @@ public XdrUnsignedInteger(Long number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedInteger} from a non-negative {@link Integer}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedInteger(Integer number) { if (number < 0) { throw new IllegalArgumentException( @@ -33,6 +53,14 @@ public XdrUnsignedInteger(Integer number) { this.number = number.longValue(); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedInteger is a leaf type with no recursive decoding int intValue = stream.readInt(); @@ -40,15 +68,33 @@ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) return new XdrUnsignedInteger(uint32Value); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(number.intValue()); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -58,6 +104,13 @@ Object toJsonObject() { return this.number; } + /** + * Parses an {@link XdrUnsignedInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -69,11 +122,25 @@ static XdrUnsignedInteger fromJsonObject(Object json) { return new XdrUnsignedInteger(XdrElement.jsonToLong(json)); } + /** + * Decodes an {@link XdrUnsignedInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/test/HasStuff.java b/xdr-generator/test/snapshots/test/HasStuff.java index f85f20b9d..9ca187752 100644 --- a/xdr-generator/test/snapshots/test/HasStuff.java +++ b/xdr-generator/test/snapshots/test/HasStuff.java @@ -31,6 +31,12 @@ @AllArgsConstructor @Builder(toBuilder = true) public class HasStuff implements XdrElement { + /** + * Value of the {@code data} field. + * + * @param data the {@code data} field value + * @return the {@code data} field value + */ private LotsOfMyStructs data; public void encode(XdrDataOutputStream stream) throws IOException{ data.encode(stream); diff --git a/xdr-generator/test/snapshots/test/Hash.java b/xdr-generator/test/snapshots/test/Hash.java index f34e51fea..b64390fc8 100644 --- a/xdr-generator/test/snapshots/test/Hash.java +++ b/xdr-generator/test/snapshots/test/Hash.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Hash implements XdrElement { + /** + * Value of the {@code Hash} field. + * + * @param Hash the {@code Hash} field value + * @return the {@code Hash} field value + */ private byte[] Hash; public void encode(XdrDataOutputStream stream) throws IOException { int HashSize = Hash.length; diff --git a/xdr-generator/test/snapshots/test/Hashes1.java b/xdr-generator/test/snapshots/test/Hashes1.java index e7c7d16d8..337773b4b 100644 --- a/xdr-generator/test/snapshots/test/Hashes1.java +++ b/xdr-generator/test/snapshots/test/Hashes1.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Hashes1 implements XdrElement { + /** + * Value of the {@code Hashes1} field. + * + * @param Hashes1 the {@code Hashes1} field value + * @return the {@code Hashes1} field value + */ private Hash[] Hashes1; public void encode(XdrDataOutputStream stream) throws IOException { int Hashes1Size = getHashes1().length; diff --git a/xdr-generator/test/snapshots/test/Hashes2.java b/xdr-generator/test/snapshots/test/Hashes2.java index a5addd136..df049353d 100644 --- a/xdr-generator/test/snapshots/test/Hashes2.java +++ b/xdr-generator/test/snapshots/test/Hashes2.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Hashes2 implements XdrElement { + /** + * Value of the {@code Hashes2} field. + * + * @param Hashes2 the {@code Hashes2} field value + * @return the {@code Hashes2} field value + */ private Hash[] Hashes2; public void encode(XdrDataOutputStream stream) throws IOException { int Hashes2Size = getHashes2().length; diff --git a/xdr-generator/test/snapshots/test/Hashes3.java b/xdr-generator/test/snapshots/test/Hashes3.java index 6c51fbe0b..00a71098e 100644 --- a/xdr-generator/test/snapshots/test/Hashes3.java +++ b/xdr-generator/test/snapshots/test/Hashes3.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Hashes3 implements XdrElement { + /** + * Value of the {@code Hashes3} field. + * + * @param Hashes3 the {@code Hashes3} field value + * @return the {@code Hashes3} field value + */ private Hash[] Hashes3; public void encode(XdrDataOutputStream stream) throws IOException { int Hashes3Size = getHashes3().length; diff --git a/xdr-generator/test/snapshots/test/Int1.java b/xdr-generator/test/snapshots/test/Int1.java index 414b5827e..2a6da856a 100644 --- a/xdr-generator/test/snapshots/test/Int1.java +++ b/xdr-generator/test/snapshots/test/Int1.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Int1 implements XdrElement { + /** + * Value of the {@code int1} field. + * + * @param int1 the {@code int1} field value + * @return the {@code int1} field value + */ private Integer int1; public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(int1); diff --git a/xdr-generator/test/snapshots/test/Int2.java b/xdr-generator/test/snapshots/test/Int2.java index 6fa08b36c..cab459f3c 100644 --- a/xdr-generator/test/snapshots/test/Int2.java +++ b/xdr-generator/test/snapshots/test/Int2.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Int2 implements XdrElement { + /** + * Value of the {@code int2} field. + * + * @param int2 the {@code int2} field value + * @return the {@code int2} field value + */ private Long int2; public void encode(XdrDataOutputStream stream) throws IOException { stream.writeLong(int2); diff --git a/xdr-generator/test/snapshots/test/Int3.java b/xdr-generator/test/snapshots/test/Int3.java index 5474d4135..cb8ad7041 100644 --- a/xdr-generator/test/snapshots/test/Int3.java +++ b/xdr-generator/test/snapshots/test/Int3.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Int3 implements XdrElement { + /** + * Value of the {@code int3} field. + * + * @param int3 the {@code int3} field value + * @return the {@code int3} field value + */ private XdrUnsignedInteger int3; public void encode(XdrDataOutputStream stream) throws IOException { int3.encode(stream); diff --git a/xdr-generator/test/snapshots/test/Int4.java b/xdr-generator/test/snapshots/test/Int4.java index e6368becc..71373b6dc 100644 --- a/xdr-generator/test/snapshots/test/Int4.java +++ b/xdr-generator/test/snapshots/test/Int4.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Int4 implements XdrElement { + /** + * Value of the {@code int4} field. + * + * @param int4 the {@code int4} field value + * @return the {@code int4} field value + */ private XdrUnsignedHyperInteger int4; public void encode(XdrDataOutputStream stream) throws IOException { int4.encode(stream); diff --git a/xdr-generator/test/snapshots/test/LotsOfMyStructs.java b/xdr-generator/test/snapshots/test/LotsOfMyStructs.java index 2a28ddc20..48829c698 100644 --- a/xdr-generator/test/snapshots/test/LotsOfMyStructs.java +++ b/xdr-generator/test/snapshots/test/LotsOfMyStructs.java @@ -31,6 +31,12 @@ @AllArgsConstructor @Builder(toBuilder = true) public class LotsOfMyStructs implements XdrElement { + /** + * Value of the {@code members} field. + * + * @param members the {@code members} field value + * @return the {@code members} field value + */ private MyStruct[] members; public void encode(XdrDataOutputStream stream) throws IOException{ int membersSize = getMembers().length; diff --git a/xdr-generator/test/snapshots/test/MyStruct.java b/xdr-generator/test/snapshots/test/MyStruct.java index b9719fbe3..db3a71a65 100644 --- a/xdr-generator/test/snapshots/test/MyStruct.java +++ b/xdr-generator/test/snapshots/test/MyStruct.java @@ -37,12 +37,54 @@ @AllArgsConstructor @Builder(toBuilder = true) public class MyStruct implements XdrElement { + /** + * Value of the {@code field1} field. + * + * @param field1 the {@code field1} field value + * @return the {@code field1} field value + */ private Uint512 field1; + /** + * Value of the {@code field2} field. + * + * @param field2 the {@code field2} field value + * @return the {@code field2} field value + */ private OptHash1 field2; + /** + * Value of the {@code field3} field. + * + * @param field3 the {@code field3} field value + * @return the {@code field3} field value + */ private Int1 field3; + /** + * Value of the {@code field4} field. + * + * @param field4 the {@code field4} field value + * @return the {@code field4} field value + */ private XdrUnsignedInteger field4; + /** + * Value of the {@code field5} field. + * + * @param field5 the {@code field5} field value + * @return the {@code field5} field value + */ private Float field5; + /** + * Value of the {@code field6} field. + * + * @param field6 the {@code field6} field value + * @return the {@code field6} field value + */ private Double field6; + /** + * Value of the {@code field7} field. + * + * @param field7 the {@code field7} field value + * @return the {@code field7} field value + */ private Boolean field7; public void encode(XdrDataOutputStream stream) throws IOException{ field1.encode(stream); diff --git a/xdr-generator/test/snapshots/test/Nester.java b/xdr-generator/test/snapshots/test/Nester.java index 41492f445..8155a0621 100644 --- a/xdr-generator/test/snapshots/test/Nester.java +++ b/xdr-generator/test/snapshots/test/Nester.java @@ -47,8 +47,26 @@ @AllArgsConstructor @Builder(toBuilder = true) public class Nester implements XdrElement { + /** + * Value of the {@code nestedEnum} field. + * + * @param nestedEnum the {@code nestedEnum} field value + * @return the {@code nestedEnum} field value + */ private NesterNestedEnum nestedEnum; + /** + * Value of the {@code nestedStruct} field. + * + * @param nestedStruct the {@code nestedStruct} field value + * @return the {@code nestedStruct} field value + */ private NesterNestedStruct nestedStruct; + /** + * Value of the {@code nestedUnion} field. + * + * @param nestedUnion the {@code nestedUnion} field value + * @return the {@code nestedUnion} field value + */ private NesterNestedUnion nestedUnion; public void encode(XdrDataOutputStream stream) throws IOException{ nestedEnum.encode(stream); @@ -195,6 +213,12 @@ static NestedEnum fromJsonObject(Object json) { @AllArgsConstructor @Builder(toBuilder = true) public static class NesterNestedStruct implements XdrElement { + /** + * Value of the {@code blah} field. + * + * @param blah the {@code blah} field value + * @return the {@code blah} field value + */ private Integer blah; public void encode(XdrDataOutputStream stream) throws IOException{ stream.writeInt(blah); @@ -260,7 +284,19 @@ static NesterNestedStruct fromJsonObject(Object json) { @AllArgsConstructor @Builder(toBuilder = true) public static class NesterNestedUnion implements XdrElement { + /** + * Value of the {@code discriminant} field. + * + * @param discriminant the {@code discriminant} field value + * @return the {@code discriminant} field value + */ private Color discriminant; + /** + * Value of the {@code blah2} field. + * + * @param blah2 the {@code blah2} field value + * @return the {@code blah2} field value + */ private Integer blah2; public void encode(XdrDataOutputStream stream) throws IOException { diff --git a/xdr-generator/test/snapshots/test/OptHash1.java b/xdr-generator/test/snapshots/test/OptHash1.java index 9fb28b8ca..55c369ea2 100644 --- a/xdr-generator/test/snapshots/test/OptHash1.java +++ b/xdr-generator/test/snapshots/test/OptHash1.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class OptHash1 implements XdrElement { + /** + * Value of the {@code optHash1} field. + * + * @param optHash1 the {@code optHash1} field value + * @return the {@code optHash1} field value + */ private Hash optHash1; public void encode(XdrDataOutputStream stream) throws IOException { if (optHash1 != null) { diff --git a/xdr-generator/test/snapshots/test/OptHash2.java b/xdr-generator/test/snapshots/test/OptHash2.java index 3a67e8dee..980ac0c59 100644 --- a/xdr-generator/test/snapshots/test/OptHash2.java +++ b/xdr-generator/test/snapshots/test/OptHash2.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class OptHash2 implements XdrElement { + /** + * Value of the {@code optHash2} field. + * + * @param optHash2 the {@code optHash2} field value + * @return the {@code optHash2} field value + */ private Hash optHash2; public void encode(XdrDataOutputStream stream) throws IOException { if (optHash2 != null) { diff --git a/xdr-generator/test/snapshots/test/Str.java b/xdr-generator/test/snapshots/test/Str.java index b99eb5e80..4447ff577 100644 --- a/xdr-generator/test/snapshots/test/Str.java +++ b/xdr-generator/test/snapshots/test/Str.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Str implements XdrElement { + /** + * Value of the {@code str} field. + * + * @param str the {@code str} field value + * @return the {@code str} field value + */ private XdrString str; public void encode(XdrDataOutputStream stream) throws IOException { int strSize = str.getBytes().length; diff --git a/xdr-generator/test/snapshots/test/Str2.java b/xdr-generator/test/snapshots/test/Str2.java index dfcc11bd8..3bf6d66ae 100644 --- a/xdr-generator/test/snapshots/test/Str2.java +++ b/xdr-generator/test/snapshots/test/Str2.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Str2 implements XdrElement { + /** + * Value of the {@code str2} field. + * + * @param str2 the {@code str2} field value + * @return the {@code str2} field value + */ private XdrString str2; public void encode(XdrDataOutputStream stream) throws IOException { str2.encode(stream); diff --git a/xdr-generator/test/snapshots/test/Uint512.java b/xdr-generator/test/snapshots/test/Uint512.java index dde68c7b4..b03e85699 100644 --- a/xdr-generator/test/snapshots/test/Uint512.java +++ b/xdr-generator/test/snapshots/test/Uint512.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Uint512 implements XdrElement { + /** + * Value of the {@code uint512} field. + * + * @param uint512 the {@code uint512} field value + * @return the {@code uint512} field value + */ private byte[] uint512; public void encode(XdrDataOutputStream stream) throws IOException { int uint512Size = uint512.length; diff --git a/xdr-generator/test/snapshots/test/Uint513.java b/xdr-generator/test/snapshots/test/Uint513.java index 19d84e67b..eadbd27be 100644 --- a/xdr-generator/test/snapshots/test/Uint513.java +++ b/xdr-generator/test/snapshots/test/Uint513.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Uint513 implements XdrElement { + /** + * Value of the {@code uint513} field. + * + * @param uint513 the {@code uint513} field value + * @return the {@code uint513} field value + */ private byte[] uint513; public void encode(XdrDataOutputStream stream) throws IOException { int uint513Size = uint513.length; diff --git a/xdr-generator/test/snapshots/test/Uint514.java b/xdr-generator/test/snapshots/test/Uint514.java index da0175b50..408dc34c9 100644 --- a/xdr-generator/test/snapshots/test/Uint514.java +++ b/xdr-generator/test/snapshots/test/Uint514.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Uint514 implements XdrElement { + /** + * Value of the {@code uint514} field. + * + * @param uint514 the {@code uint514} field value + * @return the {@code uint514} field value + */ private byte[] uint514; public void encode(XdrDataOutputStream stream) throws IOException { int uint514Size = uint514.length; diff --git a/xdr-generator/test/snapshots/test/XdrDataInputStream.java b/xdr-generator/test/snapshots/test/XdrDataInputStream.java index 0dd3098d9..2491769a6 100644 --- a/xdr-generator/test/snapshots/test/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/test/XdrDataInputStream.java @@ -7,6 +7,7 @@ import java.nio.charset.Charset; import lombok.Setter; +/** XDR-aware input stream with padding handling and decode safety checks. */ public class XdrDataInputStream extends DataInputStream { /** Default maximum decoding depth to prevent stack overflow from deeply nested structures. */ @@ -19,6 +20,8 @@ public class XdrDataInputStream extends DataInputStream { * Maximum input length, -1 if unknown. * This is used to validate that the declared size of variable-length * arrays/opaques doesn't exceed the remaining input length, preventing DoS attacks. + * + * @param maxInputLen the maximum input length, or -1 if unknown */ @Setter private int maxInputLen = -1; @@ -69,6 +72,8 @@ public boolean readXdrBoolean() throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded integer array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public int[] readIntArray() throws IOException { @@ -88,6 +93,8 @@ private int[] readIntArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded float array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public float[] readFloatArray() throws IOException { @@ -107,6 +114,8 @@ private float[] readFloatArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded double array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public double[] readDoubleArray() throws IOException { diff --git a/xdr-generator/test/snapshots/test/XdrDataOutputStream.java b/xdr-generator/test/snapshots/test/XdrDataOutputStream.java index 9bb857a64..d5d8cda41 100644 --- a/xdr-generator/test/snapshots/test/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/test/XdrDataOutputStream.java @@ -5,15 +5,27 @@ import java.io.OutputStream; import java.nio.charset.Charset; +/** XDR-aware output stream that writes variable-length values with the required padding. */ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; + /** + * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * + * @param out the specified output stream + */ public XdrDataOutputStream(OutputStream out) { super(new XdrOutputStream(out)); mOut = (XdrOutputStream) super.out; } + /** + * Writes an XDR variable-length array of integers. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeIntArray(int[] a) throws IOException { writeInt(a.length); writeIntArray(a, a.length); @@ -25,6 +37,12 @@ private void writeIntArray(int[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of floats. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeFloatArray(float[] a) throws IOException { writeInt(a.length); writeFloatArray(a, a.length); @@ -36,6 +54,12 @@ private void writeFloatArray(float[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of doubles. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeDoubleArray(double[] a) throws IOException { writeInt(a.length); writeDoubleArray(a, a.length); diff --git a/xdr-generator/test/snapshots/test/XdrElement.java b/xdr-generator/test/snapshots/test/XdrElement.java index ef8f9efd6..99e832356 100644 --- a/xdr-generator/test/snapshots/test/XdrElement.java +++ b/xdr-generator/test/snapshots/test/XdrElement.java @@ -16,6 +16,7 @@ /** Common parent interface for all generated classes. */ public interface XdrElement { + /** Shared Gson instance used by generated XDR classes for JSON serialization. */ Gson gson = new GsonBuilder() .disableHtmlEscaping() @@ -23,12 +24,30 @@ public interface XdrElement { .setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) .create(); + /** + * Encodes this value to XDR and writes it to the provided stream. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ void encode(XdrDataOutputStream stream) throws IOException; + /** + * Encodes this value to XDR and returns the base64-encoded result. + * + * @return the base64-encoded XDR representation + * @throws IOException if an I/O error occurs while encoding the value + */ default String toXdrBase64() throws IOException { return Base64Factory.getInstance().encodeToString(toXdrByteArray()); } + /** + * Encodes this value to XDR and returns the raw bytes. + * + * @return the raw XDR byte representation + * @throws IOException if an I/O error occurs while encoding the value + */ default byte[] toXdrByteArray() throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); @@ -36,8 +55,19 @@ default byte[] toXdrByteArray() throws IOException { return byteArrayOutputStream.toByteArray(); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ String toJson(); + /** + * Returns the lowercase hexadecimal representation of a byte array. + * + * @param bytes the bytes to encode + * @return the lowercase hexadecimal representation + */ static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { @@ -46,6 +76,13 @@ static String bytesToHex(byte[] bytes) { return sb.toString(); } + /** + * Decodes a hexadecimal string into bytes. + * + * @param hex the hexadecimal string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input length is odd or contains non-hex characters + */ static byte[] hexToBytes(String hex) { if (hex.length() % 2 != 0) { throw new IllegalArgumentException("Hex string must have an even length"); @@ -63,6 +100,12 @@ static byte[] hexToBytes(String hex) { return data; } + /** + * Converts a byte array to an escaped ASCII string suitable for JSON serialization. + * + * @param data the bytes to encode + * @return the escaped ASCII representation + */ static String bytesToEscapedAscii(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { @@ -95,6 +138,13 @@ static String bytesToEscapedAscii(byte[] data) { return sb.toString(); } + /** + * Decodes an escaped ASCII string produced by {@link #bytesToEscapedAscii(byte[])}. + * + * @param s the escaped ASCII string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input contains invalid escape sequences or characters + */ static byte[] escapedAsciiToBytes(String s) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; @@ -155,6 +205,13 @@ static byte[] escapedAsciiToBytes(String s) { return out.toByteArray(); } + /** + * Converts a JSON scalar into a Java {@code long}. + * + * @param json the JSON value to convert + * @return the converted {@code long} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static long jsonToLong(Object json) { if (json instanceof String) { return Long.parseLong((String) json); @@ -168,6 +225,13 @@ static long jsonToLong(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a JSON scalar into a {@link BigInteger}. + * + * @param json the JSON value to convert + * @return the converted {@link BigInteger} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static BigInteger jsonToBigInteger(Object json) { if (json instanceof String) { return new BigInteger((String) json); @@ -181,6 +245,14 @@ static BigInteger jsonToBigInteger(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a Java array into a JSON array using the provided mapper. + * + * @param array the array to convert + * @param mapper maps each element index to a JSON-compatible value + * @param the Java element type + * @return the converted JSON array + */ @SuppressWarnings("unchecked") static List arrayToJsonArray(T[] array, IntFunction mapper) { List list = new ArrayList<>(array.length); @@ -190,6 +262,15 @@ static List arrayToJsonArray(T[] array, IntFunction mapper) return list; } + /** + * Converts a JSON array into a Java array using the provided mapper. + * + * @param list the JSON array to convert + * @param clazz the Java array component type + * @param mapper maps each JSON value to the target Java type + * @param the Java element type + * @return the converted Java array + */ @SuppressWarnings("unchecked") static T[] jsonArrayToArray(List list, Class clazz, Function mapper) { T[] array = (T[]) Array.newInstance(clazz, list.size()); diff --git a/xdr-generator/test/snapshots/test/XdrString.java b/xdr-generator/test/snapshots/test/XdrString.java index e50113cfa..269f7b9d3 100644 --- a/xdr-generator/test/snapshots/test/XdrString.java +++ b/xdr-generator/test/snapshots/test/XdrString.java @@ -6,24 +6,55 @@ import lombok.Value; import org.stellar.sdk.Base64Factory; +/** Represents XDR string data. */ @Value public class XdrString implements XdrElement { + /** + * Raw bytes of the XDR string value. + * + * @return the encoded string bytes + */ byte[] bytes; + /** + * Creates an {@link XdrString} from raw bytes. + * + * @param bytes the string bytes + */ public XdrString(byte[] bytes) { this.bytes = bytes; } + /** + * Creates an {@link XdrString} from UTF-8 text. + * + * @param text the text value + */ public XdrString(String text) { this.bytes = text.getBytes(StandardCharsets.UTF_8); } + /** + * Encodes this string to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(this.bytes.length); stream.write(this.bytes, 0, this.bytes.length); } + /** + * Decodes an {@link XdrString} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxSize) throws IOException { // maxDepth is intentionally not checked - XdrString is a leaf type with no recursive decoding int size = stream.readInt(); @@ -42,19 +73,50 @@ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxS return new XdrString(bytes); } + /** + * Decodes an {@link XdrString} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxSize) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr, int maxSize) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr) throws IOException { return fromXdrBase64(xdr, Integer.MAX_VALUE); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -62,6 +124,13 @@ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOExcep return decode(xdrDataInputStream, maxSize); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -69,6 +138,11 @@ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { return decode(xdrDataInputStream, Integer.MAX_VALUE); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this string + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -78,6 +152,12 @@ Object toJsonObject() { return XdrElement.bytesToEscapedAscii(this.bytes); } + /** + * Parses an {@link XdrString} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrString}, or {@code null} if the input is {@code null} + */ public static XdrString fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -92,6 +172,11 @@ static XdrString fromJsonObject(Object json) { return new XdrString(XdrElement.escapedAsciiToBytes((String) json)); } + /** + * Returns this value decoded as a UTF-8 string. + * + * @return the UTF-8 string representation + */ @Override public String toString() { return new String(bytes, StandardCharsets.UTF_8); diff --git a/xdr-generator/test/snapshots/test/XdrUnsignedHyperInteger.java b/xdr-generator/test/snapshots/test/XdrUnsignedHyperInteger.java index e5237302c..58ff42684 100644 --- a/xdr-generator/test/snapshots/test/XdrUnsignedHyperInteger.java +++ b/xdr-generator/test/snapshots/test/XdrUnsignedHyperInteger.java @@ -15,10 +15,24 @@ */ @Value public class XdrUnsignedHyperInteger implements XdrElement { + /** Largest value representable by XDR unsigned hyper integer. */ public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615"); + /** Smallest value representable by XDR unsigned hyper integer. */ public static final BigInteger MIN_VALUE = BigInteger.ZERO; + + /** + * Numeric value stored by this XDR unsigned hyper integer. + * + * @return the unsigned 64-bit value + */ BigInteger number; + /** + * Creates an {@link XdrUnsignedHyperInteger} from a {@link BigInteger}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedHyperInteger(BigInteger number) { if (number.compareTo(MIN_VALUE) < 0 || number.compareTo(MAX_VALUE) > 0) { throw new IllegalArgumentException("number must be between 0 and 2^64 - 1 inclusive"); @@ -26,6 +40,12 @@ public XdrUnsignedHyperInteger(BigInteger number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedHyperInteger} from a non-negative {@link Long}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedHyperInteger(Long number) { if (number < 0) { throw new IllegalArgumentException( @@ -34,11 +54,25 @@ public XdrUnsignedHyperInteger(Long number) { this.number = BigInteger.valueOf(number); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.write(getBytes()); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedHyperInteger is a leaf type with no recursive decoding byte[] bytes = new byte[8]; @@ -47,6 +81,14 @@ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxD return new XdrUnsignedHyperInteger(uint64); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream using the default maximum + * depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } @@ -61,6 +103,11 @@ private byte[] getBytes() { return paddedBytes; } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -70,6 +117,13 @@ Object toJsonObject() { return this.number.toString(); } + /** + * Parses an {@link XdrUnsignedHyperInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedHyperInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedHyperInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -81,11 +135,25 @@ static XdrUnsignedHyperInteger fromJsonObject(Object json) { return new XdrUnsignedHyperInteger(XdrElement.jsonToBigInteger(json)); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/test/XdrUnsignedInteger.java b/xdr-generator/test/snapshots/test/XdrUnsignedInteger.java index 522554bc0..f0686a651 100644 --- a/xdr-generator/test/snapshots/test/XdrUnsignedInteger.java +++ b/xdr-generator/test/snapshots/test/XdrUnsignedInteger.java @@ -14,10 +14,24 @@ */ @Value public class XdrUnsignedInteger implements XdrElement { + /** Largest value representable by XDR unsigned integer. */ public static final long MAX_VALUE = (1L << 32) - 1; + /** Smallest value representable by XDR unsigned integer. */ public static final long MIN_VALUE = 0; + + /** + * Numeric value stored by this XDR unsigned integer. + * + * @return the unsigned 32-bit value as a {@link Long} + */ Long number; + /** + * Creates an {@link XdrUnsignedInteger} from a {@link Long}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedInteger(Long number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive"); @@ -25,6 +39,12 @@ public XdrUnsignedInteger(Long number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedInteger} from a non-negative {@link Integer}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedInteger(Integer number) { if (number < 0) { throw new IllegalArgumentException( @@ -33,6 +53,14 @@ public XdrUnsignedInteger(Integer number) { this.number = number.longValue(); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedInteger is a leaf type with no recursive decoding int intValue = stream.readInt(); @@ -40,15 +68,33 @@ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) return new XdrUnsignedInteger(uint32Value); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(number.intValue()); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -58,6 +104,13 @@ Object toJsonObject() { return this.number; } + /** + * Parses an {@link XdrUnsignedInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -69,11 +122,25 @@ static XdrUnsignedInteger fromJsonObject(Object json) { return new XdrUnsignedInteger(XdrElement.jsonToLong(json)); } + /** + * Decodes an {@link XdrUnsignedInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/union/Error.java b/xdr-generator/test/snapshots/union/Error.java index a8ca35bb5..1b1a59c76 100644 --- a/xdr-generator/test/snapshots/union/Error.java +++ b/xdr-generator/test/snapshots/union/Error.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Error implements XdrElement { + /** + * Value of the {@code Error} field. + * + * @param Error the {@code Error} field value + * @return the {@code Error} field value + */ private Integer Error; public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(Error); diff --git a/xdr-generator/test/snapshots/union/IntUnion.java b/xdr-generator/test/snapshots/union/IntUnion.java index 50dc51451..e32c9ab89 100644 --- a/xdr-generator/test/snapshots/union/IntUnion.java +++ b/xdr-generator/test/snapshots/union/IntUnion.java @@ -35,8 +35,26 @@ @AllArgsConstructor @Builder(toBuilder = true) public class IntUnion implements XdrElement { + /** + * Value of the {@code discriminant} field. + * + * @param discriminant the {@code discriminant} field value + * @return the {@code discriminant} field value + */ private Integer discriminant; + /** + * Value of the {@code error} field. + * + * @param error the {@code error} field value + * @return the {@code error} field value + */ private Error error; + /** + * Value of the {@code things} field. + * + * @param things the {@code things} field value + * @return the {@code things} field value + */ private Multi[] things; public void encode(XdrDataOutputStream stream) throws IOException { diff --git a/xdr-generator/test/snapshots/union/IntUnion2.java b/xdr-generator/test/snapshots/union/IntUnion2.java index dc904a241..265682c76 100644 --- a/xdr-generator/test/snapshots/union/IntUnion2.java +++ b/xdr-generator/test/snapshots/union/IntUnion2.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class IntUnion2 implements XdrElement { + /** + * Value of the {@code IntUnion2} field. + * + * @param IntUnion2 the {@code IntUnion2} field value + * @return the {@code IntUnion2} field value + */ private IntUnion IntUnion2; public void encode(XdrDataOutputStream stream) throws IOException { IntUnion2.encode(stream); diff --git a/xdr-generator/test/snapshots/union/Multi.java b/xdr-generator/test/snapshots/union/Multi.java index 9e68813db..cb9b7321b 100644 --- a/xdr-generator/test/snapshots/union/Multi.java +++ b/xdr-generator/test/snapshots/union/Multi.java @@ -26,6 +26,12 @@ @NoArgsConstructor @AllArgsConstructor public class Multi implements XdrElement { + /** + * Value of the {@code Multi} field. + * + * @param Multi the {@code Multi} field value + * @return the {@code Multi} field value + */ private Integer Multi; public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(Multi); diff --git a/xdr-generator/test/snapshots/union/MyUnion.java b/xdr-generator/test/snapshots/union/MyUnion.java index 28c6a8e1f..ee796289c 100644 --- a/xdr-generator/test/snapshots/union/MyUnion.java +++ b/xdr-generator/test/snapshots/union/MyUnion.java @@ -36,8 +36,26 @@ @AllArgsConstructor @Builder(toBuilder = true) public class MyUnion implements XdrElement { + /** + * Value of the {@code discriminant} field. + * + * @param discriminant the {@code discriminant} field value + * @return the {@code discriminant} field value + */ private UnionKey discriminant; + /** + * Value of the {@code error} field. + * + * @param error the {@code error} field value + * @return the {@code error} field value + */ private Error error; + /** + * Value of the {@code things} field. + * + * @param things the {@code things} field value + * @return the {@code things} field value + */ private Multi[] things; public void encode(XdrDataOutputStream stream) throws IOException { diff --git a/xdr-generator/test/snapshots/union/XdrDataInputStream.java b/xdr-generator/test/snapshots/union/XdrDataInputStream.java index 0dd3098d9..2491769a6 100644 --- a/xdr-generator/test/snapshots/union/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/union/XdrDataInputStream.java @@ -7,6 +7,7 @@ import java.nio.charset.Charset; import lombok.Setter; +/** XDR-aware input stream with padding handling and decode safety checks. */ public class XdrDataInputStream extends DataInputStream { /** Default maximum decoding depth to prevent stack overflow from deeply nested structures. */ @@ -19,6 +20,8 @@ public class XdrDataInputStream extends DataInputStream { * Maximum input length, -1 if unknown. * This is used to validate that the declared size of variable-length * arrays/opaques doesn't exceed the remaining input length, preventing DoS attacks. + * + * @param maxInputLen the maximum input length, or -1 if unknown */ @Setter private int maxInputLen = -1; @@ -69,6 +72,8 @@ public boolean readXdrBoolean() throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded integer array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public int[] readIntArray() throws IOException { @@ -88,6 +93,8 @@ private int[] readIntArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded float array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public float[] readFloatArray() throws IOException { @@ -107,6 +114,8 @@ private float[] readFloatArray(int l) throws IOException { * @deprecated This method does not validate the array length and may cause * OutOfMemoryError or NegativeArraySizeException with untrusted input. * Use generated XDR type decoders instead which include proper validation. + * @return the decoded double array + * @throws IOException if an I/O error occurs while reading the array */ @Deprecated public double[] readDoubleArray() throws IOException { diff --git a/xdr-generator/test/snapshots/union/XdrDataOutputStream.java b/xdr-generator/test/snapshots/union/XdrDataOutputStream.java index 9bb857a64..d5d8cda41 100644 --- a/xdr-generator/test/snapshots/union/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/union/XdrDataOutputStream.java @@ -5,15 +5,27 @@ import java.io.OutputStream; import java.nio.charset.Charset; +/** XDR-aware output stream that writes variable-length values with the required padding. */ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; + /** + * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * + * @param out the specified output stream + */ public XdrDataOutputStream(OutputStream out) { super(new XdrOutputStream(out)); mOut = (XdrOutputStream) super.out; } + /** + * Writes an XDR variable-length array of integers. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeIntArray(int[] a) throws IOException { writeInt(a.length); writeIntArray(a, a.length); @@ -25,6 +37,12 @@ private void writeIntArray(int[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of floats. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeFloatArray(float[] a) throws IOException { writeInt(a.length); writeFloatArray(a, a.length); @@ -36,6 +54,12 @@ private void writeFloatArray(float[] a, int l) throws IOException { } } + /** + * Writes an XDR variable-length array of doubles. + * + * @param a the array to write + * @throws IOException if an I/O error occurs while writing the array + */ public void writeDoubleArray(double[] a) throws IOException { writeInt(a.length); writeDoubleArray(a, a.length); diff --git a/xdr-generator/test/snapshots/union/XdrElement.java b/xdr-generator/test/snapshots/union/XdrElement.java index ef8f9efd6..99e832356 100644 --- a/xdr-generator/test/snapshots/union/XdrElement.java +++ b/xdr-generator/test/snapshots/union/XdrElement.java @@ -16,6 +16,7 @@ /** Common parent interface for all generated classes. */ public interface XdrElement { + /** Shared Gson instance used by generated XDR classes for JSON serialization. */ Gson gson = new GsonBuilder() .disableHtmlEscaping() @@ -23,12 +24,30 @@ public interface XdrElement { .setObjectToNumberStrategy(ToNumberPolicy.BIG_DECIMAL) .create(); + /** + * Encodes this value to XDR and writes it to the provided stream. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ void encode(XdrDataOutputStream stream) throws IOException; + /** + * Encodes this value to XDR and returns the base64-encoded result. + * + * @return the base64-encoded XDR representation + * @throws IOException if an I/O error occurs while encoding the value + */ default String toXdrBase64() throws IOException { return Base64Factory.getInstance().encodeToString(toXdrByteArray()); } + /** + * Encodes this value to XDR and returns the raw bytes. + * + * @return the raw XDR byte representation + * @throws IOException if an I/O error occurs while encoding the value + */ default byte[] toXdrByteArray() throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); @@ -36,8 +55,19 @@ default byte[] toXdrByteArray() throws IOException { return byteArrayOutputStream.toByteArray(); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ String toJson(); + /** + * Returns the lowercase hexadecimal representation of a byte array. + * + * @param bytes the bytes to encode + * @return the lowercase hexadecimal representation + */ static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { @@ -46,6 +76,13 @@ static String bytesToHex(byte[] bytes) { return sb.toString(); } + /** + * Decodes a hexadecimal string into bytes. + * + * @param hex the hexadecimal string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input length is odd or contains non-hex characters + */ static byte[] hexToBytes(String hex) { if (hex.length() % 2 != 0) { throw new IllegalArgumentException("Hex string must have an even length"); @@ -63,6 +100,12 @@ static byte[] hexToBytes(String hex) { return data; } + /** + * Converts a byte array to an escaped ASCII string suitable for JSON serialization. + * + * @param data the bytes to encode + * @return the escaped ASCII representation + */ static String bytesToEscapedAscii(byte[] data) { StringBuilder sb = new StringBuilder(); for (byte b : data) { @@ -95,6 +138,13 @@ static String bytesToEscapedAscii(byte[] data) { return sb.toString(); } + /** + * Decodes an escaped ASCII string produced by {@link #bytesToEscapedAscii(byte[])}. + * + * @param s the escaped ASCII string to decode + * @return the decoded bytes + * @throws IllegalArgumentException if the input contains invalid escape sequences or characters + */ static byte[] escapedAsciiToBytes(String s) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int i = 0; @@ -155,6 +205,13 @@ static byte[] escapedAsciiToBytes(String s) { return out.toByteArray(); } + /** + * Converts a JSON scalar into a Java {@code long}. + * + * @param json the JSON value to convert + * @return the converted {@code long} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static long jsonToLong(Object json) { if (json instanceof String) { return Long.parseLong((String) json); @@ -168,6 +225,13 @@ static long jsonToLong(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a JSON scalar into a {@link BigInteger}. + * + * @param json the JSON value to convert + * @return the converted {@link BigInteger} value + * @throws IllegalArgumentException if the JSON value is not a string or number + */ static BigInteger jsonToBigInteger(Object json) { if (json instanceof String) { return new BigInteger((String) json); @@ -181,6 +245,14 @@ static BigInteger jsonToBigInteger(Object json) { throw new IllegalArgumentException("Expected JSON string or number, got: " + json); } + /** + * Converts a Java array into a JSON array using the provided mapper. + * + * @param array the array to convert + * @param mapper maps each element index to a JSON-compatible value + * @param the Java element type + * @return the converted JSON array + */ @SuppressWarnings("unchecked") static List arrayToJsonArray(T[] array, IntFunction mapper) { List list = new ArrayList<>(array.length); @@ -190,6 +262,15 @@ static List arrayToJsonArray(T[] array, IntFunction mapper) return list; } + /** + * Converts a JSON array into a Java array using the provided mapper. + * + * @param list the JSON array to convert + * @param clazz the Java array component type + * @param mapper maps each JSON value to the target Java type + * @param the Java element type + * @return the converted Java array + */ @SuppressWarnings("unchecked") static T[] jsonArrayToArray(List list, Class clazz, Function mapper) { T[] array = (T[]) Array.newInstance(clazz, list.size()); diff --git a/xdr-generator/test/snapshots/union/XdrString.java b/xdr-generator/test/snapshots/union/XdrString.java index e50113cfa..269f7b9d3 100644 --- a/xdr-generator/test/snapshots/union/XdrString.java +++ b/xdr-generator/test/snapshots/union/XdrString.java @@ -6,24 +6,55 @@ import lombok.Value; import org.stellar.sdk.Base64Factory; +/** Represents XDR string data. */ @Value public class XdrString implements XdrElement { + /** + * Raw bytes of the XDR string value. + * + * @return the encoded string bytes + */ byte[] bytes; + /** + * Creates an {@link XdrString} from raw bytes. + * + * @param bytes the string bytes + */ public XdrString(byte[] bytes) { this.bytes = bytes; } + /** + * Creates an {@link XdrString} from UTF-8 text. + * + * @param text the text value + */ public XdrString(String text) { this.bytes = text.getBytes(StandardCharsets.UTF_8); } + /** + * Encodes this string to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(this.bytes.length); stream.write(this.bytes, 0, this.bytes.length); } + /** + * Decodes an {@link XdrString} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxSize) throws IOException { // maxDepth is intentionally not checked - XdrString is a leaf type with no recursive decoding int size = stream.readInt(); @@ -42,19 +73,50 @@ public static XdrString decode(XdrDataInputStream stream, int maxDepth, int maxS return new XdrString(bytes); } + /** + * Decodes an {@link XdrString} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the encoded size is invalid or an I/O error occurs + */ public static XdrString decode(XdrDataInputStream stream, int maxSize) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr, int maxSize) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes, maxSize); } + /** + * Decodes an {@link XdrString} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrBase64(String xdr) throws IOException { return fromXdrBase64(xdr, Integer.MAX_VALUE); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @param maxSize the maximum allowed string size in bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -62,6 +124,13 @@ public static XdrString fromXdrByteArray(byte[] xdr, int maxSize) throws IOExcep return decode(xdrDataInputStream, maxSize); } + /** + * Decodes an {@link XdrString} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrString} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); @@ -69,6 +138,11 @@ public static XdrString fromXdrByteArray(byte[] xdr) throws IOException { return decode(xdrDataInputStream, Integer.MAX_VALUE); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this string + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -78,6 +152,12 @@ Object toJsonObject() { return XdrElement.bytesToEscapedAscii(this.bytes); } + /** + * Parses an {@link XdrString} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrString}, or {@code null} if the input is {@code null} + */ public static XdrString fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -92,6 +172,11 @@ static XdrString fromJsonObject(Object json) { return new XdrString(XdrElement.escapedAsciiToBytes((String) json)); } + /** + * Returns this value decoded as a UTF-8 string. + * + * @return the UTF-8 string representation + */ @Override public String toString() { return new String(bytes, StandardCharsets.UTF_8); diff --git a/xdr-generator/test/snapshots/union/XdrUnsignedHyperInteger.java b/xdr-generator/test/snapshots/union/XdrUnsignedHyperInteger.java index e5237302c..58ff42684 100644 --- a/xdr-generator/test/snapshots/union/XdrUnsignedHyperInteger.java +++ b/xdr-generator/test/snapshots/union/XdrUnsignedHyperInteger.java @@ -15,10 +15,24 @@ */ @Value public class XdrUnsignedHyperInteger implements XdrElement { + /** Largest value representable by XDR unsigned hyper integer. */ public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615"); + /** Smallest value representable by XDR unsigned hyper integer. */ public static final BigInteger MIN_VALUE = BigInteger.ZERO; + + /** + * Numeric value stored by this XDR unsigned hyper integer. + * + * @return the unsigned 64-bit value + */ BigInteger number; + /** + * Creates an {@link XdrUnsignedHyperInteger} from a {@link BigInteger}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedHyperInteger(BigInteger number) { if (number.compareTo(MIN_VALUE) < 0 || number.compareTo(MAX_VALUE) > 0) { throw new IllegalArgumentException("number must be between 0 and 2^64 - 1 inclusive"); @@ -26,6 +40,12 @@ public XdrUnsignedHyperInteger(BigInteger number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedHyperInteger} from a non-negative {@link Long}. + * + * @param number the unsigned 64-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedHyperInteger(Long number) { if (number < 0) { throw new IllegalArgumentException( @@ -34,11 +54,25 @@ public XdrUnsignedHyperInteger(Long number) { this.number = BigInteger.valueOf(number); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.write(getBytes()); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedHyperInteger is a leaf type with no recursive decoding byte[] bytes = new byte[8]; @@ -47,6 +81,14 @@ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream, int maxD return new XdrUnsignedHyperInteger(uint64); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from the provided stream using the default maximum + * depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } @@ -61,6 +103,11 @@ private byte[] getBytes() { return paddedBytes; } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -70,6 +117,13 @@ Object toJsonObject() { return this.number.toString(); } + /** + * Parses an {@link XdrUnsignedHyperInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedHyperInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedHyperInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -81,11 +135,25 @@ static XdrUnsignedHyperInteger fromJsonObject(Object json) { return new XdrUnsignedHyperInteger(XdrElement.jsonToBigInteger(json)); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedHyperInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedHyperInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedHyperInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); diff --git a/xdr-generator/test/snapshots/union/XdrUnsignedInteger.java b/xdr-generator/test/snapshots/union/XdrUnsignedInteger.java index 522554bc0..f0686a651 100644 --- a/xdr-generator/test/snapshots/union/XdrUnsignedInteger.java +++ b/xdr-generator/test/snapshots/union/XdrUnsignedInteger.java @@ -14,10 +14,24 @@ */ @Value public class XdrUnsignedInteger implements XdrElement { + /** Largest value representable by XDR unsigned integer. */ public static final long MAX_VALUE = (1L << 32) - 1; + /** Smallest value representable by XDR unsigned integer. */ public static final long MIN_VALUE = 0; + + /** + * Numeric value stored by this XDR unsigned integer. + * + * @return the unsigned 32-bit value as a {@link Long} + */ Long number; + /** + * Creates an {@link XdrUnsignedInteger} from a {@link Long}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is outside the valid range + */ public XdrUnsignedInteger(Long number) { if (number < MIN_VALUE || number > MAX_VALUE) { throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive"); @@ -25,6 +39,12 @@ public XdrUnsignedInteger(Long number) { this.number = number; } + /** + * Creates an {@link XdrUnsignedInteger} from a non-negative {@link Integer}. + * + * @param number the unsigned 32-bit value + * @throws IllegalArgumentException if {@code number} is negative + */ public XdrUnsignedInteger(Integer number) { if (number < 0) { throw new IllegalArgumentException( @@ -33,6 +53,14 @@ public XdrUnsignedInteger(Integer number) { this.number = number.longValue(); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream. + * + * @param stream the source XDR input stream + * @param maxDepth the maximum decoding depth, ignored for this leaf type + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) throws IOException { // maxDepth is intentionally not checked - XdrUnsignedInteger is a leaf type with no recursive decoding int intValue = stream.readInt(); @@ -40,15 +68,33 @@ public static XdrUnsignedInteger decode(XdrDataInputStream stream, int maxDepth) return new XdrUnsignedInteger(uint32Value); } + /** + * Decodes an {@link XdrUnsignedInteger} from the provided stream using the default maximum depth. + * + * @param stream the source XDR input stream + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if an I/O error occurs while reading the value + */ public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException { return decode(stream, XdrDataInputStream.DEFAULT_MAX_DEPTH); } + /** + * Encodes this value to XDR. + * + * @param stream the destination XDR output stream + * @throws IOException if an I/O error occurs while writing the value + */ @Override public void encode(XdrDataOutputStream stream) throws IOException { stream.writeInt(number.intValue()); } + /** + * Serializes this value to JSON. + * + * @return the JSON representation of this value + */ @Override public String toJson() { return XdrElement.gson.toJson(toJsonObject()); @@ -58,6 +104,13 @@ Object toJsonObject() { return this.number; } + /** + * Parses an {@link XdrUnsignedInteger} from JSON. + * + * @param json the JSON representation + * @return the parsed {@link XdrUnsignedInteger}, or {@code null} if the input is {@code null} + * @throws IllegalArgumentException if the JSON value is invalid + */ public static XdrUnsignedInteger fromJson(String json) { return fromJsonObject(XdrElement.gson.fromJson(json, Object.class)); } @@ -69,11 +122,25 @@ static XdrUnsignedInteger fromJsonObject(Object json) { return new XdrUnsignedInteger(XdrElement.jsonToLong(json)); } + /** + * Decodes an {@link XdrUnsignedInteger} from a base64-encoded XDR string. + * + * @param xdr the base64-encoded XDR string + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrBase64(String xdr) throws IOException { byte[] bytes = Base64Factory.getInstance().decode(xdr); return fromXdrByteArray(bytes); } + /** + * Decodes an {@link XdrUnsignedInteger} from raw XDR bytes. + * + * @param xdr the raw XDR bytes + * @return the decoded {@link XdrUnsignedInteger} + * @throws IOException if the input is invalid or cannot be decoded + */ public static XdrUnsignedInteger fromXdrByteArray(byte[] xdr) throws IOException { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xdr); XdrDataInputStream xdrDataInputStream = new XdrDataInputStream(byteArrayInputStream); From f909f3937806015ed779733b893112b1fbb5b27c Mon Sep 17 00:00:00 2001 From: Jun Luo <4catcode@gmail.com> Date: Fri, 17 Apr 2026 16:45:46 +0800 Subject: [PATCH 2/2] docs: improve xdr generator javadocs --- xdr-generator/generator/templates/XdrDataInputStream.erb | 2 +- xdr-generator/generator/templates/XdrDataOutputStream.erb | 2 +- .../test/snapshots/block_comments/XdrDataInputStream.java | 2 +- .../test/snapshots/block_comments/XdrDataOutputStream.java | 2 +- xdr-generator/test/snapshots/const/XdrDataInputStream.java | 2 +- xdr-generator/test/snapshots/const/XdrDataOutputStream.java | 2 +- xdr-generator/test/snapshots/enum/XdrDataInputStream.java | 2 +- xdr-generator/test/snapshots/enum/XdrDataOutputStream.java | 2 +- xdr-generator/test/snapshots/nesting/XdrDataInputStream.java | 2 +- xdr-generator/test/snapshots/nesting/XdrDataOutputStream.java | 2 +- xdr-generator/test/snapshots/optional/XdrDataInputStream.java | 2 +- xdr-generator/test/snapshots/optional/XdrDataOutputStream.java | 2 +- xdr-generator/test/snapshots/struct/XdrDataInputStream.java | 2 +- xdr-generator/test/snapshots/struct/XdrDataOutputStream.java | 2 +- xdr-generator/test/snapshots/test/XdrDataInputStream.java | 2 +- xdr-generator/test/snapshots/test/XdrDataOutputStream.java | 2 +- xdr-generator/test/snapshots/union/XdrDataInputStream.java | 2 +- xdr-generator/test/snapshots/union/XdrDataOutputStream.java | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/xdr-generator/generator/templates/XdrDataInputStream.erb b/xdr-generator/generator/templates/XdrDataInputStream.erb index 20e5505c6..ca22a640f 100644 --- a/xdr-generator/generator/templates/XdrDataInputStream.erb +++ b/xdr-generator/generator/templates/XdrDataInputStream.erb @@ -27,7 +27,7 @@ public class XdrDataInputStream extends DataInputStream { private int maxInputLen = -1; /** - * Creates a XdrDataInputStream that uses the specified + * Creates an XdrDataInputStream that uses the specified * underlying InputStream. * * @param in the specified input stream diff --git a/xdr-generator/generator/templates/XdrDataOutputStream.erb b/xdr-generator/generator/templates/XdrDataOutputStream.erb index 6150dbd4d..1e94a964b 100644 --- a/xdr-generator/generator/templates/XdrDataOutputStream.erb +++ b/xdr-generator/generator/templates/XdrDataOutputStream.erb @@ -11,7 +11,7 @@ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; /** - * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * Creates an XdrDataOutputStream that uses the specified underlying OutputStream. * * @param out the specified output stream */ diff --git a/xdr-generator/test/snapshots/block_comments/XdrDataInputStream.java b/xdr-generator/test/snapshots/block_comments/XdrDataInputStream.java index 2491769a6..c02011a24 100644 --- a/xdr-generator/test/snapshots/block_comments/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/block_comments/XdrDataInputStream.java @@ -27,7 +27,7 @@ public class XdrDataInputStream extends DataInputStream { private int maxInputLen = -1; /** - * Creates a XdrDataInputStream that uses the specified + * Creates an XdrDataInputStream that uses the specified * underlying InputStream. * * @param in the specified input stream diff --git a/xdr-generator/test/snapshots/block_comments/XdrDataOutputStream.java b/xdr-generator/test/snapshots/block_comments/XdrDataOutputStream.java index d5d8cda41..9e588307a 100644 --- a/xdr-generator/test/snapshots/block_comments/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/block_comments/XdrDataOutputStream.java @@ -11,7 +11,7 @@ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; /** - * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * Creates an XdrDataOutputStream that uses the specified underlying OutputStream. * * @param out the specified output stream */ diff --git a/xdr-generator/test/snapshots/const/XdrDataInputStream.java b/xdr-generator/test/snapshots/const/XdrDataInputStream.java index 2491769a6..c02011a24 100644 --- a/xdr-generator/test/snapshots/const/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/const/XdrDataInputStream.java @@ -27,7 +27,7 @@ public class XdrDataInputStream extends DataInputStream { private int maxInputLen = -1; /** - * Creates a XdrDataInputStream that uses the specified + * Creates an XdrDataInputStream that uses the specified * underlying InputStream. * * @param in the specified input stream diff --git a/xdr-generator/test/snapshots/const/XdrDataOutputStream.java b/xdr-generator/test/snapshots/const/XdrDataOutputStream.java index d5d8cda41..9e588307a 100644 --- a/xdr-generator/test/snapshots/const/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/const/XdrDataOutputStream.java @@ -11,7 +11,7 @@ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; /** - * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * Creates an XdrDataOutputStream that uses the specified underlying OutputStream. * * @param out the specified output stream */ diff --git a/xdr-generator/test/snapshots/enum/XdrDataInputStream.java b/xdr-generator/test/snapshots/enum/XdrDataInputStream.java index 2491769a6..c02011a24 100644 --- a/xdr-generator/test/snapshots/enum/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/enum/XdrDataInputStream.java @@ -27,7 +27,7 @@ public class XdrDataInputStream extends DataInputStream { private int maxInputLen = -1; /** - * Creates a XdrDataInputStream that uses the specified + * Creates an XdrDataInputStream that uses the specified * underlying InputStream. * * @param in the specified input stream diff --git a/xdr-generator/test/snapshots/enum/XdrDataOutputStream.java b/xdr-generator/test/snapshots/enum/XdrDataOutputStream.java index d5d8cda41..9e588307a 100644 --- a/xdr-generator/test/snapshots/enum/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/enum/XdrDataOutputStream.java @@ -11,7 +11,7 @@ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; /** - * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * Creates an XdrDataOutputStream that uses the specified underlying OutputStream. * * @param out the specified output stream */ diff --git a/xdr-generator/test/snapshots/nesting/XdrDataInputStream.java b/xdr-generator/test/snapshots/nesting/XdrDataInputStream.java index 2491769a6..c02011a24 100644 --- a/xdr-generator/test/snapshots/nesting/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/nesting/XdrDataInputStream.java @@ -27,7 +27,7 @@ public class XdrDataInputStream extends DataInputStream { private int maxInputLen = -1; /** - * Creates a XdrDataInputStream that uses the specified + * Creates an XdrDataInputStream that uses the specified * underlying InputStream. * * @param in the specified input stream diff --git a/xdr-generator/test/snapshots/nesting/XdrDataOutputStream.java b/xdr-generator/test/snapshots/nesting/XdrDataOutputStream.java index d5d8cda41..9e588307a 100644 --- a/xdr-generator/test/snapshots/nesting/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/nesting/XdrDataOutputStream.java @@ -11,7 +11,7 @@ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; /** - * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * Creates an XdrDataOutputStream that uses the specified underlying OutputStream. * * @param out the specified output stream */ diff --git a/xdr-generator/test/snapshots/optional/XdrDataInputStream.java b/xdr-generator/test/snapshots/optional/XdrDataInputStream.java index 2491769a6..c02011a24 100644 --- a/xdr-generator/test/snapshots/optional/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/optional/XdrDataInputStream.java @@ -27,7 +27,7 @@ public class XdrDataInputStream extends DataInputStream { private int maxInputLen = -1; /** - * Creates a XdrDataInputStream that uses the specified + * Creates an XdrDataInputStream that uses the specified * underlying InputStream. * * @param in the specified input stream diff --git a/xdr-generator/test/snapshots/optional/XdrDataOutputStream.java b/xdr-generator/test/snapshots/optional/XdrDataOutputStream.java index d5d8cda41..9e588307a 100644 --- a/xdr-generator/test/snapshots/optional/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/optional/XdrDataOutputStream.java @@ -11,7 +11,7 @@ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; /** - * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * Creates an XdrDataOutputStream that uses the specified underlying OutputStream. * * @param out the specified output stream */ diff --git a/xdr-generator/test/snapshots/struct/XdrDataInputStream.java b/xdr-generator/test/snapshots/struct/XdrDataInputStream.java index 2491769a6..c02011a24 100644 --- a/xdr-generator/test/snapshots/struct/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/struct/XdrDataInputStream.java @@ -27,7 +27,7 @@ public class XdrDataInputStream extends DataInputStream { private int maxInputLen = -1; /** - * Creates a XdrDataInputStream that uses the specified + * Creates an XdrDataInputStream that uses the specified * underlying InputStream. * * @param in the specified input stream diff --git a/xdr-generator/test/snapshots/struct/XdrDataOutputStream.java b/xdr-generator/test/snapshots/struct/XdrDataOutputStream.java index d5d8cda41..9e588307a 100644 --- a/xdr-generator/test/snapshots/struct/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/struct/XdrDataOutputStream.java @@ -11,7 +11,7 @@ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; /** - * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * Creates an XdrDataOutputStream that uses the specified underlying OutputStream. * * @param out the specified output stream */ diff --git a/xdr-generator/test/snapshots/test/XdrDataInputStream.java b/xdr-generator/test/snapshots/test/XdrDataInputStream.java index 2491769a6..c02011a24 100644 --- a/xdr-generator/test/snapshots/test/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/test/XdrDataInputStream.java @@ -27,7 +27,7 @@ public class XdrDataInputStream extends DataInputStream { private int maxInputLen = -1; /** - * Creates a XdrDataInputStream that uses the specified + * Creates an XdrDataInputStream that uses the specified * underlying InputStream. * * @param in the specified input stream diff --git a/xdr-generator/test/snapshots/test/XdrDataOutputStream.java b/xdr-generator/test/snapshots/test/XdrDataOutputStream.java index d5d8cda41..9e588307a 100644 --- a/xdr-generator/test/snapshots/test/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/test/XdrDataOutputStream.java @@ -11,7 +11,7 @@ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; /** - * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * Creates an XdrDataOutputStream that uses the specified underlying OutputStream. * * @param out the specified output stream */ diff --git a/xdr-generator/test/snapshots/union/XdrDataInputStream.java b/xdr-generator/test/snapshots/union/XdrDataInputStream.java index 2491769a6..c02011a24 100644 --- a/xdr-generator/test/snapshots/union/XdrDataInputStream.java +++ b/xdr-generator/test/snapshots/union/XdrDataInputStream.java @@ -27,7 +27,7 @@ public class XdrDataInputStream extends DataInputStream { private int maxInputLen = -1; /** - * Creates a XdrDataInputStream that uses the specified + * Creates an XdrDataInputStream that uses the specified * underlying InputStream. * * @param in the specified input stream diff --git a/xdr-generator/test/snapshots/union/XdrDataOutputStream.java b/xdr-generator/test/snapshots/union/XdrDataOutputStream.java index d5d8cda41..9e588307a 100644 --- a/xdr-generator/test/snapshots/union/XdrDataOutputStream.java +++ b/xdr-generator/test/snapshots/union/XdrDataOutputStream.java @@ -11,7 +11,7 @@ public class XdrDataOutputStream extends DataOutputStream { private final XdrOutputStream mOut; /** - * Creates a XdrDataOutputStream that uses the specified underlying OutputStream. + * Creates an XdrDataOutputStream that uses the specified underlying OutputStream. * * @param out the specified output stream */