Skip to content

Commit

Permalink
Update to match go-xdr
Browse files Browse the repository at this point in the history
  • Loading branch information
2opremio committed Nov 22, 2023
1 parent bc3719f commit f9995ef
Show file tree
Hide file tree
Showing 9 changed files with 1,108 additions and 1,173 deletions.
101 changes: 43 additions & 58 deletions lib/xdrgen/generators/go.rb
Original file line number Diff line number Diff line change
Expand Up @@ -430,11 +430,11 @@ def render_typedef_encode_to_interface(out, typedef)
# encode.
def render_encode_to_body(out, var, type, self_encode:)
def check_error(str)
<<-EOS.strip_heredoc
if #{str}; err != nil {
return err
}
EOS
<<-EOS
if #{str}; err != nil {
return err
}
EOS
end
optional = type.sub_type == :optional
if optional
Expand Down Expand Up @@ -536,7 +536,7 @@ def check_error(str)
def render_struct_decode_from_interface(out, struct)
name = name(struct)
out.puts "// DecodeFrom decodes this value using the Decoder."
out.puts "func (s *#{name}) DecodeFrom(d *xdr.Decoder, maxDepth uint, maxAllocSize int) (int, error) {"
out.puts "func (s *#{name}) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) {"
out.puts " if maxDepth == 0 {"
out.puts " return 0, fmt.Errorf(\"decoding #{name}: %w\", ErrMaxDecodingDepthReached)"
out.puts " }"
Expand All @@ -556,7 +556,7 @@ def render_struct_decode_from_interface(out, struct)
def render_union_decode_from_interface(out, union)
name = name(union)
out.puts "// DecodeFrom decodes this value using the Decoder."
out.puts "func (u *#{name}) DecodeFrom(d *xdr.Decoder, maxDepth uint, maxAllocSize int) (int, error) {"
out.puts "func (u *#{name}) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) {"
out.puts " if maxDepth == 0 {"
out.puts " return 0, fmt.Errorf(\"decoding #{name}: %w\", ErrMaxDecodingDepthReached)"
out.puts " }"
Expand Down Expand Up @@ -589,7 +589,7 @@ def render_enum_decode_from_interface(out, typedef)
type = typedef
out.puts <<-EOS.strip_heredoc
// DecodeFrom decodes this value using the Decoder.
func (e *#{name}) DecodeFrom(d *xdr.Decoder, maxDepth uint, maxAllocSize int) (int, error) {
func (e *#{name}) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) {
if maxDepth == 0 {
return 0, fmt.Errorf("decoding #{name}: %w", ErrMaxDecodingDepthReached)
}
Expand All @@ -611,7 +611,7 @@ def render_typedef_decode_from_interface(out, typedef)
name = name(typedef)
type = typedef.declaration.type
out.puts "// DecodeFrom decodes this value using the Decoder."
out.puts "func (s *#{name}) DecodeFrom(d *xdr.Decoder, maxDepth uint, maxAllocSize int) (int, error) {"
out.puts "func (s *#{name}) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) {"
out.puts " if maxDepth == 0 {"
out.puts " return 0, fmt.Errorf(\"decoding #{name}: %w\", ErrMaxDecodingDepthReached)"
out.puts " }"
Expand Down Expand Up @@ -649,12 +649,12 @@ def render_variable_declaration(out, indent, var, type, declared_variables:)
# xdr.Decoder, and a variable defined by `var` that is the value to
# encode.
def render_decode_from_body(out, var, type, declared_variables:, self_encode:)
tail = <<-EOS.strip_heredoc
n += nTmp
if err != nil {
return n, fmt.Errorf("decoding #{name type}: %w", err)
}
EOS
tail = <<-EOS
n += nTmp
if err != nil {
return n, fmt.Errorf("decoding #{name type}: %w", err)
}
EOS
optional = type.sub_type == :optional
if optional
render_variable_declaration(out, " ", 'b', "bool", declared_variables: declared_variables)
Expand All @@ -681,20 +681,19 @@ def render_decode_from_body(out, var, type, declared_variables:, self_encode:)
out.puts " #{var}, nTmp, err = d.DecodeBool()"
out.puts tail
when AST::Typespecs::String
arg = "maxAllocSize"
arg = "mergeMaxAllocSizeAndMaxSize(maxAllocSize, #{type.decl.resolved_size})" unless type.decl.resolved_size.nil?
arg = "0"
arg = type.decl.resolved_size unless type.decl.resolved_size.nil?
out.puts " #{var}, nTmp, err = d.DecodeString(#{arg})"
out.puts tail
when AST::Typespecs::Opaque
if type.fixed?
out.puts " nTmp, err = d.DecodeFixedOpaqueInplace(#{var}[:])"
out.puts tail
else
arg = "maxAllocSize"
arg = "mergeMaxAllocSizeAndMaxSize(maxAllocSize, #{type.decl.resolved_size})" unless type.decl.resolved_size.nil?
arg = "0"
arg = type.decl.resolved_size unless type.decl.resolved_size.nil?
out.puts " #{var}, nTmp, err = d.DecodeOpaque(#{arg})"
out.puts tail
end
out.puts tail
when AST::Typespecs::Simple
case type.sub_type
when :simple, :optional
Expand All @@ -708,7 +707,7 @@ def render_decode_from_body(out, var, type, declared_variables:, self_encode:)
out.puts " #{var} = new(#{name type.resolved_type.declaration.type})"
end
var = "(*#{name type})(#{var})" if self_encode
out.puts " nTmp, err = #{var}.DecodeFrom(d, maxDepth, maxAllocSize)"
out.puts " nTmp, err = #{var}.DecodeFrom(d, maxDepth)"
out.puts tail
if optional_within
out.puts " }"
Expand All @@ -725,7 +724,7 @@ def render_decode_from_body(out, var, type, declared_variables:, self_encode:)
out.puts " if eb {"
var = "(*#{element_var})"
end
out.puts " nTmp, err = #{element_var}.DecodeFrom(d, maxDepth, maxAllocSize)"
out.puts " nTmp, err = #{element_var}.DecodeFrom(d, maxDepth)"
out.puts tail
if optional_within
out.puts " }"
Expand All @@ -740,17 +739,13 @@ def render_decode_from_body(out, var, type, declared_variables:, self_encode:)
out.puts " return n, fmt.Errorf(\"decoding #{name type}: data size (%d) exceeds size limit (#{type.decl.resolved_size})\", l)"
out.puts " }"
end
out.puts " if maxAllocSize > 0 {"
out.puts " var phony #{name type}"
out.puts " allocSize := unsafe.Sizeof(phony) * uintptr(l)"
out.puts " if uintptr(maxAllocSize) < allocSize {"
out.puts " return n, fmt.Errorf(\"decoding #{name type}: allocation size (%d) exceeds limit (%d)\", allocSize, maxAllocSize)"
out.puts " }"
out.puts " }"
out.puts " #{var} = nil"
out.puts " if l > 0 {"
out.puts " if il, ok := d.InputLen(); ok && uint(il) < uint(l) {"
out.puts " return n, fmt.Errorf(\"decoding #{name type}: length (%d) exceeds remaining input length (%d)\", l, il)"
out.puts " }"
out.puts " #{var} = make([]#{name type}, l)"
out.puts " for i := uint32(0); i < l; i++ {"
out.puts " for i := uint32(0); uint(i) < uint(l); i++ {"
element_var = "#{var}[i]"
optional_within = type.is_a?(AST::Identifier) && type.resolved_type.sub_type == :optional
if optional_within
Expand All @@ -762,7 +757,7 @@ def render_decode_from_body(out, var, type, declared_variables:, self_encode:)
out.puts " #{element_var} = new(#{name type.resolved_type.declaration.type})"
var = "(*#{element_var})"
end
out.puts " nTmp, err = #{element_var}.DecodeFrom(d, maxDepth, maxAllocSize)"
out.puts " nTmp, err = #{element_var}.DecodeFrom(d, maxDepth)"
out.puts tail
if optional_within
out.puts " }"
Expand All @@ -774,13 +769,13 @@ def render_decode_from_body(out, var, type, declared_variables:, self_encode:)
end
when AST::Definitions::Base
if self_encode
out.puts " nTmp, err = #{name type}(#{var}).DecodeFrom(d, maxDepth, maxAllocSize)"
out.puts " nTmp, err = #{name type}(#{var}).DecodeFrom(d, maxDepth)"
else
out.puts " nTmp, err = #{var}.DecodeFrom(d, maxDepth, maxAllocSize)"
out.puts " nTmp, err = #{var}.DecodeFrom(d, maxDepth)"
end
out.puts tail
else
out.puts " nTmp, err = d.DecodeWithMaxDepth(&#{var}, maxDepth, maxAllocSize)"
out.puts " nTmp, err = d.DecodeWithMaxDepth(&#{var}, maxDepth)"
out.puts tail
end
if optional
Expand All @@ -800,8 +795,10 @@ def render_binary_interface(out, name)
out.puts "// UnmarshalBinary implements encoding.BinaryUnmarshaler."
out.puts "func (s *#{name}) UnmarshalBinary(inp []byte) error {"
out.puts " r := bytes.NewReader(inp)"
out.puts " d := xdr.NewDecoder(r)"
out.puts " _, err := s.DecodeFrom(d, xdr.DecodeDefaultMaxDepth, 0)"
out.puts " o := xdr.DefaultDecodeOptions"
out.puts " o.MaxInputLen = len(inp)"
out.puts " d := xdr.NewDecoderWithOptions(r, o)"
out.puts " _, err := s.DecodeFrom(d, o.MaxDepth)"
out.puts " return err"
out.puts "}"
out.break
Expand All @@ -813,8 +810,7 @@ def render_binary_interface(out, name)
end

def render_xdr_type_interface(out, name)
out.puts "// xdrType signals that this type is an type representing"
out.puts "// representing XDR values defined by this package."
out.puts "// xdrType signals that this type represents XDR values defined by this package."
out.puts "func (s #{name}) xdrType() {}"
out.break
out.puts "var _ xdrType = (*#{name})(nil)"
Expand Down Expand Up @@ -866,32 +862,24 @@ def render_top_matter(out)
}
type decoderFrom interface {
DecodeFrom(d *xdr.Decoder, maxDepth uint, maxAllocSize int) (int, error)
DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error)
}
// Unmarshal reads an xdr element from `r` into `v`.
func Unmarshal(r io.Reader, v interface{}) (int, error) {
return UnmarshalWithMaxAllocSize(r, v, 0)
return UnmarshalWithOptions(r, v, xdr.DefaultDecodeOptions)
}
// Unmarshal reads an xdr element from `r` into `v`.
func UnmarshalWithMaxAllocSize(r io.Reader, v interface{}, maxAllocSize int) (int, error) {
// UnmarshalWithOptions works like Unmarshal but uses decoding options.
func UnmarshalWithOptions(r io.Reader, v interface{}, options xdr.DecodeOptions) (int, error) {
if decodable, ok := v.(decoderFrom); ok {
d := xdr.NewDecoder(r)
return decodable.DecodeFrom(d, xdr.DecodeDefaultMaxDepth, maxAllocSize)
d := xdr.NewDecoderWithOptions(r, options)
return decodable.DecodeFrom(d, options.MaxDepth)
}
// delegate to xdr package's Unmarshal
return xdr.Unmarshal(r, v)
}
func mergeMaxAllocSizeAndMaxSize(maxAllocSize int, maxSize int) int {
if maxAllocSize > 0 || maxAllocSize < maxSize {
return maxAllocSize
}
return maxSize
return xdr.UnmarshalWithOptions(r, v, options)
}
// Marshal writes an xdr element `v` into `w`.
func Marshal(w io.Writer, v interface{}) (int, error) {
if _, ok := v.(xdrType); ok {
Expand All @@ -911,10 +899,7 @@ def render_top_matter(out)
end

def render_bottom_matter(out)
out.puts <<-EOS
var fmtTest = fmt.Sprint("this is a dummy usage of fmt")
EOS
out.puts 'var fmtTest = fmt.Sprint("this is a dummy usage of fmt")'
end

private
Expand Down
98 changes: 45 additions & 53 deletions spec/output/generator_spec_go/block_comments.x/MyXDR_generated.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,53 +26,45 @@ var XdrFilesSHA256 = map[string]string{
"spec/fixtures/generator/block_comments.x": "e13131bc4134f38da17b9d5e9f67d2695a69ef98e3ef272833f4c18d0cc88a30",
}

var ErrMaxDecodingDepthReached = errors.New("maximum decoding depth reached")

type xdrType interface {
xdrType()
}

type decoderFrom interface {
DecodeFrom(d *xdr.Decoder, maxDepth uint, maxAllocSize int) (int, error)
}

// Unmarshal reads an xdr element from `r` into `v`.
func Unmarshal(r io.Reader, v interface{}) (int, error) {
return UnmarshalWithMaxAllocSize(r, v, 0)
}

// Unmarshal reads an xdr element from `r` into `v`.
func UnmarshalWithMaxAllocSize(r io.Reader, v interface{}, maxAllocSize int) (int, error) {
if decodable, ok := v.(decoderFrom); ok {
d := xdr.NewDecoder(r)
return decodable.DecodeFrom(d, xdr.DecodeDefaultMaxDepth, maxAllocSize)
}
// delegate to xdr package's Unmarshal
return xdr.Unmarshal(r, v)
}

func mergeMaxAllocSizeAndMaxSize(maxAllocSize int, maxSize int) int {
if maxAllocSize > 0 || maxAllocSize < maxSize {
return maxAllocSize
var ErrMaxDecodingDepthReached = errors.New("maximum decoding depth reached")

type xdrType interface {
xdrType()
}

type decoderFrom interface {
DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error)
}

// Unmarshal reads an xdr element from `r` into `v`.
func Unmarshal(r io.Reader, v interface{}) (int, error) {
return UnmarshalWithOptions(r, v, xdr.DefaultDecodeOptions)
}

// UnmarshalWithOptions works like Unmarshal but uses decoding options.
func UnmarshalWithOptions(r io.Reader, v interface{}, options xdr.DecodeOptions) (int, error) {
if decodable, ok := v.(decoderFrom); ok {
d := xdr.NewDecoderWithOptions(r, options)
return decodable.DecodeFrom(d, options.MaxDepth)
}
// delegate to xdr package's Unmarshal
return xdr.UnmarshalWithOptions(r, v, options)
}

// Marshal writes an xdr element `v` into `w`.
func Marshal(w io.Writer, v interface{}) (int, error) {
if _, ok := v.(xdrType); ok {
if bm, ok := v.(encoding.BinaryMarshaler); ok {
b, err := bm.MarshalBinary()
if err != nil {
return 0, err
}
return w.Write(b)
}
}
// delegate to xdr package's Marshal
return xdr.Marshal(w, v)
}
return maxSize
}


// Marshal writes an xdr element `v` into `w`.
func Marshal(w io.Writer, v interface{}) (int, error) {
if _, ok := v.(xdrType); ok {
if bm, ok := v.(encoding.BinaryMarshaler); ok {
b, err := bm.MarshalBinary()
if err != nil {
return 0, err
}
return w.Write(b)
}
}
// delegate to xdr package's Marshal
return xdr.Marshal(w, v)
}

// AccountFlags is an XDR Enum defines as:
//
Expand Down Expand Up @@ -111,7 +103,7 @@ func (e AccountFlags) EncodeTo(enc *xdr.Encoder) error {
}
var _ decoderFrom = (*AccountFlags)(nil)
// DecodeFrom decodes this value using the Decoder.
func (e *AccountFlags) DecodeFrom(d *xdr.Decoder, maxDepth uint, maxAllocSize int) (int, error) {
func (e *AccountFlags) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) {
if maxDepth == 0 {
return 0, fmt.Errorf("decoding AccountFlags: %w", ErrMaxDecodingDepthReached)
}
Expand All @@ -137,8 +129,10 @@ func (s AccountFlags) MarshalBinary() ([]byte, error) {
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (s *AccountFlags) UnmarshalBinary(inp []byte) error {
r := bytes.NewReader(inp)
d := xdr.NewDecoder(r)
_, err := s.DecodeFrom(d, xdr.DecodeDefaultMaxDepth, 0)
o := xdr.DefaultDecodeOptions
o.MaxInputLen = len(inp)
d := xdr.NewDecoderWithOptions(r, o)
_, err := s.DecodeFrom(d, o.MaxDepth)
return err
}

Expand All @@ -147,11 +141,9 @@ var (
_ encoding.BinaryUnmarshaler = (*AccountFlags)(nil)
)

// xdrType signals that this type is an type representing
// representing XDR values defined by this package.
// xdrType signals that this type represents XDR values defined by this package.
func (s AccountFlags) xdrType() {}

var _ xdrType = (*AccountFlags)(nil)

var fmtTest = fmt.Sprint("this is a dummy usage of fmt")

var fmtTest = fmt.Sprint("this is a dummy usage of fmt")
Loading

0 comments on commit f9995ef

Please sign in to comment.