Skip to content

Commit

Permalink
fix(java): Fix the representation of UnsignedInteger and UnsignedHype…
Browse files Browse the repository at this point in the history
…rInteger. (stellar#163)
  • Loading branch information
overcat authored Aug 7, 2023
1 parent 96e91ce commit a5e8042
Show file tree
Hide file tree
Showing 22 changed files with 1,314 additions and 28 deletions.
26 changes: 17 additions & 9 deletions lib/xdrgen/generators/java.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ def render_lib
template = IO.read(__dir__ + "/java/XdrString.erb")
result = ERB.new(template).result binding
@output.write "XdrString.java", result

template = IO.read(__dir__ + "/java/XdrUnsignedHyperInteger.erb")
result = ERB.new(template).result binding
@output.write "XdrUnsignedHyperInteger.java", result

template = IO.read(__dir__ + "/java/XdrUnsignedInteger.erb")
result = ERB.new(template).result binding
@output.write "XdrUnsignedInteger.java", result
end

def render_definitions(node)
Expand Down Expand Up @@ -506,13 +514,13 @@ def render_union(union, out)
out.puts "stream.writeInt(encoded#{name union}.getDiscriminant().intValue());"
elsif type_string(union.discriminant.type) == "Uint32"
# ugly workaround for compile error after generating source for AuthenticatedMessage in stellar-core
out.puts "stream.writeInt(encoded#{name union}.getDiscriminant().getUint32());"
out.puts "stream.writeInt(encoded#{name union}.getDiscriminant().getUint32().getNumber().intValue());"
else
out.puts "stream.writeInt(encoded#{name union}.getDiscriminant().getValue());"
end
if type_string(union.discriminant.type) == "Uint32"
# ugly workaround for compile error after generating source for AuthenticatedMessage in stellar-core
out.puts "switch (encoded#{name union}.getDiscriminant().getUint32()) {"
out.puts "switch (encoded#{name union}.getDiscriminant().getUint32().getNumber().intValue()) {"
else
out.puts "switch (encoded#{name union}.getDiscriminant()) {"
end
Expand Down Expand Up @@ -555,7 +563,7 @@ def render_union(union, out)

if type_string(union.discriminant.type) == "Uint32"
# ugly workaround for compile error after generating source for AuthenticatedMessage in stellar-core
out.puts "switch (decoded#{name union}.getDiscriminant().getUint32()) {"
out.puts "switch (decoded#{name union}.getDiscriminant().getUint32().getNumber().intValue()) {"
else
out.puts "switch (decoded#{name union}.getDiscriminant()) {"
end
Expand Down Expand Up @@ -722,11 +730,11 @@ def encode_type(type, value)
when AST::Typespecs::Int ;
"stream.writeInt(#{value})"
when AST::Typespecs::UnsignedInt ;
"stream.writeInt(#{value})"
"#{value}.encode(stream)"
when AST::Typespecs::Hyper ;
"stream.writeLong(#{value})"
when AST::Typespecs::UnsignedHyper ;
"stream.writeLong(#{value})"
"#{value}.encode(stream)"
when AST::Typespecs::Float ;
"stream.writeFloat(#{value})"
when AST::Typespecs::Double ;
Expand Down Expand Up @@ -793,11 +801,11 @@ def decode_type(decl)
when AST::Typespecs::Int ;
"stream.readInt()"
when AST::Typespecs::UnsignedInt ;
"stream.readInt()"
"XdrUnsignedInteger.decode(stream)"
when AST::Typespecs::Hyper ;
"stream.readLong()"
when AST::Typespecs::UnsignedHyper ;
"stream.readLong()"
"XdrUnsignedHyperInteger.decode(stream)"
when AST::Typespecs::Float ;
"stream.readFloat()"
when AST::Typespecs::Double ;
Expand Down Expand Up @@ -863,11 +871,11 @@ def type_string(type)
when AST::Typespecs::Int ;
"Integer"
when AST::Typespecs::UnsignedInt ;
"Integer"
"XdrUnsignedInteger"
when AST::Typespecs::Hyper ;
"Long"
when AST::Typespecs::UnsignedHyper ;
"Long"
"XdrUnsignedHyperInteger"
when AST::Typespecs::Float ;
"Float"
when AST::Typespecs::Double ;
Expand Down
77 changes: 77 additions & 0 deletions lib/xdrgen/generators/java/XdrUnsignedHyperInteger.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package <%= @namespace %>;

import com.google.common.base.Objects;
import java.io.IOException;
import java.math.BigInteger;

/**
* Represents XDR Unsigned Hyper Integer.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc4506#section-4.5">XDR: External Data
* Representation Standard</a>
*/
public class XdrUnsignedHyperInteger implements XdrElement {
public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615");
public static final BigInteger MIN_VALUE = BigInteger.ZERO;
private final BigInteger number;

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");
}
this.number = number;
}

public XdrUnsignedHyperInteger(Long number) {
if (number < 0) {
throw new IllegalArgumentException(
"number must be greater than or equal to 0 if you want to construct it from Long");
}
this.number = BigInteger.valueOf(number);
}

@Override
public void encode(XdrDataOutputStream stream) throws IOException {
stream.write(getBytes());
}

public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException {
byte[] bytes = new byte[8];
stream.readFully(bytes);
BigInteger uint64 = new BigInteger(1, bytes);
return new XdrUnsignedHyperInteger(uint64);
}

private byte[] getBytes() {
byte[] bytes = number.toByteArray();
byte[] paddedBytes = new byte[8];

int numBytesToCopy = Math.min(bytes.length, 8);
int copyStartIndex = bytes.length - numBytesToCopy;
System.arraycopy(bytes, copyStartIndex, paddedBytes, 8 - numBytesToCopy, numBytesToCopy);
return paddedBytes;
}

public BigInteger getNumber() {
return number;
}

@Override
public int hashCode() {
return Objects.hashCode(this.number);
}

@Override
public boolean equals(Object object) {
if (!(object instanceof XdrUnsignedHyperInteger)) {
return false;
}

XdrUnsignedHyperInteger other = (XdrUnsignedHyperInteger) object;
return Objects.equal(this.number, other.number);
}

public String toString() {
return "XdrUnsignedInteger(number=" + this.getNumber() + ")";
}
}
65 changes: 65 additions & 0 deletions lib/xdrgen/generators/java/XdrUnsignedInteger.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package <%= @namespace %>;

import com.google.common.base.Objects;
import java.io.IOException;

/**
* Represents XDR Unsigned Integer.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc4506#section-4.2">XDR: External Data
* Representation Standard</a>
*/
public class XdrUnsignedInteger implements XdrElement {
public static final long MAX_VALUE = (1L << 32) - 1;
public static final long MIN_VALUE = 0;
private final Long number;

public XdrUnsignedInteger(Long number) {
if (number < MIN_VALUE || number > MAX_VALUE) {
throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive");
}
this.number = number;
}

public XdrUnsignedInteger(Integer number) {
if (number < 0) {
throw new IllegalArgumentException(
"number must be greater than or equal to 0 if you want to construct it from Integer");
}
this.number = number.longValue();
}

public Long getNumber() {
return number;
}

public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException {
int intValue = stream.readInt();
long uint32Value = Integer.toUnsignedLong(intValue);
return new XdrUnsignedInteger(uint32Value);
}

@Override
public void encode(XdrDataOutputStream stream) throws IOException {
stream.writeInt(number.intValue());
}

@Override
public int hashCode() {
return Objects.hashCode(this.number);
}

@Override
public boolean equals(Object object) {
if (!(object instanceof XdrUnsignedInteger)) {
return false;
}

XdrUnsignedInteger other = (XdrUnsignedInteger) object;
return Objects.equal(this.number, other.number);
}

public String toString() {
return "XdrUnsignedInteger(number=" + this.getNumber() + ")";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package MyXDR;

import com.google.common.base.Objects;
import java.io.IOException;
import java.math.BigInteger;

/**
* Represents XDR Unsigned Hyper Integer.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc4506#section-4.5">XDR: External Data
* Representation Standard</a>
*/
public class XdrUnsignedHyperInteger implements XdrElement {
public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615");
public static final BigInteger MIN_VALUE = BigInteger.ZERO;
private final BigInteger number;

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");
}
this.number = number;
}

public XdrUnsignedHyperInteger(Long number) {
if (number < 0) {
throw new IllegalArgumentException(
"number must be greater than or equal to 0 if you want to construct it from Long");
}
this.number = BigInteger.valueOf(number);
}

@Override
public void encode(XdrDataOutputStream stream) throws IOException {
stream.write(getBytes());
}

public static XdrUnsignedHyperInteger decode(XdrDataInputStream stream) throws IOException {
byte[] bytes = new byte[8];
stream.readFully(bytes);
BigInteger uint64 = new BigInteger(1, bytes);
return new XdrUnsignedHyperInteger(uint64);
}

private byte[] getBytes() {
byte[] bytes = number.toByteArray();
byte[] paddedBytes = new byte[8];

int numBytesToCopy = Math.min(bytes.length, 8);
int copyStartIndex = bytes.length - numBytesToCopy;
System.arraycopy(bytes, copyStartIndex, paddedBytes, 8 - numBytesToCopy, numBytesToCopy);
return paddedBytes;
}

public BigInteger getNumber() {
return number;
}

@Override
public int hashCode() {
return Objects.hashCode(this.number);
}

@Override
public boolean equals(Object object) {
if (!(object instanceof XdrUnsignedHyperInteger)) {
return false;
}

XdrUnsignedHyperInteger other = (XdrUnsignedHyperInteger) object;
return Objects.equal(this.number, other.number);
}

public String toString() {
return "XdrUnsignedInteger(number=" + this.getNumber() + ")";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package MyXDR;

import com.google.common.base.Objects;
import java.io.IOException;

/**
* Represents XDR Unsigned Integer.
*
* @see <a href="https://datatracker.ietf.org/doc/html/rfc4506#section-4.2">XDR: External Data
* Representation Standard</a>
*/
public class XdrUnsignedInteger implements XdrElement {
public static final long MAX_VALUE = (1L << 32) - 1;
public static final long MIN_VALUE = 0;
private final Long number;

public XdrUnsignedInteger(Long number) {
if (number < MIN_VALUE || number > MAX_VALUE) {
throw new IllegalArgumentException("number must be between 0 and 2^32 - 1 inclusive");
}
this.number = number;
}

public XdrUnsignedInteger(Integer number) {
if (number < 0) {
throw new IllegalArgumentException(
"number must be greater than or equal to 0 if you want to construct it from Integer");
}
this.number = number.longValue();
}

public Long getNumber() {
return number;
}

public static XdrUnsignedInteger decode(XdrDataInputStream stream) throws IOException {
int intValue = stream.readInt();
long uint32Value = Integer.toUnsignedLong(intValue);
return new XdrUnsignedInteger(uint32Value);
}

@Override
public void encode(XdrDataOutputStream stream) throws IOException {
stream.writeInt(number.intValue());
}

@Override
public int hashCode() {
return Objects.hashCode(this.number);
}

@Override
public boolean equals(Object object) {
if (!(object instanceof XdrUnsignedInteger)) {
return false;
}

XdrUnsignedInteger other = (XdrUnsignedInteger) object;
return Objects.equal(this.number, other.number);
}

public String toString() {
return "XdrUnsignedInteger(number=" + this.getNumber() + ")";
}
}
Loading

0 comments on commit a5e8042

Please sign in to comment.