Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#911 Enhance command sysl pb --mode=pb to output binary message #912

Merged
merged 8 commits into from
Jun 24, 2020
17 changes: 13 additions & 4 deletions cmd/sysl/cmd_protobuf.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ func (p *protobuf) Name() string { return "protobuf" }
func (p *protobuf) MaxSyslModule() int { return 1 }

func (p *protobuf) Configure(app *kingpin.Application) *kingpin.CmdClause {
cmd := app.Command(p.Name(), "Generate textpb/json").Alias("pb")
cmd := app.Command(p.Name(), "Generate textpb/json/binary").Alias("pb")
cmd.Flag("output", "output file name").Short('o').Default("-").StringVar(&p.output)
opts := []string{"textpb", "json"}
opts := []string{"textpb", "json", "pb"}
ericzhang6222 marked this conversation as resolved.
Show resolved Hide resolved
cmd.Flag("mode", fmt.Sprintf("output mode: [%s]", strings.Join(opts, ","))).
Default(opts[0]).
EnumVar(&p.mode, opts...)
Expand All @@ -44,8 +44,17 @@ func (p *protobuf) Execute(args cmdutils.ExecuteArgs) error {
}
return pbutil.JSONPB(args.Modules[0], p.output, args.Filesystem)
}

if p.mode == "" || p.mode == "textpb" {
if p.output == "-" {
return pbutil.FTextPB(os.Stdout, args.Modules[0])
}
return pbutil.TextPB(args.Modules[0], p.output, args.Filesystem)
}

// output format is binary
if p.output == "-" {
return pbutil.FTextPB(os.Stdout, args.Modules[0])
return pbutil.GeneratePBBinaryMessage(os.Stdout, args.Modules[0])
}
return pbutil.TextPB(args.Modules[0], p.output, args.Filesystem)
return pbutil.GeneratePBBinaryMessageFile(args.Modules[0], p.output, args.Filesystem)
}
28 changes: 28 additions & 0 deletions pkg/pbutil/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/spf13/afero"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/encoding/prototext"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
)

Expand Down Expand Up @@ -64,3 +65,30 @@ func FTextPB(w io.Writer, m protoreflect.ProtoMessage) error {
_, err = w.Write(mt)
return err
}

// GeneratePBBinaryMessageFile generates binary message to the file specified by `filename`.
func GeneratePBBinaryMessageFile(m protoreflect.ProtoMessage, filename string, fs afero.Fs) error {
if m == nil {
return fmt.Errorf("module is nil: %#v", filename)
}

f, err := fs.Create(filename)
if err != nil {
return err
}
defer f.Close()
return GeneratePBBinaryMessage(f, m)
}

// GeneratePBBinaryMessage generates binary message to IO writer specified by `w`.
func GeneratePBBinaryMessage(w io.Writer, m protoreflect.ProtoMessage) error {
if m == nil {
return fmt.Errorf("module is nil")
}
bytes, err := proto.Marshal(m)
if err != nil {
return err
}
_, err = w.Write(bytes)
return err
}
40 changes: 40 additions & 0 deletions pkg/pbutil/output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,43 @@ func TestFTextPBNilModule(t *testing.T) {
require.Error(t, FTextPB(&output, nil))
assert.Equal(t, "", output.String())
}

func TestGeneratePBBinaryMessage(t *testing.T) {
t.Parallel()

unmarshalled := &sysl.Module{}
var output bytes.Buffer
require.NoError(t, GeneratePBBinaryMessage(&output, testModule()))
require.NoError(t, proto.Unmarshal(output.Bytes(), unmarshalled))
assert.True(t, proto.Equal(unmarshalled, protoreflect.ProtoMessage(testModule())))
}

func TestGeneratePBBinaryMessageNilModule(t *testing.T) {
t.Parallel()

var output bytes.Buffer
require.Error(t, GeneratePBBinaryMessage(&output, nil))
assert.Equal(t, "", output.String())
}

func TestGeneratePBBinaryMessageFile(t *testing.T) {
t.Parallel()

unmarshalled := &sysl.Module{}
fs := afero.NewMemMapFs()
filename := "/out.pb"
require.NoError(t, GeneratePBBinaryMessageFile(testModule(), filename, fs))
output, err := afero.ReadFile(fs, filename)
require.NoError(t, err)
require.NoError(t, proto.Unmarshal(output, unmarshalled))
assert.True(t, proto.Equal(unmarshalled, protoreflect.ProtoMessage(testModule())))
}

func TestGeneratePBBinaryMessageFileNilModule(t *testing.T) {
t.Parallel()

fs := afero.NewMemMapFs()
filename := "/out.pb"
require.Error(t, GeneratePBBinaryMessageFile(nil, filename, fs))
syslutil.AssertFsHasExactly(t, fs)
}