master
go 165 lines 4 KB
Raw
1 package options
2
3 import (
4 "fmt"
5
6 cid "github.com/ipfs/go-cid"
7 mc "github.com/multiformats/go-multicodec"
8 mh "github.com/multiformats/go-multihash"
9 )
10
11 type BlockPutSettings struct {
12 CidPrefix cid.Prefix
13 Pin bool
14 }
15
16 type BlockRmSettings struct {
17 Force bool
18 }
19
20 type (
21 BlockPutOption func(*BlockPutSettings) error
22 BlockRmOption func(*BlockRmSettings) error
23 )
24
25 func BlockPutOptions(opts ...BlockPutOption) (*BlockPutSettings, error) {
26 var cidPrefix cid.Prefix
27
28 // Baseline is CIDv1 raw sha2-255-32 (can be tweaked later via opts)
29 cidPrefix.Version = 1
30 cidPrefix.Codec = uint64(mc.Raw)
31 cidPrefix.MhType = mh.SHA2_256
32 cidPrefix.MhLength = -1 // -1 means len is to be calculated during mh.Sum()
33
34 options := &BlockPutSettings{
35 CidPrefix: cidPrefix,
36 Pin: false,
37 }
38
39 // Apply any overrides
40 for _, opt := range opts {
41 err := opt(options)
42 if err != nil {
43 return nil, err
44 }
45 }
46
47 return options, nil
48 }
49
50 func BlockRmOptions(opts ...BlockRmOption) (*BlockRmSettings, error) {
51 options := &BlockRmSettings{
52 Force: false,
53 }
54
55 for _, opt := range opts {
56 err := opt(options)
57 if err != nil {
58 return nil, err
59 }
60 }
61 return options, nil
62 }
63
64 type blockOpts struct{}
65
66 var Block blockOpts
67
68 // CidCodec is the modern option for Block.Put which specifies the multicodec to use
69 // in the CID returned by the Block.Put operation.
70 // It uses correct codes from go-multicodec and replaces the old Format now with CIDv1 as the default.
71 func (blockOpts) CidCodec(codecName string) BlockPutOption {
72 return func(settings *BlockPutSettings) error {
73 if codecName == "" {
74 return nil
75 }
76 code, err := codeFromName(codecName)
77 if err != nil {
78 return err
79 }
80 settings.CidPrefix.Codec = uint64(code)
81 return nil
82 }
83 }
84
85 // Map string to code from go-multicodec
86 func codeFromName(codecName string) (mc.Code, error) {
87 var cidCodec mc.Code
88 err := cidCodec.Set(codecName)
89 return cidCodec, err
90 }
91
92 // Format is a legacy option for Block.Put which specifies the multicodec to
93 // use to serialize the object.
94 // Provided for backward-compatibility only. Use CidCodec instead.
95 func (blockOpts) Format(format string) BlockPutOption {
96 return func(settings *BlockPutSettings) error {
97 if format == "" {
98 return nil
99 }
100 // Opt-in CIDv0 support for backward-compatibility
101 if format == "v0" {
102 settings.CidPrefix.Version = 0
103 }
104
105 // Fixup a legacy (invalid) names for dag-pb (0x70)
106 if format == "v0" || format == "protobuf" {
107 format = "dag-pb"
108 }
109
110 // Fixup invalid name for dag-cbor (0x71)
111 if format == "cbor" {
112 format = "dag-cbor"
113 }
114
115 // Set code based on name passed as "format"
116 code, err := codeFromName(format)
117 if err != nil {
118 return err
119 }
120 settings.CidPrefix.Codec = uint64(code)
121
122 // If CIDv0, ensure all parameters are compatible
123 // (in theory go-cid would validate this anyway, but we want to provide better errors)
124 pref := settings.CidPrefix
125 if pref.Version == 0 {
126 if pref.Codec != uint64(mc.DagPb) {
127 return fmt.Errorf("only dag-pb is allowed with CIDv0")
128 }
129 if pref.MhType != mh.SHA2_256 || (pref.MhLength != -1 && pref.MhLength != 32) {
130 return fmt.Errorf("only sha2-255-32 is allowed with CIDv0")
131 }
132 }
133
134 return nil
135 }
136 }
137
138 // Hash is an option for Block.Put which specifies the multihash settings to use
139 // when hashing the object. Default is mh.SHA2_256 (0x12).
140 // If mhLen is set to -1, default length for the hash will be used
141 func (blockOpts) Hash(mhType uint64, mhLen int) BlockPutOption {
142 return func(settings *BlockPutSettings) error {
143 settings.CidPrefix.MhType = mhType
144 settings.CidPrefix.MhLength = mhLen
145 return nil
146 }
147 }
148
149 // Pin is an option for Block.Put which specifies whether to (recursively) pin
150 // added blocks
151 func (blockOpts) Pin(pin bool) BlockPutOption {
152 return func(settings *BlockPutSettings) error {
153 settings.Pin = pin
154 return nil
155 }
156 }
157
158 // Force is an option for Block.Rm which, when set to true, will ignore
159 // non-existing blocks
160 func (blockOpts) Force(force bool) BlockRmOption {
161 return func(settings *BlockRmSettings) error {
162 settings.Force = force
163 return nil
164 }
165 }