Skip to content

Commit 678a428

Browse files
authored
Merge pull request #153 from ipld/codec/cbor
implement non-dag cbor codec
2 parents f02df08 + 6e55e9b commit 678a428

File tree

4 files changed

+50
-15
lines changed

4 files changed

+50
-15
lines changed

codec/cbor/multicodec.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package cbor
2+
3+
import (
4+
"io"
5+
6+
"github.com/polydawn/refmt/cbor"
7+
8+
"github.com/ipld/go-ipld-prime"
9+
"github.com/ipld/go-ipld-prime/codec/dagcbor"
10+
"github.com/ipld/go-ipld-prime/multicodec"
11+
)
12+
13+
var (
14+
_ ipld.Decoder = Decode
15+
_ ipld.Encoder = Encode
16+
)
17+
18+
func init() {
19+
multicodec.RegisterEncoder(0x51, Encode)
20+
multicodec.RegisterDecoder(0x51, Decode)
21+
}
22+
23+
func Decode(na ipld.NodeAssembler, r io.Reader) error {
24+
return dagcbor.Unmarshal(na, cbor.NewDecoder(cbor.DecodeOptions{}, r), false)
25+
}
26+
27+
func Encode(n ipld.Node, w io.Writer) error {
28+
return dagcbor.Marshal(n, cbor.NewEncoder(w), false)
29+
}

codec/dagcbor/marshal.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ import (
1313
// This should be identical to the general feature in the parent package,
1414
// except for the `case ipld.Kind_Link` block,
1515
// which is dag-cbor's special sauce for schemafree links.
16-
func Marshal(n ipld.Node, sink shared.TokenSink) error {
16+
func Marshal(n ipld.Node, sink shared.TokenSink, allowLinks bool) error {
1717
var tk tok.Token
18-
return marshal(n, &tk, sink)
18+
return marshal(n, &tk, sink, allowLinks)
1919
}
2020

21-
func marshal(n ipld.Node, tk *tok.Token, sink shared.TokenSink) error {
21+
func marshal(n ipld.Node, tk *tok.Token, sink shared.TokenSink, allowLinks bool) error {
2222
switch n.Kind() {
2323
case ipld.Kind_Invalid:
2424
return fmt.Errorf("cannot traverse a node that is absent")
@@ -47,7 +47,7 @@ func marshal(n ipld.Node, tk *tok.Token, sink shared.TokenSink) error {
4747
if _, err := sink.Step(tk); err != nil {
4848
return err
4949
}
50-
if err := marshal(v, tk, sink); err != nil {
50+
if err := marshal(v, tk, sink, allowLinks); err != nil {
5151
return err
5252
}
5353
}
@@ -69,7 +69,7 @@ func marshal(n ipld.Node, tk *tok.Token, sink shared.TokenSink) error {
6969
if err != nil {
7070
return err
7171
}
72-
if err := marshal(v, tk, sink); err != nil {
72+
if err := marshal(v, tk, sink, allowLinks); err != nil {
7373
return err
7474
}
7575
}
@@ -123,6 +123,9 @@ func marshal(n ipld.Node, tk *tok.Token, sink shared.TokenSink) error {
123123
_, err = sink.Step(tk)
124124
return err
125125
case ipld.Kind_Link:
126+
if !allowLinks {
127+
return fmt.Errorf("cannot Marshal ipld links to CBOR")
128+
}
126129
v, err := n.AsLink()
127130
if err != nil {
128131
return err

codec/dagcbor/multicodec.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func Decode(na ipld.NodeAssembler, r io.Reader) error {
2828
return na2.DecodeDagCbor(r)
2929
}
3030
// Okay, generic builder path.
31-
return Unmarshal(na, cbor.NewDecoder(cbor.DecodeOptions{}, r))
31+
return Unmarshal(na, cbor.NewDecoder(cbor.DecodeOptions{}, r), true)
3232
}
3333

3434
func Encode(n ipld.Node, w io.Writer) error {
@@ -40,5 +40,5 @@ func Encode(n ipld.Node, w io.Writer) error {
4040
return n2.EncodeDagCbor(w)
4141
}
4242
// Okay, generic inspection path.
43-
return Marshal(n, cbor.NewEncoder(w))
43+
return Marshal(n, cbor.NewEncoder(w), true)
4444
}

codec/dagcbor/unmarshal.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,16 @@ const (
2727
// except for the `case tok.TBytes` block,
2828
// which has dag-cbor's special sauce for detecting schemafree links.
2929

30-
func Unmarshal(na ipld.NodeAssembler, tokSrc shared.TokenSource) error {
30+
func Unmarshal(na ipld.NodeAssembler, tokSrc shared.TokenSource, allowLinks bool) error {
3131
// Have a gas budget, which will be decremented as we allocate memory, and an error returned when execeeded (or about to be exceeded).
3232
// This is a DoS defense mechanism.
3333
// It's *roughly* in units of bytes (but only very, VERY roughly) -- it also treats words as 1 in many cases.
3434
// FUTURE: this ought be configurable somehow. (How, and at what granularity though?)
3535
var gas int = 1048576 * 10
36-
return unmarshal1(na, tokSrc, &gas)
36+
return unmarshal1(na, tokSrc, &gas, allowLinks)
3737
}
3838

39-
func unmarshal1(na ipld.NodeAssembler, tokSrc shared.TokenSource, gas *int) error {
39+
func unmarshal1(na ipld.NodeAssembler, tokSrc shared.TokenSource, gas *int, allowLinks bool) error {
4040
var tk tok.Token
4141
done, err := tokSrc.Step(&tk)
4242
if err != nil {
@@ -45,12 +45,12 @@ func unmarshal1(na ipld.NodeAssembler, tokSrc shared.TokenSource, gas *int) erro
4545
if done && !tk.Type.IsValue() {
4646
return fmt.Errorf("unexpected eof")
4747
}
48-
return unmarshal2(na, tokSrc, &tk, gas)
48+
return unmarshal2(na, tokSrc, &tk, gas, allowLinks)
4949
}
5050

5151
// starts with the first token already primed. Necessary to get recursion
5252
// to flow right without a peek+unpeek system.
53-
func unmarshal2(na ipld.NodeAssembler, tokSrc shared.TokenSource, tk *tok.Token, gas *int) error {
53+
func unmarshal2(na ipld.NodeAssembler, tokSrc shared.TokenSource, tk *tok.Token, gas *int, allowLinks bool) error {
5454
// FUTURE: check for schema.TypedNodeBuilder that's going to parse a Link (they can slurp any token kind they want).
5555
switch tk.Type {
5656
case tok.TMapOpen:
@@ -97,7 +97,7 @@ func unmarshal2(na ipld.NodeAssembler, tokSrc shared.TokenSource, tk *tok.Token,
9797
if err != nil { // return in error if the key was rejected
9898
return err
9999
}
100-
err = unmarshal1(mva, tokSrc, gas)
100+
err = unmarshal1(mva, tokSrc, gas, allowLinks)
101101
if err != nil { // return in error if some part of the recursion errored
102102
return err
103103
}
@@ -140,7 +140,7 @@ func unmarshal2(na ipld.NodeAssembler, tokSrc shared.TokenSource, tk *tok.Token,
140140
if observedLen > expectLen {
141141
return fmt.Errorf("unexpected continuation of array elements beyond declared length")
142142
}
143-
err := unmarshal2(la.AssembleValue(), tokSrc, tk, gas)
143+
err := unmarshal2(la.AssembleValue(), tokSrc, tk, gas, allowLinks)
144144
if err != nil { // return in error if some part of the recursion errored
145145
return err
146146
}
@@ -166,14 +166,17 @@ func unmarshal2(na ipld.NodeAssembler, tokSrc shared.TokenSource, tk *tok.Token,
166166
}
167167
switch tk.Tag {
168168
case linkTag:
169+
if !allowLinks {
170+
return fmt.Errorf("unhandled cbor tag %d", tk.Tag)
171+
}
169172
if len(tk.Bytes) < 1 || tk.Bytes[0] != 0 {
170173
return ErrInvalidMultibase
171174
}
172175
elCid, err := cid.Cast(tk.Bytes[1:])
173176
if err != nil {
174177
return err
175178
}
176-
return na.AssignLink(cidlink.Link{elCid})
179+
return na.AssignLink(cidlink.Link{Cid: elCid})
177180
default:
178181
return fmt.Errorf("unhandled cbor tag %d", tk.Tag)
179182
}

0 commit comments

Comments
 (0)