1
1
package main
2
2
3
3
import (
4
- "bytes"
5
4
"fmt"
6
5
"os"
7
6
"strings"
8
7
9
8
c "github.com/ipfs/go-cid"
10
9
11
10
mb "github.com/multiformats/go-multibase"
12
- mh "github.com/multiformats/go-multihash"
13
11
)
14
12
15
13
func usage () {
16
14
fmt .Fprintf (os .Stderr , "usage: %s [-b multibase-code] [-v cid-version] <fmt-str> <cid> ...\n \n " , os .Args [0 ])
17
- fmt .Fprintf (os .Stderr , "<fmt-str> is either 'prefix' or a printf style format string:\n %s" , fmtRef )
15
+ fmt .Fprintf (os .Stderr , "<fmt-str> is either 'prefix' or a printf style format string:\n %s" , c . FormatRef )
18
16
os .Exit (2 )
19
17
}
20
18
21
- const fmtRef = `
22
- %% literal %
23
- %b multibase name
24
- %B multibase code
25
- %v version string
26
- %V version number
27
- %c codec name
28
- %C codec code
29
- %h multihash name
30
- %H multihash code
31
- %L hash digest length
32
- %m multihash encoded in base %b (with multibase prefix)
33
- %M multihash encoded in base %b without multibase prefix
34
- %d hash digest encoded in base %b (with multibase prefix)
35
- %D hash digest encoded in base %b without multibase prefix
36
- %s cid string encoded in base %b (1)
37
- %s cid string encoded in base %b without multibase prefix
38
- %P cid prefix: %v-%c-%h-%L
39
-
40
- (1) For CID version 0 the multibase must be base58btc and no prefix is
41
- used. For Cid version 1 the multibase prefix is included.
42
- `
43
-
44
19
func main () {
45
20
if len (os .Args ) < 2 {
46
21
usage ()
@@ -55,11 +30,12 @@ outer:
55
30
if len (args ) < 2 {
56
31
usage ()
57
32
}
58
- if len (args [1 ]) != 1 {
59
- fmt .Fprintf (os .Stderr , "Error: Invalid multibase code: %s\n " , args [1 ])
33
+ encoder , err := mb .EncoderByName (args [1 ])
34
+ if err != nil {
35
+ fmt .Fprintf (os .Stderr , "Error: %s\n " , err .Error ())
60
36
os .Exit (2 )
61
37
}
62
- newBase = mb .Encoding (args [ 1 ][ 0 ] )
38
+ newBase = encoder .Encoding ()
63
39
args = args [2 :]
64
40
case "-v" :
65
41
if len (args ) < 2 {
@@ -93,15 +69,16 @@ outer:
93
69
}
94
70
}
95
71
for _ , cidStr := range args [1 :] {
96
- base , cid , err := decode (cidStr )
72
+ cid , err := c . Decode (cidStr )
97
73
if err != nil {
98
74
fmt .Fprintf (os .Stdout , "!INVALID_CID!\n " )
99
75
errorMsg ("%s: %v" , cidStr , err )
100
76
// Don't abort on a bad cid
101
77
continue
102
78
}
103
- if newBase != - 1 {
104
- base = newBase
79
+ base := newBase
80
+ if newBase == - 1 {
81
+ base , _ = c .ExtractEncoding (cidStr )
105
82
}
106
83
if verConv != nil {
107
84
cid , err = verConv (cid )
@@ -112,11 +89,18 @@ outer:
112
89
continue
113
90
}
114
91
}
115
- str , err := fmtCid (fmtStr , base , cid )
116
- if err != nil {
92
+ str , err := c .Format (fmtStr , base , cid )
93
+ switch err .(type ) {
94
+ case c.FormatStringError :
117
95
fmt .Fprintf (os .Stderr , "Error: %v\n " , err )
118
- // An error here means a bad format string, no point in continuing
119
96
os .Exit (2 )
97
+ default :
98
+ fmt .Fprintf (os .Stdout , "!ERROR!\n " )
99
+ errorMsg ("%s: %v" , cidStr , err )
100
+ // Don't abort on cid specific errors
101
+ continue
102
+ case nil :
103
+ // no error
120
104
}
121
105
fmt .Fprintf (os .Stdout , "%s\n " , str )
122
106
}
@@ -132,139 +116,6 @@ func errorMsg(fmtStr string, a ...interface{}) {
132
116
exitCode = 1
133
117
}
134
118
135
- func decode (v string ) (mb.Encoding , * c.Cid , error ) {
136
- if len (v ) < 2 {
137
- return 0 , nil , c .ErrCidTooShort
138
- }
139
-
140
- if len (v ) == 46 && v [:2 ] == "Qm" {
141
- hash , err := mh .FromB58String (v )
142
- if err != nil {
143
- return 0 , nil , err
144
- }
145
-
146
- return mb .Base58BTC , c .NewCidV0 (hash ), nil
147
- }
148
-
149
- base , data , err := mb .Decode (v )
150
- if err != nil {
151
- return 0 , nil , err
152
- }
153
-
154
- cid , err := c .Cast (data )
155
-
156
- return base , cid , err
157
- }
158
-
159
- const ERR_STR = "!ERROR!"
160
-
161
- func fmtCid (fmtStr string , base mb.Encoding , cid * c.Cid ) (string , error ) {
162
- p := cid .Prefix ()
163
- out := new (bytes.Buffer )
164
- var err error
165
- for i := 0 ; i < len (fmtStr ); i ++ {
166
- if fmtStr [i ] != '%' {
167
- out .WriteByte (fmtStr [i ])
168
- continue
169
- }
170
- i ++
171
- if i >= len (fmtStr ) {
172
- return "" , fmt .Errorf ("premature end of format string" )
173
- }
174
- switch fmtStr [i ] {
175
- case '%' :
176
- out .WriteByte ('%' )
177
- case 'b' : // base name
178
- out .WriteString (baseToString (base ))
179
- case 'B' : // base code
180
- out .WriteByte (byte (base ))
181
- case 'v' : // version string
182
- fmt .Fprintf (out , "cidv%d" , p .Version )
183
- case 'V' : // version num
184
- fmt .Fprintf (out , "%d" , p .Version )
185
- case 'c' : // codec name
186
- out .WriteString (codecToString (p .Codec ))
187
- case 'C' : // codec code
188
- fmt .Fprintf (out , "%d" , p .Codec )
189
- case 'h' : // hash fun name
190
- out .WriteString (hashToString (p .MhType ))
191
- case 'H' : // hash fun code
192
- fmt .Fprintf (out , "%d" , p .MhType )
193
- case 'L' : // hash length
194
- fmt .Fprintf (out , "%d" , p .MhLength )
195
- case 'm' , 'M' : // multihash encoded in base %b
196
- out .WriteString (encode (base , cid .Hash (), fmtStr [i ] == 'M' ))
197
- case 'd' , 'D' : // hash digest encoded in base %b
198
- dec , err := mh .Decode (cid .Hash ())
199
- if err != nil {
200
- out .WriteString (ERR_STR )
201
- errorMsg ("%v" , err )
202
- continue
203
- }
204
- out .WriteString (encode (base , dec .Digest , fmtStr [i ] == 'D' ))
205
- case 's' : // cid string encoded in base %b
206
- str , err := cid .StringOfBase (base )
207
- if err != nil {
208
- out .WriteString (ERR_STR )
209
- errorMsg ("%v" , err )
210
- continue
211
- }
212
- out .WriteString (str )
213
- case 'S' : // cid string without base prefix
214
- out .WriteString (encode (base , cid .Bytes (), true ))
215
- case 'P' : // prefix
216
- fmt .Fprintf (out , "cidv%d-%s-%s-%d" ,
217
- p .Version ,
218
- codecToString (p .Codec ),
219
- hashToString (p .MhType ),
220
- p .MhLength ,
221
- )
222
- default :
223
- return "" , fmt .Errorf ("unrecognized specifier in format string: %c" , fmtStr [i ])
224
- }
225
-
226
- }
227
- return out .String (), err
228
- }
229
-
230
- func baseToString (base mb.Encoding ) string {
231
- // FIXME: Use lookup tables when they are added to go-multibase
232
- switch base {
233
- case mb .Base58BTC :
234
- return "base58btc"
235
- default :
236
- return fmt .Sprintf ("base?%c" , base )
237
- }
238
- }
239
-
240
- func codecToString (num uint64 ) string {
241
- name , ok := c .CodecToStr [num ]
242
- if ! ok {
243
- return fmt .Sprintf ("codec?%d" , num )
244
- }
245
- return name
246
- }
247
-
248
- func hashToString (num uint64 ) string {
249
- name , ok := mh .Codes [num ]
250
- if ! ok {
251
- return fmt .Sprintf ("hash?%d" , num )
252
- }
253
- return name
254
- }
255
-
256
- func encode (base mb.Encoding , data []byte , strip bool ) string {
257
- str , err := mb .Encode (base , data )
258
- if err != nil {
259
- errorMsg ("%v" , err )
260
- return ERR_STR
261
- }
262
- if strip {
263
- return str [1 :]
264
- }
265
- return str
266
- }
267
-
268
119
func toCidV0 (cid * c.Cid ) (* c.Cid , error ) {
269
120
if cid .Type () != c .DagProtobuf {
270
121
return nil , fmt .Errorf ("can't convert non-protobuf nodes to cidv0" )
0 commit comments