diff --git a/go.mod b/go.mod index e7a470c..ef3146c 100644 --- a/go.mod +++ b/go.mod @@ -3,14 +3,14 @@ module go.unistack.org/micro-codec-segmentio/v3 go 1.19 require ( - github.com/segmentio/encoding v0.3.6 - go.unistack.org/micro-proto/v3 v3.3.1 - go.unistack.org/micro/v3 v3.10.14 - google.golang.org/protobuf v1.28.1 + github.com/segmentio/encoding v0.4.0 + go.unistack.org/micro-proto/v3 v3.4.1 + go.unistack.org/micro/v3 v3.10.88 + google.golang.org/protobuf v1.34.2 ) require ( github.com/google/go-cmp v0.5.7 // indirect github.com/segmentio/asm v1.2.0 // indirect - golang.org/x/sys v0.6.0 // indirect + golang.org/x/sys v0.25.0 // indirect ) diff --git a/go.sum b/go.sum index 85895d0..480bdb8 100644 --- a/go.sum +++ b/go.sum @@ -61,6 +61,8 @@ github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/segmentio/encoding v0.3.6 h1:E6lVLyDPseWEulBmCmAKPanDd3jiyGDo5gMcugCRwZQ= github.com/segmentio/encoding v0.3.6/go.mod h1:n0JeuIqEQrQoPDGsjo8UNd1iA0U8d8+oHAA4E3G3OxM= +github.com/segmentio/encoding v0.4.0 h1:MEBYvRqiUB2nfR2criEXWqwdY6HJOUrCn5hboVOVmy8= +github.com/segmentio/encoding v0.4.0/go.mod h1:/d03Cd8PoaDeceuhUUUQWjU0KhWjrmYrWPgtJHYZSnI= github.com/silas/dag v0.0.0-20211117232152-9d50aa809f35/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= @@ -73,8 +75,12 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.unistack.org/micro-proto/v3 v3.3.1 h1:nQ0MtWvP2G3QrpOgawVOPhpZZYkq6umTGDqs8FxJYIo= go.unistack.org/micro-proto/v3 v3.3.1/go.mod h1:cwRyv8uInM2I7EbU7O8Fx2Ls3N90Uw9UCCcq4olOdfE= +go.unistack.org/micro-proto/v3 v3.4.1 h1:UTjLSRz2YZuaHk9iSlVqqsA50JQNAEK2ZFboGqtEa9Q= +go.unistack.org/micro-proto/v3 v3.4.1/go.mod h1:okx/cnOhzuCX0ggl/vToatbCupi0O44diiiLLsZ93Zo= go.unistack.org/micro/v3 v3.10.14 h1:7fgLpwGlCN67twhwtngJDEQvrMkUBDSA5vzZqxIDqNE= go.unistack.org/micro/v3 v3.10.14/go.mod h1:uMAc0U/x7dmtICCrblGf0ZLgYegu3VwQAquu+OFCw1Q= +go.unistack.org/micro/v3 v3.10.88 h1:MxlzP+77Y6Kphb3lzHxROL4XfE/WdCQMQpnPv4D9Z8U= +go.unistack.org/micro/v3 v3.10.88/go.mod h1:erMgt3Bl7vQQ0e9UpQyR5NlLiZ9pKeEJ9+1tfYFaqUg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -109,6 +115,8 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40W golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -150,6 +158,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/json/codec_test.go b/json/codec_test.go index b4bbf0f..b8140b7 100644 --- a/json/codec_test.go +++ b/json/codec_test.go @@ -36,15 +36,3 @@ func TestFrameFlatten(t *testing.T) { t.Fatalf("bytes not equal %s != %s", buf, `test`) } } - -func TestReadBody(t *testing.T) { - s := &struct { - Name string - }{} - c := NewCodec() - b := bytes.NewReader(nil) - err := c.ReadBody(b, s) - if err != nil { - t.Fatal(err) - } -} diff --git a/json/json.go b/json/json.go index ef2ff52..6daad65 100644 --- a/json/json.go +++ b/json/json.go @@ -2,8 +2,6 @@ package json // import "go.unistack.org/micro-codec-segmentio/v3/json" import ( - "io" - "github.com/segmentio/encoding/json" pb "go.unistack.org/micro-proto/v3/codec" "go.unistack.org/micro/v3/codec" @@ -21,10 +19,9 @@ var ( } ) -var _ codec.Codec = &jsonCodec{} - -const ( - flattenTag = "flatten" +var ( + _ codec.Codec = (*jsonCodec)() + _ codec.CodecV2 = (*jsonCodecV2)() ) type JsonMarshalOptions struct { @@ -49,6 +46,12 @@ type jsonCodec struct { decodeFlags json.ParseFlags } +type jsonCodecV2 struct { + opts codec.Options + encodeFlags json.AppendFlags + decodeFlags json.ParseFlags +} + func getMarshalFlags(o JsonMarshalOptions) json.AppendFlags { var encodeFlags json.AppendFlags @@ -111,8 +114,10 @@ func (c *jsonCodec) Marshal(v interface{}, opts ...codec.Option) ([]byte, error) o(&options) } - if nv, err := rutil.StructFieldByTag(v, options.TagName, flattenTag); err == nil { - v = nv + if options.Flatten { + if nv, err := rutil.StructFieldByTag(v, options.TagName, "flatten"); err == nil { + v = nv + } } switch m := v.(type) { @@ -145,8 +150,10 @@ func (c *jsonCodec) Unmarshal(b []byte, v interface{}, opts ...codec.Option) err o(&options) } - if nv, err := rutil.StructFieldByTag(v, options.TagName, flattenTag); err == nil { - v = nv + if options.Flatten { + if nv, err := rutil.StructFieldByTag(v, options.TagName, "flatten"); err == nil { + v = nv + } } switch m := v.(type) { @@ -169,41 +176,82 @@ func (c *jsonCodec) Unmarshal(b []byte, v interface{}, opts ...codec.Option) err return err } -func (c *jsonCodec) ReadHeader(conn io.Reader, m *codec.Message, t codec.MessageType) error { - return nil +func (c *jsonCodec) String() string { + return "json" } -func (c *jsonCodec) ReadBody(conn io.Reader, v interface{}) error { +func (c *jsonCodecV2) Marshal(b []byte, v interface{}, opts ...codec.Option) ([]byte, error) { if v == nil { - return nil + return nil, nil } - buf, err := io.ReadAll(conn) - if err != nil { - return err - } else if len(buf) == 0 { - return nil + options := c.opts + for _, o := range opts { + o(&options) } - return c.Unmarshal(buf, v) + + if options.Flatten { + if nv, err := rutil.StructFieldByTag(v, options.TagName, "flatten"); err == nil { + v = nv + } + } + + switch m := v.(type) { + case *codec.Frame: + return m.Data, nil + case *pb.Frame: + return m.Data, nil + } + + marshalOptions := DefaultMarshalOptions + if options.Context != nil { + if f, ok := options.Context.Value(marshalOptionsKey{}).(JsonMarshalOptions); ok { + marshalOptions = f + } + } + + var err error + b, err = json.Append(b, v, getMarshalFlags(marshalOptions)) + return b, err } -func (c *jsonCodec) Write(conn io.Writer, m *codec.Message, v interface{}) error { - if v == nil { +func (c *jsonCodecV2) Unmarshal(b []byte, v interface{}, opts ...codec.Option) error { + if len(b) == 0 || v == nil { return nil } - buf, err := c.Marshal(v) - if err != nil { - return err - } else if len(buf) == 0 { - return codec.ErrInvalidMessage + options := c.opts + for _, o := range opts { + o(&options) } - _, err = conn.Write(buf) + if options.Flatten { + if nv, err := rutil.StructFieldByTag(v, options.TagName, "flatten"); err == nil { + v = nv + } + } + + switch m := v.(type) { + case *codec.Frame: + m.Data = b + return nil + case *pb.Frame: + m.Data = b + return nil + } + + unmarshalOptions := DefaultUnmarshalOptions + if options.Context != nil { + if f, ok := options.Context.Value(unmarshalOptionsKey{}).(JsonUnmarshalOptions); ok { + unmarshalOptions = f + } + } + + _, err := json.Parse(b, v, getUnmarshalFlags(unmarshalOptions)) return err } -func (c *jsonCodec) String() string { +func (c *jsonCodecV2) String() string { return "json" } diff --git a/proto/codec_test.go b/proto/codec_test.go index 00daea7..81bcfdf 100644 --- a/proto/codec_test.go +++ b/proto/codec_test.go @@ -28,7 +28,7 @@ func TestFrameFlatten(t *testing.T) { Name: &codec.Frame{Data: []byte("test")}, } - buf, err := NewCodec().Marshal(s) + buf, err := NewCodec(codec.Flatten(true)).Marshal(s) if err != nil { t.Fatal(err) } @@ -36,16 +36,3 @@ func TestFrameFlatten(t *testing.T) { t.Fatalf("bytes not equal %s != %s", buf, `test`) } } - -func TestReadBody(t *testing.T) { - t.Skip("no proto generated") - s := &struct { - Name string - }{} - c := NewCodec() - b := bytes.NewReader(nil) - err := c.ReadBody(b, s) - if err != nil { - t.Fatal(err) - } -} diff --git a/proto/proto.go b/proto/proto.go index 05b0227..75bf93a 100644 --- a/proto/proto.go +++ b/proto/proto.go @@ -2,8 +2,6 @@ package proto // import "go.unistack.org/micro-codec-segmentio/v3/proto" import ( - "io" - "github.com/segmentio/encoding/proto" pb "go.unistack.org/micro-proto/v3/codec" "go.unistack.org/micro/v3/codec" @@ -17,10 +15,6 @@ type protoCodec struct { var _ codec.Codec = &protoCodec{} -const ( - flattenTag = "flatten" -) - func (c *protoCodec) Marshal(v interface{}, opts ...codec.Option) ([]byte, error) { if v == nil { return nil, nil @@ -31,8 +25,10 @@ func (c *protoCodec) Marshal(v interface{}, opts ...codec.Option) ([]byte, error o(&options) } - if nv, nerr := rutil.StructFieldByTag(v, options.TagName, flattenTag); nerr == nil { - v = nv + if options.Flatten { + if nv, nerr := rutil.StructFieldByTag(v, options.TagName, "flatten"); nerr == nil { + v = nv + } } switch m := v.(type) { @@ -47,9 +43,9 @@ func (c *protoCodec) Marshal(v interface{}, opts ...codec.Option) ([]byte, error return proto.Marshal(m) case newproto.Message: return proto.Marshal(m) + default: + return nil, codec.ErrInvalidMessage } - - return nil, codec.ErrInvalidMessage } func (c *protoCodec) Unmarshal(d []byte, v interface{}, opts ...codec.Option) error { @@ -62,8 +58,10 @@ func (c *protoCodec) Unmarshal(d []byte, v interface{}, opts ...codec.Option) er o(&options) } - if nv, nerr := rutil.StructFieldByTag(v, options.TagName, flattenTag); nerr == nil { - v = nv + if options.Flatten { + if nv, nerr := rutil.StructFieldByTag(v, options.TagName, "flatten"); nerr == nil { + v = nv + } } switch m := v.(type) { @@ -80,43 +78,9 @@ func (c *protoCodec) Unmarshal(d []byte, v interface{}, opts ...codec.Option) er return proto.Unmarshal(d, m) case newproto.Message: return proto.Unmarshal(d, m) - - } - - return codec.ErrInvalidMessage -} - -func (c *protoCodec) ReadHeader(conn io.Reader, m *codec.Message, t codec.MessageType) error { - return nil -} - -func (c *protoCodec) ReadBody(conn io.Reader, v interface{}) error { - if v == nil { - return nil - } - buf, err := io.ReadAll(conn) - if err != nil { - return err - } else if len(buf) == 0 { - return nil - } - return c.Unmarshal(buf, v) -} - -func (c *protoCodec) Write(conn io.Writer, m *codec.Message, v interface{}) error { - if v == nil { - return nil - } - - buf, err := c.Marshal(v) - if err != nil { - return err - } else if len(buf) == 0 { + default: return codec.ErrInvalidMessage } - - _, err = conn.Write(buf) - return err } func (c *protoCodec) String() string {