Skip to content

Commit

Permalink
Merge branch 'master' into python-sdk
Browse files Browse the repository at this point in the history
# Conflicts:
#	spec/lib/xdrgen/generator_spec.rb
  • Loading branch information
overcat committed Nov 21, 2023
2 parents 7d58520 + 70a8851 commit 9c5b749
Show file tree
Hide file tree
Showing 103 changed files with 34,288 additions and 3,529 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
xdrgen (0.1.1)
xdrgen (0.1.3)
activesupport (~> 6)
memoist (~> 0.11.0)
slop (~> 3.4)
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ The command line:

`xdrgen [-o OUTPUT_DIR] [-l LANGUAGE] [-n NAMESPACE] [INPUT_FILES ...]`

### Language Specific Options

### Rust

`--rust-types-custom-str-impl`: Used to specify a comma-separated list of type names that should not have string conversion code generated as it will be provided by custom implementations provided by the developer using the generated code.

## Usage as a library

Add this line to your application's Gemfile:
Expand All @@ -64,7 +70,10 @@ c = Xdrgen::Compilation.new(
["MyProgram.x"],
output_dir:"src/generated",
language: :ruby,
namespace: "MyProgram::XDR"
namespace: "MyProgram::XDR",
options: {
rust_types_custom_str_impl: [],
},
)

# then run compile
Expand Down
6 changes: 5 additions & 1 deletion lib/xdrgen/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ def self.run(args)
on 'o', 'output=', 'The output directory'
on 'l', 'language=', 'The output language', default: 'ruby'
on 'n', 'namespace=', '"namespace" to generate code within (language-specific)'
on 'rust-types-custom-str-impl=', 'Rust types that should not have str implementations generated as they will be provided via custom implementations (rust-specific)'
end

fail(opts) if args.blank?
Expand All @@ -18,7 +19,10 @@ def self.run(args)
args,
output_dir: opts[:output],
language: opts[:language].to_sym,
namespace: opts[:namespace]
namespace: opts[:namespace],
options: {
rust_types_custom_str_impl: opts[:"rust-types-custom-str-impl"]&.split(',') || [],
},
)
compilation.compile
end
Expand Down
7 changes: 4 additions & 3 deletions lib/xdrgen/compilation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ module Xdrgen
class Compilation
extend Memoist

def initialize(source_paths, output_dir:".", language: :ruby, namespace: nil)
def initialize(source_paths, output_dir:".", language: :ruby, namespace: nil, options: {})
@source_paths = source_paths
@output_dir = output_dir
@namespace = namespace
@language = language
@options = options
end

memoize def source
Expand All @@ -22,10 +23,10 @@ def compile
output = Output.new(@source_paths, @output_dir)


generator = Generators.for_language(@language).new(ast, output, @namespace)
generator = Generators.for_language(@language).new(ast, output, @namespace, @options)
generator.generate
ensure
output.close
end
end
end
end
5 changes: 3 additions & 2 deletions lib/xdrgen/generators/base.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
class Xdrgen::Generators::Base
def initialize(top, output, namespace=nil)
def initialize(top, output, namespace=nil, options={})
@top = top
@output = output
@namespace = namespace
@options = options
end

def generate
raise NotImplementedError
end
end
end
51 changes: 35 additions & 16 deletions lib/xdrgen/generators/go.rb
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,11 @@ 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) (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 " }"
out.puts " maxDepth -= 1"
out.puts " var err error"
out.puts " var n, nTmp int"
declared_variables = []
Expand All @@ -552,7 +556,11 @@ 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) (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 " }"
out.puts " maxDepth -= 1"
out.puts " var err error"
out.puts " var n, nTmp int"
render_decode_from_body(out, "u.#{name(union.discriminant)}", union.discriminant.type, declared_variables: [], self_encode: false)
Expand Down Expand Up @@ -581,10 +589,14 @@ 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) (int, error) {
func (e *#{name}) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) {
if maxDepth == 0 {
return 0, fmt.Errorf("decoding #{name}: %w", ErrMaxDecodingDepthReached)
}
maxDepth -= 1
v, n, err := d.DecodeInt()
if err != nil {
return n, fmt.Errorf("decoding #{name}: %s", err)
return n, fmt.Errorf("decoding #{name}: %w", err)
}
if _, ok := #{private_name type}Map[v]; !ok {
return n, fmt.Errorf("'%d' is not a valid #{name} enum value", v)
Expand All @@ -599,7 +611,11 @@ 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) (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 " }"
out.puts " maxDepth -= 1"
out.puts " var err error"
out.puts " var n, nTmp int"
var = "s"
Expand Down Expand Up @@ -636,7 +652,7 @@ 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}: %s", err)
return n, fmt.Errorf("decoding #{name type}: %w", err)
}
EOS
optional = type.sub_type == :optional
Expand Down Expand Up @@ -692,7 +708,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)"
out.puts " nTmp, err = #{var}.DecodeFrom(d, maxDepth)"
out.puts tail
if optional_within
out.puts " }"
Expand All @@ -709,7 +725,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)"
out.puts " nTmp, err = #{element_var}.DecodeFrom(d, maxDepth)"
out.puts tail
if optional_within
out.puts " }"
Expand Down Expand Up @@ -739,7 +755,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)"
out.puts " nTmp, err = #{element_var}.DecodeFrom(d, maxDepth)"
out.puts tail
if optional_within
out.puts " }"
Expand All @@ -751,13 +767,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)"
out.puts " nTmp, err = #{name type}(#{var}).DecodeFrom(d, maxDepth)"
else
out.puts " nTmp, err = #{var}.DecodeFrom(d)"
out.puts " nTmp, err = #{var}.DecodeFrom(d, maxDepth)"
end
out.puts tail
else
out.puts " nTmp, err = d.Decode(&#{var})"
out.puts " nTmp, err = d.DecodeWithMaxDepth(&#{var}, maxDepth)"
out.puts tail
end
if optional
Expand All @@ -778,7 +794,7 @@ def render_binary_interface(out, name)
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)"
out.puts " _, err := s.DecodeFrom(d, xdr.DecodeDefaultMaxDepth)"
out.puts " return err"
out.puts "}"
out.break
Expand Down Expand Up @@ -817,6 +833,7 @@ def render_top_matter(out)
import (
"bytes"
"encoding"
"errors"
"io"
"fmt"
Expand All @@ -832,19 +849,21 @@ def render_top_matter(out)
EOS
out.break
out.puts <<-EOS.strip_heredoc
var ErrMaxDecodingDepthReached = errors.New("maximum decoding depth reached")
type xdrType interface {
xdrType()
}
type decoderFrom interface {
DecodeFrom(d *xdr.Decoder) (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) {
if decodable, ok := v.(decoderFrom); ok {
d := xdr.NewDecoder(r)
return decodable.DecodeFrom(d)
return decodable.DecodeFrom(d, xdr.DecodeDefaultMaxDepth)
}
// delegate to xdr package's Unmarshal
return xdr.Unmarshal(r, v)
Expand Down Expand Up @@ -979,7 +998,7 @@ def render_union_constructor(out, union)
<<-EOS
tv, ok := value.(#{reference arm.type})
if !ok {
err = fmt.Errorf("invalid value, must be #{reference arm.type}")
err = errors.New("invalid value, must be #{reference arm.type}")
return
}
result.#{name arm} = &tv
Expand Down
Loading

0 comments on commit 9c5b749

Please sign in to comment.