Skip to content

Commit 414bbd9

Browse files
committed
Marshaller and finished Endpoint example
1 parent d97b88a commit 414bbd9

File tree

7 files changed

+151
-43
lines changed

7 files changed

+151
-43
lines changed

examples/endpoint/0doc.go

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Package endpoint contains a simplified version of the EndpointID struct from
2+
// the dtn7-go <https://github.com/dtn7/dtn7-go> application.
3+
package endpoint

examples/endpoint/endpoint.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package main
1+
package endpoint
22

33
import (
44
"fmt"
@@ -12,39 +12,39 @@ const (
1212
endpointURISchemeIPN uint64 = 2
1313
)
1414

15-
type EndpointID struct {
15+
type endpointID struct {
1616
SchemeName uint64
1717
SchemeSpecificPart interface{}
1818
}
1919

20-
func newEndpointIDDTN(ssp string) EndpointID {
20+
func newEndpointIDDTN(ssp string) endpointID {
2121
var sspRaw interface{}
2222
if ssp == "none" {
2323
sspRaw = uint64(0)
2424
} else {
2525
sspRaw = string(ssp)
2626
}
2727

28-
return EndpointID{
28+
return endpointID{
2929
SchemeName: endpointURISchemeDTN,
3030
SchemeSpecificPart: sspRaw,
3131
}
3232
}
3333

34-
func newEndpointIDIPN(ssp string) EndpointID {
34+
func newEndpointIDIPN(ssp string) endpointID {
3535
re := regexp.MustCompile(`^(\d+)\.(\d+)$`)
3636
matches := re.FindStringSubmatch(ssp)
3737

3838
nodeNo, _ := strconv.ParseUint(matches[1], 10, 64)
3939
serviceNo, _ := strconv.ParseUint(matches[2], 10, 64)
4040

41-
return EndpointID{
41+
return endpointID{
4242
SchemeName: endpointURISchemeIPN,
4343
SchemeSpecificPart: [2]uint64{nodeNo, serviceNo},
4444
}
4545
}
4646

47-
func NewEndpointID(eid string) EndpointID {
47+
func newEndpointID(eid string) endpointID {
4848
re := regexp.MustCompile(`^([[:alnum:]]+):(.+)$`)
4949
matches := re.FindStringSubmatch(eid)
5050

@@ -57,11 +57,11 @@ func NewEndpointID(eid string) EndpointID {
5757
case "ipn":
5858
return newEndpointIDIPN(ssp)
5959
default:
60-
return EndpointID{}
60+
return endpointID{}
6161
}
6262
}
6363

64-
func (eid EndpointID) String() string {
64+
func (eid endpointID) String() string {
6565
var b strings.Builder
6666

6767
switch eid.SchemeName {

examples/endpoint/endpoint_cbor.go

+54-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
package main
1+
package endpoint
22

33
import (
4+
"fmt"
45
"io"
56

67
"github.com/dtn7/cboring"
78
)
89

9-
func (eid *EndpointID) MarshalCbor(w io.Writer) error {
10+
func (eid *endpointID) MarshalCbor(w io.Writer) error {
1011
// Start an array with two elements
1112
if err := cboring.WriteArrayLength(2, w); err != nil {
1213
return err
@@ -48,7 +49,56 @@ func (eid *EndpointID) MarshalCbor(w io.Writer) error {
4849
return nil
4950
}
5051

51-
func (eid *EndpointID) UnmarshalCbor(r io.Reader) error {
52-
// TODO
52+
func (eid *endpointID) UnmarshalCbor(r io.Reader) error {
53+
// Start of an array with two elements
54+
if l, err := cboring.ReadArrayLength(r); err != nil {
55+
return err
56+
} else if l != 2 {
57+
return fmt.Errorf("Expected array with length 2, got %d", l)
58+
}
59+
60+
// URI code: scheme name
61+
if sn, err := cboring.ReadUInt(r); err != nil {
62+
return err
63+
} else {
64+
eid.SchemeName = sn
65+
}
66+
67+
// SSP
68+
if m, n, err := cboring.ReadMajors(r); err != nil {
69+
return err
70+
} else {
71+
switch m {
72+
case cboring.UInt:
73+
// dtn:none
74+
eid.SchemeSpecificPart = n
75+
76+
case cboring.TextString:
77+
// dtn:whatsoever
78+
if tmp, err := cboring.ReadRawBytes(n, r); err != nil {
79+
return err
80+
} else {
81+
eid.SchemeSpecificPart = string(tmp)
82+
}
83+
84+
case cboring.Array:
85+
// ipn:23.42
86+
if n != 2 {
87+
return fmt.Errorf("Expected array with length 2, got %d", n)
88+
}
89+
90+
var ssps [2]uint64
91+
for i := 0; i < 2; i++ {
92+
if n, err := cboring.ReadUInt(r); err != nil {
93+
return err
94+
} else {
95+
ssps[i] = n
96+
}
97+
}
98+
99+
eid.SchemeSpecificPart = ssps
100+
}
101+
}
102+
53103
return nil
54104
}

examples/endpoint/endpoint_test.go

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package endpoint
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"reflect"
7+
"testing"
8+
9+
"github.com/dtn7/cboring"
10+
)
11+
12+
var endpointTests = []struct {
13+
eid string
14+
cbor []byte
15+
}{
16+
{"dtn:none", []byte{0x82, 0x01, 0x00}},
17+
{"dtn:foo", []byte{0x82, 0x01, 0x63, 0x66, 0x6F, 0x6F}},
18+
{"dtn:foo/bar", []byte{0x82, 0x01, 0x67, 0x66, 0x6F, 0x6F, 0x2F, 0x62, 0x61, 0x72}},
19+
{"ipn:0.0", []byte{0x82, 0x02, 0x82, 0x00, 0x00}},
20+
{"ipn:23.42", []byte{0x82, 0x02, 0x82, 0x17, 0x18, 0x2A}},
21+
}
22+
23+
func TestEndpoint(t *testing.T) {
24+
for _, test := range endpointTests {
25+
t.Run(fmt.Sprintf("marshal-%s", test.eid), func(t *testing.T) {
26+
e := newEndpointID(test.eid)
27+
28+
buff := new(bytes.Buffer)
29+
if err := cboring.Marshal(&e, buff); err != nil {
30+
t.Fatalf("Marshaling %s failed: %v", test.eid, err)
31+
}
32+
33+
if data := buff.Bytes(); !reflect.DeepEqual(data, test.cbor) {
34+
t.Fatalf("CBOR differs: %x != %x", data, test.cbor)
35+
}
36+
})
37+
38+
t.Run(fmt.Sprintf("unmarshal-%s", test.eid), func(t *testing.T) {
39+
e := endpointID{}
40+
41+
buff := bytes.NewBuffer(test.cbor)
42+
if err := cboring.Unmarshal(&e, buff); err != nil {
43+
t.Fatalf("Unmarshaling %s failed: %v", test.eid, err)
44+
}
45+
46+
if e.String() != test.eid {
47+
t.Fatalf("EID differs: %s != %s", e.String(), test.eid)
48+
}
49+
})
50+
}
51+
}
52+
53+
func BenchmarkEndpoint(b *testing.B) {
54+
for _, test := range endpointTests {
55+
b.Run(fmt.Sprintf("marshal-%s", test.eid), func(b *testing.B) {
56+
e := newEndpointID(test.eid)
57+
58+
buff := new(bytes.Buffer)
59+
if err := cboring.Marshal(&e, buff); err != nil {
60+
b.Fatalf("Marshaling %s failed: %v", test.eid, err)
61+
}
62+
})
63+
64+
b.Run(fmt.Sprintf("unmarshal-%s", test.eid), func(b *testing.B) {
65+
e := endpointID{}
66+
67+
buff := bytes.NewBuffer(test.cbor)
68+
if err := cboring.Unmarshal(&e, buff); err != nil {
69+
b.Fatalf("Unmarshaling %s failed: %v", test.eid, err)
70+
}
71+
})
72+
}
73+
}

examples/endpoint/main.go

-18
This file was deleted.

marshal.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@ package cboring
22

33
import "io"
44

5+
// CborMarshaler is the interface implemented by an object that can both marshal
6+
// itself into a CBOR form and unmarshal a CBOR representation of itself.
57
type CborMarshaler interface {
68
MarshalCbor(w io.Writer) error
79
UnmarshalCbor(r io.Reader) error
810
}
911

10-
/*
12+
// Marshal writes a CBOR representation of a CborMarshaler into the Writer.
1113
func Marshal(data CborMarshaler, w io.Writer) error {
12-
14+
return data.MarshalCbor(w)
1315
}
1416

17+
// Unmarshal reads a CBOR representation from a Reader into a CborMarshaler.
1518
func Unmarshal(data CborMarshaler, r io.Reader) error {
19+
return data.UnmarshalCbor(r)
1620
}
17-
*/

strings.go

+6-9
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@ import (
55
"io"
66
)
77

8-
func readString(len int, r io.Reader) (data []byte, err error) {
9-
data = make([]byte, len)
10-
if rn, rerr := io.ReadFull(r, data); err != nil {
11-
err = rerr
12-
} else if rn != len {
13-
err = fmt.Errorf("readString: read length mismatches: %d != %d", rn, len)
14-
}
8+
// ReadRawBytes reads the next l bytes from r into a new byte slice.
9+
func ReadRawBytes(l uint64, r io.Reader) (data []byte, err error) {
10+
data = make([]byte, l)
11+
_, err = io.ReadFull(r, data)
1512
return
1613
}
1714

@@ -23,7 +20,7 @@ func ReadByteString(r io.Reader) (data []byte, err error) {
2320
return
2421
}
2522

26-
return readString(int(n), r)
23+
return ReadRawBytes(n, r)
2724
}
2825

2926
// WriteByteString writes a byte string into the Writer.
@@ -49,7 +46,7 @@ func ReadTextString(r io.Reader) (data string, err error) {
4946
return
5047
}
5148

52-
if rdata, rerr := readString(int(n), r); rerr != nil {
49+
if rdata, rerr := ReadRawBytes(n, r); rerr != nil {
5350
err = rerr
5451
} else {
5552
data = string(rdata)

0 commit comments

Comments
 (0)