Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
dms3
go-cid
Commits
7333c60a
Commit
7333c60a
authored
Aug 15, 2017
by
Kevin Atkinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement 'cid-fmt' utility.
parent
f62e35b8
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
255 additions
and
28 deletions
+255
-28
cid-fmt/main.go
cid-fmt/main.go
+182
-28
cid-fmt/main_test.go
cid-fmt/main_test.go
+73
-0
No files found.
cid-fmt/main.go
View file @
7333c60a
package
main
import
(
"bytes"
"fmt"
"os"
"strings"
c
"github.com/ipfs/go-cid"
mb
"github.com/multiformats/go-multibase"
mh
"github.com/multiformats/go-multihash"
)
func
usage
()
{
fmt
.
Fprintf
(
os
.
Stderr
,
"usage: %s [-b multibase-code] <fmt-str> <cid> ...
\n\n
"
,
os
.
Args
[
0
])
fmt
.
Fprintf
(
os
.
Stderr
,
"<fmt-str> is either 'prefix' or a printf style format string:
\n
%s"
,
fmtRef
)
os
.
Exit
(
1
)
}
const
fmtRef
=
`
%% literal %
%b multibase name
%B multibase code
%v version string
%V version number
%c codec name
%C codec code
%h multihash name
%H multihash code
%L hash digest length
%m multihash encoded in base %b (with multibase prefix)
%M multihash encoded in base %b without multibase prefix
%d hash digest encoded in base %b (with multibase prefix)
%D hash digest encoded in base %b without multibase prefix
%s cid string encoded in base %b (1)
%s cid string encoded in base %b without multibase prefix
%P cid prefix: %v-%c-%h-%L
(1) For CID version 0 the multibase must be base58btc and no prefix is
used. For Cid version 1 the multibase prefix is included.
`
func
main
()
{
if
len
(
os
.
Args
)
<
2
{
fmt
.
Fprintf
(
os
.
Stderr
,
"usage: %s prefix ...
\n
"
,
os
.
Args
[
0
])
os
.
Exit
(
1
)
usage
()
}
newBase
:=
mb
.
Encoding
(
-
1
)
args
:=
os
.
Args
[
1
:
]
if
args
[
0
]
==
"-b"
{
if
len
(
args
)
<
2
{
usage
()
}
if
len
(
args
[
1
])
!=
1
{
fmt
.
Fprintf
(
os
.
Stderr
,
"Error: Invalid multibase code: %s
\n
"
,
args
[
1
])
}
newBase
=
mb
.
Encoding
(
args
[
1
][
0
])
args
=
args
[
2
:
]
}
if
len
(
args
)
<
2
{
usage
()
}
switch
os
.
Args
[
1
]
{
fmtStr
:=
args
[
0
]
switch
fmtStr
{
case
"prefix"
:
err
:=
prefixCmd
(
os
.
Args
[
2
:
])
fmtStr
=
"%P"
default
:
if
strings
.
IndexByte
(
fmtStr
,
'%'
)
==
-
1
{
fmt
.
Fprintf
(
os
.
Stderr
,
"Error: Invalid format string: %s
\n
"
,
fmtStr
)
}
}
for
_
,
cidStr
:=
range
args
[
1
:
]
{
base
,
cid
,
err
:=
decode
(
cidStr
)
if
newBase
!=
-
1
{
base
=
newBase
}
if
err
!=
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"%v
\n
"
,
err
)
fmt
.
Fprintf
(
os
.
Stderr
,
"Error: %s: %v
\n
"
,
cidStr
,
err
)
fmt
.
Fprintf
(
os
.
Stdout
,
"!INVALID_CID!
\n
"
)
// Don't abort on a bad cid
continue
}
str
,
err
:=
fmtCid
(
fmtStr
,
base
,
cid
)
if
err
!=
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"Error: %v
\n
"
,
err
)
// An error here means a bad format string, no point in continuing
os
.
Exit
(
1
)
}
default
:
fmt
.
Fprintf
(
os
.
Stderr
,
"usage: %s prefix ...
\n
"
)
os
.
Exit
(
1
)
fmt
.
Fprintf
(
os
.
Stdout
,
"%s
\n
"
,
str
)
}
}
func
prefixCmd
(
args
[]
string
)
error
{
for
_
,
cid
:=
range
args
{
p
,
err
:=
prefix
(
cid
)
func
decode
(
v
string
)
(
mb
.
Encoding
,
*
c
.
Cid
,
error
)
{
if
len
(
v
)
<
2
{
return
0
,
nil
,
c
.
ErrCidTooShort
}
if
len
(
v
)
==
46
&&
v
[
:
2
]
==
"Qm"
{
hash
,
err
:=
mh
.
FromB58String
(
v
)
if
err
!=
nil
{
return
err
return
0
,
nil
,
err
}
fmt
.
Fprintf
(
os
.
Stdout
,
"%s
\n
"
,
p
)
return
mb
.
Base58BTC
,
c
.
NewCidV0
(
hash
),
nil
}
return
nil
}
func
prefix
(
str
string
)
(
string
,
error
)
{
cid
,
err
:=
c
.
Decode
(
str
)
base
,
data
,
err
:=
mb
.
Decode
(
v
)
if
err
!=
nil
{
return
""
,
err
return
0
,
nil
,
err
}
cid
,
err
:=
c
.
Cast
(
data
)
return
base
,
cid
,
err
}
const
ERR_STR
=
"!ERROR!"
func
fmtCid
(
fmtStr
string
,
base
mb
.
Encoding
,
cid
*
c
.
Cid
)
(
string
,
error
)
{
p
:=
cid
.
Prefix
()
return
fmt
.
Sprintf
(
"cidv%d-%s-%s-%d"
,
p
.
Version
,
codecToStr
(
p
.
Codec
),
mhToStr
(
p
.
MhType
),
p
.
MhLength
,
),
nil
out
:=
new
(
bytes
.
Buffer
)
for
i
:=
0
;
i
<
len
(
fmtStr
);
i
++
{
if
fmtStr
[
i
]
!=
'%'
{
out
.
WriteByte
(
fmtStr
[
i
])
continue
}
i
++
if
i
>=
len
(
fmtStr
)
{
return
""
,
fmt
.
Errorf
(
"premature end of format string"
)
}
switch
fmtStr
[
i
]
{
case
'%'
:
out
.
WriteByte
(
'%'
)
case
'b'
:
// base name
out
.
WriteString
(
baseToString
(
base
))
case
'B'
:
// base code
out
.
WriteByte
(
byte
(
base
))
case
'v'
:
// version string
fmt
.
Fprintf
(
out
,
"cidv%d"
,
p
.
Version
)
case
'V'
:
// version num
fmt
.
Fprintf
(
out
,
"%d"
,
p
.
Version
)
case
'c'
:
// codec name
out
.
WriteString
(
codecToString
(
p
.
Codec
))
case
'C'
:
// codec code
fmt
.
Fprintf
(
out
,
"%d"
,
p
.
Codec
)
case
'h'
:
// hash fun name
out
.
WriteString
(
hashToString
(
p
.
MhType
))
case
'H'
:
// hash fun code
fmt
.
Fprintf
(
out
,
"%d"
,
p
.
MhType
)
case
'L'
:
// hash length
fmt
.
Fprintf
(
out
,
"%d"
,
p
.
MhLength
)
case
'm'
,
'M'
:
// multihash encoded in base %b
out
.
WriteString
(
encode
(
base
,
cid
.
Hash
(),
fmtStr
[
i
]
==
'M'
))
case
'd'
,
'D'
:
// hash digest encoded in base %b
dec
,
err
:=
mh
.
Decode
(
cid
.
Hash
())
if
err
!=
nil
{
out
.
WriteString
(
ERR_STR
)
fmt
.
Fprintf
(
os
.
Stderr
,
"Error: %v
\n
"
,
err
)
continue
}
out
.
WriteString
(
encode
(
base
,
dec
.
Digest
,
fmtStr
[
i
]
==
'D'
))
case
's'
:
// cid string encoded in base %b
str
,
err
:=
cid
.
StringOfBase
(
base
)
if
err
!=
nil
{
out
.
WriteString
(
ERR_STR
)
fmt
.
Fprintf
(
os
.
Stderr
,
"Error: %v
\n
"
,
err
)
continue
}
out
.
WriteString
(
str
)
case
'S'
:
// cid string without base prefix
out
.
WriteString
(
encode
(
base
,
cid
.
Bytes
(),
true
))
case
'P'
:
// prefix
fmt
.
Fprintf
(
out
,
"cidv%d-%s-%s-%d"
,
p
.
Version
,
codecToString
(
p
.
Codec
),
hashToString
(
p
.
MhType
),
p
.
MhLength
,
)
default
:
return
""
,
fmt
.
Errorf
(
"unrecognized specifier in format string: %c
\n
"
,
fmtStr
[
i
])
}
}
return
out
.
String
(),
nil
}
func
codecToStr
(
num
uint64
)
string
{
func
baseToString
(
base
mb
.
Encoding
)
string
{
// FIXME: Use lookup tables when they are added to go-multibase
switch
base
{
case
mb
.
Base58BTC
:
return
"base58btc"
default
:
return
fmt
.
Sprintf
(
"base?%c"
,
base
)
}
}
func
codecToString
(
num
uint64
)
string
{
name
,
ok
:=
c
.
CodecToStr
[
num
]
if
!
ok
{
return
fmt
.
Sprintf
(
"c?%d"
,
num
)
return
fmt
.
Sprintf
(
"c
odec
?%d"
,
num
)
}
return
name
}
func
m
hToStr
(
num
uint64
)
string
{
func
has
hToStr
ing
(
num
uint64
)
string
{
name
,
ok
:=
mh
.
Codes
[
num
]
if
!
ok
{
return
fmt
.
Sprintf
(
"h?%d"
,
num
)
return
fmt
.
Sprintf
(
"h
ash
?%d"
,
num
)
}
return
name
}
func
encode
(
base
mb
.
Encoding
,
data
[]
byte
,
strip
bool
)
string
{
str
,
err
:=
mb
.
Encode
(
base
,
data
)
if
err
!=
nil
{
fmt
.
Fprintf
(
os
.
Stderr
,
"Error: %v
\n
"
,
err
)
return
ERR_STR
}
if
strip
{
return
str
[
1
:
]
}
return
str
}
cid-fmt/main_test.go
0 → 100644
View file @
7333c60a
package
main
import
(
"fmt"
"testing"
mb
"github.com/multiformats/go-multibase"
)
func
TestFmt
(
t
*
testing
.
T
)
{
cids
:=
map
[
string
]
string
{
"cidv0"
:
"QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"
,
"cidv1"
:
"zdj7WfLr9DhLrb1hsoSi4fSdjjxuZmeqgEtBPWxMLtPbDNbFD"
,
}
tests
:=
[]
struct
{
cidId
string
newBase
mb
.
Encoding
fmtStr
string
result
string
}{
{
"cidv0"
,
-
1
,
"%P"
,
"cidv0-protobuf-sha2-256-32"
},
{
"cidv0"
,
-
1
,
"%b-%v-%c-%h-%L"
,
"base58btc-cidv0-protobuf-sha2-256-32"
},
{
"cidv0"
,
-
1
,
"%s"
,
"QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"
},
{
"cidv0"
,
-
1
,
"%S"
,
"QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"
},
{
"cidv0"
,
-
1
,
"ver#%V/#%C/#%H/%L"
,
"ver#0/#112/#18/32"
},
{
"cidv0"
,
-
1
,
"%m"
,
"zQmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"
},
{
"cidv0"
,
-
1
,
"%M"
,
"QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"
},
{
"cidv0"
,
-
1
,
"%d"
,
"z72gdmFAgRzYHkJzKiL8MgMMRW3BTSCGyDHroPxJbxMJn"
},
{
"cidv0"
,
-
1
,
"%D"
,
"72gdmFAgRzYHkJzKiL8MgMMRW3BTSCGyDHroPxJbxMJn"
},
{
"cidv0"
,
'B'
,
"%S"
,
"CIQFTFEEHEDF6KLBT32BFAGLXEZL4UWFNWM4LFTLMXQBCERZ6CMLX3Y"
},
{
"cidv0"
,
'B'
,
"%B%S"
,
"BCIQFTFEEHEDF6KLBT32BFAGLXEZL4UWFNWM4LFTLMXQBCERZ6CMLX3Y"
},
{
"cidv1"
,
-
1
,
"%P"
,
"cidv1-protobuf-sha2-256-32"
},
{
"cidv1"
,
-
1
,
"%b-%v-%c-%h-%L"
,
"base58btc-cidv1-protobuf-sha2-256-32"
},
{
"cidv1"
,
-
1
,
"%s"
,
"zdj7WfLr9DhLrb1hsoSi4fSdjjxuZmeqgEtBPWxMLtPbDNbFD"
},
{
"cidv1"
,
-
1
,
"%S"
,
"dj7WfLr9DhLrb1hsoSi4fSdjjxuZmeqgEtBPWxMLtPbDNbFD"
},
{
"cidv1"
,
-
1
,
"ver#%V/#%C/#%H/%L"
,
"ver#1/#112/#18/32"
},
{
"cidv1"
,
-
1
,
"%m"
,
"zQmYFbmndVP7QqAVWyKhpmMuQHMaD88pkK57RgYVimmoh5H"
},
{
"cidv1"
,
-
1
,
"%M"
,
"QmYFbmndVP7QqAVWyKhpmMuQHMaD88pkK57RgYVimmoh5H"
},
{
"cidv1"
,
-
1
,
"%d"
,
"zAux4gVVsLRMXtsZ9fd3tFEZN4jGYB6kP37fgoZNTc11H"
},
{
"cidv1"
,
-
1
,
"%D"
,
"Aux4gVVsLRMXtsZ9fd3tFEZN4jGYB6kP37fgoZNTc11H"
},
{
"cidv1"
,
'B'
,
"%s"
,
"bAFYBEIETJGSRL3EQPQPCABV3G6IUBYTSIFVQ24XRRHD3JUETSKLTGQ7DJA"
},
// note: ^ "bAFYB.." should probably be "BAFYB.." (upper case b)
{
"cidv1"
,
'B'
,
"%S"
,
"AFYBEIETJGSRL3EQPQPCABV3G6IUBYTSIFVQ24XRRHD3JUETSKLTGQ7DJA"
},
{
"cidv1"
,
'B'
,
"%B%S"
,
"BAFYBEIETJGSRL3EQPQPCABV3G6IUBYTSIFVQ24XRRHD3JUETSKLTGQ7DJA"
},
}
for
_
,
tc
:=
range
tests
{
name
:=
fmt
.
Sprintf
(
"%s/%s"
,
tc
.
cidId
,
tc
.
fmtStr
)
if
tc
.
newBase
!=
-
1
{
name
=
fmt
.
Sprintf
(
"%s/%c"
,
name
,
tc
.
newBase
)
}
cidStr
:=
cids
[
tc
.
cidId
]
t
.
Run
(
name
,
func
(
t
*
testing
.
T
)
{
testFmt
(
t
,
cidStr
,
tc
.
newBase
,
tc
.
fmtStr
,
tc
.
result
)
})
}
}
func
testFmt
(
t
*
testing
.
T
,
cidStr
string
,
newBase
mb
.
Encoding
,
fmtStr
string
,
result
string
)
{
base
,
cid
,
err
:=
decode
(
cidStr
)
if
newBase
!=
-
1
{
base
=
newBase
}
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
str
,
err
:=
fmtCid
(
fmtStr
,
base
,
cid
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
str
!=
result
{
t
.
Error
(
fmt
.
Sprintf
(
"expected: %s; but got: %s"
,
result
,
str
))
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment