├── .gitignore ├── LICENSE ├── README.md ├── endian_386.go ├── endian_amd64.go ├── endian_amd64p32.go ├── endian_arm.go ├── endian_arm64.go ├── endian_loong64.go ├── endian_mips64.go ├── endian_mips64le.go ├── endian_ppc64.go ├── endian_ppc64le.go ├── endian_riscv64.go ├── endian_s390x.go ├── messaging.go └── messaging_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 qrtz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nativemessaging 2 | Native messaging host library for go application 3 | 4 | ## Usage 5 | 6 | **Go host application** 7 | 8 | ``` go 9 | package main 10 | 11 | import ( 12 | "io" 13 | "os" 14 | 15 | "github.com/qrtz/nativemessaging" 16 | ) 17 | 18 | func main() { 19 | decoder := nativemessaging.NewNativeJSONDecoder(os.Stdin) 20 | encoder := nativemessaging.NewNativeJSONEncoder(os.Stdout) 21 | 22 | for { 23 | var rsp response 24 | var msg message 25 | err := decoder.Decode(&msg) 26 | 27 | if err != nil { 28 | if err == io.EOF { 29 | // exit 30 | return 31 | } 32 | rsp.Text = err.Error() 33 | } else { 34 | if msg.Text == "ping" { 35 | rsp.Text = "pong" 36 | rsp.Success = true 37 | } else { 38 | // Echo the message back to the client 39 | rsp.Text = msg.Text 40 | } 41 | } 42 | 43 | if err := encoder.Encode(rsp); err != nil { 44 | // Log the error and exit 45 | return 46 | } 47 | } 48 | } 49 | 50 | type message struct { 51 | Text string `json:"text"` 52 | } 53 | 54 | type response struct { 55 | Text string `json:"text"` 56 | Success bool `json:"success"` 57 | } 58 | ``` 59 | 60 | **Javascript client** 61 | 62 | ``` js 63 | chrome.runtime.sendNativeMessage('com.github.qrtz.nativemessaginghost', {text:'ping'}, (response) => { 64 | console.log('Native messaging host response ', response); 65 | }) 66 | ``` 67 | 68 | **More info:** 69 | 70 | https://developer.chrome.com/extensions/nativeMessaging 71 | https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Native_messaging 72 | -------------------------------------------------------------------------------- /endian_386.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.LittleEndian 9 | -------------------------------------------------------------------------------- /endian_amd64.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.LittleEndian 9 | -------------------------------------------------------------------------------- /endian_amd64p32.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.LittleEndian 9 | -------------------------------------------------------------------------------- /endian_arm.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.LittleEndian 9 | -------------------------------------------------------------------------------- /endian_arm64.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.LittleEndian 9 | -------------------------------------------------------------------------------- /endian_loong64.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.LittleEndian 9 | -------------------------------------------------------------------------------- /endian_mips64.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.BigEndian 9 | -------------------------------------------------------------------------------- /endian_mips64le.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.LittleEndian 9 | -------------------------------------------------------------------------------- /endian_ppc64.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.BigEndian 9 | -------------------------------------------------------------------------------- /endian_ppc64le.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.LittleEndian 9 | -------------------------------------------------------------------------------- /endian_riscv64.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.LittleEndian 9 | -------------------------------------------------------------------------------- /endian_s390x.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "encoding/binary" 5 | ) 6 | 7 | // NativeEndian system native byte order 8 | var NativeEndian = binary.BigEndian 9 | -------------------------------------------------------------------------------- /messaging.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "encoding/json" 7 | "errors" 8 | "io" 9 | "io/ioutil" 10 | ) 11 | 12 | var ( 13 | 14 | // ErrInvalidMessageSize unable to read message size 15 | ErrInvalidMessageSize = errors.New("Invalid message size") 16 | // ErrByteOrderNotSet byter order is set on the first read 17 | ErrByteOrderNotSet = errors.New("Byte order not set") 18 | messageSizeInBytes = binary.Size(uint32(0)) 19 | ) 20 | 21 | // Writer is an interface that wraps the Write method. 22 | type Writer interface { 23 | // Write writes bytes from the given io.Reader to the underlying io.Writer 24 | // It returns the number of bytes from io.Reader and any error from the write operation. 25 | Write(io.Reader) (int, error) 26 | } 27 | 28 | // Reader is an interface that wraps the Read method. 29 | type Reader interface { 30 | // Read reads bytes from an io.Reader. 31 | // It returns the bytes read and an error from the read operation. 32 | // Read may return io.EOF when the underlying stream reach the end or is closed 33 | Read() ([]byte, error) 34 | } 35 | 36 | // JSONEncoder writes JSON values to an output stream. 37 | type JSONEncoder interface { 38 | Encode(interface{}) error 39 | } 40 | 41 | // JSONDecoder reads and decodes JSON values from an input stream. 42 | type JSONDecoder interface { 43 | Decode(interface{}) error 44 | } 45 | 46 | type writer struct { 47 | w io.Writer 48 | bo binary.ByteOrder 49 | } 50 | 51 | // NewWriter returns a new writer that writes to w 52 | // The data is preceded with 32-bit data length in the specified byte order 53 | func NewWriter(w io.Writer, bo binary.ByteOrder) Writer { 54 | return &writer{ 55 | w: w, 56 | bo: bo, 57 | } 58 | } 59 | 60 | // NewNativeWriter returns a new writer that writes to the given io.Writer 61 | // The data is preceded with 32-bit data length in native byte order 62 | func NewNativeWriter(w io.Writer) Writer { 63 | return &writer{ 64 | w: w, 65 | bo: NativeEndian, 66 | } 67 | } 68 | 69 | func (w *writer) Write(r io.Reader) (int, error) { 70 | return Write(w.w, r, w.bo) 71 | } 72 | 73 | type reader struct { 74 | r io.Reader 75 | bo binary.ByteOrder 76 | } 77 | 78 | // NewReader returns a new reader that reads from the given io.Reader 79 | // interpreting the first 4 bytes as 32-bit data length in the specified byte order 80 | func NewReader(r io.Reader, bo binary.ByteOrder) Reader { 81 | return &reader{ 82 | r: r, 83 | bo: bo, 84 | } 85 | } 86 | 87 | // NewNativeReader returns a new reader that reads from the given io.Reader 88 | // interpreting the first 4 bytes as 32-bit data length in native byte order 89 | func NewNativeReader(r io.Reader) Reader { 90 | return &reader{ 91 | r: r, 92 | bo: NativeEndian, 93 | } 94 | } 95 | 96 | func (r *reader) Read() ([]byte, error) { 97 | return Read(r.r, r.bo) 98 | } 99 | 100 | type jsonEncoder struct { 101 | w io.Writer 102 | bo binary.ByteOrder 103 | } 104 | 105 | // NewJSONEncoder returns a new jsonEncoder that write to the given io.Writer 106 | // The data is preceded with 32-bit data length in the specified byte order 107 | func NewJSONEncoder(w io.Writer, bo binary.ByteOrder) JSONEncoder { 108 | return &jsonEncoder{ 109 | w: w, 110 | bo: bo, 111 | } 112 | } 113 | 114 | // NewNativeJSONEncoder returns a new jsonEncoder that writes to the given io.Writer 115 | // The data is preceded with 32-bit data length in native byte order 116 | func NewNativeJSONEncoder(w io.Writer) JSONEncoder { 117 | return &jsonEncoder{ 118 | w: w, 119 | bo: NativeEndian, 120 | } 121 | } 122 | 123 | func (e *jsonEncoder) Encode(v interface{}) error { 124 | _, err := Encode(e.w, v, e.bo) 125 | return err 126 | } 127 | 128 | type jsonDecoder struct { 129 | r io.Reader 130 | bo binary.ByteOrder 131 | } 132 | 133 | // NewJSONDecoder returns a new jsonDecoder that reads from the given io.Reader 134 | // interpreting the first 4 bytes as 32-bit data length in the specified byte order 135 | func NewJSONDecoder(r io.Reader, bo binary.ByteOrder) JSONDecoder { 136 | return &jsonDecoder{ 137 | r: r, 138 | bo: bo, 139 | } 140 | } 141 | 142 | // NewNativeJSONDecoder returns a new jsonDecoder that reads from the given io.Reader 143 | // interpreting the first 4 bytes as 32-bit data length in native byte order 144 | func NewNativeJSONDecoder(r io.Reader) JSONDecoder { 145 | return &jsonDecoder{ 146 | r: r, 147 | bo: NativeEndian, 148 | } 149 | } 150 | 151 | func (d *jsonDecoder) Decode(v interface{}) error { 152 | return Decode(d.r, v, d.bo) 153 | } 154 | 155 | type host struct { 156 | r io.Reader 157 | w io.Writer 158 | bo binary.ByteOrder 159 | } 160 | 161 | func (h *host) Read() ([]byte, error) { 162 | return Read(h.r, h.bo) 163 | } 164 | 165 | func (h *host) Write(message io.Reader) (int, error) { 166 | return Write(h.w, message, h.bo) 167 | } 168 | 169 | func (h *host) Send(v interface{}) (int, error) { 170 | return Encode(h.w, v, h.bo) 171 | 172 | } 173 | func (h *host) Receive(v interface{}) error { 174 | return Decode(h.r, v, h.bo) 175 | } 176 | 177 | // Read reads a message from the given io.Reader interpreting the 178 | // leading first 4 bytes as a 32-bit unsigned integer encoded in the specified byte order 179 | func Read(r io.Reader, order binary.ByteOrder) ([]byte, error) { 180 | b := make([]byte, messageSizeInBytes) 181 | i, err := r.Read(b) 182 | if err != nil { 183 | return nil, err 184 | } 185 | if i == 0 { 186 | return nil, ErrInvalidMessageSize 187 | } 188 | 189 | ln := order.Uint32(b) 190 | 191 | if ln == 0 { 192 | return nil, ErrInvalidMessageSize 193 | } 194 | m := make([]byte, ln) 195 | _, err = r.Read(m) 196 | if err != nil { 197 | return nil, err 198 | } 199 | return m, nil 200 | } 201 | 202 | // Decode parses the incoming JSON-encoded data and stores the result in the value pointed to by v. 203 | // The leading first 4 bytes of the data is interpreted as a 32-bit unsigned integer encoded in the specified byte order 204 | func Decode(r io.Reader, v interface{}, order binary.ByteOrder) error { 205 | b, err := Read(r, order) 206 | if err != nil { 207 | return err 208 | } 209 | err = json.Unmarshal(b, v) 210 | if err != nil { 211 | return errors.New(err.Error() + string(b)) 212 | } 213 | return nil 214 | } 215 | 216 | // Write writes to io.Writer the data read from the given io.Reader 217 | // The data is preceded with a 32-bit unsigned integer data length in the specified byte order 218 | func Write(w io.Writer, message io.Reader, order binary.ByteOrder) (i int, err error) { 219 | data, err := ioutil.ReadAll(message) 220 | if err != nil { 221 | return 0, err 222 | } 223 | 224 | header := make([]byte, messageSizeInBytes) 225 | order.PutUint32(header, uint32(len(data))) 226 | return w.Write(append(header, data...)) 227 | } 228 | 229 | // Encode writes to io.Writer the json encoded data of the given value 230 | // The data is preceded with a 32-bit unsigned integer data length in the specified byte order 231 | func Encode(w io.Writer, v interface{}, order binary.ByteOrder) (int, error) { 232 | b, err := json.Marshal(v) 233 | if err != nil { 234 | return 0, err 235 | } 236 | return Write(w, bytes.NewReader(b), order) 237 | } 238 | -------------------------------------------------------------------------------- /messaging_test.go: -------------------------------------------------------------------------------- 1 | package nativemessaging 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "encoding/json" 7 | "strings" 8 | "testing" 9 | ) 10 | 11 | // Test writer 12 | func write(t *testing.T, endian binary.ByteOrder) { 13 | var w Writer 14 | buf := new(bytes.Buffer) 15 | value := "native message host" 16 | if endian == nil { 17 | w = NewNativeWriter(buf) 18 | } else { 19 | w = NewWriter(buf, endian) 20 | } 21 | i, err := w.Write(strings.NewReader(value)) 22 | 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | 27 | if i != len(value)+binary.Size(uint32(0)) { 28 | t.Fatal("Invalid write length") 29 | } 30 | 31 | result := buf.String()[4:] 32 | if result != value { 33 | t.Fatalf("Expected: %s Got: %s", value, result) 34 | } 35 | } 36 | 37 | func testWriter(t *testing.T, endian binary.ByteOrder) { 38 | var w Writer 39 | buf := new(bytes.Buffer) 40 | value := "native message host" 41 | if endian == nil { 42 | w = NewNativeWriter(buf) 43 | } else { 44 | w = NewWriter(buf, endian) 45 | } 46 | i, err := w.Write(strings.NewReader(value)) 47 | 48 | if err != nil { 49 | t.Fatal(err) 50 | } 51 | 52 | if i != len(value)+binary.Size(uint32(0)) { 53 | t.Fatal("Invalid write length") 54 | } 55 | 56 | result := buf.String()[4:] 57 | if result != value { 58 | t.Fatalf("Expected: %s Got: %s", value, result) 59 | } 60 | } 61 | 62 | func testJSONEncoder(t *testing.T, endian binary.ByteOrder) { 63 | var encoder JSONEncoder 64 | value := struct{ Text string }{Text: "native messaging host"} 65 | buf := new(bytes.Buffer) 66 | 67 | if endian == nil { 68 | encoder = NewNativeJSONEncoder(buf) 69 | } else { 70 | encoder = NewJSONEncoder(buf, endian) 71 | } 72 | 73 | err := encoder.Encode(value) 74 | if err != nil { 75 | t.Fatal(err) 76 | } 77 | 78 | var result struct{ Text string } 79 | 80 | err = json.Unmarshal(buf.Bytes()[binary.Size(uint32(0)):], &result) 81 | if err != nil { 82 | t.Fatal(err) 83 | } 84 | if result.Text != value.Text { 85 | t.Fatalf("Invalid result: %s", buf) 86 | } 87 | } 88 | func testJSONDecoder(t *testing.T, endian binary.ByteOrder) { 89 | var decoder JSONDecoder 90 | value := struct{ Text string }{Text: "native messaging host"} 91 | b, err := json.Marshal(value) 92 | if err != nil { 93 | t.Fatal(err) 94 | } 95 | header := make([]byte, binary.Size(uint32(0))) 96 | if endian == nil { 97 | endian = NativeEndian 98 | endian.PutUint32(header, uint32(len(b))) 99 | decoder = NewNativeJSONDecoder(bytes.NewReader(append(header, b...))) 100 | } else { 101 | endian.PutUint32(header, uint32(len(b))) 102 | decoder = NewJSONDecoder(bytes.NewReader(append(header, b...)), endian) 103 | } 104 | var result struct{ Text string } 105 | err = decoder.Decode(&result) 106 | 107 | if err != nil { 108 | t.Fatal(err) 109 | } 110 | 111 | if result.Text != value.Text { 112 | t.Fatalf("Invalid result: %#v", result) 113 | } 114 | } 115 | 116 | func TestNativeJSONEncoder(t *testing.T) { 117 | testJSONEncoder(t, nil) 118 | } 119 | 120 | func TestBigEndianJSONEncoder(t *testing.T) { 121 | testJSONEncoder(t, binary.BigEndian) 122 | } 123 | 124 | func TestLittleEndianJSONEncoder(t *testing.T) { 125 | testJSONEncoder(t, binary.LittleEndian) 126 | } 127 | 128 | func TestNativeJSONDecoder(t *testing.T) { 129 | testJSONDecoder(t, nil) 130 | } 131 | 132 | func TestBigEndianJSONDecoder(t *testing.T) { 133 | testJSONDecoder(t, binary.BigEndian) 134 | } 135 | 136 | func TestLittleEndianJSONDecoder(t *testing.T) { 137 | testJSONDecoder(t, binary.LittleEndian) 138 | } 139 | 140 | func TestWriteNativeEndian(t *testing.T) { 141 | write(t, nil) 142 | } 143 | 144 | func TestWriteLittleEndian(t *testing.T) { 145 | write(t, binary.LittleEndian) 146 | } 147 | 148 | func TestWriteBigEndian(t *testing.T) { 149 | write(t, binary.BigEndian) 150 | } 151 | func TestNativeEndianWriter(t *testing.T) { 152 | testWriter(t, nil) 153 | } 154 | 155 | func TestLittleEndianWriter(t *testing.T) { 156 | testWriter(t, binary.LittleEndian) 157 | } 158 | 159 | func TestBigEndianWriter(t *testing.T) { 160 | testWriter(t, binary.BigEndian) 161 | } 162 | 163 | // Test JSONEncoder 164 | func encode(t *testing.T, endian binary.ByteOrder) { 165 | var encoder JSONEncoder 166 | value := struct{ Text string }{Text: "native messaging host"} 167 | buf := new(bytes.Buffer) 168 | 169 | if endian == nil { 170 | encoder = NewNativeJSONEncoder(buf) 171 | } else { 172 | encoder = NewJSONEncoder(buf, endian) 173 | } 174 | 175 | err := encoder.Encode(value) 176 | if err != nil { 177 | t.Fatal(err) 178 | } 179 | 180 | var result struct{ Text string } 181 | 182 | err = json.Unmarshal(buf.Bytes()[binary.Size(uint32(0)):], &result) 183 | if err != nil { 184 | t.Fatal(err) 185 | } 186 | if result.Text != value.Text { 187 | t.Fatalf("Invalid result: %s", buf) 188 | } 189 | } 190 | func TestSendNativeEndian(t *testing.T) { 191 | encode(t, nil) 192 | } 193 | 194 | func TestSendLittleEndian(t *testing.T) { 195 | encode(t, binary.LittleEndian) 196 | } 197 | 198 | func TestSendBigEndian(t *testing.T) { 199 | encode(t, binary.BigEndian) 200 | } 201 | 202 | // Test Reader 203 | func read(t *testing.T, endian binary.ByteOrder) { 204 | var reader Reader 205 | value := struct{ Text string }{Text: "native messaging host"} 206 | data, err := json.Marshal(value) 207 | if err != nil { 208 | t.Fatal(err) 209 | } 210 | header := make([]byte, binary.Size(uint32(0))) 211 | 212 | if endian == nil { 213 | endian = NativeEndian 214 | endian.PutUint32(header, uint32(len(data))) 215 | reader = NewNativeReader(bytes.NewReader(append(header, data...))) 216 | } else { 217 | endian.PutUint32(header, uint32(len(data))) 218 | reader = NewReader(bytes.NewReader(append(header, data...)), endian) 219 | } 220 | 221 | result, err := reader.Read() 222 | 223 | if err != nil { 224 | t.Fatal(err) 225 | } 226 | 227 | if string(result) != string(data) { 228 | t.Fatalf("Got: %s: Expected: %s", string(data), string(result)) 229 | } 230 | } 231 | func testReader(t *testing.T, endian binary.ByteOrder) { 232 | var r Reader 233 | 234 | value := struct{ Text string }{Text: "native messaging host"} 235 | data, err := json.Marshal(value) 236 | if err != nil { 237 | t.Fatal(err) 238 | } 239 | header := make([]byte, binary.Size(uint32(0))) 240 | 241 | if endian == nil { 242 | endian = NativeEndian 243 | endian.PutUint32(header, uint32(len(data))) 244 | r = NewNativeReader(bytes.NewReader(append(header, data...))) 245 | } else { 246 | endian.PutUint32(header, uint32(len(data))) 247 | r = NewReader(bytes.NewReader(append(header, data...)), endian) 248 | } 249 | 250 | result, err := r.Read() 251 | 252 | if err != nil { 253 | t.Fatal(err) 254 | } 255 | 256 | if string(result) != string(data) { 257 | t.Fatalf("Got: %s: Expected: %s", string(data), string(result)) 258 | } 259 | } 260 | 261 | func TestReadNativeEndian(t *testing.T) { 262 | read(t, nil) 263 | } 264 | 265 | func TestReadLittleEndian(t *testing.T) { 266 | read(t, binary.LittleEndian) 267 | } 268 | 269 | func TestReadBigEndian(t *testing.T) { 270 | read(t, binary.BigEndian) 271 | } 272 | 273 | func TestNativeEndianReader(t *testing.T) { 274 | testReader(t, nil) 275 | } 276 | 277 | func TestLittleEndianReader(t *testing.T) { 278 | testReader(t, binary.LittleEndian) 279 | } 280 | 281 | func TestBigEndianReader(t *testing.T) { 282 | testReader(t, binary.BigEndian) 283 | } 284 | 285 | // Test JSONDecoder 286 | func decode(t *testing.T, endian binary.ByteOrder) { 287 | var decoder JSONDecoder 288 | value := struct{ Text string }{Text: "native messaging host"} 289 | b, err := json.Marshal(value) 290 | if err != nil { 291 | t.Fatal(err) 292 | } 293 | header := make([]byte, binary.Size(uint32(0))) 294 | if endian == nil { 295 | endian = NativeEndian 296 | endian.PutUint32(header, uint32(len(b))) 297 | decoder = NewNativeJSONDecoder(bytes.NewReader(append(header, b...))) 298 | } else { 299 | endian.PutUint32(header, uint32(len(b))) 300 | decoder = NewJSONDecoder(bytes.NewReader(append(header, b...)), endian) 301 | } 302 | var result struct{ Text string } 303 | err = decoder.Decode(&result) 304 | 305 | if err != nil { 306 | t.Fatal(err) 307 | } 308 | 309 | if result.Text != value.Text { 310 | t.Fatalf("Invalid result: %#v", result) 311 | } 312 | } 313 | 314 | func TestReceiveNativeEndian(t *testing.T) { 315 | decode(t, nil) 316 | } 317 | 318 | func TestReceiveLittleEndian(t *testing.T) { 319 | decode(t, binary.LittleEndian) 320 | } 321 | 322 | func TestReceiveBigEndian(t *testing.T) { 323 | decode(t, binary.BigEndian) 324 | } 325 | --------------------------------------------------------------------------------