Skip to content

Commit

Permalink
Java: simplify the generated XDR code. (#198)
Browse files Browse the repository at this point in the history
* Java: remove the static encode method.

* Java: no longer import all constants.
  • Loading branch information
overcat authored May 29, 2024
1 parent cf9a274 commit bdf833d
Show file tree
Hide file tree
Showing 76 changed files with 279 additions and 1,347 deletions.
98 changes: 35 additions & 63 deletions lib/xdrgen/generators/java.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,10 @@ def add_imports_for_definition(defn, imports)
imports.add("lombok.NoArgsConstructor")
imports.add("lombok.AllArgsConstructor")
imports.add("lombok.Builder")
imports.add("static #{@namespace}.Constants.*")
when AST::Definitions::Typedef
imports.add("lombok.Data")
imports.add("lombok.NoArgsConstructor")
imports.add("lombok.AllArgsConstructor")
imports.add("static #{@namespace}.Constants.*")
end

if defn.respond_to? :nested_definitions
Expand Down Expand Up @@ -224,12 +222,8 @@ def render_enum(enum, out)
}
}
public static void encode(XdrDataOutputStream stream, #{name_string enum.name} value) throws IOException {
stream.writeInt(value.getValue());
}
public void encode(XdrDataOutputStream stream) throws IOException {
encode(stream, this);
stream.writeInt(value);
}
EOS
render_base64((name_string enum.name), out)
Expand All @@ -241,20 +235,14 @@ def render_struct(struct, out)
out.puts "private #{decl_string(m.declaration)} #{m.name};"
end

out.puts "public static void encode(XdrDataOutputStream stream, #{name struct} encoded#{name struct}) throws IOException{"
out.puts "public void encode(XdrDataOutputStream stream) throws IOException{"
struct.members.each do |m|
out.indent do
encode_member "encoded#{name struct}", m, out
encode_member m, out
end
end
out.puts "}"

out.puts <<-EOS.strip_heredoc
public void encode(XdrDataOutputStream stream) throws IOException {
encode(stream, this);
}
EOS

out.puts <<-EOS.strip_heredoc
public static #{name struct} decode(XdrDataInputStream stream) throws IOException {
#{name struct} decoded#{name struct} = new #{name struct}();
Expand All @@ -275,19 +263,13 @@ def render_struct(struct, out)

def render_typedef(typedef, out)
out.puts "private #{decl_string typedef.declaration} #{typedef.name};"
out.puts "public static void encode(XdrDataOutputStream stream, #{name typedef} encoded#{name typedef}) throws IOException {"
out.puts "public void encode(XdrDataOutputStream stream) throws IOException {"
out.indent do
encode_member "encoded#{name typedef}", typedef, out
encode_member typedef, out
end
out.puts "}"
out.break

out.puts <<-EOS.strip_heredoc
public void encode(XdrDataOutputStream stream) throws IOException {
encode(stream, this);
}
EOS

out.puts <<-EOS.strip_heredoc
public static #{name typedef} decode(XdrDataInputStream stream) throws IOException {
#{name typedef} decoded#{name typedef} = new #{name typedef}();
Expand All @@ -309,22 +291,20 @@ def render_union(union, out)
end
out.break

out.puts "public static void encode(XdrDataOutputStream stream, #{name union} encoded#{name union}) throws IOException {"
out.puts('//' + union.discriminant.type.class.to_s)
out.puts("//" + type_string(union.discriminant.type))
out.puts "public void encode(XdrDataOutputStream stream) throws IOException {"
if union.discriminant.type.is_a?(AST::Typespecs::Int)
out.puts "stream.writeInt(encoded#{name union}.getDiscriminant().intValue());"
out.puts "stream.writeInt(discriminant);"
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().getNumber().intValue());"
out.puts "stream.writeInt(discriminant.getUint32().getNumber().intValue());"
else
out.puts "stream.writeInt(encoded#{name union}.getDiscriminant().getValue());"
out.puts "stream.writeInt(discriminant.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().getNumber().intValue()) {"
out.puts "switch (discriminant.getUint32().getNumber().intValue()) {"
else
out.puts "switch (encoded#{name union}.getDiscriminant()) {"
out.puts "switch (discriminant) {"
end
union.arms.each do |arm|
case arm
Expand All @@ -344,15 +324,10 @@ def render_union(union, out)
end
end
end
encode_member "encoded#{name union}", arm, out
encode_member arm, out
out.puts "break;"
end
out.puts "}\n}"
out.puts <<-EOS.strip_heredoc
public void encode(XdrDataOutputStream stream) throws IOException {
encode(stream, this);
}
EOS

out.puts "public static #{name union} decode(XdrDataInputStream stream) throws IOException {"
out.puts "#{name union} decoded#{name union} = new #{name union}();"
Expand Down Expand Up @@ -425,19 +400,6 @@ def render_source_comment(out, defn)

def render_base64(return_type, out)
out.puts <<-EOS.strip_heredoc
@Override
public String toXdrBase64() throws IOException {
return Base64Factory.getInstance().encodeToString(toXdrByteArray());
}
@Override
public byte[] toXdrByteArray() throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream);
encode(xdrDataOutputStream);
return byteArrayOutputStream.toByteArray();
}
public static #{return_type} fromXdrBase64(String xdr) throws IOException {
byte[] bytes = Base64Factory.getInstance().decode(xdr);
return fromXdrByteArray(bytes);
Expand All @@ -451,37 +413,37 @@ def render_base64(return_type, out)
EOS
end

def encode_member(value, member, out)
def encode_member(member, out)
case member.declaration
when AST::Declarations::Void
return
end

if member.type.sub_type == :optional
out.puts "if (#{value}.#{member.name} != null) {"
out.puts "if (#{member.name} != null) {"
out.puts "stream.writeInt(1);"
end
case member.declaration
when AST::Declarations::Opaque ;
out.puts "int #{member.name}Size = #{value}.#{member.name}.length;"
out.puts "int #{member.name}Size = #{member.name}.length;"
unless member.declaration.fixed?
out.puts "stream.writeInt(#{member.name}Size);"
end
out.puts <<-EOS.strip_heredoc
stream.write(#{value}.get#{member.name.slice(0,1).capitalize+member.name.slice(1..-1)}(), 0, #{member.name}Size);
stream.write(get#{member.name.slice(0,1).capitalize+member.name.slice(1..-1)}(), 0, #{member.name}Size);
EOS
when AST::Declarations::Array ;
out.puts "int #{member.name}Size = #{value}.get#{member.name.slice(0,1).capitalize+member.name.slice(1..-1)}().length;"
out.puts "int #{member.name}Size = get#{member.name.slice(0,1).capitalize+member.name.slice(1..-1)}().length;"
unless member.declaration.fixed?
out.puts "stream.writeInt(#{member.name}Size);"
end
out.puts <<-EOS.strip_heredoc
for (int i = 0; i < #{member.name}Size; i++) {
#{encode_type member.declaration.type, "#{value}.#{member.name}[i]"};
#{encode_type member.declaration.type, "#{member.name}[i]"};
}
EOS
else
out.puts "#{encode_type member.declaration.type, "#{value}.#{member.name}"};"
out.puts "#{encode_type member.declaration.type, "#{member.name}"};"
end
if member.type.sub_type == :optional
out.puts "} else {"
Expand Down Expand Up @@ -511,9 +473,9 @@ def encode_type(type, value)
when AST::Typespecs::String ;
"#{value}.encode(stream)"
when AST::Typespecs::Simple ;
"#{name type.resolved_type}.encode(stream, #{value})"
"#{value}.encode(stream)"
when AST::Concerns::NestedDefinition ;
"#{name type}.encode(stream, #{value})"
"#{value}.encode(stream)"
else
raise "Unknown typespec: #{type.class.name}"
end
Expand All @@ -533,7 +495,7 @@ def decode_member(value, member, out)
case member.declaration
when AST::Declarations::Opaque ;
if (member.declaration.fixed?)
out.puts "int #{member.name}Size = #{member.declaration.size};"
out.puts "int #{member.name}Size = #{convert_constant member.declaration.size};"
else
out.puts "int #{member.name}Size = stream.readInt();"
end
Expand All @@ -543,7 +505,7 @@ def decode_member(value, member, out)
EOS
when AST::Declarations::Array ;
if (member.declaration.fixed?)
out.puts "int #{member.name}Size = #{member.declaration.size};"
out.puts "int #{member.name}Size = #{convert_constant member.declaration.size};"
else
out.puts "int #{member.name}Size = stream.readInt();"
end
Expand Down Expand Up @@ -580,7 +542,7 @@ def decode_type(decl)
when AST::Typespecs::Bool ;
"stream.readInt() == 1 ? true : false"
when AST::Typespecs::String ;
"XdrString.decode(stream, #{decl.size || 'Integer.MAX_VALUE'})"
"XdrString.decode(stream, #{(convert_constant decl.size) || 'Integer.MAX_VALUE'})"
when AST::Typespecs::Simple ;
"#{name decl.type.resolved_type}.decode(stream)"
when AST::Concerns::NestedDefinition ;
Expand Down Expand Up @@ -650,7 +612,7 @@ def type_string(type)
when AST::Typespecs::Bool ;
"Boolean"
when AST::Typespecs::Opaque ;
"Byte[#{type.size}]"
"Byte[#{convert_constant type.size}]"
when AST::Typespecs::String ;
"XdrString"
when AST::Typespecs::Simple ;
Expand Down Expand Up @@ -680,6 +642,16 @@ def escape_html(value)
.gsub('>', '&gt;')
.gsub('*', '&#42;') # to avoid encountering`*/`
end

def convert_constant(str)
if str.nil? || str.empty?
str
elsif str =~ /\A\d+\z/
str
else
"Constants.#{str}"
end
end
end
end
end
21 changes: 14 additions & 7 deletions lib/xdrgen/generators/java/XdrElement.erb
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package <%= @namespace %>;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.stellar.sdk.Base64Factory;

/**
* Common parent interface for all generated classes.
*/
/** Common parent interface for all generated classes. */
interface XdrElement {
void encode(XdrDataOutputStream stream) throws IOException;
void encode(XdrDataOutputStream stream) throws IOException;

String toXdrBase64() throws IOException;
default String toXdrBase64() throws IOException {
return Base64Factory.getInstance().encodeToString(toXdrByteArray());
}

byte[] toXdrByteArray() throws IOException;
}
default byte[] toXdrByteArray() throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream);
encode(xdrDataOutputStream);
return byteArrayOutputStream.toByteArray();
}
}
13 changes: 0 additions & 13 deletions lib/xdrgen/generators/java/XdrString.erb
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,6 @@ public class XdrString implements XdrElement {
return new XdrString(bytes);
}

@Override
public String toXdrBase64() throws IOException {
return Base64Factory.getInstance().encodeToString(toXdrByteArray());
}

@Override
public byte[] toXdrByteArray() throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream);
encode(xdrDataOutputStream);
return byteArrayOutputStream.toByteArray();
}

public static XdrString fromXdrBase64(String xdr, int maxSize) throws IOException {
byte[] bytes = Base64Factory.getInstance().decode(xdr);
return fromXdrByteArray(bytes, maxSize);
Expand Down
13 changes: 0 additions & 13 deletions lib/xdrgen/generators/java/XdrUnsignedHyperInteger.erb
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,6 @@ public class XdrUnsignedHyperInteger implements XdrElement {
return paddedBytes;
}

@Override
public String toXdrBase64() throws IOException {
return Base64Factory.getInstance().encodeToString(toXdrByteArray());
}

@Override
public byte[] toXdrByteArray() throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream);
encode(xdrDataOutputStream);
return byteArrayOutputStream.toByteArray();
}

public static XdrUnsignedHyperInteger fromXdrBase64(String xdr) throws IOException {
byte[] bytes = Base64Factory.getInstance().decode(xdr);
return fromXdrByteArray(bytes);
Expand Down
13 changes: 0 additions & 13 deletions lib/xdrgen/generators/java/XdrUnsignedInteger.erb
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,6 @@ public class XdrUnsignedInteger implements XdrElement {
stream.writeInt(number.intValue());
}

@Override
public String toXdrBase64() throws IOException {
return Base64Factory.getInstance().encodeToString(toXdrByteArray());
}

@Override
public byte[] toXdrByteArray() throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream);
encode(xdrDataOutputStream);
return byteArrayOutputStream.toByteArray();
}

public static XdrUnsignedInteger fromXdrBase64(String xdr) throws IOException {
byte[] bytes = Base64Factory.getInstance().decode(xdr);
return fromXdrByteArray(bytes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,9 @@ public static AccountFlags decode(XdrDataInputStream stream) throws IOException
}
}

public static void encode(XdrDataOutputStream stream, AccountFlags value) throws IOException {
stream.writeInt(value.getValue());
}

public void encode(XdrDataOutputStream stream) throws IOException {
encode(stream, this);
}
@Override
public String toXdrBase64() throws IOException {
return Base64Factory.getInstance().encodeToString(toXdrByteArray());
stream.writeInt(value);
}

@Override
public byte[] toXdrByteArray() throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream);
encode(xdrDataOutputStream);
return byteArrayOutputStream.toByteArray();
}

public static AccountFlags fromXdrBase64(String xdr) throws IOException {
byte[] bytes = Base64Factory.getInstance().decode(xdr);
return fromXdrByteArray(bytes);
Expand Down
19 changes: 13 additions & 6 deletions spec/output/generator_spec_java/block_comments.x/XdrElement.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package MyXDR;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.stellar.sdk.Base64Factory;

/**
* Common parent interface for all generated classes.
*/
/** Common parent interface for all generated classes. */
interface XdrElement {
void encode(XdrDataOutputStream stream) throws IOException;
void encode(XdrDataOutputStream stream) throws IOException;

String toXdrBase64() throws IOException;
default String toXdrBase64() throws IOException {
return Base64Factory.getInstance().encodeToString(toXdrByteArray());
}

byte[] toXdrByteArray() throws IOException;
default byte[] toXdrByteArray() throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream);
encode(xdrDataOutputStream);
return byteArrayOutputStream.toByteArray();
}
}
Loading

0 comments on commit bdf833d

Please sign in to comment.