├── .gitignore
├── .babelrc
├── docs
└── img
│ └── screen.png
├── static
├── img
│ └── grpc.png
└── index.html
├── README.md
├── src
├── index.js
├── sass
│ ├── vars.scss
│ └── mixins.scss
└── components
│ ├── Error.js
│ ├── Sidebar.scss
│ ├── Sidebar.js
│ ├── Loader.js
│ ├── Response.js
│ ├── Request.js
│ ├── Method.scss
│ ├── app.scss
│ ├── types.js
│ ├── Method.js
│ ├── App.js
│ └── fields.js
├── Makefile
├── glide.yaml
├── Dockerfile
├── proto
├── decode_bytes.go
├── message.go
├── call_test.go
├── proto.go
├── call.go
├── encode_message.go
├── decode_message.go
├── encode_bytes.go
├── reflect.go
├── encode.go
├── decode_number.go
├── decode.go
├── encode_number_test.go
├── encode_number.go
└── decode_number_test.go
├── main.go
├── webpack.config.js
├── fixtures
└── simple
│ ├── simple.proto
│ └── simple.pb.go
├── package.json
├── glide.lock
├── test_server
├── main.go
└── pb
│ ├── example.proto
│ └── example.pb.go
├── reflection
├── reflection_test.go
├── info.go
└── pool.go
├── http_server
└── http_server.go
└── LICENSE
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 | node_modules/
3 | .idea/
4 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "react", "stage-0"]
3 | }
--------------------------------------------------------------------------------
/docs/img/screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/komly/grpc-ui/HEAD/docs/img/screen.png
--------------------------------------------------------------------------------
/static/img/grpc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/komly/grpc-ui/HEAD/static/img/grpc.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # grpc-ui
2 | A gRPC Web Interface
3 |
4 | 
5 |
6 | ### Installing
7 | go get -u github.com/komly/grpc-ui
8 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './components/App';
4 |
5 |
6 | ReactDOM.render(, document.getElementById('root'));
7 |
--------------------------------------------------------------------------------
/src/sass/vars.scss:
--------------------------------------------------------------------------------
1 | $primary: rgb(4, 172, 180);
2 | $primary-light: lighten(rgb(4, 172, 180), 5%);
3 | $primary-dark: darken(rgb(4, 172, 180), 5%);
4 |
5 | $danger: #e6736d;
6 | $success: #c9ffd5;
7 |
--------------------------------------------------------------------------------
/src/sass/mixins.scss:
--------------------------------------------------------------------------------
1 | @mixin container {
2 | &__container {
3 | width: 1180px;
4 | margin: 0 auto;
5 | }
6 | }
7 |
8 | @mixin link-unstyled {
9 | &, &:active, &:visited {
10 | color: inherit;
11 | text-decoration: none;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | gen:
2 | protoc -I test_server/pb --go_out=plugins=grpc:test_server/pb test_server/pb/example.proto
3 | gen-fixtures:
4 | protoc -I reflection/fixtures/simple --go_out=plugins=grpc:reflection/fixtures/simple reflection/fixtures/simple/simple.proto
5 | build:
6 | npm install
7 | webpack
8 | go generate ./...
9 |
--------------------------------------------------------------------------------
/glide.yaml:
--------------------------------------------------------------------------------
1 | package: github.com/komly/grpc-ui
2 | import:
3 | - package: github.com/golang/protobuf
4 | subpackages:
5 | - jsonpb
6 | - proto
7 | - protoc-gen-go/descriptor
8 | - package: golang.org/x/net
9 | subpackages:
10 | - context
11 | - package: google.golang.org/grpc
12 | subpackages:
13 | - reflection/grpc_reflection_v1alpha
--------------------------------------------------------------------------------
/src/components/Error.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import injectSheet from 'react-jss';
3 |
4 | const styles = {
5 | error: {
6 | background: '#e6736d',
7 | color: '#fff',
8 | padding: '20px',
9 | }
10 | };
11 |
12 |
13 | const Error = (props) =>
14 |
15 | {props.error}
16 |
;
17 |
18 | export default injectSheet(styles)(Error);
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:17.10
2 |
3 | WORKDIR /root
4 | ENV GOPATH=/root
5 |
6 | RUN apt-get update && apt-get install -y golang-go golang-glide
7 |
8 | ADD reflection proto fixtures src/github.com/komly/grpc-ui/reflection
9 | ADD static src/github.com/komly/grpc-ui/static
10 | ADD main.go glide.yaml glide.lock src/github.com/komly/grpc-ui/
11 |
12 | RUN cd src/github.com/komly/grpc-ui && glide install
13 | RUN go install github.com/komly/grpc-ui
14 |
15 | CMD /root/bin/grpc-ui
--------------------------------------------------------------------------------
/src/components/Sidebar.scss:
--------------------------------------------------------------------------------
1 | @import "mixins.scss";
2 | @import "vars.scss";
3 |
4 | .sidebar {
5 | padding-top: 30px;
6 | width: 30%;
7 | float: left;
8 |
9 | &__link {
10 | @include link-unstyled;
11 |
12 | &:hover {
13 | color: $primary;
14 | }
15 | }
16 |
17 | &__packages-list {
18 | list-style: none;
19 | margin: 0;
20 | padding: 0;
21 | }
22 |
23 | &__services-list {
24 | margin: 0;
25 | }
26 |
27 | &__methods-list {
28 | margin: 0;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/proto/decode_bytes.go:
--------------------------------------------------------------------------------
1 | /*
2 | Decoders for byte types
3 | */
4 |
5 | package proto
6 |
7 | import (
8 | "encoding/base64"
9 | )
10 |
11 | func decodeBytes(buf []byte) (x interface{}, i int, err error) {
12 | // Encode raw bytes as base64 string
13 | var v []byte
14 | v, i = DecodeBytes(buf)
15 | x = base64.StdEncoding.EncodeToString([]byte(v))
16 | return
17 | }
18 |
19 | func decodeString(buf []byte) (x interface{}, i int, err error) {
20 | var v []byte
21 | v, i = DecodeBytes(buf)
22 | x = string(v)
23 | return
24 | }
25 |
--------------------------------------------------------------------------------
/static/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 | grpc-ui
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | //go:generate esc -o http_server/esc.go -pkg=http_server static
4 | import (
5 | "flag"
6 | "fmt"
7 | "log"
8 | "os"
9 |
10 | "github.com/komly/grpc-ui/http_server"
11 | )
12 |
13 | var (
14 | httpAddr string
15 | // devMode for developping (use local FS instead of memFS in this mode)
16 | devMode bool
17 | )
18 |
19 | func main() {
20 | flag.StringVar(&httpAddr, "http", ":8080", "http server listening addr")
21 | flag.BoolVar(&devMode, "dev_mode", false, "developping mode")
22 | flag.Parse()
23 |
24 | srv := http_server.New(httpAddr, devMode)
25 | fmt.Printf("grpc-ui started at %s\ndev_mode=%t\n", httpAddr, devMode)
26 | if err := srv.Start(); err != nil {
27 | log.Printf("http server error: %v", err)
28 | os.Exit(1)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/proto/message.go:
--------------------------------------------------------------------------------
1 | package proto
2 |
3 | import (
4 | "fmt"
5 | "github.com/komly/grpc-ui/reflection"
6 | )
7 |
8 | // Dynamic proto Message
9 |
10 | type FieldValue struct{
11 | Number int `json:"number"`
12 | Value interface{} `json:"val"`
13 | }
14 |
15 | type Message struct {
16 | TypeInfo map[string]*reflection.TypeInfo
17 | TypeName string
18 | Data []FieldValue
19 | PB map[string]interface{}
20 | }
21 |
22 | // proto.Message interface
23 |
24 | func (m *Message) Reset() {}
25 |
26 | func (m *Message) String() string {
27 | return "TODO"
28 | }
29 |
30 | func (m *Message) ProtoMessage() {}
31 |
32 | // Marshaler and Unarshaler interfaces
33 |
34 | func (m *Message) Marshal() ([]byte, error) {
35 | return Encode(m.TypeInfo, m.TypeName, m.Data)
36 | }
37 |
38 | func (m *Message) Unmarshal(buf []byte) error {
39 | res, err := Decode(m.TypeInfo, m.TypeName, buf, nil)
40 | _res, ok := res.(map[string]interface{})
41 | if !ok {
42 | err = fmt.Errorf("Invalid unmarshaled message, err: %v", err)
43 | }
44 | m.PB = _res
45 | return err
46 | }
47 |
--------------------------------------------------------------------------------
/src/components/Sidebar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import './Sidebar.scss';
3 |
4 | export default (props) => {
5 | return (
6 |
7 |
8 | {Object.keys(props.packages).map(p =>
9 | -
10 | {p}
11 |
12 | {props.packages[p].map((s) => (
13 | -
14 | {s.name}
15 |
16 | {s.methods.map((m) =>
17 | - {m.name}
18 | )}
19 |
20 |
21 | ))}
22 |
23 |
24 | )}
25 |
26 |
27 | )
28 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | entry: './src/index.js',
5 | devtool: 'inline-source-map',
6 | output: {
7 | path: path.resolve(__dirname) + "/static",
8 | filename: "bundle.js"
9 | },
10 | module: {
11 | rules: [
12 | {
13 | test: /\.js$/,
14 | include: [
15 | path.resolve(__dirname + "/src"),
16 | ],
17 | loader: "babel-loader"
18 | },
19 | {
20 | test: /\.scss$/,
21 | use: [{
22 | loader: "style-loader" // creates style nodes from JS strings
23 | }, {
24 | loader: "css-loader" // translates CSS into CommonJS
25 | }, {
26 | loader: "sass-loader", // compiles Sass to CSS
27 | options: {
28 | includePaths: [
29 | path.resolve(__dirname + "/src/sass"),
30 | ]
31 | }
32 | }]
33 | }
34 | ],
35 | },
36 | }
--------------------------------------------------------------------------------
/fixtures/simple/simple.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package simple;
4 |
5 | service Simple {
6 | rpc Test(Req) returns (Res);
7 | }
8 |
9 | message Req {
10 | int32 int32field = 1;
11 | int64 int64field = 2;
12 | float floatfield = 3;
13 | double doublefield = 4;
14 | uint32 uint32field = 5;
15 | uint64 uint64field = 6;
16 | sint32 sint32field = 7;
17 | sint64 sint64field = 8;
18 | fixed32 fixed32field = 9;
19 | fixed64 fixed64field = 10;
20 | sfixed32 sfixed32field = 11;
21 | sfixed64 sfixed64field = 12;
22 | bool boolfield = 13;
23 | string stringfield = 14;
24 | bytes bytesfield = 15;
25 | repeated int32 int32Repeated = 16;
26 |
27 | };
28 |
29 | message Res {
30 | int32 int32field = 1;
31 | int64 int64field = 2;
32 | float floatfield = 3;
33 | double doublefield = 4;
34 | uint32 uint32field = 5;
35 | uint64 uint64field = 6;
36 | sint32 sint32field = 7;
37 | sint64 sint64field = 8;
38 | fixed32 fixed32field = 9;
39 | fixed64 fixed64field = 10;
40 | sfixed32 sfixed32field = 11;
41 | sfixed64 sfixed64field = 12;
42 | bool boolfield = 13;
43 | string stringfield = 14;
44 | bytes bytesfield = 15;
45 | repeated int32 int32Repeated = 16;
46 | };
--------------------------------------------------------------------------------
/proto/call_test.go:
--------------------------------------------------------------------------------
1 | package proto
2 |
3 | import (
4 | "log"
5 | "net"
6 | "testing"
7 | "time"
8 |
9 | "github.com/komly/grpc-ui/fixtures/simple"
10 | "golang.org/x/net/context"
11 | "google.golang.org/grpc"
12 | grpcr "google.golang.org/grpc/reflection"
13 | )
14 |
15 | type stub struct {
16 | }
17 |
18 | func (s *stub) Test(ctx context.Context, req *simple.Req) (*simple.Res, error) {
19 | return &simple.Res{
20 | Int32Field: req.Int32Field,
21 | }, nil
22 | }
23 |
24 | func TestSimpleTypes(t *testing.T) {
25 | t.SkipNow()
26 | ln, err := net.Listen("tcp", "127.0.0.1:0")
27 | if err != nil {
28 | t.Fatal(err)
29 | }
30 |
31 | defer ln.Close()
32 |
33 | s := grpc.NewServer()
34 | simple.RegisterSimpleServer(s, &stub{})
35 | grpcr.Register(s)
36 |
37 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
38 | defer cancel()
39 |
40 | go func() {
41 | if err := s.Serve(ln); err != nil {
42 | t.Fatal(err)
43 | }
44 | defer s.Stop()
45 |
46 | <-ctx.Done()
47 | }()
48 |
49 | resp, err := Invoke(ctx, ln.Addr().String(), "simple", "Simple", "Test", []FieldValue{
50 | FieldValue{1, "1"},
51 | })
52 | if err != nil {
53 | t.Fatalf("Invoke err: %v", err)
54 | }
55 |
56 | log.Printf("Resp: %v", resp)
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "grpc-ui",
3 | "version": "1.0.0",
4 | "description": "A gRPC Web Interface",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/komly/grpc-ui.git"
12 | },
13 | "keywords": [],
14 | "author": "",
15 | "license": "ISC",
16 | "bugs": {
17 | "url": "https://github.com/komly/grpc-ui/issues"
18 | },
19 | "homepage": "https://github.com/komly/grpc-ui#readme",
20 | "devDependencies": {
21 | "awesome-typescript-loader": "^3.3.0",
22 | "babel-core": "^6.26.0",
23 | "babel-loader": "^7.1.2",
24 | "babel-preset-es2015": "^6.24.1",
25 | "babel-preset-react": "^6.24.1",
26 | "babel-preset-stage-0": "^6.24.1",
27 | "css-loader": "^0.28.7",
28 | "node-sass": "^4.8.3",
29 | "sass-loader": "^6.0.6",
30 | "style-loader": "^0.19.0",
31 | "webpack": "^3.8.1"
32 | },
33 | "dependencies": {
34 | "axios": "^0.17.0",
35 | "qs": "^6.5.1",
36 | "react": "^16.0.0",
37 | "react-dom": "^16.0.0",
38 | "react-json-tree": "^0.11.0",
39 | "react-jss": "^8.1.0",
40 | "react-redux": "^5.0.6",
41 | "redux": "^3.7.2",
42 | "redux-thunk": "^2.2.0"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/components/Loader.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import injectSheet from 'react-jss';
3 |
4 | const styles = {
5 | loader: {
6 | 'height': '400px',
7 | 'position': 'relative',
8 | },
9 | title: {
10 | 'font-weight': 'bold',
11 | 'font-size': '32px',
12 | 'position': 'absolute',
13 | 'top': '50%',
14 | 'left': '50%',
15 | 'transform': 'translate(-50%, -50%)'
16 | },
17 | };
18 |
19 |
20 | class Loader extends Component {
21 | constructor(props) {
22 | super(props);
23 |
24 | this.state = {
25 | points: 1,
26 | timer: null,
27 | };
28 | }
29 | componentDidMount() {
30 | this.setState({
31 | timer: setInterval(() => {
32 | this.setState({
33 | points: ((this.state.points + 1) % 3),
34 | });
35 | }, 500),
36 | })
37 | }
38 | componentWillUnmount() {
39 | clearInterval(this.state.timer)
40 | }
41 | render() {
42 | return (
43 |
44 |
Loading{Array(this.state.points + 1).fill(0).map(_ => '.')}
45 |
46 | );
47 | }
48 | }
49 |
50 | export default Loader = injectSheet(styles)(Loader);
--------------------------------------------------------------------------------
/proto/proto.go:
--------------------------------------------------------------------------------
1 | package proto
2 |
3 | import (
4 | "github.com/golang/protobuf/proto"
5 | "github.com/golang/protobuf/protoc-gen-go/descriptor"
6 | )
7 |
8 | func FieldTypeToWireType(typeId descriptor.FieldDescriptorProto_Type) (wireType int) {
9 | switch typeId {
10 |
11 | case descriptor.FieldDescriptorProto_TYPE_FLOAT:
12 | wireType = proto.WireFixed32
13 |
14 | case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
15 | wireType = proto.WireFixed64
16 |
17 | case descriptor.FieldDescriptorProto_TYPE_FIXED32,
18 | descriptor.FieldDescriptorProto_TYPE_SFIXED32:
19 | wireType = proto.WireFixed32
20 |
21 | case descriptor.FieldDescriptorProto_TYPE_FIXED64,
22 | descriptor.FieldDescriptorProto_TYPE_SFIXED64:
23 | wireType = proto.WireFixed64
24 |
25 | case descriptor.FieldDescriptorProto_TYPE_BOOL,
26 | descriptor.FieldDescriptorProto_TYPE_INT32,
27 | descriptor.FieldDescriptorProto_TYPE_INT64,
28 | descriptor.FieldDescriptorProto_TYPE_SINT32,
29 | descriptor.FieldDescriptorProto_TYPE_SINT64,
30 | descriptor.FieldDescriptorProto_TYPE_UINT32,
31 | descriptor.FieldDescriptorProto_TYPE_UINT64,
32 | descriptor.FieldDescriptorProto_TYPE_ENUM:
33 | wireType = proto.WireVarint
34 |
35 | case descriptor.FieldDescriptorProto_TYPE_BYTES,
36 | descriptor.FieldDescriptorProto_TYPE_STRING,
37 | descriptor.FieldDescriptorProto_TYPE_MESSAGE:
38 | wireType = proto.WireBytes
39 |
40 | }
41 |
42 | return
43 | }
44 |
--------------------------------------------------------------------------------
/glide.lock:
--------------------------------------------------------------------------------
1 | hash: 5e3d9ce93ad910088097f4874f4a16778b26d4e145cd20abaa7d480649c058a3
2 | updated: 2017-10-31T13:36:44.52059392+03:00
3 | imports:
4 | - name: github.com/golang/protobuf
5 | version: 130e6b02ab059e7b717a096f397c5b60111cae74
6 | subpackages:
7 | - jsonpb
8 | - proto
9 | - protoc-gen-go/descriptor
10 | - ptypes/any
11 | - name: github.com/gorilla/websocket
12 | version: 3ab3a8b8831546bd18fd182c20687ca853b2bb13
13 | - name: golang.org/x/net
14 | version: c8c74377599bd978aee1cf3b9b63a8634051cec2
15 | subpackages:
16 | - context
17 | - http2
18 | - http2/hpack
19 | - idna
20 | - internal/timeseries
21 | - lex/httplex
22 | - trace
23 | - name: golang.org/x/text
24 | version: 6eab0e8f74e86c598ec3b6fad4888e0c11482d48
25 | subpackages:
26 | - secure/bidirule
27 | - transform
28 | - unicode/bidi
29 | - unicode/norm
30 | - name: google.golang.org/genproto
31 | version: f676e0f3ac6395ff1a529ae59a6670878a8371a6
32 | subpackages:
33 | - googleapis/rpc/status
34 | - name: google.golang.org/grpc
35 | version: b3ddf786825de56a4178401b7e174ee332173b66
36 | subpackages:
37 | - codes
38 | - connectivity
39 | - credentials
40 | - grpclb/grpc_lb_v1
41 | - grpclog
42 | - internal
43 | - keepalive
44 | - metadata
45 | - naming
46 | - peer
47 | - reflection
48 | - reflection/grpc_reflection_v1alpha
49 | - stats
50 | - status
51 | - tap
52 | - transport
53 | testImports: []
54 |
--------------------------------------------------------------------------------
/src/components/Response.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import injectSheet from 'react-jss';
3 | import {getTypeName, TYPE_MESSAGE} from './types';
4 |
5 |
6 | const styles = {
7 | response: {
8 | 'padding': '20px',
9 | },
10 | title: {
11 | 'font-weight': 'body',
12 | 'font-size': '20px',
13 | 'margin': '0',
14 | 'padding': '0',
15 | 'padding-bottom': '20px',
16 | }
17 | };
18 |
19 | const Response = (props) => {
20 | const type = props.types[props.type_name];
21 |
22 | return type ?
23 |
24 |
{props.type_name}
25 |
26 |
27 | {type.fields.map(f =>
28 |
29 | |
30 |
31 | |
32 |
33 | {f.type_id === TYPE_MESSAGE ? f.type_name : getTypeName(f.type_id)} {f.is_repeated ? '(+)': ''}
34 | |
35 |
36 | )}
37 |
38 |
:
39 | Unknown type: {props.type_name}
40 | }
41 |
42 |
43 | export default injectSheet(styles)(Response);
--------------------------------------------------------------------------------
/proto/call.go:
--------------------------------------------------------------------------------
1 | package proto
2 |
3 | import (
4 | "context"
5 | "fmt"
6 |
7 | "github.com/komly/grpc-ui/reflection"
8 | "google.golang.org/grpc"
9 | )
10 |
11 | func Invoke(ctx context.Context, addr string, packageName, serviceName, methodName string, data []FieldValue) (interface{}, error) {
12 | info, err := reflection.GetInfo(ctx, addr)
13 | if err != nil {
14 | return nil, err
15 | }
16 |
17 | inType, outType, err := findInType(info, packageName, serviceName, methodName)
18 | if err != nil {
19 | return nil, err
20 | }
21 | in := &Message{
22 | TypeInfo: info.Types,
23 | TypeName: inType,
24 | Data: data,
25 | }
26 |
27 | out := &Message{
28 | TypeInfo: info.Types,
29 | TypeName: outType,
30 | }
31 |
32 | conn, err := grpc.DialContext(ctx, addr, grpc.WithInsecure())
33 | if err != nil {
34 | return nil, err
35 | }
36 |
37 | var methodFqdn string
38 | if packageName == "" {
39 | methodFqdn = fmt.Sprintf("/%s/%s", serviceName, methodName)
40 | } else {
41 | methodFqdn = fmt.Sprintf("/%s.%s/%s", packageName, serviceName, methodName)
42 | }
43 |
44 | if err := grpc.Invoke(ctx, methodFqdn, in, out, conn); err != nil {
45 | return nil, err
46 | }
47 |
48 | return out.PB, nil
49 | }
50 |
51 | func findInType(info *reflection.InfoResp, packageName, serviceName, methodName string) (string, string, error) {
52 | for _, s := range info.Packages[packageName] {
53 | if s.Name == serviceName {
54 | for _, m := range s.Methods {
55 | if m.Name == methodName {
56 | return m.In, m.Out, nil
57 | }
58 | }
59 | }
60 | }
61 | return "", "", fmt.Errorf("no such method: %v", methodName)
62 | }
63 |
--------------------------------------------------------------------------------
/test_server/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/komly/grpc-ui/test_server/pb"
5 | "golang.org/x/net/context"
6 | "google.golang.org/grpc"
7 | "google.golang.org/grpc/reflection"
8 | "net"
9 | "strings"
10 | )
11 |
12 | type impl struct {
13 | pb.ExampleServer
14 | }
15 |
16 | func (i *impl) Test(ctx context.Context, req *pb.Req) (*pb.Res, error) {
17 | return &pb.Res{
18 | Int32Field: req.Int32Field,
19 | Int64Field: req.Int64Field,
20 | Floatfield: req.Floatfield,
21 | Doublefield: req.Doublefield,
22 | Uint32Field: req.Uint32Field,
23 | Uint64Field: req.Uint64Field,
24 | Sint32Field: req.Sint32Field,
25 | Sint64Field: req.Sint64Field,
26 | Fixed32Field: req.Fixed32Field,
27 | Fixed64Field: req.Fixed64Field,
28 | Sfixed32Field: req.Sfixed32Field,
29 | Sfixed64Field: req.Sfixed64Field,
30 | Boolfield: req.Boolfield,
31 | Stringfield: req.Stringfield,
32 | Bytesfield: req.Bytesfield,
33 | }, nil
34 | }
35 |
36 | func (i *impl) GetUser(ctx context.Context, req *pb.GetUserReq) (*pb.UserResp, error) {
37 | return &pb.UserResp{
38 | FirstName: req.FirstName + "[server]",
39 | LastName: req.LastName + " [server]",
40 | Active: len(req.FirstName) > 3,
41 | Age: req.Age,
42 | Skills: strings.Join(req.Skills, ", "),
43 | }, nil
44 | }
45 |
46 | func start() error {
47 | ln, err := net.Listen("tcp", ":3001")
48 | if err != nil {
49 | return err
50 | }
51 | s := grpc.NewServer()
52 | pb.RegisterExampleServer(s, &impl{})
53 |
54 | reflection.Register(s)
55 |
56 | return s.Serve(ln)
57 | }
58 |
59 | func main() {
60 | if err := start(); err != nil {
61 | panic(err)
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/proto/encode_message.go:
--------------------------------------------------------------------------------
1 | /*
2 | Encoders for map types
3 | */
4 |
5 | package proto
6 |
7 | import (
8 | )
9 | //
10 | //func encodeMap(value interface{}, n int, wt int, typeName string, typeInfo map[string]*reflection.TypeInfo, fieldPath []int) (resultBuf []byte, err error) {
11 | //
12 | // rv := reflect.ValueOf(value)
13 | // for _, k := range rv.MapKeys() {
14 | // v := rv.MapIndex(k)
15 | //
16 | // _value := map[string]interface{}{
17 | // "key": k.Interface(),
18 | // "value": v.Interface(),
19 | // }
20 | //
21 | // var msgBuf []byte
22 | // msgBuf, err = Encode(typeInfo, typeName, _value, append(fieldPath, n))
23 | // if err != nil {
24 | // return
25 | // }
26 | //
27 | // resultBuf = append(resultBuf, EncodeTag(n, wt)...)
28 | // resultBuf = append(resultBuf, EncodeBytes(msgBuf)...)
29 | // }
30 | //
31 | // return
32 | //}
33 | //
34 | //func encodeMessage(value interface{}, n int, wt int, typeInfo map[string]*reflection.TypeInfo, typeName string, fieldPath []int, repeated bool) (resultBuf []byte, err error) {
35 | //
36 | // if repeated {
37 | //
38 | // _value, ok := value.([]interface{})
39 | // if !ok {
40 | // err = fmt.Errorf("encodeMessage: Conversion error %#v to []interface{}", value)
41 | // return
42 | // }
43 | //
44 | // for _, v := range _value {
45 | // var msgBuf []byte
46 | // msgBuf, err = encodeMessage(v, n, wt, typeInfo, typeName, fieldPath, false)
47 | // resultBuf = append(resultBuf, msgBuf...)
48 | // }
49 | //
50 | // } else {
51 | //
52 | // _value, ok := value.(map[string]interface{})
53 | // if !ok {
54 | // err = fmt.Errorf("encodeMessage: Conversion error %#v to map[string]interface{}", value)
55 | // return
56 | // }
57 | //
58 | // var msgBuf []byte
59 | // msgBuf, err = Encode(typeInfo, typeName, _value, append(fieldPath, n))
60 | // if err != nil {
61 | // return
62 | // }
63 | //
64 | // resultBuf = append(resultBuf, EncodeTag(n, wt)...)
65 | // resultBuf = append(resultBuf, EncodeBytes(msgBuf)...)
66 | // }
67 | //
68 | // return
69 | //}
70 |
--------------------------------------------------------------------------------
/proto/decode_message.go:
--------------------------------------------------------------------------------
1 | /*
2 | Decoders for map types
3 | */
4 |
5 | package proto
6 |
7 | import (
8 | "fmt"
9 | "reflect"
10 |
11 | "github.com/komly/grpc-ui/reflection"
12 | )
13 |
14 | func decodeMessage(buf []byte, n int, typeName string, typeInfo map[string]*reflection.TypeInfo, fieldPath []int) (x interface{}, i int, err error) {
15 | var msgBuf []byte
16 | msgBuf, i = DecodeBytes(buf)
17 | x, err = Decode(typeInfo, typeName, msgBuf, append(fieldPath, n))
18 | return
19 | }
20 |
21 | func appendValue(result *map[string]interface{}, key string, value interface{}, mapField bool) (err error) {
22 |
23 | msgValue := (*result)[key]
24 |
25 | if mapField {
26 |
27 | _value, ok := value.(map[string]interface{})
28 | if !ok {
29 | err = fmt.Errorf("Conversion error %#v to map[string]interface{}", value)
30 | return
31 | }
32 |
33 | var _msgValue map[string]interface{}
34 |
35 | if msgValue != nil {
36 | var ok bool
37 | _msgValue, ok = msgValue.(map[string]interface{})
38 | if !ok {
39 | err = fmt.Errorf("Conversion error %#v to map[string]interface{}", msgValue)
40 | return
41 | }
42 | } else {
43 | _msgValue = make(map[string]interface{})
44 | }
45 |
46 | var _key string
47 | if kind := reflect.TypeOf(_value["key"]).Kind(); kind >= reflect.Int && kind <= reflect.Float64 {
48 | _key = fmt.Sprintf("%d", _value["key"])
49 | } else {
50 | var ok bool
51 | _key, ok = _value["key"].(string)
52 | if !ok {
53 | err = fmt.Errorf("Conversion error %#v to string", _value["key"])
54 | return
55 | }
56 | }
57 |
58 | _msgValue[_key] = _value["value"]
59 |
60 | (*result)[key] = _msgValue
61 |
62 | } else {
63 |
64 | var _msgValue []interface{}
65 |
66 | if msgValue != nil {
67 | var ok bool
68 | _msgValue, ok = msgValue.([]interface{})
69 | if !ok {
70 | err = fmt.Errorf("Conversion error %#v to []map[string]interface{}", value)
71 | return
72 | }
73 | } else {
74 | _msgValue = make([]interface{}, 0)
75 | }
76 |
77 | _msgValue = append(_msgValue, value)
78 |
79 | (*result)[key] = _msgValue
80 |
81 | }
82 |
83 | return
84 | }
85 |
--------------------------------------------------------------------------------
/src/components/Request.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import {Message} from './fields';
3 | import {getDefaultValue} from './types';
4 |
5 | function fieldsToVal(fields, val, types) {
6 | return fields.map((f, i) => {
7 | let exportedVal = val[i];
8 | switch (f.type_id) {
9 | case 11:
10 | const type = types[f.type_name];
11 | exportedVal = fieldsToVal(type.fields, val[i], types);
12 | }
13 | return {
14 | number: f.number,
15 | val: exportedVal,
16 | }
17 | })
18 | }
19 |
20 | export default class Request extends Component {
21 | constructor(props) {
22 | super(props);
23 |
24 | const type = props.types[props.type_name];
25 |
26 | this.state = !type ? {} : {
27 | val: type.fields.map((f) => getDefaultValue(f.type_id, f.is_repeated, f.type_name, props.enums, props.types)),
28 | };
29 | }
30 |
31 |
32 | handleInvokeMethod(e) {
33 | e.preventDefault();
34 | const type = this.props.types[this.props.type_name];
35 |
36 | this.props.onInvokeMethod(fieldsToVal(type.fields, this.state.val, this.props.types));
37 | }
38 |
39 | handleChange(val) {
40 | console.log(val);
41 | this.setState({
42 | val,
43 | });
44 | }
45 |
46 | render() {
47 | const type = this.props.types[this.props.type_name];
48 | return type ?
49 |
50 |
{this.props.type_name}
51 |
59 |
60 | : Unknown type: {this.props.type_name}
;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/test_server/pb/example.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package pb;
4 |
5 | service Example {
6 | //rpc Test(Req) returns (Res);
7 | rpc GetUser(GetUserReq) returns (UserResp);
8 | rpc CreateUser(CreateUserReq) returns (CreateUserResp);
9 | rpc UserList(UserListReq) returns (UserListResp);
10 | rpc DeleteUser(DeleteUserReq) returns (DeleteUserResp);
11 | }
12 |
13 | message CreateUserReq {
14 |
15 | };
16 |
17 | message CreateUserResp {
18 |
19 | };
20 |
21 | message UserListReq {
22 |
23 | };
24 |
25 | message UserListResp {
26 |
27 | };
28 |
29 | message DeleteUserReq {
30 |
31 | };
32 |
33 | message DeleteUserResp {
34 |
35 | };
36 |
37 | message Inner {
38 | int32 a = 1;
39 | string b = 2;
40 | };
41 |
42 | message GetUserReq {
43 | string firstName = 1;
44 | string lastName = 2;
45 | repeated string skills = 3;
46 | repeated int32 ids = 4;
47 | int32 age = 5;
48 | Inner in = 6;
49 | }
50 |
51 | message UserResp {
52 | string firstName = 1;
53 | string lastName = 2;
54 | bool active = 3;
55 | int32 age = 4;
56 | string skills = 5;
57 | }
58 |
59 | message Req {
60 | int32 int32field = 1;
61 | int64 int64field = 2;
62 | float floatfield = 3;
63 | double doublefield = 4;
64 | uint32 uint32field = 5;
65 | uint64 uint64field = 6;
66 | sint32 sint32field = 7;
67 | sint64 sint64field = 8;
68 | fixed32 fixed32field = 9;
69 | fixed64 fixed64field = 10;
70 | sfixed32 sfixed32field = 11;
71 | sfixed64 sfixed64field = 12;
72 | bool boolfield = 13;
73 | string stringfield = 14;
74 | bytes bytesfield = 15;
75 | repeated int32 int32Repeated = 16;
76 |
77 | };
78 |
79 | message Res {
80 | int32 int32field = 1;
81 | int64 int64field = 2;
82 | float floatfield = 3;
83 | double doublefield = 4;
84 | uint32 uint32field = 5;
85 | uint64 uint64field = 6;
86 | sint32 sint32field = 7;
87 | sint64 sint64field = 8;
88 | fixed32 fixed32field = 9;
89 | fixed64 fixed64field = 10;
90 | sfixed32 sfixed32field = 11;
91 | sfixed64 sfixed64field = 12;
92 | bool boolfield = 13;
93 | string stringfield = 14;
94 | bytes bytesfield = 15;
95 | repeated int32 int32Repeated = 16;
96 | };
--------------------------------------------------------------------------------
/src/components/Method.scss:
--------------------------------------------------------------------------------
1 | @import "vars.scss";
2 |
3 | .method {
4 | border: 1px solid #eee;
5 | margin-bottom: 20px;
6 | transition: all 200ms ease-in-out;
7 |
8 | &__heading {
9 | cursor: pointer;
10 | padding: 15px;
11 | background: $primary;
12 | color: #fff;
13 | font: {
14 | wight: bold;
15 | size: 20px;
16 | };
17 | }
18 |
19 | &__name {
20 | margin: 0;
21 | }
22 |
23 | &--loading {
24 | .method__body {
25 | position: relative;
26 |
27 | &:after {
28 | background: rgba(white, 0.8);
29 | content: "";
30 | display: block;
31 | position: absolute;
32 | top: 0;
33 | left: 0;
34 | right: 0;
35 | bottom: 0;
36 | }
37 | }
38 | }
39 |
40 | &__result {
41 | padding: 20px;
42 | background: $success;
43 | }
44 |
45 | &__error {
46 | padding: 20px;
47 | background: $danger;
48 | }
49 | }
50 |
51 | .form {
52 | padding: 20px 20px 40px 20px;
53 |
54 | &__controls {
55 | padding-top: 10px;
56 | text-align: right;
57 | }
58 |
59 | &__title {
60 | font: {
61 | weight: bold;
62 | size: 20px;
63 | };
64 | margin: 0;
65 | padding: 0;
66 | padding-bottom: 10px;
67 | }
68 | }
69 |
70 | .message {
71 | border-collapse: collapse;
72 | width: 100%;
73 |
74 | &--in {
75 | border-bottom: 1px solid #eee;
76 | }
77 |
78 | &__cell {
79 | padding: 10px;
80 | border: 1px solid #eee;
81 |
82 | &--first {
83 | width: 100px;
84 | }
85 |
86 | &--last {
87 | text-align: right;
88 | width: 100px;
89 | }
90 | }
91 | }
92 |
93 | .button {
94 | padding: 10px;
95 | background: none;
96 | outline: none;
97 | border-radius: 10px;
98 | cursor: pointer;
99 | border: 2px solid $primary;
100 | font: {
101 | family: Roboto, sans-serif;
102 | weight: bold;
103 | size: 14px;
104 | };
105 | transition: all 150ms ease-in-out;
106 |
107 | &--small {
108 | margin-right: 5px;
109 | padding: 6px 10px;
110 | font: {
111 | size: 14px;
112 | };
113 | }
114 |
115 | &:hover {
116 | background: $primary;
117 | border: 2px solid $primary-light;
118 | color: #fff;
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/proto/encode_bytes.go:
--------------------------------------------------------------------------------
1 | /*
2 | Encoders for byte types
3 | */
4 |
5 | package proto
6 |
7 | import (
8 | "encoding/base64"
9 | "fmt"
10 | )
11 |
12 | func _interfaceStringArrayToStringArray(value interface{}) (res []string, err error) {
13 | _value, ok := value.([]interface{})
14 | if !ok {
15 | err = fmt.Errorf("Conversion error (%T) %#v to []interface{}", value, value)
16 | return
17 | }
18 | res = make([]string, len(_value))
19 | for i, v := range _value {
20 | vv, ok := v.(string)
21 | if !ok {
22 | err = fmt.Errorf("Conversion error (%T) %#v to string", v, v)
23 | return
24 | }
25 | res[i] = vv
26 | }
27 | return
28 | }
29 |
30 | func encodeBytes(value interface{}, n int, wt int, repeated bool) (resultBuf []byte, err error) {
31 | // Decode base64 to raw bytes
32 | if repeated {
33 | var _value []string
34 | _value, err = _interfaceStringArrayToStringArray(value)
35 | if err != nil {
36 | return
37 | }
38 | var vv []byte
39 | for _, v := range _value {
40 | vv, err = base64.StdEncoding.DecodeString(v)
41 | if err != nil {
42 | return
43 | }
44 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
45 | resultBuf = append(resultBuf, EncodeBytes(vv)...)
46 | }
47 | } else {
48 | _value, ok := value.(string)
49 | if !ok {
50 | err = fmt.Errorf("encodeBytes: Conversion error %#v to string", value)
51 | return
52 | }
53 | var vv []byte
54 | vv, err = base64.StdEncoding.DecodeString(_value)
55 | if err != nil {
56 | return
57 | }
58 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
59 | resultBuf = append(resultBuf, EncodeBytes(vv)...)
60 | }
61 | return
62 | }
63 |
64 | func encodeString(value interface{}, n int, wt int, repeated bool) (resultBuf []byte, err error) {
65 | if repeated {
66 | var _value []string
67 | _value, err = _interfaceStringArrayToStringArray(value)
68 | if err != nil {
69 | return
70 | }
71 | for _, v := range _value {
72 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
73 | resultBuf = append(resultBuf, EncodeBytes([]byte(v))...)
74 | }
75 | } else {
76 | _value, ok := value.(string)
77 | if !ok {
78 | err = fmt.Errorf("encodeString: Conversion error %#v to string", value)
79 | return
80 | }
81 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
82 | resultBuf = append(resultBuf, EncodeBytes([]byte(_value))...)
83 | }
84 | return
85 | }
86 |
--------------------------------------------------------------------------------
/src/components/app.scss:
--------------------------------------------------------------------------------
1 | @import "mixins.scss";
2 | @import "vars.scss";
3 |
4 | @mixin font-stack {
5 | font-family: "Roboto", sans-serif;
6 | }
7 |
8 | html, body {
9 | margin: 0;
10 | padding: 0;
11 |
12 | @include font-stack;
13 | }
14 |
15 | @mixin placeholder {
16 | &::placeholder {
17 | @content;
18 | }
19 | &::-webkit-input-placeholder {
20 | @content;
21 | }
22 | &::-moz-placeholder {
23 | @content;
24 | }
25 | &::-ms-input-placeholder {
26 | @content;
27 | }
28 | &::-moz-placeholder {
29 | @content;
30 | }
31 | }
32 |
33 | @mixin clearfix {
34 | &:after {
35 | content: "";
36 | display: table;
37 | clear: both;
38 | }
39 | }
40 |
41 | .navbar {
42 | padding: 20px;
43 | border-bottom: 1px solid #eee;
44 |
45 | @include container;
46 |
47 | &__container {
48 | @include clearfix;
49 | }
50 |
51 | &__logo {
52 | float: left;
53 | }
54 |
55 | &__host-form {
56 | float: right;
57 | }
58 | }
59 |
60 | .logo {
61 | display: inline-block;
62 | width: 80px;
63 | height: 28px;
64 | background-image: url("/static/img/grpc.png");
65 | }
66 |
67 | .host-form {
68 | display: inline-block;
69 |
70 | &__input {
71 | padding: 10px;
72 | width: 200px;
73 | margin-right: 5px;
74 | font-size: 14px;
75 | @include placeholder {
76 | @include font-stack;
77 | font-size: 14px;
78 | }
79 | }
80 | }
81 |
82 |
83 | .app {
84 | @include container;
85 |
86 | &__container {
87 | padding-top: 20px;
88 | }
89 |
90 | &__sidebar {
91 | width: 30%;
92 | float: left;
93 | }
94 |
95 | &__packages-list {
96 | width: 70%;
97 | float: left;
98 | }
99 | }
100 |
101 | .field {
102 | border-bottom: 1px solid #eee;
103 | padding-bottom: 20px;
104 | margin-bottom: 10px;
105 |
106 | &__label {
107 | padding: 10px 0;
108 | display: block;
109 | }
110 |
111 | &__input {
112 | font-size: 14px;
113 | box-sizing: border-box;
114 | padding: 10px;
115 | margin-bottom: 10px;
116 |
117 | &--text {
118 | width: 100%;
119 | }
120 | }
121 |
122 | &__controls {
123 | text-align: right;
124 | }
125 |
126 | &__group {
127 | text-align: right;
128 | margin: 5px 0;
129 | }
130 | }
131 |
132 | .package {
133 | &__title {
134 | font: {
135 | size: 28px;
136 | weight: bold;
137 | };
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/components/types.js:
--------------------------------------------------------------------------------
1 |
2 | export const TYPE_DOUBLE = 1;
3 | export const TYPE_FLOAT = 2;
4 | export const TYPE_INT64 = 3;
5 | export const TYPE_UINT64 = 4;
6 | export const TYPE_INT32 = 5;
7 | export const TYPE_FIXED64 = 6;
8 | export const TYPE_FIXED32 = 7;
9 | export const TYPE_BOOL = 8;
10 | export const TYPE_STRING = 9;
11 | export const TYPE_GROUP = 10;
12 | export const TYPE_MESSAGE = 11;
13 | export const TYPE_BYTES = 12;
14 | export const TYPE_UINT32 = 13;
15 | export const TYPE_ENUM = 14;
16 | export const TYPE_SFIXED32 = 15;
17 | export const TYPE_SFIXED64 = 16;
18 | export const TYPE_SINT32 = 17;
19 | export const TYPE_SINT64 = 18;
20 |
21 | export const INT_TYPES = {}
22 |
23 | const ints = [
24 | TYPE_DOUBLE, TYPE_FLOAT, TYPE_INT64, TYPE_UINT64,
25 | TYPE_INT32, TYPE_FIXED64, TYPE_FIXED32, TYPE_UINT32,
26 | TYPE_SFIXED32, TYPE_SFIXED64, TYPE_SINT32, TYPE_SINT64
27 | ];
28 | for (let i = 0; i < ints.length; i++) {
29 | INT_TYPES[ints[i]] = i;
30 | }
31 |
32 | export const getTypeName = (type_id) => {
33 | switch (type_id) {
34 | case TYPE_DOUBLE: return "double";
35 | case TYPE_FLOAT: return "float";
36 | case TYPE_INT64: return "int64";
37 | case TYPE_UINT64: return "uint64";
38 | case TYPE_INT32: return "int32";
39 | case TYPE_FIXED64: return "fixed64";
40 | case TYPE_FIXED32: return "fixed32";
41 | case TYPE_BOOL: return "bool";
42 | case TYPE_STRING: return "string";
43 | case TYPE_GROUP: return "group";
44 | case TYPE_MESSAGE: return "message";
45 | case TYPE_BYTES: return "bytes";
46 | case TYPE_UINT32: return "uint32";
47 | case TYPE_ENUM: return "enum";
48 | case TYPE_SFIXED32: return "sfixed32";
49 | case TYPE_SFIXED64: return "sfixed64";
50 | case TYPE_SINT32: return "sint32";
51 | case TYPE_SINT64: return "sint64";
52 | default:
53 | return '???';
54 | }
55 | };
56 |
57 | export const getDefaultValue = (type_id, repeated, type_name, enums, types) => {
58 | if (repeated) {
59 | return [];
60 | }
61 |
62 | if (type_id in INT_TYPES) {
63 | return '0';
64 | }
65 | switch (type_id) {
66 | case TYPE_BOOL: //bool
67 | return 'false';
68 | case 11: //msg
69 | const type = types[type_name];
70 | if (!type) { //TODO: hack for unknown types
71 | return [];
72 | }
73 | return type.fields.map(f => getDefaultValue(f.type_id, f.is_repeated, f.type_name, enums, types));
74 | case 14:
75 | const e = enums[type_name].values;
76 | const keys = Object.keys(e);
77 | return keys[0];
78 | default:
79 | return '';
80 | }
81 | };
--------------------------------------------------------------------------------
/proto/reflect.go:
--------------------------------------------------------------------------------
1 | /*
2 | gRPC reflection from soa_manager helpers
3 | */
4 |
5 | package proto
6 |
7 | import (
8 | "context"
9 | "fmt"
10 | "github.com/komly/grpc-ui/reflection"
11 | "strings"
12 | "time"
13 | )
14 |
15 | func _treeSearch(typeInfo map[string]*reflection.TypeInfo, typeName string, fieldPath []int) (fields []*reflection.FieldInfo, err error) {
16 | fields = typeInfo[typeName].Fields
17 | for _, fieldNumber := range fieldPath {
18 |
19 | var found bool
20 |
21 | for _, fi := range fields {
22 | if fi.Number == fieldNumber {
23 | fields = typeInfo[fi.TypeName].Fields
24 | found = true
25 | break
26 | }
27 | }
28 |
29 | if !found {
30 | err = fmt.Errorf("Invalid field path: %v", fieldPath)
31 | return
32 | }
33 | }
34 |
35 | return
36 | }
37 |
38 | func findFieldInfoByName(typeInfo map[string]*reflection.TypeInfo, typeName, fieldName string, fieldPath []int) (fieldInfo *reflection.FieldInfo, err error) {
39 | var fields []*reflection.FieldInfo
40 | fields, err = _treeSearch(typeInfo, typeName, fieldPath)
41 | if err != nil {
42 | return
43 | }
44 |
45 | var found bool
46 | for _, fi := range fields {
47 | if fi.Name == fieldName {
48 | fieldInfo = fi
49 | found = true
50 | break
51 | }
52 | }
53 |
54 | if !found {
55 | err = fmt.Errorf("Invalid field name: %v", fieldName)
56 | return
57 | }
58 |
59 | return
60 | }
61 |
62 | func findFieldInfoByNumber(typeInfo map[string]*reflection.TypeInfo, typeName string, fieldNumber int, fieldPath []int) (fieldInfo *reflection.FieldInfo, err error) {
63 | var fields []*reflection.FieldInfo
64 | fields, err = _treeSearch(typeInfo, typeName, fieldPath)
65 | if err != nil {
66 | return
67 | }
68 |
69 | var found bool
70 | for _, fi := range fields {
71 | if fi.Number == fieldNumber {
72 | fieldInfo = fi
73 | found = true
74 | break
75 | }
76 | }
77 |
78 | if !found {
79 | err = fmt.Errorf("Invalid field number: %v", fieldNumber)
80 | return
81 | }
82 |
83 | return
84 | }
85 |
86 | func FetchMethodReflection(serverAddr string, methodPath string) (result *reflection.Method, err error) {
87 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
88 | defer cancel()
89 |
90 | services_list, err := reflection.GetInfo(ctx, serverAddr)
91 | if err != nil {
92 | return
93 | }
94 |
95 | _methodPath := strings.Split(methodPath, "/")
96 | if len(_methodPath) != 3 || _methodPath[0] != "" {
97 | err = fmt.Errorf("Invalid methodPath param: %v", methodPath)
98 | return
99 | }
100 | serviceName := _methodPath[1]
101 | funcName := _methodPath[2]
102 |
103 | _serviceName := strings.Split(serviceName, ".")
104 | if len(_serviceName) != 2 {
105 | err = fmt.Errorf("Invalid methodPath param: %v", methodPath)
106 | return
107 | }
108 | packageName := _serviceName[0]
109 | serviceName = _serviceName[1]
110 |
111 | for pName, services := range services_list.Packages{
112 | for _, s := range services {
113 | if pName == packageName && s.Name == serviceName {
114 | for _, m := range s.Methods {
115 | if m.Name == funcName {
116 | result = m
117 | }
118 | }
119 | }
120 | }
121 |
122 | }
123 |
124 | return
125 | }
126 |
--------------------------------------------------------------------------------
/src/components/Method.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import './Method.scss';
3 | import axios from 'axios/index';
4 | import Request from './request';
5 | import JSONTree from 'react-json-tree'
6 | import Response from './Response';
7 |
8 |
9 | class Method extends Component {
10 | constructor(props) {
11 | super(props);
12 | this.state = {
13 | loading: false,
14 | expanded: false,
15 | result: '',
16 | error: '',
17 | };
18 |
19 | }
20 | onHeadingClick() {
21 | this.setState({
22 | expanded: !this.state.expanded,
23 | })
24 | }
25 | handleInvokeMethod(args) {
26 | this.setState({
27 | error: '',
28 | response: '',
29 | loading: true,
30 | });
31 |
32 | axios.post('/api/invoke', {
33 | package_name: this.props.package_name,
34 | service_name: this.props.service_name,
35 | method_name: this.props.name,
36 | addr: this.props.addr,
37 | grpc_args: args,
38 | })
39 | .then((resp) => {
40 | this.setState({
41 | result: resp.data.data,
42 | loading: false,
43 | });
44 | })
45 | .catch((error) => {
46 | if (error.response) {
47 | this.setState({
48 | error: error.response.data.error,
49 | loading: false,
50 | });
51 | } else {
52 | this.setState({
53 | error: error,
54 | loading: false,
55 | });
56 | }
57 |
58 | })
59 | }
60 | render() {
61 | const theme = {
62 | scheme: 'bright',
63 | author: 'chris kempson (http://chriskempson.com)',
64 | base00: '#000000',
65 | base01: '#303030',
66 | base02: '#505050',
67 | base03: '#b0b0b0',
68 | base04: '#d0d0d0',
69 | base05: '#e0e0e0',
70 | base06: '#f5f5f5',
71 | base07: '#ffffff',
72 | base08: '#fb0120',
73 | base09: '#fc6d24',
74 | base0A: '#fda331',
75 | base0B: '#a1c659',
76 | base0C: '#76c7b7',
77 | base0D: '#04acb4',
78 | base0E: '#d381c3',
79 | base0F: '#be643c'
80 | };
81 |
82 | return
83 |
84 |
{this.props.name}
85 |
86 |
87 |
88 |
89 | {this.state.error ?
90 | {this.state.error}
: null}
91 | {this.state.result ?
92 |
: null}
93 |
94 |
95 |
96 |
97 |
98 | }
99 | }
100 |
101 | export default Method;
--------------------------------------------------------------------------------
/reflection/reflection_test.go:
--------------------------------------------------------------------------------
1 | package reflection
2 |
3 | import (
4 | "context"
5 | "net"
6 | "testing"
7 | "time"
8 |
9 | "github.com/golang/protobuf/protoc-gen-go/descriptor"
10 | "github.com/komly/grpc-ui/fixtures/simple"
11 | "google.golang.org/grpc"
12 | grpcr "google.golang.org/grpc/reflection"
13 | )
14 |
15 | func TestSimpleTypes(t *testing.T) {
16 | t.SkipNow()
17 | var stub struct {
18 | simple.SimpleServer
19 | }
20 |
21 | ln, err := net.Listen("tcp", "127.0.0.1:0")
22 | if err != nil {
23 | t.Fatal(err)
24 | }
25 |
26 | defer ln.Close()
27 |
28 | s := grpc.NewServer()
29 | simple.RegisterSimpleServer(s, stub)
30 | grpcr.Register(s)
31 |
32 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
33 | defer cancel()
34 |
35 | go func() {
36 | if err := s.Serve(ln); err != nil {
37 | t.Fatal(err)
38 | }
39 | defer s.Stop()
40 |
41 | <-ctx.Done()
42 | }()
43 |
44 | info, err := GetInfo(ctx, ln.Addr().String())
45 | if err != nil {
46 | t.Fatalf("GetInfo err: %v", err)
47 | }
48 | if _, ok := info.Packages["simple"]; !ok {
49 | t.Fatalf("Should have package `simple`, got: %+v", info.Packages)
50 | }
51 |
52 | if len(info.Packages["simple"]) != 1 {
53 | t.Fatalf("Should have 1 servce, got: %v", len(info.Packages["simple"]))
54 | }
55 |
56 | simpleService := info.Packages["simple"][0]
57 |
58 | if len(simpleService.Methods) != 1 {
59 | t.Fatalf("Should have 1 method, got: %v", simpleService.Methods)
60 | }
61 |
62 | if simpleService.Methods[0].Name != "Test" {
63 | t.Fatalf("Service `Simple` have `Test` method, got: %v", simpleService.Methods[0].Name)
64 | }
65 |
66 | if simpleService.Methods[0].In != ".simple.Req" {
67 | t.Fatalf("`Test` method shoud have `.simple.Req` type , got: %v", simpleService.Methods[0].In)
68 | }
69 |
70 | if simpleService.Methods[0].Out != ".simple.Res" {
71 | t.Fatalf("`Test` method shoud have `.simple.Res` type , got: %v", simpleService.Methods[0].Out)
72 | }
73 |
74 | for _, tp := range []string{".simple.Req", ".simple.Res"} {
75 | if _, ok := info.Types[tp]; !ok {
76 | t.Fatalf("Should have `%v` type, got: %+v", tp, info.Types)
77 | }
78 | }
79 |
80 | req := info.Types[".simple.Req"]
81 |
82 | fields := []struct {
83 | Name string
84 | Number int
85 | TypeID descriptor.FieldDescriptorProto_Type
86 | IsRepeated bool
87 | IsRequired bool
88 | }{
89 | {"int32field", 1, descriptor.FieldDescriptorProto_TYPE_INT32, false, false},
90 | {"int64field", 2, descriptor.FieldDescriptorProto_TYPE_INT64, false, false},
91 | {"floatfield", 3, descriptor.FieldDescriptorProto_TYPE_FLOAT, false, false},
92 | {"doublefield", 4, descriptor.FieldDescriptorProto_TYPE_DOUBLE, false, false},
93 | {"uint32field", 5, descriptor.FieldDescriptorProto_TYPE_UINT32, false, false},
94 | {"uint64field", 6, descriptor.FieldDescriptorProto_TYPE_UINT64, false, false},
95 | {"sint32field", 7, descriptor.FieldDescriptorProto_TYPE_SINT32, false, false},
96 | {"sint64field", 8, descriptor.FieldDescriptorProto_TYPE_SINT64, false, false},
97 | {"fixed32field", 9, descriptor.FieldDescriptorProto_TYPE_FIXED32, false, false},
98 | {"fixed64field", 10, descriptor.FieldDescriptorProto_TYPE_FIXED64, false, false},
99 | {"sfixed32field", 11, descriptor.FieldDescriptorProto_TYPE_SFIXED32, false, false},
100 | {"sfixed64field", 12, descriptor.FieldDescriptorProto_TYPE_SFIXED64, false, false},
101 | {"boolfield", 13, descriptor.FieldDescriptorProto_TYPE_BOOL, false, false},
102 | {"stringfield", 14, descriptor.FieldDescriptorProto_TYPE_STRING, false, false},
103 | {"bytesfield", 15, descriptor.FieldDescriptorProto_TYPE_BYTES, false, false},
104 | {"int32Repeated", 16, descriptor.FieldDescriptorProto_TYPE_INT32, true, false},
105 | }
106 |
107 | if len(fields) != len(req.Fields) {
108 | t.Fatalf("Should have `%v` fields, got `%v`", len(fields), len(req.Fields))
109 |
110 | }
111 |
112 | for i, f := range fields {
113 | if req.Fields[i].Name != f.Name {
114 | t.Fatalf("Should names `%v`, got: `%v`", f.Name, req.Fields[i].Name)
115 | }
116 | if req.Fields[i].Name != f.Name {
117 | t.Fatalf("Should have type `%v`, got: `%v`", descriptor.FieldDescriptorProto_Type_name[int32(f.TypeID)], descriptor.FieldDescriptorProto_Type_name[int32(req.Fields[i].TypeID)])
118 | }
119 |
120 | if req.Fields[i].IsRepeated != f.IsRepeated {
121 | t.Fatalf("Field `%v` should have repeated flag `%v`, got: `%v`", f.Name, f.IsRepeated, req.Fields[i].IsRepeated)
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/reflection/info.go:
--------------------------------------------------------------------------------
1 | package reflection
2 |
3 | import (
4 | "context"
5 | "strings"
6 |
7 | "github.com/golang/protobuf/protoc-gen-go/descriptor"
8 | "github.com/golang/protobuf/proto"
9 | "log"
10 | "compress/gzip"
11 | "bytes"
12 | "io/ioutil"
13 | )
14 |
15 | type InfoResp struct {
16 | Types map[string]*TypeInfo `json:"types"`
17 | Enums map[string]*EnumInfo `json:"enums"`
18 | Packages map[string][]*Service `json:"packages"`
19 | }
20 |
21 | type EnumInfo struct {
22 | Id int `json:"id"`
23 | Name string `json:"name"`
24 | Values map[int32]string `json:"values"`
25 | }
26 |
27 | type Package struct {
28 | Name string `json:"name"`
29 | Services []*Service `json:"services"`
30 | }
31 |
32 | type Service struct {
33 | Name string `json:"name"`
34 | Methods []*Method `json:"methods"`
35 | }
36 |
37 | type Method struct {
38 | Name string `json:"name"`
39 |
40 | In string `json:"in"`
41 | Out string `json:"out"`
42 |
43 | InStream bool `json:"in_stream"`
44 | OutStream bool `json:"out_stream"`
45 | }
46 |
47 | type TypeInfo struct {
48 | Id int `json:"id"`
49 | Fields []*FieldInfo `json:"fields"`
50 | }
51 |
52 | type FieldInfo struct {
53 | Name string `json:"name"`
54 | Number int `json:"number"`
55 | IsRepeated bool `json:"is_repeated"`
56 | IsMap bool `json:"is_map"` //TODO: implement
57 | DefaultValue string `json:"default_value"`
58 | TypeName string `json:"type_name"`
59 | TypeID int `json:"type_id"`
60 | }
61 |
62 | func GetInfo(ctx context.Context, addr string) (*InfoResp, error) {
63 | pool := &descPool{}
64 | if err := pool.connect(ctx, addr); err != nil {
65 | return nil, err
66 | }
67 |
68 | defer pool.disconnect()
69 |
70 | services, err := pool.getServicesDescriptors()
71 | if err != nil {
72 | return nil, err
73 | }
74 |
75 | for _, name := range []string{
76 | "google/protobuf/any.proto",
77 | "google/protobuf/duration.proto",
78 | "google/protobuf/empty.proto",
79 | "google/protobuf/struct.proto",
80 | "google/protobuf/timestamp.proto",
81 | "google/protobuf/wrappers.proto",
82 | } {
83 | gzdata := proto.FileDescriptor(name)
84 | rd, err := gzip.NewReader(bytes.NewReader(gzdata))
85 | if err != nil {
86 | return nil, err
87 | }
88 | data, err := ioutil.ReadAll(rd)
89 | if err != nil {
90 | return nil, err
91 | }
92 | if err := pool.parseFileDescriptor(data); err != nil {
93 | log.Printf("Can't parseFileDescriptor: %v", err)
94 | }
95 | }
96 |
97 | res := &InfoResp{
98 | Packages: make(map[string][]*Service),
99 | Types: make(map[string]*TypeInfo),
100 | }
101 |
102 | for sname, descr := range services {
103 | packageName := strings.Split(sname, "/")[0]
104 | if packageName == "grpc.reflection.v1alpha" {
105 | continue
106 | }
107 |
108 | s := &Service{
109 | Name: *descr.Name,
110 | Methods: make([]*Method, 0),
111 | }
112 | for _, method := range descr.Method {
113 | s.Methods = append(s.Methods, &Method{
114 | Name: method.GetName(),
115 | In: method.GetInputType(),
116 | Out: method.GetOutputType(),
117 |
118 | InStream: method.GetClientStreaming(),
119 | OutStream: method.GetServerStreaming(),
120 | })
121 | }
122 |
123 | res.Packages[packageName] = append(res.Packages[packageName], s)
124 | }
125 |
126 | res.Types = make(map[string]*TypeInfo)
127 | for k := range pool.getTypes() {
128 | res.Types[k] = GetTypeInfo(pool, k)
129 | }
130 |
131 | res.Enums = make(map[string]*EnumInfo)
132 | for k := range pool.getEnums() {
133 | res.Enums[k] = GetEnumInfo(pool, k)
134 | }
135 |
136 | return res, nil
137 | }
138 |
139 | func GetTypeInfo(pool *descPool, typeName string) *TypeInfo {
140 | desc := pool.getTypeDescriptor(typeName)
141 | if desc == nil {
142 | return nil
143 | }
144 |
145 | info := &TypeInfo{
146 | Fields: make([]*FieldInfo, 0),
147 | }
148 |
149 | for _, field := range desc.GetField() {
150 | label := field.GetLabel()
151 | info.Fields = append(info.Fields, &FieldInfo{
152 | Name: field.GetName(),
153 | Number: int(field.GetNumber()),
154 | TypeName: field.GetTypeName(),
155 | TypeID: int(field.GetType()),
156 | DefaultValue: field.GetDefaultValue(),
157 | IsRepeated: label == descriptor.FieldDescriptorProto_LABEL_REPEATED,
158 | })
159 |
160 | }
161 | return info
162 | }
163 |
164 | func GetEnumInfo(pool *descPool, enumName string) *EnumInfo {
165 | desc := pool.getEnumDescriptor(enumName)
166 | if desc == nil {
167 | return nil
168 | }
169 |
170 |
171 | info := &EnumInfo{
172 | Name: desc.GetName(),
173 | Values: make(map[int32]string),
174 | }
175 |
176 | for _, d := range desc.Value {
177 | info.Values[d.GetNumber()] = d.GetName()
178 | }
179 |
180 | return info
181 | }
182 |
--------------------------------------------------------------------------------
/http_server/http_server.go:
--------------------------------------------------------------------------------
1 | package http_server
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "log"
7 | "net/http"
8 | "strings"
9 |
10 | "github.com/gorilla/websocket"
11 | "github.com/komly/grpc-ui/proto"
12 | "github.com/komly/grpc-ui/reflection"
13 | )
14 |
15 | // New create HTTPServer on `addr`
16 | // if `devMode=true` then we use localFS instead of memFS
17 | func New(addr string, devMode bool) *HTTPServer {
18 | mux := http.NewServeMux()
19 |
20 | s := &HTTPServer{
21 | addr: addr,
22 | mux: mux,
23 | }
24 |
25 | mux.HandleFunc("/api/info", s.infoHandler)
26 | mux.HandleFunc("/api/invoke", s.invokeHandler)
27 |
28 | mux.Handle("/static/", http.FileServer(FS(devMode)))
29 | mux.HandleFunc("/", s.indexHandler)
30 |
31 | return s
32 | }
33 |
34 | type HTTPServer struct {
35 | addr string
36 | targetAddr string
37 | mux *http.ServeMux
38 | }
39 |
40 | type InvokeReq struct {
41 | Addr string `json:"addr"`
42 | ServiceName string `json:"service_name"`
43 | PackageName string `json:"package_name"`
44 | MethodName string `json:"method_name"`
45 | GRPCArgs []proto.FieldValue `json:"grpc_args"`
46 | }
47 |
48 | type InvokeResp struct {
49 | Status string `json:"status"`
50 | Data interface{} `json:"data"`
51 | Error string `json:"error"`
52 | }
53 |
54 | type InvokeStreamReq struct {
55 | GRPCMethod string `json:"grpc_method"`
56 | GRPCArgs string `json:"grpc_args"`
57 | }
58 |
59 | type InvokeStreamResp struct {
60 | Status string `json:"status"`
61 | Data interface{} `json:"data"`
62 | Error string `json:"error"`
63 | }
64 |
65 | type InfoResp struct {
66 | Status string `json:"status"`
67 | Data interface{} `json:"data"`
68 | Error string `json:"error"`
69 | }
70 |
71 | var upgrader = websocket.Upgrader{
72 | ReadBufferSize: 2048,
73 | WriteBufferSize: 2048,
74 | }
75 |
76 | func (h *HTTPServer) infoHandler(w http.ResponseWriter, r *http.Request) {
77 | info, err := reflection.GetInfo(r.Context(), r.FormValue("addr"))
78 | enc := json.NewEncoder(w)
79 | if err != nil {
80 | log.Printf("Can't get grpc info: %v", err)
81 |
82 | w.WriteHeader(http.StatusInternalServerError)
83 | resp := &InfoResp{
84 | Status: "error",
85 | Error: fmt.Sprintf("Can't get grpc info: %v", err),
86 | }
87 | if err := enc.Encode(resp); err != nil {
88 | log.Printf("Can't encode json response: %v", err)
89 |
90 | }
91 | return
92 | }
93 |
94 | resp := &InfoResp{
95 | Status: "ok",
96 | Data: info,
97 | }
98 | if err := enc.Encode(resp); err != nil {
99 | log.Printf("Can't encode json response: %v", err)
100 |
101 | }
102 | }
103 |
104 | func (h *HTTPServer) invokeHandler(w http.ResponseWriter, r *http.Request) {
105 | if r.FormValue("stream") == "" {
106 | h.handleUnary(w, r)
107 | return
108 | }
109 | h.handleStream(w, r)
110 | }
111 |
112 | func (h *HTTPServer) handleUnary(w http.ResponseWriter, r *http.Request) {
113 | req := InvokeReq{}
114 |
115 | defer r.Body.Close()
116 |
117 | enc := json.NewEncoder(w)
118 |
119 | if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
120 | w.WriteHeader(http.StatusBadRequest)
121 | enc.Encode(&InvokeResp{
122 | Status: "error",
123 | Error: err.Error(),
124 | })
125 | log.Printf("Can't decode request body: %v", err)
126 | return
127 | }
128 | invokeRes, err := proto.Invoke(r.Context(), req.Addr, req.PackageName, req.ServiceName, req.MethodName, req.GRPCArgs)
129 | if err != nil {
130 | w.WriteHeader(http.StatusInternalServerError)
131 | enc.Encode(&InvokeResp{
132 | Status: "error",
133 | Error: err.Error(),
134 | })
135 | return
136 | }
137 | enc.Encode(&InvokeResp{
138 | Status: "ok",
139 | Data: invokeRes,
140 | })
141 | }
142 |
143 | func (h *HTTPServer) handleStream(w http.ResponseWriter, r *http.Request) {
144 | conn, err := upgrader.Upgrade(w, r, nil)
145 | if err != nil {
146 | log.Printf("Can't upgrade connection: %v", err)
147 | return
148 | }
149 | defer conn.Close()
150 |
151 | log.Print("WebSocket connected")
152 | defer log.Print("WebSocket disconnected")
153 | //
154 | //ctx, cancel := context.WithCancel(r.Context())
155 | //defer cancel()
156 | //
157 | //for {
158 | // req := InvokeStreamReq{}
159 | // if err := conn.ReadJSON(&req); err != nil {
160 | // if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
161 | // log.Printf("ReadJSON error: %v", err)
162 | // }
163 | // return
164 | // }
165 | //}
166 |
167 | }
168 |
169 | func (h *HTTPServer) indexHandler(w http.ResponseWriter, r *http.Request) {
170 | if r.URL.Path == "/" || strings.HasPrefix(r.URL.Path, "/index.html") {
171 | w.Write(FSMustByte(false, "/static/index.html"))
172 | return
173 | }
174 | w.WriteHeader(404)
175 | }
176 |
177 | func (h *HTTPServer) Start() error {
178 | return http.ListenAndServe(h.addr, h.mux)
179 | }
180 |
--------------------------------------------------------------------------------
/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import injectSheet from 'react-jss';
3 | import Sidebar from './Sidebar';
4 | import Method from './Method';
5 | import Loader from './Loader';
6 | import Error from './Error';
7 |
8 | import './app.scss';
9 | import axios from 'axios';
10 | import qs from 'qs';
11 |
12 |
13 | class App extends Component {
14 | constructor(props) {
15 | super(props);
16 | this.state = {
17 | loading: false,
18 | error: null,
19 | addr: '',
20 | packages: [],
21 | types: {},
22 | enums: {},
23 | }
24 | }
25 | componentDidMount() {
26 |
27 | }
28 | handleSubmitHostForm(e) {
29 | e.preventDefault();
30 |
31 | this.setState({
32 | loading: true,
33 | });
34 |
35 | axios.get('/api/info?' + qs.stringify({addr: this.state.addr}))
36 | .then(({data: {data: {packages, types, enums}}}) => {
37 | this.setState({
38 | packages, types, enums,
39 | error: null,
40 | loading: false,
41 | })
42 | })
43 | .catch(({response: {data: {error}}}) => {
44 | this.setState({
45 | loading: false,
46 | error: error,
47 | });
48 | });
49 | }
50 | render() {
51 | return (
52 |
53 |
70 |
71 |
72 | {this.state.loading ?
73 |
:
74 | this.state.error ?
:
75 |
76 |
77 |
78 |
79 |
80 |
81 | {Object.keys(this.state.packages).map(package_name => {
82 | return this.state.packages[package_name].map((service) => {
83 | return
84 |
{package_name + ' / ' + service.name}
85 | {service.methods.map((method) =>
86 |
94 | )}
95 |
96 |
97 | });
98 | })}
99 |
100 |
101 |
102 | }
103 |
104 |
105 |
106 |
107 | );
108 | }
109 | }
110 |
111 |
112 | export default App;
--------------------------------------------------------------------------------
/src/components/fields.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {TYPE_BOOL, TYPE_ENUM, TYPE_INT32, TYPE_MESSAGE, getTypeName, getDefaultValue} from './types';
3 |
4 | export const Field = (props) => {
5 | let input = null;
6 |
7 | switch(props.type_id) {
8 | case TYPE_BOOL:
9 | input = props.onChange(e.target.checked ? 'true' : 'false')}/>
10 | break;
11 | case TYPE_INT32:
12 | input = props.onChange(e.target.value)}/>
13 | break;
14 | case TYPE_MESSAGE:
15 | const type = props.types[props.type_name];
16 | if (!type) {
17 | return ?????
;
18 | }
19 | input =
20 | break;
21 | case TYPE_ENUM:
22 | const enum_ = props.enums[props.type_name];
23 | if (!enum_) {
24 | return ?????
;
25 | }
26 | input = ;
29 | break;
30 | default:
31 | input = props.onChange(e.target.value)}/>
32 | break;
33 | }
34 |
35 | return
36 | {input}
37 |
;
38 | };
39 |
40 | export const RepeatedField = (props) =>
41 |
42 | {props.val.map((v, i) =>
{
51 | const newVal = props.val.slice();
52 | newVal[i] = val;
53 | props.onChange(newVal);
54 | }}/> )}
55 |
56 | {props.val.length ? : null}
57 |
58 |
59 | ;
60 |
61 | const getLabel = (type_id, type_name) => {
62 | if (type_id === TYPE_MESSAGE) {
63 | const parts = type_name.split('.');
64 | return parts[parts.length - 1];
65 | }
66 | return getTypeName(type_id)
67 | }
68 |
69 | export const Message = (props) =>
70 |
71 | {props.type.fields.map((f, i) =>
72 |
73 | |
74 |
75 | |
76 |
77 | {f.is_repeated ?
78 | {
86 | const newArr = props.val.slice();
87 | newArr[i] = val;
88 | props.onChange(newArr);
89 | }}/>
90 | :
91 | {
99 | const newArr = props.val.slice();
100 | newArr[i] = val;
101 | props.onChange(newArr);
102 | }} />
103 | }
104 | |
105 |
106 | {getLabel(f.type_id, f.type_name)} {f.is_repeated ? '(+)': ''}
107 | |
108 |
109 | )}
110 |
;
111 |
--------------------------------------------------------------------------------
/proto/encode.go:
--------------------------------------------------------------------------------
1 | /*
2 | Dynamic map -> protobuf generator
3 | */
4 |
5 | package proto
6 |
7 | import (
8 | "encoding/binary"
9 | "fmt"
10 |
11 | "github.com/golang/protobuf/proto"
12 | "github.com/golang/protobuf/protoc-gen-go/descriptor"
13 | "github.com/komly/grpc-ui/reflection"
14 | )
15 |
16 | func Encode(typeInfo map[string]*reflection.TypeInfo, typeName string, data []FieldValue) (resBuf []byte, err error) {
17 | for _, field := range data {
18 | // get field info
19 |
20 | var fieldInfo *reflection.FieldInfo
21 | for _, fi := range typeInfo[typeName].Fields {
22 | if fi.Number == field.Number {
23 | fieldInfo = fi
24 | break
25 | }
26 | }
27 | if fieldInfo == nil {
28 | return nil, fmt.Errorf("no such field with number: %v", field.Number)
29 | }
30 |
31 |
32 | typeId := descriptor.FieldDescriptorProto_Type(fieldInfo.TypeID)
33 |
34 | wireType := FieldTypeToWireType(typeId)
35 | if fieldInfo.IsRepeated {
36 | wireType = proto.WireBytes
37 | }
38 |
39 | // encode value
40 |
41 | var fieldBuf []byte
42 |
43 | switch typeId {
44 | case descriptor.FieldDescriptorProto_TYPE_FLOAT:
45 | fieldBuf, err = encodeFloat(
46 | field.Value,
47 | fieldInfo.Number, wireType,
48 | fieldInfo.IsRepeated,
49 | )
50 |
51 | case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
52 | fieldBuf, err = encodeDouble(
53 | field.Value,
54 | fieldInfo.Number, wireType,
55 | fieldInfo.IsRepeated,
56 | )
57 |
58 | case descriptor.FieldDescriptorProto_TYPE_SINT32:
59 | fieldBuf, err = encodeSInt32(
60 | field.Value,
61 | fieldInfo.Number, wireType,
62 | fieldInfo.IsRepeated,
63 | )
64 |
65 | case descriptor.FieldDescriptorProto_TYPE_SINT64:
66 | fieldBuf, err = encodeSInt64(
67 | field.Value,
68 | fieldInfo.Number, wireType,
69 | fieldInfo.IsRepeated,
70 | )
71 |
72 | case descriptor.FieldDescriptorProto_TYPE_FIXED32,
73 | descriptor.FieldDescriptorProto_TYPE_SFIXED32:
74 | fieldBuf, err = encodeFixed32(
75 | field.Value,
76 | fieldInfo.Number, wireType,
77 | fieldInfo.IsRepeated,
78 | )
79 |
80 | case descriptor.FieldDescriptorProto_TYPE_FIXED64,
81 | descriptor.FieldDescriptorProto_TYPE_SFIXED64:
82 | fieldBuf, err = encodeFixed64(
83 | field.Value,
84 | fieldInfo.Number, wireType,
85 | fieldInfo.IsRepeated,
86 | )
87 |
88 | case descriptor.FieldDescriptorProto_TYPE_BOOL:
89 | fieldBuf, err = encodeBool(
90 | field.Value,
91 | fieldInfo.Number, wireType,
92 | fieldInfo.IsRepeated,
93 | )
94 |
95 | case descriptor.FieldDescriptorProto_TYPE_INT32,
96 | descriptor.FieldDescriptorProto_TYPE_INT64,
97 | descriptor.FieldDescriptorProto_TYPE_UINT32,
98 | descriptor.FieldDescriptorProto_TYPE_UINT64,
99 | descriptor.FieldDescriptorProto_TYPE_ENUM:
100 | fieldBuf, err = encodeInt(
101 | field.Value,
102 | fieldInfo.Number, wireType,
103 | fieldInfo.IsRepeated,
104 | )
105 |
106 | case descriptor.FieldDescriptorProto_TYPE_BYTES:
107 | fieldBuf, err = encodeBytes(
108 | field.Value,
109 | fieldInfo.Number, wireType,
110 | fieldInfo.IsRepeated,
111 | )
112 |
113 | case descriptor.FieldDescriptorProto_TYPE_STRING:
114 | fieldBuf, err = encodeString(
115 | field.Value,
116 | fieldInfo.Number, wireType,
117 | fieldInfo.IsRepeated,
118 | )
119 |
120 | //case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
121 | // if fieldInfo.IsMap {
122 | // fieldBuf, err = encodeMap(
123 | // field.Value,
124 | // fieldInfo.Number, wireType,
125 | // typeName,
126 | // typeInfo, fieldPath,
127 | // )
128 | // } else {
129 | // fieldBuf, err = encodeMessage(
130 | // field.Value,
131 | // fieldInfo.Number, wireType,
132 | // typeInfo, typeName,fieldPath,
133 | // fieldInfo.IsRepeated,
134 | // )
135 | // }
136 | //
137 | }
138 |
139 | if err != nil {
140 | return nil, err
141 | }
142 | // write encoded data to buffer
143 |
144 | if len(fieldBuf) > 0 {
145 | resBuf = append(resBuf, fieldBuf...)
146 | }
147 |
148 | }
149 |
150 | return
151 | }
152 |
153 | func EncodeTag(n int, wt int) []byte {
154 | /*
155 | set field tag: field number and wire type
156 | */
157 | return EncodeVarint(uint64((uint32(n) << 3) | uint32(wt)))
158 | }
159 |
160 | func EncodeVarint(x uint64) []byte {
161 | /*
162 | encode types:
163 | - int32
164 | - int64
165 | - uint32
166 | - uint64
167 | */
168 | return proto.EncodeVarint(x)
169 | }
170 |
171 | func EncodeFixed32(x uint32) []byte {
172 | /*
173 | encode types:
174 | - fixed32
175 | - sfixed32
176 | - float
177 | */
178 | buf := make([]byte, 4)
179 | binary.LittleEndian.PutUint32(buf, x)
180 | return buf
181 | }
182 |
183 | func EncodeFixed64(x uint64) []byte {
184 | /*
185 | encode types:
186 | - fixed64
187 | - sfixed64
188 | - double
189 | */
190 | buf := make([]byte, 8)
191 | binary.LittleEndian.PutUint64(buf, x)
192 | return buf
193 | }
194 |
195 | func EncodeZigzag32(x uint64) []byte {
196 | /*
197 | encode types:
198 | - sint32
199 | */
200 | return EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
201 | }
202 |
203 | func EncodeZigzag64(x uint64) []byte {
204 | /*
205 | encode types:
206 | - sint64
207 | */
208 | return EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
209 | }
210 |
211 | func EncodeBytes(x []byte) (buf []byte) {
212 | /*
213 | encode types:
214 | - []byte
215 | - message
216 | */
217 | buf = append(buf, EncodeVarint(uint64(len(x)))...)
218 | buf = append(buf, x...)
219 | return
220 | }
221 |
--------------------------------------------------------------------------------
/proto/decode_number.go:
--------------------------------------------------------------------------------
1 | /*
2 | Decoders for number types
3 | */
4 |
5 | package proto
6 |
7 | import (
8 | "math"
9 | )
10 |
11 | func decodeFloat(buf []byte, repeated bool) (x interface{}, i int, err error) {
12 | if repeated {
13 | len, shift := DecodeVarint(buf[i:])
14 | i += shift
15 | var vv []float64
16 | var max int = i + int(len)
17 | for {
18 | v, shift := DecodeFixed32(buf[i:])
19 | i += shift
20 | vv = append(vv, float64(math.Float32frombits(v)))
21 | if i >= max {
22 | break
23 | }
24 | }
25 | x = []float64(vv)
26 | } else {
27 | var v uint32
28 | v, i = DecodeFixed32(buf)
29 | x = float64(math.Float32frombits(v))
30 | }
31 | return
32 | }
33 |
34 | func decodeDouble(buf []byte, repeated bool) (x interface{}, i int, err error) {
35 | if repeated {
36 | len, shift := DecodeVarint(buf[i:])
37 | i += shift
38 | var vv []float64
39 | var max int = i + int(len)
40 | for {
41 | v, shift := DecodeFixed64(buf[i:])
42 | i += shift
43 | vv = append(vv, float64(math.Float64frombits(v)))
44 | if i >= max {
45 | break
46 | }
47 | }
48 | x = []float64(vv)
49 | } else {
50 | var v uint64
51 | v, i = DecodeFixed64(buf)
52 | x = float64(math.Float64frombits(v))
53 | }
54 | return
55 | }
56 |
57 | func decodeBool(buf []byte, repeated bool) (x interface{}, i int, err error) {
58 | if repeated {
59 | len, shift := DecodeVarint(buf[i:])
60 | i += shift
61 | var vv []bool
62 | var max int = i + int(len)
63 | for {
64 | v, shift := DecodeVarint(buf[i:])
65 | i += shift
66 | if int(v) > 0 {
67 | vv = append(vv, true)
68 | } else {
69 | vv = append(vv, false)
70 | }
71 | if i >= max {
72 | break
73 | }
74 | }
75 | x = []bool(vv)
76 | } else {
77 | var v uint64
78 | v, i = DecodeVarint(buf)
79 | if v > 0 {
80 | x = true
81 | } else {
82 | x = false
83 | }
84 | }
85 | return
86 | }
87 |
88 | func decodeSInt32(buf []byte, repeated bool) (x interface{}, i int, err error) {
89 | if repeated {
90 | len, shift := DecodeVarint(buf[i:])
91 | i += shift
92 | var vv []int
93 | var max int = i + int(len)
94 | for {
95 | v, shift := DecodeZigzag32(buf[i:])
96 | i += shift
97 | vv = append(vv, int(int32(v)))
98 | if i >= max {
99 | break
100 | }
101 | }
102 | x = []int(vv)
103 | } else {
104 | var v uint64
105 | v, i = DecodeZigzag32(buf)
106 | x = int(int32(v))
107 | }
108 | return
109 | }
110 |
111 | func decodeSInt64(buf []byte, repeated bool) (x interface{}, i int, err error) {
112 | if repeated {
113 | len, shift := DecodeVarint(buf[i:])
114 | i += shift
115 | var vv []int
116 | var max int = i + int(len)
117 | for {
118 | v, shift := DecodeZigzag64(buf[i:])
119 | i += shift
120 | vv = append(vv, int(v))
121 | if i >= max {
122 | break
123 | }
124 | }
125 | x = []int(vv)
126 | } else {
127 | var v uint64
128 | v, i = DecodeZigzag64(buf)
129 | x = int(v)
130 | }
131 | return
132 | }
133 |
134 | func decodeFixed32(buf []byte, repeated bool) (x interface{}, i int, err error) {
135 | if repeated {
136 | len, shift := DecodeVarint(buf[i:])
137 | i += shift
138 | var vv []uint32
139 | var max int = i + int(len)
140 | for {
141 | v, shift := DecodeFixed32(buf[i:])
142 | i += shift
143 | vv = append(vv, uint32(int32(v)))
144 | if i >= max {
145 | break
146 | }
147 | }
148 | x = []uint32(vv)
149 | } else {
150 | var v uint32
151 | v, i = DecodeFixed32(buf)
152 | x = uint32(int32(v))
153 | }
154 | return
155 | }
156 |
157 | func decodeFixed64(buf []byte, repeated bool) (x interface{}, i int, err error) {
158 | if repeated {
159 | len, shift := DecodeVarint(buf[i:])
160 | i += shift
161 | var vv []uint64
162 | var max int = i + int(len)
163 | for {
164 | v, shift := DecodeFixed64(buf[i:])
165 | i += shift
166 | vv = append(vv, uint64(v))
167 | if i >= max {
168 | break
169 | }
170 | }
171 | x = []uint64(vv)
172 | } else {
173 | var v uint64
174 | v, i = DecodeFixed64(buf)
175 | x = uint64(v)
176 | }
177 | return
178 | }
179 |
180 | func decodeSFixed32(buf []byte, repeated bool) (x interface{}, i int, err error) {
181 | if repeated {
182 | len, shift := DecodeVarint(buf[i:])
183 | i += shift
184 | var vv []int32
185 | var max int = i + int(len)
186 | for {
187 | v, shift := DecodeFixed32(buf[i:])
188 | i += shift
189 | vv = append(vv, int32(v))
190 | if i >= max {
191 | break
192 | }
193 | }
194 | x = []int32(vv)
195 | } else {
196 | var v uint32
197 | v, i = DecodeFixed32(buf)
198 | x = int32(v)
199 | }
200 | return
201 | }
202 |
203 | func decodeSFixed64(buf []byte, repeated bool) (x interface{}, i int, err error) {
204 | if repeated {
205 | len, shift := DecodeVarint(buf[i:])
206 | i += shift
207 | var vv []int64
208 | var max int = i + int(len)
209 | for {
210 | v, shift := DecodeFixed64(buf[i:])
211 | i += shift
212 | vv = append(vv, int64(v))
213 | if i >= max {
214 | break
215 | }
216 | }
217 | x = []int64(vv)
218 | } else {
219 | var v uint64
220 | v, i = DecodeFixed64(buf)
221 | x = int64(v)
222 | }
223 | return
224 | }
225 |
226 | func decodeUInt(buf []byte, repeated bool) (x interface{}, i int, err error) {
227 | if repeated {
228 | len, shift := DecodeVarint(buf[i:])
229 | i += shift
230 | var vv []uint
231 | var max int = i + int(len)
232 | for {
233 | v, shift := DecodeVarint(buf[i:])
234 | i += shift
235 | vv = append(vv, uint(v))
236 | if i >= max {
237 | break
238 | }
239 | }
240 | x = []uint(vv)
241 | } else {
242 | var v uint64
243 | v, i = DecodeVarint(buf)
244 | x = uint(v)
245 | }
246 | return
247 | }
248 |
249 | func decodeInt(buf []byte, repeated bool) (x interface{}, i int, err error) {
250 | if repeated {
251 | len, shift := DecodeVarint(buf[i:])
252 | i += shift
253 | var vv []int
254 | var max int = i + int(len)
255 | for {
256 | v, shift := DecodeVarint(buf[i:])
257 | i += shift
258 | vv = append(vv, int(v))
259 | if i >= max {
260 | break
261 | }
262 | }
263 | x = []int(vv)
264 | } else {
265 | var v uint64
266 | v, i = DecodeVarint(buf)
267 | x = int(v)
268 | }
269 | return
270 | }
271 |
--------------------------------------------------------------------------------
/reflection/pool.go:
--------------------------------------------------------------------------------
1 | package reflection
2 |
3 | import (
4 | "context"
5 | "errors"
6 | "fmt"
7 | "strings"
8 |
9 | "github.com/golang/protobuf/proto"
10 | "github.com/golang/protobuf/protoc-gen-go/descriptor"
11 | "google.golang.org/grpc"
12 | pb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha"
13 | "log"
14 |
15 | _ "github.com/golang/protobuf/ptypes/any"
16 | _ "github.com/golang/protobuf/ptypes/duration"
17 | _ "github.com/golang/protobuf/ptypes/empty"
18 | _ "github.com/golang/protobuf/ptypes/struct"
19 | _ "github.com/golang/protobuf/ptypes/timestamp"
20 | _ "github.com/golang/protobuf/ptypes/wrappers"
21 | )
22 |
23 | type descPool struct {
24 | stream pb.ServerReflection_ServerReflectionInfoClient
25 | services map[string]*descriptor.ServiceDescriptorProto
26 | types map[string]*descriptor.DescriptorProto
27 | enum_types map[string]*descriptor.EnumDescriptorProto
28 | conn *grpc.ClientConn
29 | }
30 |
31 | func (p *descPool) connect(ctx context.Context, addr string) error {
32 |
33 | conn, err := grpc.DialContext(ctx, addr, grpc.WithInsecure())
34 | if err != nil {
35 | return err
36 | }
37 | p.conn = conn
38 |
39 | c := pb.NewServerReflectionClient(conn)
40 |
41 | p.stream, err = c.ServerReflectionInfo(ctx)
42 | if err != nil {
43 | p.disconnect()
44 | return err
45 | }
46 |
47 | return nil
48 | }
49 |
50 | func (p *descPool) disconnect() {
51 | if p.conn != nil {
52 | go p.conn.Close()
53 | }
54 | }
55 |
56 | func (p *descPool) getServicesDescriptors() (map[string]*descriptor.ServiceDescriptorProto, error) {
57 | err := p.stream.SendMsg(&pb.ServerReflectionRequest{
58 | MessageRequest: &pb.ServerReflectionRequest_ListServices{},
59 | })
60 | if err != nil {
61 | return nil, err
62 | }
63 |
64 | serviceResp, err := p.stream.Recv()
65 | if err != nil {
66 | return nil, err
67 | }
68 |
69 | if err := serviceResp.GetErrorResponse(); err != nil {
70 | return nil, errors.New(err.String())
71 | }
72 |
73 | for _, service := range serviceResp.GetListServicesResponse().Service {
74 | p.updateSymbolFile(service.Name)
75 | }
76 |
77 | return p.services, nil
78 | }
79 |
80 | func (p *descPool) updateSymbolFile(name string) error {
81 | err := p.stream.SendMsg(&pb.ServerReflectionRequest{
82 | MessageRequest: &pb.ServerReflectionRequest_FileContainingSymbol{
83 | FileContainingSymbol: name,
84 | },
85 | })
86 |
87 | file, err := p.stream.Recv()
88 | if err != nil {
89 | return err
90 | }
91 |
92 | if err := file.GetErrorResponse(); err != nil {
93 | return errors.New(err.String())
94 | }
95 |
96 | for _, descData := range file.GetFileDescriptorResponse().FileDescriptorProto {
97 | if err := p.parseFileDescriptor(descData); err != nil {
98 | return err
99 | }
100 | }
101 |
102 | return nil
103 | }
104 |
105 |
106 | func (p *descPool) parseFile(name string) error {
107 | err := p.stream.SendMsg(&pb.ServerReflectionRequest{
108 | MessageRequest: &pb.ServerReflectionRequest_FileByFilename{
109 | FileByFilename: name,
110 | },
111 | })
112 |
113 | file, err := p.stream.Recv()
114 | if err != nil {
115 | return err
116 | }
117 |
118 | if err := file.GetErrorResponse(); err != nil {
119 | return errors.New(err.String())
120 | }
121 |
122 | for _, descData := range file.GetFileDescriptorResponse().FileDescriptorProto {
123 | if err := p.parseFileDescriptor(descData); err != nil {
124 | return err
125 | }
126 | }
127 |
128 | return nil
129 | }
130 |
131 | func (p *descPool) parseFileDescriptor(data []byte) error {
132 | d := &descriptor.FileDescriptorProto{}
133 | if err := proto.Unmarshal(data, d); err != nil {
134 | return err
135 | }
136 |
137 | if p.services == nil {
138 | p.services = make(map[string]*descriptor.ServiceDescriptorProto)
139 | }
140 |
141 | for _, service := range d.Service {
142 | sname := fmt.Sprintf("%v/%v", d.GetPackage(), service.GetName())
143 | p.services[sname] = service
144 | }
145 |
146 | if p.types == nil {
147 | p.types = make(map[string]*descriptor.DescriptorProto)
148 | }
149 | if p.enum_types == nil {
150 | p.enum_types = make(map[string]*descriptor.EnumDescriptorProto)
151 | }
152 |
153 | fullName := ""
154 |
155 | pack := d.GetPackage()
156 | if pack != "" {
157 | fullName = "."+d.GetPackage()
158 |
159 | }
160 | p.processEnumDescriptors(fullName, d.EnumType)
161 |
162 | p.processTypeDescriptors(fullName, d.MessageType)
163 |
164 |
165 | for _, filename := range d.Dependency {
166 | parts := strings.Split(filename, "/")
167 | name := parts[len(parts) - 1]
168 |
169 | if err := p.parseFile(filename); err != nil {
170 | if err := p.parseFile(name); err != nil {
171 | log.Printf("Can't resolve %v: %v", filename, err)
172 | }
173 | log.Printf("Can't resolve %v: %v", filename, err)
174 | }
175 | }
176 | return nil
177 | }
178 |
179 | func (p *descPool) processTypeDescriptors(prefix string, desc []*descriptor.DescriptorProto) {
180 | for _, d := range desc {
181 | fullName := prefix + "." + d.GetName()
182 | p.types[fullName] = d
183 | p.processTypeDescriptors(fullName, d.NestedType)
184 | p.processEnumDescriptors(fullName, d.EnumType)
185 | }
186 | }
187 |
188 | func (p *descPool) processEnumDescriptors(prefix string, desc []*descriptor.EnumDescriptorProto) {
189 | for _, d := range desc {
190 | fullName := prefix + "." + d.GetName()
191 | p.enum_types[fullName] = d
192 | }
193 | }
194 |
195 | func (p *descPool) getTypeDescriptor(name string) *descriptor.DescriptorProto {
196 |
197 | // update symbol from protobuf standart
198 | if strings.HasPrefix(name, ".google.protobuf") {
199 | p.updateSymbolFile(name[1:])
200 | }
201 |
202 | if p.types == nil {
203 | return nil
204 | }
205 | if t, ok := p.types[name]; ok {
206 | return t
207 | }
208 | return nil
209 | }
210 |
211 | func (p *descPool) getEnumDescriptor(name string) *descriptor.EnumDescriptorProto {
212 | if p.enum_types == nil {
213 | return nil
214 | }
215 | if t, ok := p.enum_types[name]; ok {
216 | return t
217 | }
218 | return nil
219 | }
220 |
221 | func (p *descPool) getTypes() map[string]*descriptor.DescriptorProto {
222 | return p.types
223 | }
224 |
225 | func (p *descPool) getEnums() map[string]*descriptor.EnumDescriptorProto {
226 | return p.enum_types
227 | }
--------------------------------------------------------------------------------
/proto/decode.go:
--------------------------------------------------------------------------------
1 | /*
2 | Dynamic protobuf -> map generator
3 | */
4 |
5 | package proto
6 |
7 | import (
8 | "encoding/binary"
9 | "fmt"
10 |
11 | "github.com/golang/protobuf/proto"
12 | "github.com/golang/protobuf/protoc-gen-go/descriptor"
13 |
14 | "github.com/komly/grpc-ui/reflection"
15 | )
16 |
17 | func Decode(typeInfo map[string]*reflection.TypeInfo, typeName string, buf []byte, fieldPath []int) (msg interface{}, err error) {
18 | // https://developers.google.com/protocol-buffers/docs/encoding
19 | // Base on:
20 | // github.com/golang/protobuf/proto/decode.go
21 | // unmarshalType
22 |
23 | message := map[string]interface{}{}
24 |
25 | index := 0
26 | shift := 0
27 |
28 | for err == nil && index < len(buf) {
29 |
30 | // parse tag
31 |
32 | var wireType int
33 | var fieldNumber int
34 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
35 | index += shift
36 |
37 | if fieldNumber <= 0 {
38 | err = fmt.Errorf("Invalid field number: %v", fieldNumber)
39 | return
40 | }
41 |
42 | // get field info
43 |
44 | var fieldInfo *reflection.FieldInfo
45 | fieldInfo, err = findFieldInfoByNumber(typeInfo, typeName, fieldNumber, fieldPath)
46 | if err != nil {
47 | return
48 | }
49 |
50 | // set repeated flag
51 |
52 | var repeatedField bool
53 | var mapField bool
54 | var append bool
55 | if fieldInfo.IsRepeated {
56 | repeatedField = true
57 | append = true
58 | }
59 |
60 | if fieldInfo.IsMap {
61 | mapField = true
62 | append = true
63 | }
64 |
65 | typeId := descriptor.FieldDescriptorProto_Type(fieldInfo.TypeID)
66 |
67 | // validate wire type
68 |
69 | _wireType := FieldTypeToWireType(typeId)
70 | if repeatedField {
71 | _wireType = proto.WireBytes
72 | }
73 |
74 | if wireType != _wireType {
75 | err = fmt.Errorf("tag wire type %v != field wire type %v", wireType, _wireType)
76 | return
77 | }
78 |
79 | // decode message
80 |
81 | var value interface{} = nil
82 | shift = 0
83 |
84 | switch typeId {
85 | case descriptor.FieldDescriptorProto_TYPE_FLOAT:
86 | value, shift, err = decodeFloat(buf[index:], repeatedField)
87 | index += shift
88 |
89 | case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
90 | value, shift, err = decodeDouble(buf[index:], repeatedField)
91 | index += shift
92 |
93 | case descriptor.FieldDescriptorProto_TYPE_SINT32:
94 | value, shift, err = decodeSInt32(buf[index:], repeatedField)
95 | index += shift
96 |
97 | case descriptor.FieldDescriptorProto_TYPE_SINT64:
98 | value, shift, err = decodeSInt64(buf[index:], repeatedField)
99 | index += shift
100 |
101 | case descriptor.FieldDescriptorProto_TYPE_FIXED32:
102 | value, shift, err = decodeFixed32(buf[index:], repeatedField)
103 | index += shift
104 |
105 | case descriptor.FieldDescriptorProto_TYPE_FIXED64:
106 | value, shift, err = decodeFixed64(buf[index:], repeatedField)
107 | index += shift
108 |
109 | case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
110 | value, shift, err = decodeSFixed32(buf[index:], repeatedField)
111 | index += shift
112 |
113 | case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
114 | value, shift, err = decodeSFixed64(buf[index:], repeatedField)
115 | index += shift
116 |
117 | case descriptor.FieldDescriptorProto_TYPE_BOOL:
118 | value, shift, err = decodeBool(buf[index:], repeatedField)
119 | index += shift
120 |
121 | case descriptor.FieldDescriptorProto_TYPE_UINT32,
122 | descriptor.FieldDescriptorProto_TYPE_UINT64:
123 | value, shift, err = decodeUInt(buf[index:], repeatedField)
124 | index += shift
125 |
126 | case descriptor.FieldDescriptorProto_TYPE_INT32,
127 | descriptor.FieldDescriptorProto_TYPE_INT64,
128 | descriptor.FieldDescriptorProto_TYPE_ENUM:
129 | value, shift, err = decodeInt(buf[index:], repeatedField)
130 | index += shift
131 |
132 | case descriptor.FieldDescriptorProto_TYPE_BYTES:
133 | value, shift, err = decodeBytes(buf[index:])
134 | index += shift
135 |
136 | case descriptor.FieldDescriptorProto_TYPE_STRING:
137 | value, shift, err = decodeString(buf[index:])
138 | index += shift
139 |
140 | case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
141 | value, shift, err = decodeMessage(buf[index:], fieldInfo.Number, typeName, typeInfo, fieldPath)
142 | index += shift
143 |
144 | }
145 |
146 | if err != nil {
147 | return
148 | }
149 |
150 | if append {
151 | err = appendValue(&message, fieldInfo.Name, value, mapField)
152 | if err != nil {
153 | return
154 | }
155 | } else {
156 | message[fieldInfo.Name] = value
157 | }
158 |
159 | }
160 |
161 | msg = interface{}(message)
162 |
163 | return
164 | }
165 |
166 | func DecodeTag(buf []byte) (wireType int, fieldNumber int, i int) {
167 | /*
168 | Decode wire type and field number from tag
169 | */
170 |
171 | var tagValue uint64
172 | tagValue, i = DecodeVarint(buf)
173 |
174 | wireType = int(tagValue & 0x7)
175 | fieldNumber = int(tagValue >> 3)
176 |
177 | return
178 | }
179 |
180 | func DecodeVarint(buf []byte) (x uint64, i int) {
181 | /*
182 | decode types:
183 | - int32
184 | - int64
185 | - uint32
186 | - uint64
187 | */
188 | return proto.DecodeVarint(buf)
189 | }
190 |
191 | func DecodeFixed32(buf []byte) (x uint32, i int) {
192 | /*
193 | decode types:
194 | - fixed32
195 | - sfixed32
196 | - float
197 | */
198 | x = binary.LittleEndian.Uint32(buf)
199 | i = 4
200 | return
201 | }
202 |
203 | func DecodeFixed64(buf []byte) (x uint64, i int) {
204 | /*
205 | decode types:
206 | - fixed64
207 | - sfixed64
208 | - double
209 | */
210 | x = binary.LittleEndian.Uint64(buf)
211 | i = 8
212 | return
213 | }
214 |
215 | func DecodeZigzag32(buf []byte) (x uint64, i int) {
216 | /*
217 | decode types:
218 | - sint32
219 | */
220 | var v uint64
221 | v, i = DecodeVarint(buf)
222 | x = uint64((uint32(v) >> 1) ^ uint32((int32(v&1)<<31)>>31))
223 | return
224 | }
225 |
226 | func DecodeZigzag64(buf []byte) (x uint64, i int) {
227 | /*
228 | decode types:
229 | - sint64
230 | */
231 | x, i = DecodeVarint(buf)
232 | x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
233 | return
234 | }
235 |
236 | func DecodeBytes(buf []byte) (x []byte, i int) {
237 | /*
238 | decode types:
239 | - []byte
240 | - message
241 | */
242 | shift := 0
243 |
244 | var len uint64
245 | len, shift = DecodeVarint(buf[i:])
246 | i += shift
247 |
248 | x = make([]byte, len)
249 | copy(x, buf[i:])
250 | i += int(len)
251 |
252 | return
253 | }
254 |
--------------------------------------------------------------------------------
/proto/encode_number_test.go:
--------------------------------------------------------------------------------
1 | package proto
2 |
3 | import (
4 | "testing"
5 |
6 | "bytes"
7 |
8 | "github.com/golang/protobuf/protoc-gen-go/descriptor"
9 | )
10 |
11 | func TestEncodeFloat(t *testing.T) {
12 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_FLOAT)
13 | n := 1
14 |
15 | var buf []byte
16 | var err error
17 |
18 | buf, err = encodeFloat(10.01, n, wt, false)
19 |
20 | if err != nil {
21 | t.Fatalf("Error with encodeFloat: %#v", err)
22 | }
23 |
24 | if !bytes.Equal(buf, []byte{0xd, 0xf6, 0x28, 0x20, 0x41}) {
25 | t.Fatalf("Invalid encodeFloat result: %#v", buf)
26 | }
27 | }
28 |
29 | func TestEncodeFloatRepeated(t *testing.T) {
30 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_FLOAT)
31 | n := 1
32 |
33 | var buf []byte
34 | var err error
35 |
36 | buf, err = encodeFloat([]interface{}{20.02, 30.03}, n, wt, true)
37 |
38 | if err != nil {
39 | t.Fatalf("Error with encodeFloat (repeated): %#v", err)
40 | }
41 |
42 | if !bytes.Equal(buf, []byte{0xd, 0x8, 0xf6, 0x28, 0xa0, 0x41, 0x71, 0x3d, 0xf0, 0x41}) {
43 | t.Fatalf("Invalid encodeFloat (repeated) result: %#v", buf)
44 | }
45 | }
46 |
47 | func TestEncodeDouble(t *testing.T) {
48 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
49 | n := 1
50 |
51 | var buf []byte
52 | var err error
53 |
54 | buf, err = encodeDouble(10.01, n, wt, false)
55 |
56 | if err != nil {
57 | t.Fatalf("Error with encodeDouble: %#v", err)
58 | }
59 |
60 | if !bytes.Equal(buf, []byte{0x9, 0x85, 0xeb, 0x51, 0xb8, 0x1e, 0x5, 0x24, 0x40}) {
61 | t.Fatalf("Invalid encodeDouble result: %#v", buf)
62 | }
63 | }
64 |
65 | func TestEncodeDoubleRepeated(t *testing.T) {
66 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
67 | n := 1
68 |
69 | var buf []byte
70 | var err error
71 |
72 | buf, err = encodeDouble([]interface{}{20.02, 30.03}, n, wt, true)
73 |
74 | if err != nil {
75 | t.Fatalf("Error with encodeDouble (repeated): %#v", err)
76 | }
77 |
78 | if !bytes.Equal(buf, []byte{0x9, 0x10, 0x85, 0xeb, 0x51, 0xb8, 0x1e, 0x5, 0x34, 0x40, 0x48, 0xe1, 0x7a, 0x14, 0xae, 0x7, 0x3e, 0x40}) {
79 | t.Fatalf("Invalid encodeDouble (repeated) result: %#v", buf)
80 | }
81 | }
82 |
83 | func TestEncodeBool(t *testing.T) {
84 | t.SkipNow()
85 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_BOOL)
86 | n := 1
87 |
88 | var buf []byte
89 | var err error
90 |
91 | buf, err = encodeBool(true, n, wt, false)
92 |
93 | if err != nil {
94 | t.Fatalf("Error with encodeBool: %#v", err)
95 | }
96 |
97 | if !bytes.Equal(buf, []byte{0x8, 0x1}) {
98 | t.Fatalf("Invalid encodeBool result: %#v", buf)
99 | }
100 | }
101 |
102 | func TestEncodeBoolRepeated(t *testing.T) {
103 | t.SkipNow()
104 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_BOOL)
105 | n := 1
106 |
107 | var buf []byte
108 | var err error
109 |
110 | buf, err = encodeBool([]interface{}{true, false}, n, wt, true)
111 |
112 | if err != nil {
113 | t.Fatalf("Error with encodeBool (repeated): %#v", err)
114 | }
115 |
116 | if !bytes.Equal(buf, []byte{0x8, 0x2, 0x1, 0x0}) {
117 | t.Fatalf("Invalid encodeBool (repeated) result: %#v", buf)
118 | }
119 | }
120 |
121 | func TestEncodeSInt32(t *testing.T) {
122 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_SINT32)
123 | n := 1
124 |
125 | var buf []byte
126 | var err error
127 |
128 | buf, err = encodeSInt32(float64(-100), n, wt, false)
129 |
130 | if err != nil {
131 | t.Fatalf("Error with encodeSInt32: %#v", err)
132 | }
133 |
134 | if !bytes.Equal(buf, []byte{0x8, 0xc7, 0x1}) {
135 | t.Fatalf("Invalid encodeSInt32 result: %#v", buf)
136 | }
137 | }
138 |
139 | func TestEncodeSInt32Repeated(t *testing.T) {
140 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_SINT32)
141 | n := 1
142 |
143 | var buf []byte
144 | var err error
145 |
146 | buf, err = encodeSInt32([]interface{}{float64(-200), float64(300)}, n, wt, true)
147 |
148 | if err != nil {
149 | t.Fatalf("Error with encodeSInt32 (repeated): %#v", err)
150 | }
151 |
152 | if !bytes.Equal(buf, []byte{0x8, 0x4, 0x8f, 0x3, 0xd8, 0x4}) {
153 | t.Fatalf("Invalid encodeSInt32 (repeated) result: %#v", buf)
154 | }
155 | }
156 |
157 | func TestEncodeSInt64(t *testing.T) {
158 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_SINT64)
159 | n := 1
160 |
161 | var buf []byte
162 | var err error
163 |
164 | buf, err = encodeSInt64(float64(-1000), n, wt, false)
165 |
166 | if err != nil {
167 | t.Fatalf("Error with encodeSInt64: %#v", err)
168 | }
169 |
170 | if !bytes.Equal(buf, []byte{0x8, 0xcf, 0xf}) {
171 | t.Fatalf("Invalid encodeSInt64 result: %#v", buf)
172 | }
173 | }
174 |
175 | func TestEncodeSInt64Repeated(t *testing.T) {
176 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_SINT64)
177 | n := 1
178 |
179 | var buf []byte
180 | var err error
181 |
182 | buf, err = encodeSInt64([]interface{}{float64(-2000), float64(3000)}, n, wt, true)
183 |
184 | if err != nil {
185 | t.Fatalf("Error with encodeSInt64 (repeated): %#v", err)
186 | }
187 |
188 | if !bytes.Equal(buf, []byte{0x8, 0x4, 0x9f, 0x1f, 0xf0, 0x2e}) {
189 | t.Fatalf("Invalid encodeSInt64 (repeated) result: %#v", buf)
190 | }
191 | }
192 |
193 | func TestEncodeFixed32(t *testing.T) {
194 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_FIXED32)
195 | n := 1
196 |
197 | var buf []byte
198 | var err error
199 |
200 | buf, err = encodeFixed32(float64(10000), n, wt, false)
201 |
202 | if err != nil {
203 | t.Fatalf("Error with encodeFixed32: %#v", err)
204 | }
205 |
206 | if !bytes.Equal(buf, []byte{0xd, 0x10, 0x27, 0x0, 0x0}) {
207 | t.Fatalf("Invalid encodeFixed32 result: %#v", buf)
208 | }
209 | }
210 |
211 | func TestEncodeFixed32Repeated(t *testing.T) {
212 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_FIXED32)
213 | n := 1
214 |
215 | var buf []byte
216 | var err error
217 |
218 | buf, err = encodeFixed32([]interface{}{float64(20000), float64(30000)}, n, wt, true)
219 |
220 | if err != nil {
221 | t.Fatalf("Error with encodeFixed32 (repeated): %#v", err)
222 | }
223 |
224 | if !bytes.Equal(buf, []byte{0xd, 0x8, 0x20, 0x4e, 0x0, 0x0, 0x30, 0x75, 0x0, 0x0}) {
225 | t.Fatalf("Invalid encodeFixed32 (repeated) result: %#v", buf)
226 | }
227 | }
228 |
229 | func TestEncodeFixed64(t *testing.T) {
230 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_FIXED64)
231 | n := 1
232 |
233 | var buf []byte
234 | var err error
235 |
236 | buf, err = encodeFixed64(float64(100000), n, wt, false)
237 |
238 | if err != nil {
239 | t.Fatalf("Error with encodeFixed64: %#v", err)
240 | }
241 |
242 | if !bytes.Equal(buf, []byte{0x9, 0xa0, 0x86, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0}) {
243 | t.Fatalf("Invalid encodeFixed64 result: %#v", buf)
244 | }
245 | }
246 |
247 | func TestEncodeFixed64Repeated(t *testing.T) {
248 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_FIXED64)
249 | n := 1
250 |
251 | var buf []byte
252 | var err error
253 |
254 | buf, err = encodeFixed64([]interface{}{float64(200000), float64(300000)}, n, wt, true)
255 |
256 | if err != nil {
257 | t.Fatalf("Error with encodeFixed64 (repeated): %#v", err)
258 | }
259 |
260 | if !bytes.Equal(buf, []byte{0x9, 0x10, 0x40, 0xd, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe0, 0x93, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0}) {
261 | t.Fatalf("Invalid encodeFixed64 (repeated) result: %#v", buf)
262 | }
263 | }
264 |
265 | func TestEncodeInt(t *testing.T) {
266 | t.SkipNow()
267 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_INT64)
268 | n := 1
269 |
270 | var buf []byte
271 | var err error
272 |
273 | buf, err = encodeInt(float64(500), n, wt, false)
274 |
275 | if err != nil {
276 | t.Fatalf("Error with encodeInt: %#v", err)
277 | }
278 |
279 | if !bytes.Equal(buf, []byte{0x8, 0xf4, 0x3}) {
280 | t.Fatalf("Invalid encodeInt result: %#v", buf)
281 | }
282 | }
283 |
284 | func TestEncodeIntRepeated(t *testing.T) {
285 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_INT64)
286 | n := 1
287 |
288 | var buf []byte
289 | var err error
290 |
291 | buf, err = encodeInt([]interface{}{float64(1000), float64(1500)}, n, wt, true)
292 |
293 | if err != nil {
294 | t.Fatalf("Error with encodeInt (repeated): %#v", err)
295 | }
296 |
297 | if !bytes.Equal(buf, []byte{0x8, 0x4, 0xe8, 0x7, 0xdc, 0xb}) {
298 | t.Fatalf("Invalid encodeInt (repeated) result: %#v", buf)
299 | }
300 | }
301 |
--------------------------------------------------------------------------------
/proto/encode_number.go:
--------------------------------------------------------------------------------
1 | /*
2 | Encoders for number types
3 | */
4 |
5 | package proto
6 |
7 | import (
8 | "fmt"
9 | "math"
10 | "strconv"
11 | "errors"
12 | )
13 |
14 | func _interfaceFloat64ToFloat64(value interface{}) (res float64, err error) {
15 | // try to convert interface with float64 inside
16 | _value, ok := value.(float64)
17 | if !ok {
18 | err = fmt.Errorf("Conversion error (%T) %#v to float64", value, value)
19 | // try to convert interface with string inside
20 | var vv string
21 | vv, ok = value.(string)
22 | if !ok {
23 | //err = fmt.Errorf("Conversion error (%T) %#v to string", value, value)
24 | return
25 | }
26 | // convert string to float
27 | return strconv.ParseFloat(vv, 64)
28 | }
29 | res = float64(_value)
30 | return
31 | }
32 |
33 | func _interfaceFloat64ArrayToIntArray(value interface{}) (res []int, err error) {
34 | _value, ok := value.([]interface{})
35 | if !ok {
36 | err = fmt.Errorf("Conversion error (%T) %#v to []interface{}", value, value)
37 | return
38 | }
39 | res = make([]int, len(_value))
40 | for i, v := range _value {
41 | var vv float64
42 | vv, err = _interfaceFloat64ToFloat64(v)
43 | if err != nil {
44 | return
45 | }
46 | res[i] = int(vv)
47 | }
48 | return
49 | }
50 |
51 | func _interfaceFloat64ArrayToFloat64Array(value interface{}) (res []float64, err error) {
52 | _value, ok := value.([]interface{})
53 | if !ok {
54 | err = fmt.Errorf("Conversion error (%T) %#v to []interface{}", value, value)
55 | return
56 | }
57 | res = make([]float64, len(_value))
58 | for i, v := range _value {
59 | var vv float64
60 | vv, err = _interfaceFloat64ToFloat64(v)
61 | if err != nil {
62 | return
63 | }
64 | res[i] = vv
65 | }
66 | return
67 | }
68 |
69 | func encodeFloat(value interface{}, n int, wt int, repeated bool) (resultBuf []byte, err error) {
70 | if repeated {
71 | var _value []float64
72 | _value, err = _interfaceFloat64ArrayToFloat64Array(value)
73 | if err != nil {
74 | return
75 | }
76 | var repBuf []byte
77 | for _, v := range _value {
78 | repBuf = append(repBuf, EncodeFixed32((math.Float32bits(float32(v))))...)
79 | }
80 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
81 | resultBuf = append(resultBuf, EncodeBytes(repBuf)...)
82 | } else {
83 | var _value float64
84 | _value, err = _interfaceFloat64ToFloat64(value)
85 | if err != nil {
86 | return
87 | }
88 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
89 | resultBuf = append(resultBuf, EncodeFixed32((math.Float32bits(float32(_value))))...)
90 | }
91 | return
92 | }
93 |
94 | func encodeDouble(value interface{}, n int, wt int, repeated bool) (resultBuf []byte, err error) {
95 | if repeated {
96 | var _value []float64
97 | _value, err = _interfaceFloat64ArrayToFloat64Array(value)
98 | if err != nil {
99 | return
100 | }
101 | var repBuf []byte
102 | for _, v := range _value {
103 | repBuf = append(repBuf, EncodeFixed64((math.Float64bits(float64(v))))...)
104 | }
105 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
106 | resultBuf = append(resultBuf, EncodeBytes(repBuf)...)
107 | } else {
108 | var _value float64
109 | _value, err = _interfaceFloat64ToFloat64(value)
110 | if err != nil {
111 | return
112 | }
113 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
114 | resultBuf = append(resultBuf, EncodeFixed64((math.Float64bits(float64(_value))))...)
115 | }
116 | return
117 | }
118 |
119 | func encodeBool(value interface{}, n int, wt int, repeated bool) (resultBuf []byte, err error) {
120 | if repeated {
121 | _value, ok := value.([]interface{})
122 | if !ok {
123 | err = fmt.Errorf("encodeBool: Conversion error (%T) %#v to []interface{}", value, value)
124 | return
125 | }
126 | var repBuf []byte
127 | for _, v := range _value {
128 | vv, ok := v.(string)
129 | if !ok {
130 | err = fmt.Errorf("encodeBool: Conversion error (%T) %#v to string", v, v)
131 | }
132 | if vv == "true" {
133 | repBuf = append(repBuf, EncodeVarint(uint64(1))...)
134 | } else if vv == "false" {
135 | repBuf = append(repBuf, EncodeVarint(uint64(0))...)
136 | } else {
137 | err = fmt.Errorf("encodeBool: Conversion error (%v) %#v to bool", vv, v)
138 | }
139 |
140 | }
141 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
142 | resultBuf = append(resultBuf, EncodeBytes(repBuf)...)
143 | } else {
144 | _value, ok := value.(string)
145 | if !ok {
146 | err = fmt.Errorf("encodeBool: Conversion error (%T) %#v to string", value, value)
147 | return
148 | }
149 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
150 |
151 | if _value == "true" {
152 | resultBuf = append(resultBuf, EncodeVarint(uint64(1))...)
153 | } else if _value == "false" {
154 | resultBuf = append(resultBuf, EncodeVarint(uint64(0))...)
155 | } else {
156 | err = fmt.Errorf("encodeBool: Conversion error (%v) to bool", _value)
157 | }
158 | }
159 | return
160 | }
161 |
162 | func encodeSInt32(value interface{}, n int, wt int, repeated bool) (resultBuf []byte, err error) {
163 | if repeated {
164 | var _value []int
165 | _value, err = _interfaceFloat64ArrayToIntArray(value)
166 | if err != nil {
167 | return
168 | }
169 | var repBuf []byte
170 | for _, v := range _value {
171 | repBuf = append(repBuf, EncodeZigzag32(uint64(v))...)
172 | }
173 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
174 | resultBuf = append(resultBuf, EncodeBytes(repBuf)...)
175 | } else {
176 | var _value float64
177 | _value, err = _interfaceFloat64ToFloat64(value)
178 | if err != nil {
179 | return
180 | }
181 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
182 | resultBuf = append(resultBuf, EncodeZigzag32(uint64(_value))...)
183 | }
184 | return
185 | }
186 |
187 | func encodeSInt64(value interface{}, n int, wt int, repeated bool) (resultBuf []byte, err error) {
188 | if repeated {
189 | var _value []int
190 | _value, err = _interfaceFloat64ArrayToIntArray(value)
191 | if err != nil {
192 | return
193 | }
194 | var repBuf []byte
195 | for _, v := range _value {
196 | repBuf = append(repBuf, EncodeZigzag64(uint64(v))...)
197 | }
198 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
199 | resultBuf = append(resultBuf, EncodeBytes(repBuf)...)
200 | } else {
201 | var _value float64
202 | _value, err = _interfaceFloat64ToFloat64(value)
203 | if err != nil {
204 | return
205 | }
206 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
207 | resultBuf = append(resultBuf, EncodeZigzag64(uint64(_value))...)
208 | }
209 | return
210 | }
211 |
212 | func encodeFixed32(value interface{}, n int, wt int, repeated bool) (resultBuf []byte, err error) {
213 | if repeated {
214 | var _value []int
215 | _value, err = _interfaceFloat64ArrayToIntArray(value)
216 | if err != nil {
217 | return
218 | }
219 | var repBuf []byte
220 | for _, v := range _value {
221 | repBuf = append(repBuf, EncodeFixed32(uint32(v))...)
222 | }
223 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
224 | resultBuf = append(resultBuf, EncodeBytes(repBuf)...)
225 | } else {
226 | var _value float64
227 | _value, err = _interfaceFloat64ToFloat64(value)
228 | if err != nil {
229 | return
230 | }
231 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
232 | resultBuf = append(resultBuf, EncodeFixed32(uint32(_value))...)
233 | }
234 | return
235 | }
236 |
237 | func encodeFixed64(value interface{}, n int, wt int, repeated bool) (resultBuf []byte, err error) {
238 | if repeated {
239 | var _value []int
240 | _value, err = _interfaceFloat64ArrayToIntArray(value)
241 | if err != nil {
242 | return
243 | }
244 | var repBuf []byte
245 | for _, v := range _value {
246 | repBuf = append(repBuf, EncodeFixed64(uint64(v))...)
247 | }
248 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
249 | resultBuf = append(resultBuf, EncodeBytes(repBuf)...)
250 | } else {
251 | var _value float64
252 | _value, err = _interfaceFloat64ToFloat64(value)
253 | if err != nil {
254 | return
255 | }
256 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
257 | resultBuf = append(resultBuf, EncodeFixed64(uint64(_value))...)
258 | }
259 | return
260 | }
261 |
262 | func encodeInt(value interface{}, n int, wt int, repeated bool) (resultBuf []byte, err error) {
263 | if repeated {
264 | var _value []int
265 | _value, err = _interfaceFloat64ArrayToIntArray(value)
266 | if err != nil {
267 | return
268 | }
269 | var repBuf []byte
270 | for _, v := range _value {
271 | repBuf = append(repBuf, EncodeVarint(uint64(v))...)
272 | }
273 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
274 | resultBuf = append(resultBuf, EncodeBytes(repBuf)...)
275 | } else {
276 | valStr, ok := value.(string)
277 | if !ok {
278 | return nil, errors.New("Should be a string")
279 | }
280 |
281 | _value, err := strconv.ParseInt(valStr, 10, 64)
282 | if err != nil {
283 | return nil, err
284 | }
285 | resultBuf = append(resultBuf, EncodeTag(n, wt)...)
286 | resultBuf = append(resultBuf, EncodeVarint(uint64(_value))...)
287 | }
288 | return
289 | }
290 |
--------------------------------------------------------------------------------
/fixtures/simple/simple.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: simple.proto
3 | // DO NOT EDIT!
4 |
5 | /*
6 | Package simple is a generated protocol buffer package.
7 |
8 | It is generated from these files:
9 | simple.proto
10 |
11 | It has these top-level messages:
12 | Req
13 | Res
14 | */
15 | package simple
16 |
17 | import proto "github.com/golang/protobuf/proto"
18 | import fmt "fmt"
19 | import math "math"
20 |
21 | import (
22 | context "golang.org/x/net/context"
23 | grpc "google.golang.org/grpc"
24 | )
25 |
26 | // Reference imports to suppress errors if they are not otherwise used.
27 | var _ = proto.Marshal
28 | var _ = fmt.Errorf
29 | var _ = math.Inf
30 |
31 | // This is a compile-time assertion to ensure that this generated file
32 | // is compatible with the proto package it is being compiled against.
33 | // A compilation error at this line likely means your copy of the
34 | // proto package needs to be updated.
35 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
36 |
37 | type Req struct {
38 | Int32Field int32 `protobuf:"varint,1,opt,name=int32field" json:"int32field,omitempty"`
39 | Int64Field int64 `protobuf:"varint,2,opt,name=int64field" json:"int64field,omitempty"`
40 | Floatfield float32 `protobuf:"fixed32,3,opt,name=floatfield" json:"floatfield,omitempty"`
41 | Doublefield float64 `protobuf:"fixed64,4,opt,name=doublefield" json:"doublefield,omitempty"`
42 | Uint32Field uint32 `protobuf:"varint,5,opt,name=uint32field" json:"uint32field,omitempty"`
43 | Uint64Field uint64 `protobuf:"varint,6,opt,name=uint64field" json:"uint64field,omitempty"`
44 | Sint32Field int32 `protobuf:"zigzag32,7,opt,name=sint32field" json:"sint32field,omitempty"`
45 | Sint64Field int64 `protobuf:"zigzag64,8,opt,name=sint64field" json:"sint64field,omitempty"`
46 | Fixed32Field uint32 `protobuf:"fixed32,9,opt,name=fixed32field" json:"fixed32field,omitempty"`
47 | Fixed64Field uint64 `protobuf:"fixed64,10,opt,name=fixed64field" json:"fixed64field,omitempty"`
48 | Sfixed32Field int32 `protobuf:"fixed32,11,opt,name=sfixed32field" json:"sfixed32field,omitempty"`
49 | Sfixed64Field int64 `protobuf:"fixed64,12,opt,name=sfixed64field" json:"sfixed64field,omitempty"`
50 | Boolfield bool `protobuf:"varint,13,opt,name=boolfield" json:"boolfield,omitempty"`
51 | Stringfield string `protobuf:"bytes,14,opt,name=stringfield" json:"stringfield,omitempty"`
52 | Bytesfield []byte `protobuf:"bytes,15,opt,name=bytesfield,proto3" json:"bytesfield,omitempty"`
53 | Int32Repeated []int32 `protobuf:"varint,16,rep,packed,name=int32Repeated" json:"int32Repeated,omitempty"`
54 | }
55 |
56 | func (m *Req) Reset() { *m = Req{} }
57 | func (m *Req) String() string { return proto.CompactTextString(m) }
58 | func (*Req) ProtoMessage() {}
59 | func (*Req) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
60 |
61 | func (m *Req) GetInt32Field() int32 {
62 | if m != nil {
63 | return m.Int32Field
64 | }
65 | return 0
66 | }
67 |
68 | func (m *Req) GetInt64Field() int64 {
69 | if m != nil {
70 | return m.Int64Field
71 | }
72 | return 0
73 | }
74 |
75 | func (m *Req) GetFloatfield() float32 {
76 | if m != nil {
77 | return m.Floatfield
78 | }
79 | return 0
80 | }
81 |
82 | func (m *Req) GetDoublefield() float64 {
83 | if m != nil {
84 | return m.Doublefield
85 | }
86 | return 0
87 | }
88 |
89 | func (m *Req) GetUint32Field() uint32 {
90 | if m != nil {
91 | return m.Uint32Field
92 | }
93 | return 0
94 | }
95 |
96 | func (m *Req) GetUint64Field() uint64 {
97 | if m != nil {
98 | return m.Uint64Field
99 | }
100 | return 0
101 | }
102 |
103 | func (m *Req) GetSint32Field() int32 {
104 | if m != nil {
105 | return m.Sint32Field
106 | }
107 | return 0
108 | }
109 |
110 | func (m *Req) GetSint64Field() int64 {
111 | if m != nil {
112 | return m.Sint64Field
113 | }
114 | return 0
115 | }
116 |
117 | func (m *Req) GetFixed32Field() uint32 {
118 | if m != nil {
119 | return m.Fixed32Field
120 | }
121 | return 0
122 | }
123 |
124 | func (m *Req) GetFixed64Field() uint64 {
125 | if m != nil {
126 | return m.Fixed64Field
127 | }
128 | return 0
129 | }
130 |
131 | func (m *Req) GetSfixed32Field() int32 {
132 | if m != nil {
133 | return m.Sfixed32Field
134 | }
135 | return 0
136 | }
137 |
138 | func (m *Req) GetSfixed64Field() int64 {
139 | if m != nil {
140 | return m.Sfixed64Field
141 | }
142 | return 0
143 | }
144 |
145 | func (m *Req) GetBoolfield() bool {
146 | if m != nil {
147 | return m.Boolfield
148 | }
149 | return false
150 | }
151 |
152 | func (m *Req) GetStringfield() string {
153 | if m != nil {
154 | return m.Stringfield
155 | }
156 | return ""
157 | }
158 |
159 | func (m *Req) GetBytesfield() []byte {
160 | if m != nil {
161 | return m.Bytesfield
162 | }
163 | return nil
164 | }
165 |
166 | func (m *Req) GetInt32Repeated() []int32 {
167 | if m != nil {
168 | return m.Int32Repeated
169 | }
170 | return nil
171 | }
172 |
173 | type Res struct {
174 | Int32Field int32 `protobuf:"varint,1,opt,name=int32field" json:"int32field,omitempty"`
175 | Int64Field int64 `protobuf:"varint,2,opt,name=int64field" json:"int64field,omitempty"`
176 | Floatfield float32 `protobuf:"fixed32,3,opt,name=floatfield" json:"floatfield,omitempty"`
177 | Doublefield float64 `protobuf:"fixed64,4,opt,name=doublefield" json:"doublefield,omitempty"`
178 | Uint32Field uint32 `protobuf:"varint,5,opt,name=uint32field" json:"uint32field,omitempty"`
179 | Uint64Field uint64 `protobuf:"varint,6,opt,name=uint64field" json:"uint64field,omitempty"`
180 | Sint32Field int32 `protobuf:"zigzag32,7,opt,name=sint32field" json:"sint32field,omitempty"`
181 | Sint64Field int64 `protobuf:"zigzag64,8,opt,name=sint64field" json:"sint64field,omitempty"`
182 | Fixed32Field uint32 `protobuf:"fixed32,9,opt,name=fixed32field" json:"fixed32field,omitempty"`
183 | Fixed64Field uint64 `protobuf:"fixed64,10,opt,name=fixed64field" json:"fixed64field,omitempty"`
184 | Sfixed32Field int32 `protobuf:"fixed32,11,opt,name=sfixed32field" json:"sfixed32field,omitempty"`
185 | Sfixed64Field int64 `protobuf:"fixed64,12,opt,name=sfixed64field" json:"sfixed64field,omitempty"`
186 | Boolfield bool `protobuf:"varint,13,opt,name=boolfield" json:"boolfield,omitempty"`
187 | Stringfield string `protobuf:"bytes,14,opt,name=stringfield" json:"stringfield,omitempty"`
188 | Bytesfield []byte `protobuf:"bytes,15,opt,name=bytesfield,proto3" json:"bytesfield,omitempty"`
189 | Int32Repeated []int32 `protobuf:"varint,16,rep,packed,name=int32Repeated" json:"int32Repeated,omitempty"`
190 | }
191 |
192 | func (m *Res) Reset() { *m = Res{} }
193 | func (m *Res) String() string { return proto.CompactTextString(m) }
194 | func (*Res) ProtoMessage() {}
195 | func (*Res) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
196 |
197 | func (m *Res) GetInt32Field() int32 {
198 | if m != nil {
199 | return m.Int32Field
200 | }
201 | return 0
202 | }
203 |
204 | func (m *Res) GetInt64Field() int64 {
205 | if m != nil {
206 | return m.Int64Field
207 | }
208 | return 0
209 | }
210 |
211 | func (m *Res) GetFloatfield() float32 {
212 | if m != nil {
213 | return m.Floatfield
214 | }
215 | return 0
216 | }
217 |
218 | func (m *Res) GetDoublefield() float64 {
219 | if m != nil {
220 | return m.Doublefield
221 | }
222 | return 0
223 | }
224 |
225 | func (m *Res) GetUint32Field() uint32 {
226 | if m != nil {
227 | return m.Uint32Field
228 | }
229 | return 0
230 | }
231 |
232 | func (m *Res) GetUint64Field() uint64 {
233 | if m != nil {
234 | return m.Uint64Field
235 | }
236 | return 0
237 | }
238 |
239 | func (m *Res) GetSint32Field() int32 {
240 | if m != nil {
241 | return m.Sint32Field
242 | }
243 | return 0
244 | }
245 |
246 | func (m *Res) GetSint64Field() int64 {
247 | if m != nil {
248 | return m.Sint64Field
249 | }
250 | return 0
251 | }
252 |
253 | func (m *Res) GetFixed32Field() uint32 {
254 | if m != nil {
255 | return m.Fixed32Field
256 | }
257 | return 0
258 | }
259 |
260 | func (m *Res) GetFixed64Field() uint64 {
261 | if m != nil {
262 | return m.Fixed64Field
263 | }
264 | return 0
265 | }
266 |
267 | func (m *Res) GetSfixed32Field() int32 {
268 | if m != nil {
269 | return m.Sfixed32Field
270 | }
271 | return 0
272 | }
273 |
274 | func (m *Res) GetSfixed64Field() int64 {
275 | if m != nil {
276 | return m.Sfixed64Field
277 | }
278 | return 0
279 | }
280 |
281 | func (m *Res) GetBoolfield() bool {
282 | if m != nil {
283 | return m.Boolfield
284 | }
285 | return false
286 | }
287 |
288 | func (m *Res) GetStringfield() string {
289 | if m != nil {
290 | return m.Stringfield
291 | }
292 | return ""
293 | }
294 |
295 | func (m *Res) GetBytesfield() []byte {
296 | if m != nil {
297 | return m.Bytesfield
298 | }
299 | return nil
300 | }
301 |
302 | func (m *Res) GetInt32Repeated() []int32 {
303 | if m != nil {
304 | return m.Int32Repeated
305 | }
306 | return nil
307 | }
308 |
309 | func init() {
310 | proto.RegisterType((*Req)(nil), "simple.Req")
311 | proto.RegisterType((*Res)(nil), "simple.Res")
312 | }
313 |
314 | // Reference imports to suppress errors if they are not otherwise used.
315 | var _ context.Context
316 | var _ grpc.ClientConn
317 |
318 | // This is a compile-time assertion to ensure that this generated file
319 | // is compatible with the grpc package it is being compiled against.
320 | const _ = grpc.SupportPackageIsVersion4
321 |
322 | // Client API for Simple service
323 |
324 | type SimpleClient interface {
325 | Test(ctx context.Context, in *Req, opts ...grpc.CallOption) (*Res, error)
326 | }
327 |
328 | type simpleClient struct {
329 | cc *grpc.ClientConn
330 | }
331 |
332 | func NewSimpleClient(cc *grpc.ClientConn) SimpleClient {
333 | return &simpleClient{cc}
334 | }
335 |
336 | func (c *simpleClient) Test(ctx context.Context, in *Req, opts ...grpc.CallOption) (*Res, error) {
337 | out := new(Res)
338 | err := grpc.Invoke(ctx, "/simple.Simple/Test", in, out, c.cc, opts...)
339 | if err != nil {
340 | return nil, err
341 | }
342 | return out, nil
343 | }
344 |
345 | // Server API for Simple service
346 |
347 | type SimpleServer interface {
348 | Test(context.Context, *Req) (*Res, error)
349 | }
350 |
351 | func RegisterSimpleServer(s *grpc.Server, srv SimpleServer) {
352 | s.RegisterService(&_Simple_serviceDesc, srv)
353 | }
354 |
355 | func _Simple_Test_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
356 | in := new(Req)
357 | if err := dec(in); err != nil {
358 | return nil, err
359 | }
360 | if interceptor == nil {
361 | return srv.(SimpleServer).Test(ctx, in)
362 | }
363 | info := &grpc.UnaryServerInfo{
364 | Server: srv,
365 | FullMethod: "/simple.Simple/Test",
366 | }
367 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
368 | return srv.(SimpleServer).Test(ctx, req.(*Req))
369 | }
370 | return interceptor(ctx, in, info, handler)
371 | }
372 |
373 | var _Simple_serviceDesc = grpc.ServiceDesc{
374 | ServiceName: "simple.Simple",
375 | HandlerType: (*SimpleServer)(nil),
376 | Methods: []grpc.MethodDesc{
377 | {
378 | MethodName: "Test",
379 | Handler: _Simple_Test_Handler,
380 | },
381 | },
382 | Streams: []grpc.StreamDesc{},
383 | Metadata: "simple.proto",
384 | }
385 |
386 | func init() { proto.RegisterFile("simple.proto", fileDescriptor0) }
387 |
388 | var fileDescriptor0 = []byte{
389 | // 316 bytes of a gzipped FileDescriptorProto
390 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xec, 0x94, 0x41, 0x6e, 0xea, 0x30,
391 | 0x10, 0x86, 0x35, 0x24, 0x04, 0x30, 0xe1, 0xc1, 0xf3, 0x0a, 0x55, 0x55, 0x35, 0x42, 0x5d, 0x8c,
392 | 0xba, 0x60, 0x01, 0x55, 0x0f, 0x32, 0xed, 0x05, 0x88, 0x62, 0xaa, 0x48, 0x29, 0x01, 0x6c, 0xa4,
393 | 0xf6, 0x48, 0xbd, 0x65, 0x95, 0x38, 0x2e, 0xe3, 0x55, 0x2f, 0xc0, 0xd2, 0xdf, 0xff, 0xe9, 0xd7,
394 | 0x40, 0x46, 0xa3, 0x72, 0x5b, 0x7d, 0x1c, 0x6b, 0xb3, 0x3e, 0x9e, 0x1b, 0xd7, 0xe8, 0xcc, 0xbf,
395 | 0x56, 0xdf, 0xa9, 0x4a, 0xd8, 0x9c, 0xf4, 0x83, 0x52, 0xd5, 0xc1, 0x6d, 0x37, 0xfb, 0xca, 0xd4,
396 | 0xe5, 0x12, 0x10, 0x68, 0xc8, 0x82, 0xf4, 0xf9, 0xcb, 0xb3, 0xcf, 0x07, 0x08, 0x94, 0xb0, 0x20,
397 | 0x6d, 0xbe, 0xaf, 0x9b, 0x9d, 0xf3, 0x79, 0x82, 0x40, 0x03, 0x16, 0x44, 0xa3, 0x9a, 0x96, 0xcd,
398 | 0xa5, 0xa8, 0x8d, 0x17, 0x52, 0x04, 0x02, 0x96, 0xa8, 0x35, 0x2e, 0x62, 0x84, 0x21, 0x02, 0xcd,
399 | 0x58, 0xa2, 0x60, 0x84, 0x21, 0x32, 0x04, 0x4a, 0x59, 0xa2, 0xd6, 0xb0, 0xa2, 0x63, 0x84, 0x40,
400 | 0xff, 0x59, 0xa2, 0x60, 0x84, 0x8e, 0x31, 0x02, 0x69, 0x96, 0x48, 0xaf, 0x54, 0xbe, 0xaf, 0x3e,
401 | 0x4d, 0x19, 0x4a, 0x26, 0x08, 0x34, 0xe2, 0x88, 0xfd, 0x3a, 0xa1, 0x46, 0x21, 0x50, 0xc6, 0x11,
402 | 0xd3, 0x8f, 0x6a, 0x66, 0xa3, 0xa2, 0x29, 0x02, 0xcd, 0x39, 0x86, 0x57, 0x2b, 0x54, 0xe5, 0x08,
403 | 0xb4, 0xe0, 0x18, 0xea, 0x7b, 0x35, 0x29, 0x9a, 0xa6, 0xf6, 0xc6, 0x0c, 0x81, 0xc6, 0x7c, 0x05,
404 | 0xdd, 0x6f, 0x72, 0xe7, 0xea, 0xf0, 0xee, 0xf3, 0x7f, 0x08, 0x34, 0x61, 0x89, 0xda, 0xaf, 0x53,
405 | 0x7c, 0x39, 0x63, 0xbd, 0x30, 0x47, 0xa0, 0x9c, 0x05, 0x69, 0xa7, 0xe8, 0xfe, 0x23, 0x36, 0x47,
406 | 0xb3, 0x73, 0xa6, 0x5c, 0x2e, 0x30, 0xa1, 0x21, 0xc7, 0xb0, 0xdf, 0x15, 0x7b, 0xdb, 0x95, 0xdb,
407 | 0xae, 0xfc, 0xb5, 0x2b, 0x9b, 0x27, 0x95, 0xbd, 0x76, 0x17, 0x46, 0xa3, 0x4a, 0xdf, 0x8c, 0x75,
408 | 0x7a, 0xba, 0xee, 0x0f, 0x10, 0x9b, 0xd3, 0x9d, 0x78, 0xd8, 0x22, 0xeb, 0x4e, 0xd2, 0xf6, 0x27,
409 | 0x00, 0x00, 0xff, 0xff, 0xe5, 0x5d, 0x8f, 0x4e, 0xa2, 0x04, 0x00, 0x00,
410 | }
411 |
--------------------------------------------------------------------------------
/proto/decode_number_test.go:
--------------------------------------------------------------------------------
1 | package proto
2 |
3 | import (
4 | "testing"
5 |
6 | "math"
7 |
8 | "github.com/golang/protobuf/protoc-gen-go/descriptor"
9 | )
10 |
11 | const TOLERANCE = 0.001
12 |
13 | func TestDecodeFloat(t *testing.T) {
14 | VALUE := -10.01
15 |
16 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_FLOAT)
17 | n := 1
18 |
19 | var buf []byte
20 | var err error
21 |
22 | buf, err = encodeFloat(VALUE, n, wt, false)
23 |
24 | if err != nil {
25 | t.Fatalf("Error with encodeFloat: %#v", err)
26 | }
27 |
28 | index := 0
29 | shift := 0
30 |
31 | var wireType int
32 | var fieldNumber int
33 |
34 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
35 | index += shift
36 |
37 | if wt != wireType {
38 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
39 | }
40 | if n != fieldNumber {
41 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
42 | }
43 |
44 | var value interface{} = nil
45 |
46 | value, shift, err = decodeFloat(buf[index:], false)
47 | index += shift
48 |
49 | if err != nil {
50 | t.Fatalf("Error with decodeFloat: %#v", err)
51 | }
52 |
53 | _value, _ := value.(float64)
54 |
55 | if diff := math.Abs(_value - VALUE); diff > TOLERANCE {
56 | t.Fatalf("Invalid decodeFloat result: %#v != %#v", value, VALUE)
57 | }
58 | }
59 |
60 | func TestDecodeFloatRepeated(t *testing.T) {
61 | VALUE_1 := -20.02
62 | VALUE_2 := -30.03
63 |
64 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_FLOAT)
65 | n := 1
66 |
67 | var buf []byte
68 | var err error
69 |
70 | buf, err = encodeFloat([]interface{}{VALUE_1, VALUE_2}, n, wt, true)
71 |
72 | if err != nil {
73 | t.Fatalf("Error with encodeFloat (repeated): %#v", err)
74 | }
75 |
76 | index := 0
77 | shift := 0
78 |
79 | var wireType int
80 | var fieldNumber int
81 |
82 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
83 | index += shift
84 |
85 | if wt != wireType {
86 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
87 | }
88 | if n != fieldNumber {
89 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
90 | }
91 |
92 | var value interface{} = nil
93 |
94 | value, shift, err = decodeFloat(buf[index:], true)
95 | index += shift
96 |
97 | if err != nil {
98 | t.Fatalf("Error with decodeFloat (repeated): %#v", err)
99 | }
100 |
101 | _value, _ := value.([]float64)
102 |
103 | if diff := math.Abs(_value[0] - VALUE_1); diff > TOLERANCE {
104 | t.Fatalf("Invalid decodeFloat (repeated) result: %#v != %#v", _value[0], VALUE_1)
105 | }
106 | if diff := math.Abs(_value[1] - VALUE_2); diff > TOLERANCE {
107 | t.Fatalf("Invalid decodeFloat (repeated) result: %#v != %#v", _value[1], VALUE_2)
108 | }
109 | }
110 |
111 | func TestDecodeDouble(t *testing.T) {
112 | VALUE := -100.01
113 |
114 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
115 | n := 1
116 |
117 | var buf []byte
118 | var err error
119 |
120 | buf, err = encodeDouble(VALUE, n, wt, false)
121 |
122 | if err != nil {
123 | t.Fatalf("Error with encodeDouble: %#v", err)
124 | }
125 |
126 | index := 0
127 | shift := 0
128 |
129 | var wireType int
130 | var fieldNumber int
131 |
132 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
133 | index += shift
134 |
135 | if wt != wireType {
136 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
137 | }
138 | if n != fieldNumber {
139 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
140 | }
141 |
142 | var value interface{} = nil
143 |
144 | value, shift, err = decodeDouble(buf[index:], false)
145 | index += shift
146 |
147 | if err != nil {
148 | t.Fatalf("Error with decodeDouble: %#v", err)
149 | }
150 |
151 | _value, _ := value.(float64)
152 |
153 | if diff := math.Abs(_value - VALUE); diff > TOLERANCE {
154 | t.Fatalf("Invalid decodeDouble result: %#v != %#v", value, VALUE)
155 | }
156 | }
157 |
158 | func TestDecodeDoubleRepeated(t *testing.T) {
159 | VALUE_1 := -200.02
160 | VALUE_2 := -300.03
161 |
162 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
163 | n := 1
164 |
165 | var buf []byte
166 | var err error
167 |
168 | buf, err = encodeDouble([]interface{}{VALUE_1, VALUE_2}, n, wt, true)
169 |
170 | if err != nil {
171 | t.Fatalf("Error with encodeDouble (repeated): %#v", err)
172 | }
173 |
174 | index := 0
175 | shift := 0
176 |
177 | var wireType int
178 | var fieldNumber int
179 |
180 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
181 | index += shift
182 |
183 | if wt != wireType {
184 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
185 | }
186 | if n != fieldNumber {
187 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
188 | }
189 |
190 | var value interface{} = nil
191 |
192 | value, shift, err = decodeDouble(buf[index:], true)
193 | index += shift
194 |
195 | if err != nil {
196 | t.Fatalf("Error with decodeDouble (repeated): %#v", err)
197 | }
198 |
199 | _value, _ := value.([]float64)
200 |
201 | if diff := math.Abs(_value[0] - VALUE_1); diff > TOLERANCE {
202 | t.Fatalf("Invalid decodeDouble (repeated) result: %#v != %#v", _value[0], VALUE_1)
203 | }
204 | if diff := math.Abs(_value[1] - VALUE_2); diff > TOLERANCE {
205 | t.Fatalf("Invalid decodeDouble (repeated) result: %#v != %#v", _value[1], VALUE_2)
206 | }
207 | }
208 |
209 | func TestDecodeBool(t *testing.T) {
210 | t.SkipNow()
211 | VALUE := true
212 |
213 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_FLOAT)
214 | n := 1
215 |
216 | var buf []byte
217 | var err error
218 |
219 | buf, err = encodeBool(VALUE, n, wt, false)
220 |
221 | if err != nil {
222 | t.Fatalf("Error with encodeBool: %#v", err)
223 | }
224 |
225 | index := 0
226 | shift := 0
227 |
228 | var wireType int
229 | var fieldNumber int
230 |
231 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
232 | index += shift
233 |
234 | if wt != wireType {
235 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
236 | }
237 | if n != fieldNumber {
238 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
239 | }
240 |
241 | var value interface{} = nil
242 |
243 | value, shift, err = decodeBool(buf[index:], false)
244 | index += shift
245 |
246 | if err != nil {
247 | t.Fatalf("Error with decodeBool: %#v", err)
248 | }
249 |
250 | _value, _ := value.(bool)
251 |
252 | if _value != VALUE {
253 | t.Fatalf("Invalid decodeBool result: %#v != %#v", value, VALUE)
254 | }
255 | }
256 |
257 | func TestDecodeBoolRepeated(t *testing.T) {
258 | t.SkipNow()
259 | VALUE_1 := false
260 | VALUE_2 := true
261 |
262 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_FLOAT)
263 | n := 1
264 |
265 | var buf []byte
266 | var err error
267 |
268 | buf, err = encodeBool([]interface{}{VALUE_1, VALUE_2}, n, wt, true)
269 |
270 | if err != nil {
271 | t.Fatalf("Error with encodeBool (repeated): %#v", err)
272 | }
273 |
274 | index := 0
275 | shift := 0
276 |
277 | var wireType int
278 | var fieldNumber int
279 |
280 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
281 | index += shift
282 |
283 | if wt != wireType {
284 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
285 | }
286 | if n != fieldNumber {
287 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
288 | }
289 |
290 | var value interface{} = nil
291 |
292 | value, shift, err = decodeBool(buf[index:], true)
293 | index += shift
294 |
295 | if err != nil {
296 | t.Fatalf("Error with decodeBool (repeated): %#v", err)
297 | }
298 |
299 | _value, _ := value.([]bool)
300 |
301 | if _value[0] != VALUE_1 {
302 | t.Fatalf("Invalid decodeBool (repeated) result: %#v != %#v", _value[0], VALUE_1)
303 | }
304 | if _value[1] != VALUE_2 {
305 | t.Fatalf("Invalid decodeBool (repeated) result: %#v != %#v", _value[1], VALUE_2)
306 | }
307 | }
308 |
309 | func TestDecodeSInt32(t *testing.T) {
310 | VALUE := -1000
311 |
312 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
313 | n := 1
314 |
315 | var buf []byte
316 | var err error
317 |
318 | buf, err = encodeSInt32(float64(VALUE), n, wt, false)
319 |
320 | if err != nil {
321 | t.Fatalf("Error with encodeSInt32: %#v", err)
322 | }
323 |
324 | index := 0
325 | shift := 0
326 |
327 | var wireType int
328 | var fieldNumber int
329 |
330 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
331 | index += shift
332 |
333 | if wt != wireType {
334 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
335 | }
336 | if n != fieldNumber {
337 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
338 | }
339 |
340 | var value interface{} = nil
341 |
342 | value, shift, err = decodeSInt32(buf[index:], false)
343 | index += shift
344 |
345 | if err != nil {
346 | t.Fatalf("Error with decodeSInt32: %#v", err)
347 | }
348 |
349 | _value, _ := value.(int)
350 |
351 | if _value != VALUE {
352 | t.Fatalf("Invalid decodeSInt32 result: %#v != %#v", value, VALUE)
353 | }
354 | }
355 |
356 | func TestDecodeSInt32Repeated(t *testing.T) {
357 | VALUE_1 := -2000
358 | VALUE_2 := -3000
359 |
360 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
361 | n := 1
362 |
363 | var buf []byte
364 | var err error
365 |
366 | buf, err = encodeSInt32([]interface{}{float64(VALUE_1), float64(VALUE_2)}, n, wt, true)
367 |
368 | if err != nil {
369 | t.Fatalf("Error with encodeSInt32 (repeated): %#v", err)
370 | }
371 |
372 | index := 0
373 | shift := 0
374 |
375 | var wireType int
376 | var fieldNumber int
377 |
378 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
379 | index += shift
380 |
381 | if wt != wireType {
382 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
383 | }
384 | if n != fieldNumber {
385 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
386 | }
387 |
388 | var value interface{} = nil
389 |
390 | value, shift, err = decodeSInt32(buf[index:], true)
391 | index += shift
392 |
393 | if err != nil {
394 | t.Fatalf("Error with decodeSInt32 (repeated): %#v", err)
395 | }
396 |
397 | _value, _ := value.([]int)
398 |
399 | if _value[0] != VALUE_1 {
400 | t.Fatalf("Invalid decodeSInt32 (repeated) result: %#v != %#v", _value[0], VALUE_1)
401 | }
402 | if _value[1] != VALUE_2 {
403 | t.Fatalf("Invalid decodeSInt32 (repeated) result: %#v != %#v", _value[1], VALUE_2)
404 | }
405 | }
406 |
407 | func TestDecodeSInt64(t *testing.T) {
408 | VALUE := -1000
409 |
410 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
411 | n := 1
412 |
413 | var buf []byte
414 | var err error
415 |
416 | buf, err = encodeSInt64(float64(VALUE), n, wt, false)
417 |
418 | if err != nil {
419 | t.Fatalf("Error with encodeSInt64: %#v", err)
420 | }
421 |
422 | index := 0
423 | shift := 0
424 |
425 | var wireType int
426 | var fieldNumber int
427 |
428 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
429 | index += shift
430 |
431 | if wt != wireType {
432 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
433 | }
434 | if n != fieldNumber {
435 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
436 | }
437 |
438 | var value interface{} = nil
439 |
440 | value, shift, err = decodeSInt64(buf[index:], false)
441 | index += shift
442 |
443 | if err != nil {
444 | t.Fatalf("Error with decodeSInt64: %#v", err)
445 | }
446 |
447 | _value, _ := value.(int)
448 |
449 | if _value != VALUE {
450 | t.Fatalf("Invalid decodeSInt64 result: %#v != %#v", value, VALUE)
451 | }
452 | }
453 |
454 | func TestDecodeSInt64Repeated(t *testing.T) {
455 | VALUE_1 := -2000
456 | VALUE_2 := -3000
457 |
458 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
459 | n := 1
460 |
461 | var buf []byte
462 | var err error
463 |
464 | buf, err = encodeSInt64([]interface{}{float64(VALUE_1), float64(VALUE_2)}, n, wt, true)
465 |
466 | if err != nil {
467 | t.Fatalf("Error with encodeSInt64 (repeated): %#v", err)
468 | }
469 |
470 | index := 0
471 | shift := 0
472 |
473 | var wireType int
474 | var fieldNumber int
475 |
476 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
477 | index += shift
478 |
479 | if wt != wireType {
480 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
481 | }
482 | if n != fieldNumber {
483 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
484 | }
485 |
486 | var value interface{} = nil
487 |
488 | value, shift, err = decodeSInt64(buf[index:], true)
489 | index += shift
490 |
491 | if err != nil {
492 | t.Fatalf("Error with decodeSInt64 (repeated): %#v", err)
493 | }
494 |
495 | _value, _ := value.([]int)
496 |
497 | if _value[0] != VALUE_1 {
498 | t.Fatalf("Invalid decodeSInt64 (repeated) result: %#v != %#v", _value[0], VALUE_1)
499 | }
500 | if _value[1] != VALUE_2 {
501 | t.Fatalf("Invalid decodeSInt64 (repeated) result: %#v != %#v", _value[1], VALUE_2)
502 | }
503 | }
504 |
505 | func TestDecodeFixed32(t *testing.T) {
506 | var VALUE uint32 = 4294967295
507 |
508 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
509 | n := 1
510 |
511 | var buf []byte
512 | var err error
513 |
514 | buf, err = encodeFixed32(float64(VALUE), n, wt, false)
515 |
516 | if err != nil {
517 | t.Fatalf("Error with encodeFixed32: %#v", err)
518 | }
519 |
520 | index := 0
521 | shift := 0
522 |
523 | var wireType int
524 | var fieldNumber int
525 |
526 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
527 | index += shift
528 |
529 | if wt != wireType {
530 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
531 | }
532 | if n != fieldNumber {
533 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
534 | }
535 |
536 | var value interface{} = nil
537 |
538 | value, shift, err = decodeFixed32(buf[index:], false)
539 | index += shift
540 |
541 | if err != nil {
542 | t.Fatalf("Error with decodeFixed32: %#v", err)
543 | }
544 |
545 | _value, _ := value.(uint32)
546 |
547 | if _value != VALUE {
548 | t.Fatalf("Invalid decodeFixed32 result: %#v != %#v", _value, VALUE)
549 | }
550 | }
551 |
552 | func TestDecodeFixed32Repeated(t *testing.T) {
553 | var VALUE_1 uint32 = 4294967295
554 | var VALUE_2 uint32 = 4294967295 - 1
555 |
556 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
557 | n := 1
558 |
559 | var buf []byte
560 | var err error
561 |
562 | buf, err = encodeFixed32([]interface{}{float64(VALUE_1), float64(VALUE_2)}, n, wt, true)
563 |
564 | if err != nil {
565 | t.Fatalf("Error with encodeFixed32 (repeated): %#v", err)
566 | }
567 |
568 | index := 0
569 | shift := 0
570 |
571 | var wireType int
572 | var fieldNumber int
573 |
574 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
575 | index += shift
576 |
577 | if wt != wireType {
578 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
579 | }
580 | if n != fieldNumber {
581 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
582 | }
583 |
584 | var value interface{} = nil
585 |
586 | value, shift, err = decodeFixed32(buf[index:], true)
587 | index += shift
588 |
589 | if err != nil {
590 | t.Fatalf("Error with decodeFixed32 (repeated): %#v", err)
591 | }
592 |
593 | _value, _ := value.([]uint32)
594 |
595 | if _value[0] != VALUE_1 {
596 | t.Fatalf("Invalid decodeFixed32 (repeated) result: %#v != %#v", _value[0], VALUE_1)
597 | }
598 | if _value[1] != VALUE_2 {
599 | t.Fatalf("Invalid decodeFixed32 (repeated) result: %#v != %#v", _value[1], VALUE_2)
600 | }
601 | }
602 |
603 | func TestDecodeFixed64(t *testing.T) {
604 | /*
605 | uint64 -> float64 -> uint64 loss
606 | ==
607 | var BIG uint64 = 18446744073709551615
608 | fmt.Printf("%#v %#v", BIG, uint64(float64(BIG)))
609 | ==
610 | 0xffffffffffffffff 0x8000000000000000
611 | */
612 |
613 | var VALUE uint64 = 4294967295
614 |
615 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
616 | n := 1
617 |
618 | var buf []byte
619 | var err error
620 |
621 | buf, err = encodeFixed64(float64(VALUE), n, wt, false)
622 |
623 | if err != nil {
624 | t.Fatalf("Error with encodeFixed64: %#v", err)
625 | }
626 |
627 | index := 0
628 | shift := 0
629 |
630 | var wireType int
631 | var fieldNumber int
632 |
633 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
634 | index += shift
635 |
636 | if wt != wireType {
637 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
638 | }
639 | if n != fieldNumber {
640 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
641 | }
642 |
643 | var value interface{} = nil
644 |
645 | value, shift, err = decodeFixed64(buf[index:], false)
646 | index += shift
647 |
648 | if err != nil {
649 | t.Fatalf("Error with decodeFixed64: %#v", err)
650 | }
651 |
652 | _value, _ := value.(uint64)
653 |
654 | if _value != VALUE {
655 | t.Fatalf("Invalid decodeFixed64 result: %#v != %#v", _value, VALUE)
656 | }
657 | }
658 |
659 | func TestDecodeFixed64Repeated(t *testing.T) {
660 | var VALUE_1 uint64 = 4294967295
661 | var VALUE_2 uint64 = 4294967295 - 1
662 |
663 | wt := FieldTypeToWireType(descriptor.FieldDescriptorProto_TYPE_DOUBLE)
664 | n := 1
665 |
666 | var buf []byte
667 | var err error
668 |
669 | buf, err = encodeFixed64([]interface{}{float64(VALUE_1), float64(VALUE_2)}, n, wt, true)
670 |
671 | if err != nil {
672 | t.Fatalf("Error with encodeFixed64 (repeated): %#v", err)
673 | }
674 |
675 | index := 0
676 | shift := 0
677 |
678 | var wireType int
679 | var fieldNumber int
680 |
681 | wireType, fieldNumber, shift = DecodeTag(buf[index:])
682 | index += shift
683 |
684 | if wt != wireType {
685 | t.Fatalf("Invalid DecodeTag wireType: %v != %v", wt, wireType)
686 | }
687 | if n != fieldNumber {
688 | t.Fatalf("Invalid DecodeTag fieldNumber: %v != %v", n, fieldNumber)
689 | }
690 |
691 | var value interface{} = nil
692 |
693 | value, shift, err = decodeFixed64(buf[index:], true)
694 | index += shift
695 |
696 | if err != nil {
697 | t.Fatalf("Error with decodeFixed64 (repeated): %#v", err)
698 | }
699 |
700 | _value, _ := value.([]uint64)
701 |
702 | if _value[0] != VALUE_1 {
703 | t.Fatalf("Invalid decodeFixed64 (repeated) result: %#v != %#v", _value[0], VALUE_1)
704 | }
705 | if _value[1] != VALUE_2 {
706 | t.Fatalf("Invalid decodeFixed64 (repeated) result: %#v != %#v", _value[1], VALUE_2)
707 | }
708 | }
709 |
--------------------------------------------------------------------------------
/test_server/pb/example.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go.
2 | // source: example.proto
3 | // DO NOT EDIT!
4 |
5 | /*
6 | Package pb is a generated protocol buffer package.
7 |
8 | It is generated from these files:
9 | example.proto
10 |
11 | It has these top-level messages:
12 | CreateUserReq
13 | CreateUserResp
14 | UserListReq
15 | UserListResp
16 | DeleteUserReq
17 | DeleteUserResp
18 | Inner
19 | GetUserReq
20 | UserResp
21 | Req
22 | Res
23 | */
24 | package pb
25 |
26 | import proto "github.com/golang/protobuf/proto"
27 | import fmt "fmt"
28 | import math "math"
29 |
30 | import (
31 | context "golang.org/x/net/context"
32 | grpc "google.golang.org/grpc"
33 | )
34 |
35 | // Reference imports to suppress errors if they are not otherwise used.
36 | var _ = proto.Marshal
37 | var _ = fmt.Errorf
38 | var _ = math.Inf
39 |
40 | // This is a compile-time assertion to ensure that this generated file
41 | // is compatible with the proto package it is being compiled against.
42 | // A compilation error at this line likely means your copy of the
43 | // proto package needs to be updated.
44 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
45 |
46 | type CreateUserReq struct {
47 | }
48 |
49 | func (m *CreateUserReq) Reset() { *m = CreateUserReq{} }
50 | func (m *CreateUserReq) String() string { return proto.CompactTextString(m) }
51 | func (*CreateUserReq) ProtoMessage() {}
52 | func (*CreateUserReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
53 |
54 | type CreateUserResp struct {
55 | }
56 |
57 | func (m *CreateUserResp) Reset() { *m = CreateUserResp{} }
58 | func (m *CreateUserResp) String() string { return proto.CompactTextString(m) }
59 | func (*CreateUserResp) ProtoMessage() {}
60 | func (*CreateUserResp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
61 |
62 | type UserListReq struct {
63 | }
64 |
65 | func (m *UserListReq) Reset() { *m = UserListReq{} }
66 | func (m *UserListReq) String() string { return proto.CompactTextString(m) }
67 | func (*UserListReq) ProtoMessage() {}
68 | func (*UserListReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
69 |
70 | type UserListResp struct {
71 | }
72 |
73 | func (m *UserListResp) Reset() { *m = UserListResp{} }
74 | func (m *UserListResp) String() string { return proto.CompactTextString(m) }
75 | func (*UserListResp) ProtoMessage() {}
76 | func (*UserListResp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
77 |
78 | type DeleteUserReq struct {
79 | }
80 |
81 | func (m *DeleteUserReq) Reset() { *m = DeleteUserReq{} }
82 | func (m *DeleteUserReq) String() string { return proto.CompactTextString(m) }
83 | func (*DeleteUserReq) ProtoMessage() {}
84 | func (*DeleteUserReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
85 |
86 | type DeleteUserResp struct {
87 | }
88 |
89 | func (m *DeleteUserResp) Reset() { *m = DeleteUserResp{} }
90 | func (m *DeleteUserResp) String() string { return proto.CompactTextString(m) }
91 | func (*DeleteUserResp) ProtoMessage() {}
92 | func (*DeleteUserResp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
93 |
94 | type Inner struct {
95 | A int32 `protobuf:"varint,1,opt,name=a" json:"a,omitempty"`
96 | B string `protobuf:"bytes,2,opt,name=b" json:"b,omitempty"`
97 | }
98 |
99 | func (m *Inner) Reset() { *m = Inner{} }
100 | func (m *Inner) String() string { return proto.CompactTextString(m) }
101 | func (*Inner) ProtoMessage() {}
102 | func (*Inner) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
103 |
104 | func (m *Inner) GetA() int32 {
105 | if m != nil {
106 | return m.A
107 | }
108 | return 0
109 | }
110 |
111 | func (m *Inner) GetB() string {
112 | if m != nil {
113 | return m.B
114 | }
115 | return ""
116 | }
117 |
118 | type GetUserReq struct {
119 | FirstName string `protobuf:"bytes,1,opt,name=firstName" json:"firstName,omitempty"`
120 | LastName string `protobuf:"bytes,2,opt,name=lastName" json:"lastName,omitempty"`
121 | Skills []string `protobuf:"bytes,3,rep,name=skills" json:"skills,omitempty"`
122 | Ids []int32 `protobuf:"varint,4,rep,packed,name=ids" json:"ids,omitempty"`
123 | Age int32 `protobuf:"varint,5,opt,name=age" json:"age,omitempty"`
124 | In *Inner `protobuf:"bytes,6,opt,name=in" json:"in,omitempty"`
125 | }
126 |
127 | func (m *GetUserReq) Reset() { *m = GetUserReq{} }
128 | func (m *GetUserReq) String() string { return proto.CompactTextString(m) }
129 | func (*GetUserReq) ProtoMessage() {}
130 | func (*GetUserReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
131 |
132 | func (m *GetUserReq) GetFirstName() string {
133 | if m != nil {
134 | return m.FirstName
135 | }
136 | return ""
137 | }
138 |
139 | func (m *GetUserReq) GetLastName() string {
140 | if m != nil {
141 | return m.LastName
142 | }
143 | return ""
144 | }
145 |
146 | func (m *GetUserReq) GetSkills() []string {
147 | if m != nil {
148 | return m.Skills
149 | }
150 | return nil
151 | }
152 |
153 | func (m *GetUserReq) GetIds() []int32 {
154 | if m != nil {
155 | return m.Ids
156 | }
157 | return nil
158 | }
159 |
160 | func (m *GetUserReq) GetAge() int32 {
161 | if m != nil {
162 | return m.Age
163 | }
164 | return 0
165 | }
166 |
167 | func (m *GetUserReq) GetIn() *Inner {
168 | if m != nil {
169 | return m.In
170 | }
171 | return nil
172 | }
173 |
174 | type UserResp struct {
175 | FirstName string `protobuf:"bytes,1,opt,name=firstName" json:"firstName,omitempty"`
176 | LastName string `protobuf:"bytes,2,opt,name=lastName" json:"lastName,omitempty"`
177 | Active bool `protobuf:"varint,3,opt,name=active" json:"active,omitempty"`
178 | Age int32 `protobuf:"varint,4,opt,name=age" json:"age,omitempty"`
179 | Skills string `protobuf:"bytes,5,opt,name=skills" json:"skills,omitempty"`
180 | }
181 |
182 | func (m *UserResp) Reset() { *m = UserResp{} }
183 | func (m *UserResp) String() string { return proto.CompactTextString(m) }
184 | func (*UserResp) ProtoMessage() {}
185 | func (*UserResp) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
186 |
187 | func (m *UserResp) GetFirstName() string {
188 | if m != nil {
189 | return m.FirstName
190 | }
191 | return ""
192 | }
193 |
194 | func (m *UserResp) GetLastName() string {
195 | if m != nil {
196 | return m.LastName
197 | }
198 | return ""
199 | }
200 |
201 | func (m *UserResp) GetActive() bool {
202 | if m != nil {
203 | return m.Active
204 | }
205 | return false
206 | }
207 |
208 | func (m *UserResp) GetAge() int32 {
209 | if m != nil {
210 | return m.Age
211 | }
212 | return 0
213 | }
214 |
215 | func (m *UserResp) GetSkills() string {
216 | if m != nil {
217 | return m.Skills
218 | }
219 | return ""
220 | }
221 |
222 | type Req struct {
223 | Int32Field int32 `protobuf:"varint,1,opt,name=int32field" json:"int32field,omitempty"`
224 | Int64Field int64 `protobuf:"varint,2,opt,name=int64field" json:"int64field,omitempty"`
225 | Floatfield float32 `protobuf:"fixed32,3,opt,name=floatfield" json:"floatfield,omitempty"`
226 | Doublefield float64 `protobuf:"fixed64,4,opt,name=doublefield" json:"doublefield,omitempty"`
227 | Uint32Field uint32 `protobuf:"varint,5,opt,name=uint32field" json:"uint32field,omitempty"`
228 | Uint64Field uint64 `protobuf:"varint,6,opt,name=uint64field" json:"uint64field,omitempty"`
229 | Sint32Field int32 `protobuf:"zigzag32,7,opt,name=sint32field" json:"sint32field,omitempty"`
230 | Sint64Field int64 `protobuf:"zigzag64,8,opt,name=sint64field" json:"sint64field,omitempty"`
231 | Fixed32Field uint32 `protobuf:"fixed32,9,opt,name=fixed32field" json:"fixed32field,omitempty"`
232 | Fixed64Field uint64 `protobuf:"fixed64,10,opt,name=fixed64field" json:"fixed64field,omitempty"`
233 | Sfixed32Field int32 `protobuf:"fixed32,11,opt,name=sfixed32field" json:"sfixed32field,omitempty"`
234 | Sfixed64Field int64 `protobuf:"fixed64,12,opt,name=sfixed64field" json:"sfixed64field,omitempty"`
235 | Boolfield bool `protobuf:"varint,13,opt,name=boolfield" json:"boolfield,omitempty"`
236 | Stringfield string `protobuf:"bytes,14,opt,name=stringfield" json:"stringfield,omitempty"`
237 | Bytesfield []byte `protobuf:"bytes,15,opt,name=bytesfield,proto3" json:"bytesfield,omitempty"`
238 | Int32Repeated []int32 `protobuf:"varint,16,rep,packed,name=int32Repeated" json:"int32Repeated,omitempty"`
239 | }
240 |
241 | func (m *Req) Reset() { *m = Req{} }
242 | func (m *Req) String() string { return proto.CompactTextString(m) }
243 | func (*Req) ProtoMessage() {}
244 | func (*Req) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
245 |
246 | func (m *Req) GetInt32Field() int32 {
247 | if m != nil {
248 | return m.Int32Field
249 | }
250 | return 0
251 | }
252 |
253 | func (m *Req) GetInt64Field() int64 {
254 | if m != nil {
255 | return m.Int64Field
256 | }
257 | return 0
258 | }
259 |
260 | func (m *Req) GetFloatfield() float32 {
261 | if m != nil {
262 | return m.Floatfield
263 | }
264 | return 0
265 | }
266 |
267 | func (m *Req) GetDoublefield() float64 {
268 | if m != nil {
269 | return m.Doublefield
270 | }
271 | return 0
272 | }
273 |
274 | func (m *Req) GetUint32Field() uint32 {
275 | if m != nil {
276 | return m.Uint32Field
277 | }
278 | return 0
279 | }
280 |
281 | func (m *Req) GetUint64Field() uint64 {
282 | if m != nil {
283 | return m.Uint64Field
284 | }
285 | return 0
286 | }
287 |
288 | func (m *Req) GetSint32Field() int32 {
289 | if m != nil {
290 | return m.Sint32Field
291 | }
292 | return 0
293 | }
294 |
295 | func (m *Req) GetSint64Field() int64 {
296 | if m != nil {
297 | return m.Sint64Field
298 | }
299 | return 0
300 | }
301 |
302 | func (m *Req) GetFixed32Field() uint32 {
303 | if m != nil {
304 | return m.Fixed32Field
305 | }
306 | return 0
307 | }
308 |
309 | func (m *Req) GetFixed64Field() uint64 {
310 | if m != nil {
311 | return m.Fixed64Field
312 | }
313 | return 0
314 | }
315 |
316 | func (m *Req) GetSfixed32Field() int32 {
317 | if m != nil {
318 | return m.Sfixed32Field
319 | }
320 | return 0
321 | }
322 |
323 | func (m *Req) GetSfixed64Field() int64 {
324 | if m != nil {
325 | return m.Sfixed64Field
326 | }
327 | return 0
328 | }
329 |
330 | func (m *Req) GetBoolfield() bool {
331 | if m != nil {
332 | return m.Boolfield
333 | }
334 | return false
335 | }
336 |
337 | func (m *Req) GetStringfield() string {
338 | if m != nil {
339 | return m.Stringfield
340 | }
341 | return ""
342 | }
343 |
344 | func (m *Req) GetBytesfield() []byte {
345 | if m != nil {
346 | return m.Bytesfield
347 | }
348 | return nil
349 | }
350 |
351 | func (m *Req) GetInt32Repeated() []int32 {
352 | if m != nil {
353 | return m.Int32Repeated
354 | }
355 | return nil
356 | }
357 |
358 | type Res struct {
359 | Int32Field int32 `protobuf:"varint,1,opt,name=int32field" json:"int32field,omitempty"`
360 | Int64Field int64 `protobuf:"varint,2,opt,name=int64field" json:"int64field,omitempty"`
361 | Floatfield float32 `protobuf:"fixed32,3,opt,name=floatfield" json:"floatfield,omitempty"`
362 | Doublefield float64 `protobuf:"fixed64,4,opt,name=doublefield" json:"doublefield,omitempty"`
363 | Uint32Field uint32 `protobuf:"varint,5,opt,name=uint32field" json:"uint32field,omitempty"`
364 | Uint64Field uint64 `protobuf:"varint,6,opt,name=uint64field" json:"uint64field,omitempty"`
365 | Sint32Field int32 `protobuf:"zigzag32,7,opt,name=sint32field" json:"sint32field,omitempty"`
366 | Sint64Field int64 `protobuf:"zigzag64,8,opt,name=sint64field" json:"sint64field,omitempty"`
367 | Fixed32Field uint32 `protobuf:"fixed32,9,opt,name=fixed32field" json:"fixed32field,omitempty"`
368 | Fixed64Field uint64 `protobuf:"fixed64,10,opt,name=fixed64field" json:"fixed64field,omitempty"`
369 | Sfixed32Field int32 `protobuf:"fixed32,11,opt,name=sfixed32field" json:"sfixed32field,omitempty"`
370 | Sfixed64Field int64 `protobuf:"fixed64,12,opt,name=sfixed64field" json:"sfixed64field,omitempty"`
371 | Boolfield bool `protobuf:"varint,13,opt,name=boolfield" json:"boolfield,omitempty"`
372 | Stringfield string `protobuf:"bytes,14,opt,name=stringfield" json:"stringfield,omitempty"`
373 | Bytesfield []byte `protobuf:"bytes,15,opt,name=bytesfield,proto3" json:"bytesfield,omitempty"`
374 | Int32Repeated []int32 `protobuf:"varint,16,rep,packed,name=int32Repeated" json:"int32Repeated,omitempty"`
375 | }
376 |
377 | func (m *Res) Reset() { *m = Res{} }
378 | func (m *Res) String() string { return proto.CompactTextString(m) }
379 | func (*Res) ProtoMessage() {}
380 | func (*Res) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
381 |
382 | func (m *Res) GetInt32Field() int32 {
383 | if m != nil {
384 | return m.Int32Field
385 | }
386 | return 0
387 | }
388 |
389 | func (m *Res) GetInt64Field() int64 {
390 | if m != nil {
391 | return m.Int64Field
392 | }
393 | return 0
394 | }
395 |
396 | func (m *Res) GetFloatfield() float32 {
397 | if m != nil {
398 | return m.Floatfield
399 | }
400 | return 0
401 | }
402 |
403 | func (m *Res) GetDoublefield() float64 {
404 | if m != nil {
405 | return m.Doublefield
406 | }
407 | return 0
408 | }
409 |
410 | func (m *Res) GetUint32Field() uint32 {
411 | if m != nil {
412 | return m.Uint32Field
413 | }
414 | return 0
415 | }
416 |
417 | func (m *Res) GetUint64Field() uint64 {
418 | if m != nil {
419 | return m.Uint64Field
420 | }
421 | return 0
422 | }
423 |
424 | func (m *Res) GetSint32Field() int32 {
425 | if m != nil {
426 | return m.Sint32Field
427 | }
428 | return 0
429 | }
430 |
431 | func (m *Res) GetSint64Field() int64 {
432 | if m != nil {
433 | return m.Sint64Field
434 | }
435 | return 0
436 | }
437 |
438 | func (m *Res) GetFixed32Field() uint32 {
439 | if m != nil {
440 | return m.Fixed32Field
441 | }
442 | return 0
443 | }
444 |
445 | func (m *Res) GetFixed64Field() uint64 {
446 | if m != nil {
447 | return m.Fixed64Field
448 | }
449 | return 0
450 | }
451 |
452 | func (m *Res) GetSfixed32Field() int32 {
453 | if m != nil {
454 | return m.Sfixed32Field
455 | }
456 | return 0
457 | }
458 |
459 | func (m *Res) GetSfixed64Field() int64 {
460 | if m != nil {
461 | return m.Sfixed64Field
462 | }
463 | return 0
464 | }
465 |
466 | func (m *Res) GetBoolfield() bool {
467 | if m != nil {
468 | return m.Boolfield
469 | }
470 | return false
471 | }
472 |
473 | func (m *Res) GetStringfield() string {
474 | if m != nil {
475 | return m.Stringfield
476 | }
477 | return ""
478 | }
479 |
480 | func (m *Res) GetBytesfield() []byte {
481 | if m != nil {
482 | return m.Bytesfield
483 | }
484 | return nil
485 | }
486 |
487 | func (m *Res) GetInt32Repeated() []int32 {
488 | if m != nil {
489 | return m.Int32Repeated
490 | }
491 | return nil
492 | }
493 |
494 | func init() {
495 | proto.RegisterType((*CreateUserReq)(nil), "pb.CreateUserReq")
496 | proto.RegisterType((*CreateUserResp)(nil), "pb.CreateUserResp")
497 | proto.RegisterType((*UserListReq)(nil), "pb.UserListReq")
498 | proto.RegisterType((*UserListResp)(nil), "pb.UserListResp")
499 | proto.RegisterType((*DeleteUserReq)(nil), "pb.DeleteUserReq")
500 | proto.RegisterType((*DeleteUserResp)(nil), "pb.DeleteUserResp")
501 | proto.RegisterType((*Inner)(nil), "pb.Inner")
502 | proto.RegisterType((*GetUserReq)(nil), "pb.GetUserReq")
503 | proto.RegisterType((*UserResp)(nil), "pb.UserResp")
504 | proto.RegisterType((*Req)(nil), "pb.Req")
505 | proto.RegisterType((*Res)(nil), "pb.Res")
506 | }
507 |
508 | // Reference imports to suppress errors if they are not otherwise used.
509 | var _ context.Context
510 | var _ grpc.ClientConn
511 |
512 | // This is a compile-time assertion to ensure that this generated file
513 | // is compatible with the grpc package it is being compiled against.
514 | const _ = grpc.SupportPackageIsVersion4
515 |
516 | // Client API for Example service
517 |
518 | type ExampleClient interface {
519 | // rpc Test(Req) returns (Res);
520 | GetUser(ctx context.Context, in *GetUserReq, opts ...grpc.CallOption) (*UserResp, error)
521 | CreateUser(ctx context.Context, in *CreateUserReq, opts ...grpc.CallOption) (*CreateUserResp, error)
522 | UserList(ctx context.Context, in *UserListReq, opts ...grpc.CallOption) (*UserListResp, error)
523 | DeleteUser(ctx context.Context, in *DeleteUserReq, opts ...grpc.CallOption) (*DeleteUserResp, error)
524 | }
525 |
526 | type exampleClient struct {
527 | cc *grpc.ClientConn
528 | }
529 |
530 | func NewExampleClient(cc *grpc.ClientConn) ExampleClient {
531 | return &exampleClient{cc}
532 | }
533 |
534 | func (c *exampleClient) GetUser(ctx context.Context, in *GetUserReq, opts ...grpc.CallOption) (*UserResp, error) {
535 | out := new(UserResp)
536 | err := grpc.Invoke(ctx, "/pb.Example/GetUser", in, out, c.cc, opts...)
537 | if err != nil {
538 | return nil, err
539 | }
540 | return out, nil
541 | }
542 |
543 | func (c *exampleClient) CreateUser(ctx context.Context, in *CreateUserReq, opts ...grpc.CallOption) (*CreateUserResp, error) {
544 | out := new(CreateUserResp)
545 | err := grpc.Invoke(ctx, "/pb.Example/CreateUser", in, out, c.cc, opts...)
546 | if err != nil {
547 | return nil, err
548 | }
549 | return out, nil
550 | }
551 |
552 | func (c *exampleClient) UserList(ctx context.Context, in *UserListReq, opts ...grpc.CallOption) (*UserListResp, error) {
553 | out := new(UserListResp)
554 | err := grpc.Invoke(ctx, "/pb.Example/UserList", in, out, c.cc, opts...)
555 | if err != nil {
556 | return nil, err
557 | }
558 | return out, nil
559 | }
560 |
561 | func (c *exampleClient) DeleteUser(ctx context.Context, in *DeleteUserReq, opts ...grpc.CallOption) (*DeleteUserResp, error) {
562 | out := new(DeleteUserResp)
563 | err := grpc.Invoke(ctx, "/pb.Example/DeleteUser", in, out, c.cc, opts...)
564 | if err != nil {
565 | return nil, err
566 | }
567 | return out, nil
568 | }
569 |
570 | // Server API for Example service
571 |
572 | type ExampleServer interface {
573 | // rpc Test(Req) returns (Res);
574 | GetUser(context.Context, *GetUserReq) (*UserResp, error)
575 | CreateUser(context.Context, *CreateUserReq) (*CreateUserResp, error)
576 | UserList(context.Context, *UserListReq) (*UserListResp, error)
577 | DeleteUser(context.Context, *DeleteUserReq) (*DeleteUserResp, error)
578 | }
579 |
580 | func RegisterExampleServer(s *grpc.Server, srv ExampleServer) {
581 | s.RegisterService(&_Example_serviceDesc, srv)
582 | }
583 |
584 | func _Example_GetUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
585 | in := new(GetUserReq)
586 | if err := dec(in); err != nil {
587 | return nil, err
588 | }
589 | if interceptor == nil {
590 | return srv.(ExampleServer).GetUser(ctx, in)
591 | }
592 | info := &grpc.UnaryServerInfo{
593 | Server: srv,
594 | FullMethod: "/pb.Example/GetUser",
595 | }
596 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
597 | return srv.(ExampleServer).GetUser(ctx, req.(*GetUserReq))
598 | }
599 | return interceptor(ctx, in, info, handler)
600 | }
601 |
602 | func _Example_CreateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
603 | in := new(CreateUserReq)
604 | if err := dec(in); err != nil {
605 | return nil, err
606 | }
607 | if interceptor == nil {
608 | return srv.(ExampleServer).CreateUser(ctx, in)
609 | }
610 | info := &grpc.UnaryServerInfo{
611 | Server: srv,
612 | FullMethod: "/pb.Example/CreateUser",
613 | }
614 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
615 | return srv.(ExampleServer).CreateUser(ctx, req.(*CreateUserReq))
616 | }
617 | return interceptor(ctx, in, info, handler)
618 | }
619 |
620 | func _Example_UserList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
621 | in := new(UserListReq)
622 | if err := dec(in); err != nil {
623 | return nil, err
624 | }
625 | if interceptor == nil {
626 | return srv.(ExampleServer).UserList(ctx, in)
627 | }
628 | info := &grpc.UnaryServerInfo{
629 | Server: srv,
630 | FullMethod: "/pb.Example/UserList",
631 | }
632 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
633 | return srv.(ExampleServer).UserList(ctx, req.(*UserListReq))
634 | }
635 | return interceptor(ctx, in, info, handler)
636 | }
637 |
638 | func _Example_DeleteUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
639 | in := new(DeleteUserReq)
640 | if err := dec(in); err != nil {
641 | return nil, err
642 | }
643 | if interceptor == nil {
644 | return srv.(ExampleServer).DeleteUser(ctx, in)
645 | }
646 | info := &grpc.UnaryServerInfo{
647 | Server: srv,
648 | FullMethod: "/pb.Example/DeleteUser",
649 | }
650 | handler := func(ctx context.Context, req interface{}) (interface{}, error) {
651 | return srv.(ExampleServer).DeleteUser(ctx, req.(*DeleteUserReq))
652 | }
653 | return interceptor(ctx, in, info, handler)
654 | }
655 |
656 | var _Example_serviceDesc = grpc.ServiceDesc{
657 | ServiceName: "pb.Example",
658 | HandlerType: (*ExampleServer)(nil),
659 | Methods: []grpc.MethodDesc{
660 | {
661 | MethodName: "GetUser",
662 | Handler: _Example_GetUser_Handler,
663 | },
664 | {
665 | MethodName: "CreateUser",
666 | Handler: _Example_CreateUser_Handler,
667 | },
668 | {
669 | MethodName: "UserList",
670 | Handler: _Example_UserList_Handler,
671 | },
672 | {
673 | MethodName: "DeleteUser",
674 | Handler: _Example_DeleteUser_Handler,
675 | },
676 | },
677 | Streams: []grpc.StreamDesc{},
678 | Metadata: "example.proto",
679 | }
680 |
681 | func init() { proto.RegisterFile("example.proto", fileDescriptor0) }
682 |
683 | var fileDescriptor0 = []byte{
684 | // 553 bytes of a gzipped FileDescriptorProto
685 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xec, 0x95, 0x4f, 0xae, 0xd3, 0x30,
686 | 0x10, 0xc6, 0xe5, 0xa6, 0xff, 0x32, 0x4d, 0xda, 0x3e, 0x2f, 0x50, 0xa8, 0x10, 0xb2, 0x02, 0x12,
687 | 0xde, 0xd0, 0x45, 0x8b, 0xb8, 0x00, 0x20, 0x84, 0x84, 0x58, 0x8c, 0xc4, 0x01, 0x12, 0xea, 0x3e,
688 | 0x59, 0xe4, 0x25, 0x21, 0xce, 0x43, 0x8f, 0x0b, 0x70, 0x0b, 0x0e, 0xc0, 0x59, 0xb8, 0x14, 0x9a,
689 | 0x38, 0x69, 0x6c, 0x36, 0x2c, 0xde, 0xf6, 0xed, 0x32, 0xbf, 0x99, 0x7e, 0xfe, 0x6c, 0x4f, 0x3d,
690 | 0x10, 0xab, 0xbb, 0xec, 0xa6, 0x2e, 0xd4, 0xbe, 0x6e, 0xaa, 0xb6, 0xe2, 0x93, 0x3a, 0x4f, 0x37,
691 | 0x10, 0xbf, 0x69, 0x54, 0xd6, 0xaa, 0xcf, 0x46, 0x35, 0xa8, 0xbe, 0xa5, 0x5b, 0x58, 0xbb, 0xc0,
692 | 0xd4, 0x69, 0x0c, 0x2b, 0xfa, 0xfe, 0xa8, 0x4d, 0x4b, 0x05, 0x6b, 0x88, 0xc6, 0xd0, 0xd4, 0xa4,
693 | 0xf0, 0x56, 0x15, 0xca, 0x53, 0x70, 0x81, 0xa9, 0xd3, 0x67, 0x30, 0xfb, 0x50, 0x96, 0xaa, 0xe1,
694 | 0x11, 0xb0, 0x2c, 0x61, 0x82, 0xc9, 0x19, 0xb2, 0x8c, 0xa2, 0x3c, 0x99, 0x08, 0x26, 0x43, 0x64,
695 | 0x79, 0xfa, 0x8b, 0x01, 0xbc, 0x57, 0x6d, 0xaf, 0xc2, 0x9f, 0x40, 0x78, 0xd6, 0x8d, 0x69, 0x3f,
696 | 0x65, 0x37, 0xaa, 0xfb, 0x49, 0x88, 0x23, 0xe0, 0x3b, 0x58, 0x16, 0x59, 0x9f, 0xb4, 0x0a, 0x97,
697 | 0x98, 0x3f, 0x82, 0xb9, 0xf9, 0xaa, 0x8b, 0xc2, 0x24, 0x81, 0x08, 0x64, 0x88, 0x7d, 0xc4, 0xb7,
698 | 0x10, 0xe8, 0x93, 0x49, 0xa6, 0x22, 0x90, 0x33, 0xa4, 0x4f, 0x22, 0xd9, 0xb5, 0x4a, 0x66, 0x9d,
699 | 0x21, 0xfa, 0xe4, 0x8f, 0x61, 0xa2, 0xcb, 0x64, 0x2e, 0x98, 0x5c, 0x1d, 0xc2, 0x7d, 0x9d, 0xef,
700 | 0x3b, 0xdf, 0x38, 0xd1, 0x65, 0xfa, 0x93, 0xc1, 0x72, 0xd8, 0xd1, 0xfd, 0xdc, 0x65, 0x5f, 0x5a,
701 | 0xfd, 0x5d, 0x25, 0x81, 0x60, 0x72, 0x89, 0x7d, 0x34, 0x78, 0x99, 0x8e, 0x5e, 0xc6, 0x7d, 0xcc,
702 | 0x3a, 0x8d, 0x3e, 0x4a, 0x7f, 0x4f, 0x21, 0xa0, 0x13, 0x7a, 0x0a, 0xa0, 0xcb, 0xf6, 0x78, 0x38,
703 | 0x6b, 0x55, 0x9c, 0xfa, 0x53, 0x75, 0x48, 0x9f, 0x7f, 0xfd, 0xca, 0xe6, 0xc9, 0x47, 0x80, 0x0e,
704 | 0xa1, 0xfc, 0xb9, 0xa8, 0xb2, 0xd6, 0xe6, 0xc9, 0xcd, 0x04, 0x1d, 0xc2, 0x05, 0xac, 0x4e, 0xd5,
705 | 0x6d, 0x5e, 0x28, 0x5b, 0x40, 0xce, 0x18, 0xba, 0x88, 0x2a, 0x6e, 0x1d, 0x0b, 0x64, 0x33, 0x46,
706 | 0x17, 0x0d, 0x15, 0x83, 0x09, 0x3a, 0xd8, 0x29, 0xba, 0x88, 0x2a, 0x8c, 0xa3, 0xb1, 0x10, 0x4c,
707 | 0x5e, 0xa1, 0x8b, 0x86, 0x8a, 0x41, 0x63, 0x29, 0x98, 0xe4, 0xe8, 0x22, 0x9e, 0x42, 0x74, 0xd6,
708 | 0x77, 0xea, 0x34, 0x88, 0x84, 0x82, 0xc9, 0x05, 0x7a, 0xec, 0x52, 0x33, 0xc8, 0x80, 0x60, 0x72,
709 | 0x8e, 0x1e, 0xe3, 0xcf, 0x21, 0x36, 0x9e, 0xd0, 0x4a, 0x30, 0xb9, 0x41, 0x1f, 0x8e, 0x55, 0x83,
710 | 0x54, 0x24, 0x98, 0xdc, 0xa2, 0x0f, 0xa9, 0x43, 0xf2, 0xaa, 0x2a, 0x6c, 0x45, 0xdc, 0x5d, 0xf5,
711 | 0x08, 0xba, 0x3d, 0xb5, 0x8d, 0x2e, 0xaf, 0x6d, 0x7e, 0xdd, 0x5d, 0xb0, 0x8b, 0xe8, 0x76, 0xf2,
712 | 0x1f, 0xad, 0x32, 0xb6, 0x60, 0x23, 0x98, 0x8c, 0xd0, 0x21, 0xe4, 0xa2, 0x3b, 0x23, 0x54, 0x35,
713 | 0xfd, 0x5b, 0x4f, 0xc9, 0xb6, 0xeb, 0x6b, 0x1f, 0xf6, 0xbd, 0x62, 0x1e, 0x7a, 0xe5, 0xa1, 0x57,
714 | 0xfe, 0xd7, 0x2b, 0x87, 0x3f, 0x0c, 0x16, 0xef, 0xec, 0x80, 0xe0, 0x2f, 0x60, 0xd1, 0xbf, 0xc5,
715 | 0x7c, 0x4d, 0xcf, 0xe0, 0xf8, 0x30, 0xef, 0x22, 0x8a, 0x2f, 0x0f, 0xe1, 0x11, 0x60, 0x1c, 0x17,
716 | 0xfc, 0x8a, 0x72, 0xde, 0x3c, 0xd9, 0xf1, 0x7f, 0x91, 0xa9, 0xf9, 0x4b, 0xfb, 0x92, 0xd2, 0x08,
717 | 0xe1, 0x9b, 0x41, 0xae, 0x9f, 0x2f, 0xbb, 0xad, 0x0f, 0xec, 0x1a, 0xe3, 0x40, 0xb1, 0x6b, 0x78,
718 | 0x13, 0xc7, 0xae, 0xe1, 0xcf, 0x9c, 0x7c, 0xde, 0xcd, 0xb8, 0xe3, 0xdf, 0x00, 0x00, 0x00, 0xff,
719 | 0xff, 0x87, 0x43, 0xf6, 0x5d, 0xf4, 0x06, 0x00, 0x00,
720 | }
721 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
--------------------------------------------------------------------------------