diff --git a/README.md b/README.md index 8d8dc9c..6fc31f4 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@ Concretely, we would like to see the following components added: - The addition of a new `AllComments` gRPC query method. This method's input should take a `post_slug` (a string), and returns all the comments on a post. - The addition of two CLI subcommands, `tx create-comment` and `query list-comments`, which call the `CreateComment` and `AllComments` service methods under the hood. +See solution steps in [SOLUTION.md](SOLUTION.md) + ## Requirements: - Go v1.17+: https://golang.org/ diff --git a/SOLUTION.md b/SOLUTION.md new file mode 100644 index 0000000..64c79b8 --- /dev/null +++ b/SOLUTION.md @@ -0,0 +1,70 @@ +# Implementing task + +## Run node + +For first step command is from [here](https://docs.cosmos.network/v0.46/run-node/run-node.html) +For next steps I followed this [instruction](https://docs.cosmos.network/v0.46/run-node/run-node.html) + +1. Build node + + make build + +2. Init config of node with chain-id `my-test-chain`. `monadfix` is arbitrary string. + + build/regen init monadfix --chain-id my-test-chain + +- `regen` used insted of `simd` +- `--home` flag to specify dirictory of config. But then you should pass it to every command. + +3. Add account to network + + build/regen keys add monadfix --keyring-backend test + +- where `monadfix` is custom name. + +4. Fetch address. We got `cosmos1728x3mclm0f980828tf74nq3vqvaxkkkdfwuc8` + + build/regen keys show monadfix -a --keyring-backend test + +5. Add money to your address of your account. See address in step `4` + + build/regen add-genesis-account cosmos1728x3mclm0f980828tf74nq3vqvaxkkkdfwuc8 100000000000stake + +6. Create validator + + build/regen gentx monadfix 100000000stake --chain-id my-test-chain --keyring-backend test + + build/regen collect-gentxs + +7. Update gas config in `app.toml` + +Modify `minimum-gas-prices` to `"0stake"` + +8. Run local blockchain network + + build/regen start + +## Interact with blog + +0. Set chain-id + + build/regen config chain-id my-test-chain + +1. Create post + + build/regen tx blog create-post cosmos1728x3mclm0f980828tf74nq3vqvaxkkkdfwuc8 "first-post" "title" "body body body" --keyring-backend test -y + +2. List all posts + + build/regen query blog list-post + +3. Comment has key is comprised by `comment` + `slug` + `_` + `uuidV7`. + Prefix `comment` is added by KVStore. + +4. Create comment + + build/regen tx blog create-comment cosmos1728x3mclm0f980828tf74nq3vqvaxkkkdfwuc8 "first-slug" "comment comment" --keyring-backend test -y + +5. List comments of the particular slug + + build/regen query blog list-comments "first-slug" diff --git a/go.mod b/go.mod index 0ff7e6f..0bccf38 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 github.com/rakyll/statik v0.1.7 + github.com/rs/zerolog v1.23.0 github.com/spf13/cast v1.3.1 github.com/spf13/cobra v1.2.1 github.com/stretchr/testify v1.7.0 @@ -89,7 +90,6 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect github.com/regen-network/cosmos-proto v0.3.1 // indirect github.com/rs/cors v1.7.0 // indirect - github.com/rs/zerolog v1.23.0 // indirect github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect github.com/spf13/afero v1.6.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect @@ -101,6 +101,7 @@ require ( github.com/tendermint/btcd v0.1.1 // indirect github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect github.com/tendermint/go-amino v0.16.0 // indirect + github.com/uuid6/uuid6go-proto v0.2.1 // indirect github.com/zondax/hid v0.9.0 // indirect go.etcd.io/bbolt v1.3.5 // indirect golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect diff --git a/go.sum b/go.sum index 21dc754..89d59d0 100644 --- a/go.sum +++ b/go.sum @@ -719,8 +719,6 @@ github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqn github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= github.com/regen-network/protobuf v1.3.2-alpha.regen.4 h1:c9jEnU+xm6vqyrQe3M94UFWqiXxRIKKnqBOh2EACmBE= -github.com/regen-network/protobuf v1.3.2-alpha.regen.4 h1:c9jEnU+xm6vqyrQe3M94UFWqiXxRIKKnqBOh2EACmBE= -github.com/regen-network/protobuf v1.3.2-alpha.regen.4/go.mod h1:/J8/bR1T/NXyIdQDLUaq15LjNE83nRzkyrLAMcPewig= github.com/regen-network/protobuf v1.3.2-alpha.regen.4/go.mod h1:/J8/bR1T/NXyIdQDLUaq15LjNE83nRzkyrLAMcPewig= github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -834,6 +832,8 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/uuid6/uuid6go-proto v0.2.1 h1:wuHy43Hy7CnWnWOkQGthek1YO43SQD+A/X+YaDH5B3Q= +github.com/uuid6/uuid6go-proto v0.2.1/go.mod h1:SFdogh0w3t8piuOBD4PXotblZWBqP2wospaF7txygWQ= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI= diff --git a/proto/blog/v1/query.proto b/proto/blog/v1/query.proto index 09a3ce7..6ba619c 100644 --- a/proto/blog/v1/query.proto +++ b/proto/blog/v1/query.proto @@ -9,6 +9,7 @@ import "blog/v1/types.proto"; // Query defines the gRPC querier service. service Query { rpc AllPosts(QueryAllPostsRequest) returns (QueryAllPostsResponse); + rpc PostComments(QueryPostCommentsRequest) returns (QueryPostCommentsResponse); } message QueryAllPostsRequest { @@ -20,3 +21,14 @@ message QueryAllPostsResponse { cosmos.base.query.v1beta1.PageResponse pagination = 2; } + +message QueryPostCommentsRequest { + cosmos.base.query.v1beta1.PageRequest pagination = 1; + string slug = 2; +} + +message QueryPostCommentsResponse { + repeated Comment comments = 1; + + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/proto/blog/v1/tx.proto b/proto/blog/v1/tx.proto index 903b077..7809db8 100644 --- a/proto/blog/v1/tx.proto +++ b/proto/blog/v1/tx.proto @@ -6,6 +6,7 @@ option go_package = "github.com/regen-network/bec/x/blog"; // Msg is the blog.v1 Msg service service Msg { rpc CreatePost(MsgCreatePost) returns (MsgCreatePostResponse); + rpc CreateComment(MsgCreateComment) returns (MsgCreateCommentResponse); } // MsgCreatePost is the Msg/CreatePost request type. @@ -18,3 +19,13 @@ message MsgCreatePost { // MsgCreatePostResponse is the Msg/CreatePost response type. message MsgCreatePostResponse {} + +// MsgCreateComment is the Msg/CreateComment request type. +message MsgCreateComment { + string slug = 1; + string author = 2; + string body = 3; +} + +// MsgCreateCommentResponse is the Msg/CreateComment response type. +message MsgCreateCommentResponse {} diff --git a/proto/blog/v1/types.proto b/proto/blog/v1/types.proto index c22f1bc..7f1e47b 100644 --- a/proto/blog/v1/types.proto +++ b/proto/blog/v1/types.proto @@ -11,3 +11,12 @@ message Post { string title = 3; string body = 4; } + +message Comment { + // slug is a short human-readable string for the post, used as unique + // identifier for the post. + string slug = 1; + string author = 2; + string body = 3; +} + diff --git a/x/blog/client/cli/query.go b/x/blog/client/cli/query.go index 78fbbb3..ad2e1d2 100644 --- a/x/blog/client/cli/query.go +++ b/x/blog/client/cli/query.go @@ -23,7 +23,10 @@ func GetQueryCmd() *cobra.Command { RunE: client.ValidateCmd, } - cmd.AddCommand(CmdAllPosts()) + cmd.AddCommand( + CmdAllPosts(), + CmdPostComments(), + ) return cmd } @@ -63,3 +66,44 @@ func CmdAllPosts() *cobra.Command { return cmd } + +func CmdPostComments() *cobra.Command { + cmd := &cobra.Command{ + Use: "list-comments [slug]", + Short: "list all comments of the post", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + + argsSlug := string(args[0]) + + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + + pageReq, err := client.ReadPageRequest(cmd.Flags()) + if err != nil { + return err + } + + queryClient := blog.NewQueryClient(clientCtx) + + params := &blog.QueryPostCommentsRequest{ + Pagination: pageReq, + Slug: argsSlug, + } + + res, err := queryClient.PostComments(cmd.Context(), params) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + flags.AddPaginationFlagsToCmd(cmd, "blog") + + return cmd +} diff --git a/x/blog/client/cli/tx.go b/x/blog/client/cli/tx.go index 8e9f3d3..f8924ad 100644 --- a/x/blog/client/cli/tx.go +++ b/x/blog/client/cli/tx.go @@ -21,7 +21,10 @@ func GetTxCmd() *cobra.Command { RunE: client.ValidateCmd, } - cmd.AddCommand(CmdCreatePost()) + cmd.AddCommand( + CmdCreatePost(), + CmdCreateComment(), + ) return cmd } @@ -61,3 +64,37 @@ func CmdCreatePost() *cobra.Command { return cmd } + +func CmdCreateComment() *cobra.Command { + cmd := &cobra.Command{ + Use: "create-comment [author] [slug] [body]", + Short: "Creates a new comment", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + + argsSlug := string(args[1]) + argsBody := string(args[2]) + + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + msg := &blog.MsgCreateComment{ + Author: clientCtx.GetFromAddress().String(), + Slug: argsSlug, + Body: argsBody, + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/x/blog/keys.go b/x/blog/keys.go index d20755d..939cf62 100644 --- a/x/blog/keys.go +++ b/x/blog/keys.go @@ -4,7 +4,8 @@ const ( ModuleName = "blog" StoreKey = ModuleName - PostKey = "post" + PostKey = "post" + CommentKey = "comment" ) func KeyPrefix(p string) []byte { diff --git a/x/blog/query.pb.go b/x/blog/query.pb.go index 25f51cf..3fb4ccb 100644 --- a/x/blog/query.pb.go +++ b/x/blog/query.pb.go @@ -124,34 +124,145 @@ func (m *QueryAllPostsResponse) GetPagination() *query.PageResponse { return nil } +type QueryPostCommentsRequest struct { + Pagination *query.PageRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` + Slug string `protobuf:"bytes,2,opt,name=slug,proto3" json:"slug,omitempty"` +} + +func (m *QueryPostCommentsRequest) Reset() { *m = QueryPostCommentsRequest{} } +func (m *QueryPostCommentsRequest) String() string { return proto.CompactTextString(m) } +func (*QueryPostCommentsRequest) ProtoMessage() {} +func (*QueryPostCommentsRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_eb782a0cfb4fa324, []int{2} +} +func (m *QueryPostCommentsRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPostCommentsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPostCommentsRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryPostCommentsRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPostCommentsRequest.Merge(m, src) +} +func (m *QueryPostCommentsRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryPostCommentsRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPostCommentsRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPostCommentsRequest proto.InternalMessageInfo + +func (m *QueryPostCommentsRequest) GetPagination() *query.PageRequest { + if m != nil { + return m.Pagination + } + return nil +} + +func (m *QueryPostCommentsRequest) GetSlug() string { + if m != nil { + return m.Slug + } + return "" +} + +type QueryPostCommentsResponse struct { + Comments []*Comment `protobuf:"bytes,1,rep,name=comments,proto3" json:"comments,omitempty"` + Pagination *query.PageResponse `protobuf:"bytes,2,opt,name=pagination,proto3" json:"pagination,omitempty"` +} + +func (m *QueryPostCommentsResponse) Reset() { *m = QueryPostCommentsResponse{} } +func (m *QueryPostCommentsResponse) String() string { return proto.CompactTextString(m) } +func (*QueryPostCommentsResponse) ProtoMessage() {} +func (*QueryPostCommentsResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_eb782a0cfb4fa324, []int{3} +} +func (m *QueryPostCommentsResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryPostCommentsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryPostCommentsResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QueryPostCommentsResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryPostCommentsResponse.Merge(m, src) +} +func (m *QueryPostCommentsResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryPostCommentsResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryPostCommentsResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryPostCommentsResponse proto.InternalMessageInfo + +func (m *QueryPostCommentsResponse) GetComments() []*Comment { + if m != nil { + return m.Comments + } + return nil +} + +func (m *QueryPostCommentsResponse) GetPagination() *query.PageResponse { + if m != nil { + return m.Pagination + } + return nil +} + func init() { proto.RegisterType((*QueryAllPostsRequest)(nil), "blog.v1.QueryAllPostsRequest") proto.RegisterType((*QueryAllPostsResponse)(nil), "blog.v1.QueryAllPostsResponse") + proto.RegisterType((*QueryPostCommentsRequest)(nil), "blog.v1.QueryPostCommentsRequest") + proto.RegisterType((*QueryPostCommentsResponse)(nil), "blog.v1.QueryPostCommentsResponse") } func init() { proto.RegisterFile("blog/v1/query.proto", fileDescriptor_eb782a0cfb4fa324) } var fileDescriptor_eb782a0cfb4fa324 = []byte{ - // 301 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x91, 0x41, 0x4b, 0xf3, 0x30, - 0x18, 0xc7, 0x9b, 0xf7, 0x65, 0x2a, 0x19, 0x5e, 0xa2, 0xc2, 0x28, 0x18, 0xc6, 0x06, 0x3a, 0x04, - 0x13, 0x5a, 0xcf, 0x1e, 0xf4, 0xa0, 0x78, 0x9b, 0x3d, 0x7a, 0x10, 0x9a, 0xf2, 0x50, 0x8b, 0x5d, - 0xd3, 0x35, 0x69, 0x75, 0x1f, 0xc0, 0xbb, 0x1f, 0xcb, 0xe3, 0x8e, 0x1e, 0xa5, 0xfd, 0x22, 0x92, - 0xa6, 0xce, 0x29, 0x8a, 0xd7, 0xe7, 0x79, 0xfe, 0xff, 0xdf, 0xaf, 0x0d, 0xde, 0x11, 0xa9, 0x8c, - 0x79, 0xe5, 0xf1, 0x79, 0x09, 0xc5, 0x82, 0xe5, 0x85, 0xd4, 0x92, 0x6c, 0x9a, 0x21, 0xab, 0x3c, - 0xf7, 0x28, 0x92, 0x6a, 0x26, 0x15, 0x17, 0xa1, 0x02, 0x7b, 0xc1, 0x2b, 0x4f, 0x80, 0x0e, 0x3d, - 0x9e, 0x87, 0x71, 0x92, 0x85, 0x3a, 0x91, 0x99, 0x0d, 0xb9, 0xab, 0x26, 0xbd, 0xc8, 0x41, 0xd9, - 0xe1, 0xe8, 0x16, 0xef, 0x5e, 0x9b, 0xd8, 0x59, 0x9a, 0x4e, 0xa5, 0xd2, 0x2a, 0x80, 0x79, 0x09, - 0x4a, 0x93, 0x0b, 0x8c, 0x3f, 0x0b, 0x06, 0x68, 0x88, 0x26, 0x7d, 0xff, 0x80, 0x59, 0x1a, 0x33, - 0x34, 0x66, 0x7d, 0x3a, 0x1a, 0x9b, 0x86, 0x31, 0x74, 0xd9, 0x60, 0x2d, 0x39, 0x7a, 0x42, 0x78, - 0xef, 0x1b, 0x40, 0xe5, 0x32, 0x53, 0x40, 0xc6, 0xb8, 0x97, 0x9b, 0xc1, 0x00, 0x0d, 0xff, 0x4f, - 0xfa, 0xfe, 0x36, 0xeb, 0xbe, 0x89, 0x99, 0xb3, 0xc0, 0xee, 0xc8, 0xe5, 0x17, 0x8d, 0x7f, 0xad, - 0xc6, 0xe1, 0x9f, 0x1a, 0x96, 0xb0, 0xee, 0xe1, 0x07, 0xb8, 0xd7, 0x6a, 0x90, 0x2b, 0xbc, 0xf5, - 0xa1, 0x42, 0xf6, 0x57, 0xcc, 0x9f, 0xfe, 0x81, 0x4b, 0x7f, 0x5b, 0xdb, 0xfe, 0xf3, 0xd3, 0x97, - 0x9a, 0xa2, 0x65, 0x4d, 0xd1, 0x5b, 0x4d, 0xd1, 0x73, 0x43, 0x9d, 0x65, 0x43, 0x9d, 0xd7, 0x86, - 0x3a, 0x37, 0xe3, 0x38, 0xd1, 0x77, 0xa5, 0x60, 0x91, 0x9c, 0xf1, 0x02, 0x62, 0xc8, 0x8e, 0x33, - 0xd0, 0x0f, 0xb2, 0xb8, 0xe7, 0x02, 0x22, 0xfe, 0xc8, 0x4d, 0xaf, 0xd8, 0x68, 0x5f, 0xe0, 0xe4, - 0x3d, 0x00, 0x00, 0xff, 0xff, 0x83, 0x3d, 0x41, 0xc5, 0xe2, 0x01, 0x00, 0x00, + // 376 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x52, 0xcd, 0x4a, 0xeb, 0x40, + 0x14, 0xee, 0xdc, 0x7b, 0x7b, 0xad, 0x53, 0x05, 0x19, 0x15, 0x6a, 0xc0, 0x50, 0x53, 0xd0, 0x22, + 0x3a, 0x43, 0xea, 0xda, 0x85, 0x0a, 0x8a, 0xbb, 0x1a, 0x70, 0xe3, 0x42, 0x48, 0xc2, 0x10, 0x8b, + 0x49, 0x26, 0xcd, 0x4c, 0xa2, 0x7d, 0x00, 0xf7, 0xe2, 0x5b, 0xf8, 0x26, 0x2e, 0xbb, 0x74, 0x29, + 0xed, 0x8b, 0xc8, 0x64, 0xc6, 0xd8, 0x4a, 0xd5, 0x4d, 0x77, 0xe1, 0xcc, 0x77, 0xbe, 0xbf, 0x1c, + 0xb8, 0xea, 0x85, 0x2c, 0x20, 0xb9, 0x4d, 0xfa, 0x19, 0x4d, 0x07, 0x38, 0x49, 0x99, 0x60, 0x68, + 0x41, 0x0e, 0x71, 0x6e, 0x1b, 0xbb, 0x3e, 0xe3, 0x11, 0xe3, 0xc4, 0x73, 0x39, 0x55, 0x08, 0x92, + 0xdb, 0x1e, 0x15, 0xae, 0x4d, 0x12, 0x37, 0xe8, 0xc5, 0xae, 0xe8, 0xb1, 0x58, 0x2d, 0x19, 0x25, + 0x93, 0x18, 0x24, 0x94, 0xab, 0xa1, 0x75, 0x0d, 0xd7, 0x2e, 0xe4, 0xda, 0x51, 0x18, 0x76, 0x19, + 0x17, 0xdc, 0xa1, 0xfd, 0x8c, 0x72, 0x81, 0x4e, 0x21, 0xfc, 0x24, 0x68, 0x80, 0x26, 0x68, 0xd7, + 0x3b, 0xdb, 0x58, 0xa9, 0x61, 0xa9, 0x86, 0x95, 0x1f, 0xad, 0x86, 0xbb, 0x6e, 0x40, 0xf5, 0xae, + 0x33, 0xb1, 0x69, 0x3d, 0x00, 0xb8, 0xfe, 0x45, 0x80, 0x27, 0x2c, 0xe6, 0x14, 0xb5, 0x60, 0x35, + 0x91, 0x83, 0x06, 0x68, 0xfe, 0x6d, 0xd7, 0x3b, 0xcb, 0x58, 0x67, 0xc2, 0x12, 0xe6, 0xa8, 0x37, + 0x74, 0x36, 0x65, 0xe3, 0x4f, 0x61, 0x63, 0xe7, 0x57, 0x1b, 0x4a, 0x61, 0xca, 0x47, 0x0e, 0x1b, + 0x85, 0x0d, 0x49, 0x7e, 0xc2, 0xa2, 0x88, 0xc6, 0x73, 0xcf, 0x8a, 0x10, 0xfc, 0xc7, 0xc3, 0x2c, + 0x28, 0x6c, 0x2e, 0x3a, 0xc5, 0xb7, 0xf5, 0x04, 0xe0, 0xc6, 0x0c, 0x61, 0xdd, 0xc1, 0x1e, 0xac, + 0xf9, 0x7a, 0xa6, 0x6b, 0x58, 0x29, 0x6b, 0xd0, 0x60, 0xa7, 0x44, 0xcc, 0xad, 0x8c, 0xce, 0x33, + 0x80, 0xd5, 0xc2, 0x14, 0x3a, 0x87, 0xb5, 0x8f, 0x1f, 0x83, 0x36, 0x4b, 0xe9, 0x59, 0x17, 0x61, + 0x98, 0xdf, 0x3d, 0xeb, 0x2c, 0x97, 0x70, 0x69, 0x32, 0x23, 0xda, 0x9a, 0xc6, 0xcf, 0x28, 0xde, + 0xb0, 0x7e, 0x82, 0x28, 0xda, 0xe3, 0xc3, 0x97, 0x91, 0x09, 0x86, 0x23, 0x13, 0xbc, 0x8d, 0x4c, + 0xf0, 0x38, 0x36, 0x2b, 0xc3, 0xb1, 0x59, 0x79, 0x1d, 0x9b, 0x95, 0xab, 0x56, 0xd0, 0x13, 0x37, + 0x99, 0x87, 0x7d, 0x16, 0x91, 0x94, 0x06, 0x34, 0xde, 0x8f, 0xa9, 0xb8, 0x63, 0xe9, 0x2d, 0xf1, + 0xa8, 0x4f, 0xee, 0x89, 0xe4, 0xf6, 0xfe, 0x17, 0x67, 0x7e, 0xf0, 0x1e, 0x00, 0x00, 0xff, 0xff, + 0xfb, 0x16, 0x8f, 0xb8, 0x47, 0x03, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -167,6 +278,7 @@ const _ = grpc.SupportPackageIsVersion4 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type QueryClient interface { AllPosts(ctx context.Context, in *QueryAllPostsRequest, opts ...grpc.CallOption) (*QueryAllPostsResponse, error) + PostComments(ctx context.Context, in *QueryPostCommentsRequest, opts ...grpc.CallOption) (*QueryPostCommentsResponse, error) } type queryClient struct { @@ -186,9 +298,19 @@ func (c *queryClient) AllPosts(ctx context.Context, in *QueryAllPostsRequest, op return out, nil } +func (c *queryClient) PostComments(ctx context.Context, in *QueryPostCommentsRequest, opts ...grpc.CallOption) (*QueryPostCommentsResponse, error) { + out := new(QueryPostCommentsResponse) + err := c.cc.Invoke(ctx, "/blog.v1.Query/PostComments", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // QueryServer is the server API for Query service. type QueryServer interface { AllPosts(context.Context, *QueryAllPostsRequest) (*QueryAllPostsResponse, error) + PostComments(context.Context, *QueryPostCommentsRequest) (*QueryPostCommentsResponse, error) } // UnimplementedQueryServer can be embedded to have forward compatible implementations. @@ -198,6 +320,9 @@ type UnimplementedQueryServer struct { func (*UnimplementedQueryServer) AllPosts(ctx context.Context, req *QueryAllPostsRequest) (*QueryAllPostsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method AllPosts not implemented") } +func (*UnimplementedQueryServer) PostComments(ctx context.Context, req *QueryPostCommentsRequest) (*QueryPostCommentsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PostComments not implemented") +} func RegisterQueryServer(s grpc1.Server, srv QueryServer) { s.RegisterService(&_Query_serviceDesc, srv) @@ -221,6 +346,24 @@ func _Query_AllPosts_Handler(srv interface{}, ctx context.Context, dec func(inte return interceptor(ctx, in, info, handler) } +func _Query_PostComments_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryPostCommentsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).PostComments(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/blog.v1.Query/PostComments", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).PostComments(ctx, req.(*QueryPostCommentsRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _Query_serviceDesc = grpc.ServiceDesc{ ServiceName: "blog.v1.Query", HandlerType: (*QueryServer)(nil), @@ -229,6 +372,10 @@ var _Query_serviceDesc = grpc.ServiceDesc{ MethodName: "AllPosts", Handler: _Query_AllPosts_Handler, }, + { + MethodName: "PostComments", + Handler: _Query_PostComments_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "blog/v1/query.proto", @@ -318,6 +465,97 @@ func (m *QueryAllPostsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *QueryPostCommentsRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryPostCommentsRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPostCommentsRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Slug) > 0 { + i -= len(m.Slug) + copy(dAtA[i:], m.Slug) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Slug))) + i-- + dAtA[i] = 0x12 + } + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryPostCommentsResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QueryPostCommentsResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryPostCommentsResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Pagination != nil { + { + size, err := m.Pagination.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + if len(m.Comments) > 0 { + for iNdEx := len(m.Comments) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Comments[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { offset -= sovQuery(v) base := offset @@ -361,6 +599,42 @@ func (m *QueryAllPostsResponse) Size() (n int) { return n } +func (m *QueryPostCommentsRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + l = len(m.Slug) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QueryPostCommentsResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Comments) > 0 { + for _, e := range m.Comments { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + if m.Pagination != nil { + l = m.Pagination.Size() + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + func sovQuery(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -579,6 +853,250 @@ func (m *QueryAllPostsResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *QueryPostCommentsRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryPostCommentsRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPostCommentsRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageRequest{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Slug", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Slug = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryPostCommentsResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QueryPostCommentsResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryPostCommentsResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Comments", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Comments = append(m.Comments, &Comment{}) + if err := m.Comments[len(m.Comments)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Pagination", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Pagination == nil { + m.Pagination = &query.PageResponse{} + } + if err := m.Pagination.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipQuery(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/blog/requests.go b/x/blog/requests.go index f55da6d..c142e73 100644 --- a/x/blog/requests.go +++ b/x/blog/requests.go @@ -7,6 +7,7 @@ import ( var ( _ sdk.Msg = &MsgCreatePost{} + _ sdk.Msg = &MsgCreateComment{} ) func (m *MsgCreatePost) ValidateBasic() error { @@ -34,3 +35,26 @@ func (m *MsgCreatePost) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{addr} } + +func (m *MsgCreateComment) ValidateBasic() error { + if m.Author == "" { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "no author") + } + if m.Slug == "" { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "no slug") + } + if m.Body == "" { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "no body") + } + + return nil +} + +func (m *MsgCreateComment) GetSigners() []sdk.AccAddress { + addr, err := sdk.AccAddressFromBech32(m.Author) + if err != nil { + panic(err) + } + + return []sdk.AccAddress{addr} +} diff --git a/x/blog/server/msg_server.go b/x/blog/server/msg_server.go index 8b60604..21e24c6 100644 --- a/x/blog/server/msg_server.go +++ b/x/blog/server/msg_server.go @@ -8,6 +8,7 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/regen-network/bec/x/blog" + uuid "github.com/uuid6/uuid6go-proto" ) var _ blog.MsgServer = serverImpl{} @@ -38,3 +39,44 @@ func (s serverImpl) CreatePost(goCtx context.Context, request *blog.MsgCreatePos return &blog.MsgCreatePostResponse{}, nil } + +func (s serverImpl) CreateComment(goCtx context.Context, request *blog.MsgCreateComment) (*blog.MsgCreateCommentResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + storePost := prefix.NewStore(ctx.KVStore(s.storeKey), blog.KeyPrefix(blog.PostKey)) + + // We add comment to particular post thus we check the slug of the post exist in KVStore + keyPost := []byte(request.Slug) + if !storePost.Has(keyPost) { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "Post %s isn't written yet", request.Slug) + } + + comment := blog.Comment{ + Slug: request.Slug, + Author: request.Author, + Body: request.Body, + } + + bz, err := s.cdc.Marshal(&comment) + if err != nil { + return nil, err + } + + // Comment has key is comprised by `comment` + `slug` + `_` + `uuidV7`. + keyComment := blog.KeyPrefix(request.Slug + "_" + getUuid()) + // Prefix `comment` is added by KVStore here. + storeComment := prefix.NewStore(ctx.KVStore(s.storeKey), blog.KeyPrefix(blog.CommentKey)) + + storeComment.Set(keyComment, bz) + + return &blog.MsgCreateCommentResponse{}, nil +} + +// One post can have many comments. We are going to specify them with uuid +func getUuid() string { + var gen uuid.UUIDv7Generator + gen.SubsecondPrecisionLength = 12 + + id := gen.Next() + return id.ToString() +} diff --git a/x/blog/server/query_server.go b/x/blog/server/query_server.go index 57a80e0..18abd7b 100644 --- a/x/blog/server/query_server.go +++ b/x/blog/server/query_server.go @@ -2,8 +2,10 @@ package server import ( "context" + "strings" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/regen-network/bec/x/blog" ) @@ -33,3 +35,38 @@ func (s serverImpl) AllPosts(goCtx context.Context, request *blog.QueryAllPostsR Posts: posts, }, nil } + +func (s serverImpl) PostComments(goCtx context.Context, request *blog.QueryPostCommentsRequest) (*blog.QueryPostCommentsResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + slug := request.Slug + store := ctx.KVStore(s.storeKey) + iteratorComments := sdk.KVStorePrefixIterator(store, blog.KeyPrefix(blog.CommentKey)) + + defer iteratorComments.Close() + + var comments []*blog.Comment + // we itirate over keys with prefix CommentKey ("comment") + for ; iteratorComments.Valid(); iteratorComments.Next() { + key := string(iteratorComments.Key()) + // Drop "_" and uuid of the key + // Now slugFromComment = comment+slug + slugFromComment := strings.Split(key, "_")[0] + if slugFromComment == "" { + return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "can not extract slug from the key: %s", key) + } + + if blog.CommentKey+slug == slugFromComment { + var msg blog.Comment + err := s.cdc.Unmarshal(iteratorComments.Value(), &msg) + if err != nil { + return nil, err + } + comments = append(comments, &msg) + } + } + + return &blog.QueryPostCommentsResponse{ + Comments: comments, + }, nil +} diff --git a/x/blog/tx.pb.go b/x/blog/tx.pb.go index cf329b3..9c098bf 100644 --- a/x/blog/tx.pb.go +++ b/x/blog/tx.pb.go @@ -133,15 +133,115 @@ func (m *MsgCreatePostResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgCreatePostResponse proto.InternalMessageInfo +// MsgCreateComment is the Msg/CreateComment request type. +type MsgCreateComment struct { + Slug string `protobuf:"bytes,1,opt,name=slug,proto3" json:"slug,omitempty"` + Author string `protobuf:"bytes,2,opt,name=author,proto3" json:"author,omitempty"` + Body string `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"` +} + +func (m *MsgCreateComment) Reset() { *m = MsgCreateComment{} } +func (m *MsgCreateComment) String() string { return proto.CompactTextString(m) } +func (*MsgCreateComment) ProtoMessage() {} +func (*MsgCreateComment) Descriptor() ([]byte, []int) { + return fileDescriptor_f15df8808566170d, []int{2} +} +func (m *MsgCreateComment) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateComment) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateComment.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateComment) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateComment.Merge(m, src) +} +func (m *MsgCreateComment) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateComment) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateComment.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateComment proto.InternalMessageInfo + +func (m *MsgCreateComment) GetSlug() string { + if m != nil { + return m.Slug + } + return "" +} + +func (m *MsgCreateComment) GetAuthor() string { + if m != nil { + return m.Author + } + return "" +} + +func (m *MsgCreateComment) GetBody() string { + if m != nil { + return m.Body + } + return "" +} + +// MsgCreateCommentResponse is the Msg/CreateComment response type. +type MsgCreateCommentResponse struct { +} + +func (m *MsgCreateCommentResponse) Reset() { *m = MsgCreateCommentResponse{} } +func (m *MsgCreateCommentResponse) String() string { return proto.CompactTextString(m) } +func (*MsgCreateCommentResponse) ProtoMessage() {} +func (*MsgCreateCommentResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_f15df8808566170d, []int{3} +} +func (m *MsgCreateCommentResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgCreateCommentResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgCreateCommentResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgCreateCommentResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgCreateCommentResponse.Merge(m, src) +} +func (m *MsgCreateCommentResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgCreateCommentResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgCreateCommentResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgCreateCommentResponse proto.InternalMessageInfo + func init() { proto.RegisterType((*MsgCreatePost)(nil), "blog.v1.MsgCreatePost") proto.RegisterType((*MsgCreatePostResponse)(nil), "blog.v1.MsgCreatePostResponse") + proto.RegisterType((*MsgCreateComment)(nil), "blog.v1.MsgCreateComment") + proto.RegisterType((*MsgCreateCommentResponse)(nil), "blog.v1.MsgCreateCommentResponse") } func init() { proto.RegisterFile("blog/v1/tx.proto", fileDescriptor_f15df8808566170d) } var fileDescriptor_f15df8808566170d = []byte{ - // 234 bytes of a gzipped FileDescriptorProto + // 281 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x48, 0xca, 0xc9, 0x4f, 0xd7, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x07, 0x89, 0xe8, 0x95, 0x19, 0x2a, 0xa5, 0x72, 0xf1, 0xfa, 0x16, 0xa7, 0x3b, 0x17, 0xa5, 0x26, 0x96, 0xa4, @@ -149,14 +249,17 @@ var fileDescriptor_f15df8808566170d = []byte{ 0x6a, 0x70, 0x06, 0x81, 0xd9, 0x42, 0x62, 0x5c, 0x6c, 0x89, 0xa5, 0x25, 0x19, 0xf9, 0x45, 0x12, 0x4c, 0x60, 0x51, 0x28, 0x4f, 0x48, 0x84, 0x8b, 0xb5, 0x24, 0xb3, 0x24, 0x27, 0x55, 0x82, 0x19, 0x2c, 0x0c, 0xe1, 0x80, 0x4c, 0x48, 0xca, 0x4f, 0xa9, 0x94, 0x60, 0x81, 0x98, 0x00, 0x62, 0x2b, - 0x89, 0x73, 0x89, 0xa2, 0x58, 0x13, 0x94, 0x5a, 0x5c, 0x90, 0x9f, 0x57, 0x9c, 0x6a, 0xe4, 0xcd, - 0xc5, 0xec, 0x5b, 0x9c, 0x2e, 0xe4, 0xc2, 0xc5, 0x85, 0xe4, 0x06, 0x31, 0x3d, 0xa8, 0xf3, 0xf4, - 0x50, 0x34, 0x49, 0xc9, 0x61, 0x17, 0x87, 0x19, 0xe6, 0x64, 0x7b, 0xe2, 0x91, 0x1c, 0xe3, 0x85, - 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, - 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0xca, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, - 0xfa, 0x45, 0xa9, 0xe9, 0xa9, 0x79, 0xba, 0x79, 0xa9, 0x25, 0xe5, 0xf9, 0x45, 0xd9, 0xfa, 0x49, - 0xa9, 0xc9, 0xfa, 0x15, 0xfa, 0x20, 0x73, 0x93, 0xd8, 0xc0, 0x61, 0x63, 0x0c, 0x08, 0x00, 0x00, - 0xff, 0xff, 0x86, 0x8e, 0xc6, 0xb8, 0x2f, 0x01, 0x00, 0x00, + 0x89, 0x73, 0x89, 0xa2, 0x58, 0x13, 0x94, 0x5a, 0x5c, 0x90, 0x9f, 0x57, 0x9c, 0xaa, 0x14, 0xc4, + 0x25, 0x00, 0x97, 0x70, 0xce, 0xcf, 0xcd, 0x4d, 0xcd, 0x23, 0xcd, 0x09, 0x30, 0xcb, 0x98, 0x91, + 0x2c, 0x93, 0xe2, 0x92, 0x40, 0x37, 0x13, 0x66, 0x9f, 0xd1, 0x2c, 0x46, 0x2e, 0x66, 0xdf, 0xe2, + 0x74, 0x21, 0x17, 0x2e, 0x2e, 0x24, 0x4f, 0x8b, 0xe9, 0x41, 0xc3, 0x43, 0x0f, 0xc5, 0x95, 0x52, + 0x72, 0xd8, 0xc5, 0x61, 0xa6, 0x09, 0xf9, 0x72, 0xf1, 0xa2, 0x3a, 0x5d, 0x12, 0x53, 0x03, 0x54, + 0x4a, 0x4a, 0x11, 0xa7, 0x14, 0xcc, 0x38, 0x27, 0xdb, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, + 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, + 0x96, 0x63, 0x88, 0x52, 0x4e, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x2f, + 0x4a, 0x4d, 0x4f, 0xcd, 0xd3, 0xcd, 0x4b, 0x2d, 0x29, 0xcf, 0x2f, 0xca, 0xd6, 0x4f, 0x4a, 0x4d, + 0xd6, 0xaf, 0xd0, 0x07, 0x19, 0x9d, 0xc4, 0x06, 0x8e, 0x5b, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, + 0xff, 0xf0, 0xbf, 0x68, 0x1e, 0xef, 0x01, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -172,6 +275,7 @@ const _ = grpc.SupportPackageIsVersion4 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type MsgClient interface { CreatePost(ctx context.Context, in *MsgCreatePost, opts ...grpc.CallOption) (*MsgCreatePostResponse, error) + CreateComment(ctx context.Context, in *MsgCreateComment, opts ...grpc.CallOption) (*MsgCreateCommentResponse, error) } type msgClient struct { @@ -191,9 +295,19 @@ func (c *msgClient) CreatePost(ctx context.Context, in *MsgCreatePost, opts ...g return out, nil } +func (c *msgClient) CreateComment(ctx context.Context, in *MsgCreateComment, opts ...grpc.CallOption) (*MsgCreateCommentResponse, error) { + out := new(MsgCreateCommentResponse) + err := c.cc.Invoke(ctx, "/blog.v1.Msg/CreateComment", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // MsgServer is the server API for Msg service. type MsgServer interface { CreatePost(context.Context, *MsgCreatePost) (*MsgCreatePostResponse, error) + CreateComment(context.Context, *MsgCreateComment) (*MsgCreateCommentResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. @@ -203,6 +317,9 @@ type UnimplementedMsgServer struct { func (*UnimplementedMsgServer) CreatePost(ctx context.Context, req *MsgCreatePost) (*MsgCreatePostResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreatePost not implemented") } +func (*UnimplementedMsgServer) CreateComment(ctx context.Context, req *MsgCreateComment) (*MsgCreateCommentResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateComment not implemented") +} func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) @@ -226,6 +343,24 @@ func _Msg_CreatePost_Handler(srv interface{}, ctx context.Context, dec func(inte return interceptor(ctx, in, info, handler) } +func _Msg_CreateComment_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgCreateComment) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).CreateComment(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/blog.v1.Msg/CreateComment", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).CreateComment(ctx, req.(*MsgCreateComment)) + } + return interceptor(ctx, in, info, handler) +} + var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "blog.v1.Msg", HandlerType: (*MsgServer)(nil), @@ -234,6 +369,10 @@ var _Msg_serviceDesc = grpc.ServiceDesc{ MethodName: "CreatePost", Handler: _Msg_CreatePost_Handler, }, + { + MethodName: "CreateComment", + Handler: _Msg_CreateComment_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "blog/v1/tx.proto", @@ -313,6 +452,73 @@ func (m *MsgCreatePostResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *MsgCreateComment) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateComment) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateComment) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Body) > 0 { + i -= len(m.Body) + copy(dAtA[i:], m.Body) + i = encodeVarintTx(dAtA, i, uint64(len(m.Body))) + i-- + dAtA[i] = 0x1a + } + if len(m.Author) > 0 { + i -= len(m.Author) + copy(dAtA[i:], m.Author) + i = encodeVarintTx(dAtA, i, uint64(len(m.Author))) + i-- + dAtA[i] = 0x12 + } + if len(m.Slug) > 0 { + i -= len(m.Slug) + copy(dAtA[i:], m.Slug) + i = encodeVarintTx(dAtA, i, uint64(len(m.Slug))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgCreateCommentResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgCreateCommentResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgCreateCommentResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -358,6 +564,36 @@ func (m *MsgCreatePostResponse) Size() (n int) { return n } +func (m *MsgCreateComment) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Slug) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Author) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.Body) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgCreateCommentResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -598,6 +834,208 @@ func (m *MsgCreatePostResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *MsgCreateComment) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateComment: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateComment: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Slug", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Slug = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Author", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Author = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Body", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Body = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgCreateCommentResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgCreateCommentResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgCreateCommentResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/x/blog/types.pb.go b/x/blog/types.pb.go index 307e7f8..535f39c 100644 --- a/x/blog/types.pb.go +++ b/x/blog/types.pb.go @@ -92,26 +92,90 @@ func (m *Post) GetBody() string { return "" } +type Comment struct { + // slug is a short human-readable string for the post, used as unique + // identifier for the post. + Slug string `protobuf:"bytes,1,opt,name=slug,proto3" json:"slug,omitempty"` + Author string `protobuf:"bytes,2,opt,name=author,proto3" json:"author,omitempty"` + Body string `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"` +} + +func (m *Comment) Reset() { *m = Comment{} } +func (m *Comment) String() string { return proto.CompactTextString(m) } +func (*Comment) ProtoMessage() {} +func (*Comment) Descriptor() ([]byte, []int) { + return fileDescriptor_73573037ee301d2b, []int{1} +} +func (m *Comment) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Comment) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Comment.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Comment) XXX_Merge(src proto.Message) { + xxx_messageInfo_Comment.Merge(m, src) +} +func (m *Comment) XXX_Size() int { + return m.Size() +} +func (m *Comment) XXX_DiscardUnknown() { + xxx_messageInfo_Comment.DiscardUnknown(m) +} + +var xxx_messageInfo_Comment proto.InternalMessageInfo + +func (m *Comment) GetSlug() string { + if m != nil { + return m.Slug + } + return "" +} + +func (m *Comment) GetAuthor() string { + if m != nil { + return m.Author + } + return "" +} + +func (m *Comment) GetBody() string { + if m != nil { + return m.Body + } + return "" +} + func init() { proto.RegisterType((*Post)(nil), "blog.v1.Post") + proto.RegisterType((*Comment)(nil), "blog.v1.Comment") } func init() { proto.RegisterFile("blog/v1/types.proto", fileDescriptor_73573037ee301d2b) } var fileDescriptor_73573037ee301d2b = []byte{ - // 187 bytes of a gzipped FileDescriptorProto + // 205 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4e, 0xca, 0xc9, 0x4f, 0xd7, 0x2f, 0x33, 0xd4, 0x2f, 0xa9, 0x2c, 0x48, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x07, 0x09, 0xea, 0x95, 0x19, 0x2a, 0xc5, 0x70, 0xb1, 0x04, 0xe4, 0x17, 0x97, 0x08, 0x09, 0x71, 0xb1, 0x14, 0xe7, 0x94, 0xa6, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x81, 0xd9, 0x42, 0x62, 0x5c, 0x6c, 0x89, 0xa5, 0x25, 0x19, 0xf9, 0x45, 0x12, 0x4c, 0x60, 0x51, 0x28, 0x4f, 0x48, 0x84, 0x8b, 0xb5, 0x24, 0xb3, 0x24, 0x27, 0x55, 0x82, 0x19, 0x2c, 0x0c, 0xe1, 0x80, 0x4c, 0x48, - 0xca, 0x4f, 0xa9, 0x94, 0x60, 0x81, 0x98, 0x00, 0x62, 0x3b, 0xd9, 0x9e, 0x78, 0x24, 0xc7, 0x78, - 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, - 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x94, 0x72, 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, - 0xae, 0x7e, 0x51, 0x6a, 0x7a, 0x6a, 0x9e, 0x6e, 0x5e, 0x6a, 0x49, 0x79, 0x7e, 0x51, 0xb6, 0x7e, - 0x52, 0x6a, 0xb2, 0x7e, 0x85, 0x3e, 0xc8, 0x7d, 0x49, 0x6c, 0x60, 0xc7, 0x1a, 0x03, 0x02, 0x00, - 0x00, 0xff, 0xff, 0xf7, 0xa2, 0x98, 0xf3, 0xc3, 0x00, 0x00, 0x00, + 0xca, 0x4f, 0xa9, 0x94, 0x60, 0x81, 0x98, 0x00, 0x62, 0x2b, 0x79, 0x72, 0xb1, 0x3b, 0xe7, 0xe7, + 0xe6, 0xa6, 0xe6, 0x91, 0x66, 0x01, 0xcc, 0x28, 0x66, 0x84, 0x51, 0x4e, 0xb6, 0x27, 0x1e, 0xc9, + 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, + 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x9c, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, + 0x9c, 0x9f, 0xab, 0x5f, 0x94, 0x9a, 0x9e, 0x9a, 0xa7, 0x9b, 0x97, 0x5a, 0x52, 0x9e, 0x5f, 0x94, + 0xad, 0x9f, 0x94, 0x9a, 0xac, 0x5f, 0xa1, 0x0f, 0xf2, 0x6a, 0x12, 0x1b, 0xd8, 0xdf, 0xc6, 0x80, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xee, 0xcb, 0xd8, 0x6f, 0x0e, 0x01, 0x00, 0x00, } func (m *Post) Marshal() (dAtA []byte, err error) { @@ -165,6 +229,50 @@ func (m *Post) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *Comment) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Comment) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Comment) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Body) > 0 { + i -= len(m.Body) + copy(dAtA[i:], m.Body) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Body))) + i-- + dAtA[i] = 0x1a + } + if len(m.Author) > 0 { + i -= len(m.Author) + copy(dAtA[i:], m.Author) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Author))) + i-- + dAtA[i] = 0x12 + } + if len(m.Slug) > 0 { + i -= len(m.Slug) + copy(dAtA[i:], m.Slug) + i = encodeVarintTypes(dAtA, i, uint64(len(m.Slug))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { offset -= sovTypes(v) base := offset @@ -201,6 +309,27 @@ func (m *Post) Size() (n int) { return n } +func (m *Comment) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Slug) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Author) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + l = len(m.Body) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) + } + return n +} + func sovTypes(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -388,6 +517,155 @@ func (m *Post) Unmarshal(dAtA []byte) error { } return nil } +func (m *Comment) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Comment: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Comment: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Slug", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Slug = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Author", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Author = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Body", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTypes + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Body = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipTypes(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0