@cryptotaxi247 / kubo / commits / f153c01df

coreapi: functional options for DagAPI

License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>

Łukasz Magiera committed Dec 17, 2017 at 03:23 UTC f153c01dfa6917acf46df6fb36780decb59cd89f
5 files changed +151 -26
core/coreapi/coreapi.go
+1 -1
@@ -26,7 +26,7 @@ func (api *CoreAPI) Unixfs() coreiface.UnixfsAPI {
26 }
27
28 func (api *CoreAPI) Dag() coreiface.DagAPI {
29 - return (*dagAPI)(api)
29 + return &DagAPI{api, nil}
30 }
31
32 func (api *CoreAPI) ResolveNode(ctx context.Context, p coreiface.Path) (coreiface.Node, error) {
core/coreapi/dag.go
+22 -18
@@ -8,30 +8,29 @@ import (
8 gopath "path"
9
10 coreiface "github.com/ipfs/go-ipfs/core/coreapi/interface"
11 + caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
12 coredag "github.com/ipfs/go-ipfs/core/coredag"
13
13 - mh "gx/ipfs/QmYeKnKpubCMRiq3PGZcTREErthbb5Q9cXsCoSkD9bjEBd/go-multihash"
14 cid "gx/ipfs/QmeSrf6pzut73u6zLQkRFQ3ygt3k6XFT2kjdYP8Tnkwwyg/go-cid"
15 )
16
17 -type dagAPI CoreAPI
17 +type DagAPI struct {
18 + *CoreAPI
19 + *caopts.DagOptions
20 +}
21
19 -func (api *dagAPI) Put(ctx context.Context, src io.Reader, inputEnc string, format *cid.Prefix) ([]coreiface.Node, error) {
20 - if format == nil {
21 - format = &cid.Prefix{
22 - Version: 1,
23 - Codec: cid.DagCBOR,
24 - MhType: mh.SHA2_256,
25 - MhLength: mh.DefaultLengths[mh.SHA2_256],
26 - }
22 +func (api *DagAPI) Put(ctx context.Context, src io.Reader, opts ...caopts.DagPutOption) ([]coreiface.Node, error) {
23 + settings, err := caopts.DagPutOptions(opts...)
24 + if err != nil {
25 + return nil, err
26 }
27
29 - codec, ok := cid.CodecToStr[format.Codec]
28 + codec, ok := cid.CodecToStr[settings.Codec]
29 if !ok {
31 - return nil, fmt.Errorf("invalid codec %d", format.Codec)
30 + return nil, fmt.Errorf("invalid codec %d", settings.Codec)
31 }
32
34 - nds, err := coredag.ParseInputs(inputEnc, codec, src, format.MhType, format.MhLength)
33 + nds, err := coredag.ParseInputs(settings.InputEnc, codec, src, settings.MhType, settings.MhLength)
34 if err != nil {
35 return nil, err
36 }
@@ -51,16 +50,21 @@ func (api *dagAPI) Put(ctx context.Context, src io.Reader, inputEnc string, form
50 return out, nil
51 }
52
54 -func (api *dagAPI) Get(ctx context.Context, path coreiface.Path) (coreiface.Node, error) {
53 +func (api *DagAPI) Get(ctx context.Context, path coreiface.Path) (coreiface.Node, error) {
54 return api.core().ResolveNode(ctx, path)
55 }
56
58 -func (api *dagAPI) Tree(ctx context.Context, p coreiface.Path, depth int) ([]coreiface.Path, error) {
57 +func (api *DagAPI) Tree(ctx context.Context, p coreiface.Path, opts ...caopts.DagTreeOption) ([]coreiface.Path, error) {
58 + settings, err := caopts.DagTreeOptions(opts...)
59 + if err != nil {
60 + return nil, err
61 + }
62 +
63 n, err := api.Get(ctx, p)
64 if err != nil {
65 return nil, err
66 }
63 - paths := n.Tree("", depth)
67 + paths := n.Tree("", settings.Depth)
68 out := make([]coreiface.Path, len(paths))
69 for n, p2 := range paths {
70 out[n], err = ParsePath(gopath.Join(p.String(), p2))
@@ -72,6 +76,6 @@ func (api *dagAPI) Tree(ctx context.Context, p coreiface.Path, depth int) ([]cor
76 return out, nil
77 }
78
75 -func (api *dagAPI) core() coreiface.CoreAPI {
76 - return (*CoreAPI)(api)
79 +func (api *DagAPI) core() coreiface.CoreAPI {
80 + return api.CoreAPI
81 }
core/coreapi/dag_test.go
+23 -4
@@ -7,6 +7,8 @@ import (
7 "testing"
8
9 coreapi "github.com/ipfs/go-ipfs/core/coreapi"
10 +
11 + mh "gx/ipfs/QmYeKnKpubCMRiq3PGZcTREErthbb5Q9cXsCoSkD9bjEBd/go-multihash"
12 )
13
14 var (
@@ -26,7 +28,7 @@ func TestPut(t *testing.T) {
28 t.Error(err)
29 }
30
29 - res, err := api.Dag().Put(ctx, strings.NewReader(`"Hello"`), "json", nil)
31 + res, err := api.Dag().Put(ctx, strings.NewReader(`"Hello"`))
32 if err != nil {
33 t.Error(err)
34 }
@@ -36,6 +38,23 @@ func TestPut(t *testing.T) {
38 }
39 }
40
41 +func TestPutWithHash(t *testing.T) {
42 + ctx := context.Background()
43 + _, api, err := makeAPI(ctx)
44 + if err != nil {
45 + t.Error(err)
46 + }
47 +
48 + res, err := api.Dag().Put(ctx, strings.NewReader(`"Hello"`), api.Dag().WithHash(mh.ID, -1))
49 + if err != nil {
50 + t.Error(err)
51 + }
52 +
53 + if res[0].Cid().String() != "z5hRLNd2sv4z1c" {
54 + t.Errorf("got wrong cid: %s", res[0].Cid().String())
55 + }
56 +}
57 +
58 func TestPath(t *testing.T) {
59 ctx := context.Background()
60 _, api, err := makeAPI(ctx)
@@ -43,12 +62,12 @@ func TestPath(t *testing.T) {
62 t.Error(err)
63 }
64
46 - sub, err := api.Dag().Put(ctx, strings.NewReader(`"foo"`), "json", nil)
65 + sub, err := api.Dag().Put(ctx, strings.NewReader(`"foo"`))
66 if err != nil {
67 t.Error(err)
68 }
69
51 - res, err := api.Dag().Put(ctx, strings.NewReader(`{"lnk": {"/": "`+sub[0].Cid().String()+`"}}`), "json", nil)
70 + res, err := api.Dag().Put(ctx, strings.NewReader(`{"lnk": {"/": "`+sub[0].Cid().String()+`"}}`))
71 if err != nil {
72 t.Error(err)
73 }
@@ -75,7 +94,7 @@ func TestTree(t *testing.T) {
94 t.Error(err)
95 }
96
78 - res, err := api.Dag().Put(ctx, strings.NewReader(`{"a": 123, "b": "foo", "c": {"d": 321, "e": 111}}`), "json", nil)
97 + res, err := api.Dag().Put(ctx, strings.NewReader(`{"a": 123, "b": "foo", "c": {"d": 321, "e": 111}}`))
98 if err != nil {
99 t.Error(err)
100 }
core/coreapi/interface/interface.go
+22 -3
@@ -7,6 +7,8 @@ import (
7 "errors"
8 "io"
9
10 + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
11 +
12 ipld "gx/ipfs/QmNwUEK7QbwSqyKBu3mMtToo8SUc6wQJ7gdZq4gGGJqfnf/go-ipld-format"
13 cid "gx/ipfs/QmeSrf6pzut73u6zLQkRFQ3ygt3k6XFT2kjdYP8Tnkwwyg/go-cid"
14 )
@@ -60,14 +62,31 @@ type UnixfsAPI interface {
62 type DagAPI interface {
63 // Put inserts data using specified format and input encoding.
64 // If format is not specified (nil), default dag-cbor/sha256 is used
63 - Put(ctx context.Context, src io.Reader, inputEnc string, format *cid.Prefix) ([]Node, error) //TODO: make format optional
65 + Put(ctx context.Context, src io.Reader, opts ...options.DagPutOption) ([]Node, error)
66 +
67 + // WithInputEnc is an option for Put which specifies the input encoding of the
68 + // data. Default is "json", most formats/codecs support "raw"
69 + WithInputEnc(enc string) options.DagPutOption
70 +
71 + // WithCodec is an option for Put which specifies the multicodec to use to
72 + // serialize the object. Default is cid.DagCBOR (0x71)
73 + WithCodec(codec uint64) options.DagPutOption
74 +
75 + // WithHash is an option for Put which specifies the multihash settings to use
76 + // when hashing the object. Default is based on the codec used
77 + // (mh.SHA2_256 (0x12) for DagCBOR). If mhLen is set to -1, default length for
78 + // the hash will be used
79 + WithHash(mhType uint64, mhLen int) options.DagPutOption
80
81 // Get attempts to resolve and get the node specified by the path
82 Get(ctx context.Context, path Path) (Node, error)
83
84 // Tree returns list of paths within a node specified by the path.
69 - // To get all paths in a tree, set depth to -1
70 - Tree(ctx context.Context, path Path, depth int) ([]Path, error)
85 + Tree(ctx context.Context, path Path, opts ...options.DagTreeOption) ([]Path, error)
86 +
87 + // WithDepth is an option for Tree which specifies maximum depth of the
88 + // returned tree. Default is -1 (no depth limit)
89 + WithDepth(depth int) options.DagTreeOption
90 }
91
92 // type ObjectAPI interface {
core/coreapi/interface/options/dag.go new
+83
@@ -0,0 +1,83 @@
1 +package options
2 +
3 +import (
4 + "math"
5 +
6 + cid "gx/ipfs/QmeSrf6pzut73u6zLQkRFQ3ygt3k6XFT2kjdYP8Tnkwwyg/go-cid"
7 +)
8 +
9 +type DagPutSettings struct {
10 + InputEnc string
11 + Codec uint64
12 + MhType uint64
13 + MhLength int
14 +}
15 +
16 +type DagTreeSettings struct {
17 + Depth int
18 +}
19 +
20 +type DagPutOption func(*DagPutSettings) error
21 +type DagTreeOption func(*DagTreeSettings) error
22 +
23 +func DagPutOptions(opts ...DagPutOption) (*DagPutSettings, error) {
24 + options := &DagPutSettings{
25 + InputEnc: "json",
26 + Codec: cid.DagCBOR,
27 + MhType: math.MaxUint64,
28 + MhLength: -1,
29 + }
30 +
31 + for _, opt := range opts {
32 + err := opt(options)
33 + if err != nil {
34 + return nil, err
35 + }
36 + }
37 + return options, nil
38 +}
39 +
40 +func DagTreeOptions(opts ...DagTreeOption) (*DagTreeSettings, error) {
41 + options := &DagTreeSettings{
42 + Depth: -1,
43 + }
44 +
45 + for _, opt := range opts {
46 + err := opt(options)
47 + if err != nil {
48 + return nil, err
49 + }
50 + }
51 + return options, nil
52 +}
53 +
54 +type DagOptions struct{}
55 +
56 +func (api *DagOptions) WithInputEnc(enc string) DagPutOption {
57 + return func(settings *DagPutSettings) error {
58 + settings.InputEnc = enc
59 + return nil
60 + }
61 +}
62 +
63 +func (api *DagOptions) WithCodec(codec uint64) DagPutOption {
64 + return func(settings *DagPutSettings) error {
65 + settings.Codec = codec
66 + return nil
67 + }
68 +}
69 +
70 +func (api *DagOptions) WithHash(mhType uint64, mhLen int) DagPutOption {
71 + return func(settings *DagPutSettings) error {
72 + settings.MhType = mhType
73 + settings.MhLength = mhLen
74 + return nil
75 + }
76 +}
77 +
78 +func (api *DagOptions) WithDepth(depth int) DagTreeOption {
79 + return func(settings *DagTreeSettings) error {
80 + settings.Depth = depth
81 + return nil
82 + }
83 +}