Absolute hinky bare-bones implementation of multiformats in Perl
1package
2 Multiformats::CID {
3
4 use feature 'signatures';
5 use feature 'isa';
6 use Exporter 'import';
7 our @EXPORT_OK = qw/cid/;
8 use Multiformats::Varint qw/varint_decode_raw varint_decode_stream/;
9 use Multiformats::Multicodec qw/multicodec_get_codec multicodec_wrap/;
10 use Multiformats::Multibase qw/multibase_decode/;
11 use Multiformats::Multihash qw/multihash_unwrap multihash_unwrap_stream/;
12
13 sub cid($bytes) {
14 if(ref($bytes) && ($bytes isa 'IO::Handle' && $bytes isa 'IO::Seekable')) {
15 return cid_from_stream($bytes);
16 } else {
17 utf8::downgrade($bytes, 1);
18
19 # so a v0 and v1 cid in binary should start with either 0x00 or 0x01 - if that isn't the case
20 # assume we have a string cid
21 if(substr($bytes, 0, 1) ne "\0" && substr($bytes, 0, 1) ne "\1") {
22 my $binary = multibase_decode($bytes);
23 return cid_from_binary($binary);
24 } else {
25 # binary
26 return cid_from_binary($bytes);
27 }
28 }
29 }
30
31 sub cid_from_stream($stream) {
32 my ($version, $bread) = varint_decode_stream($stream);
33 die 'Unsupported CID version ', $version, ', ' unless $version == 1;
34 my ($mc_codec, $bread_codec) = varint_decode_stream($stream);
35 my $mc = Multiformats::Multicodec::_get_by_tag($mc_codec);
36 my ($mh, $hash) = multihash_unwrap_stream($stream);
37 return Multiformats::CID::CIDv1->new(version => 1, codec => $mc->[0], hash_function => $mh->[0], hash => $hash);
38 }
39
40 sub cid_from_binary($bytes) {
41 utf8::downgrade($bytes, 1);
42 my ($version, $bread) = varint_decode_raw($bytes);
43 die 'Unsupported CID version ', $version, ', ' unless $version == 1;
44
45 my ($mc_codec, $bread_codec) = varint_decode_raw(substr($bytes, $bread));
46
47 my $mc = Multiformats::Multicodec::_get_by_tag($mc_codec);
48
49 # not sure what that codec tag does in here because it doesn't appear to do
50 # anything - it's not encoding the remainder, so... what's it do Frank?!
51 my ($mh, $hash) = multihash_unwrap(substr($bytes, $bread + $bread_codec));
52 return Multiformats::CID::CIDv1->new(version => 1, codec => $mc->[0], hash_function => $mh->[0], hash => $hash);
53 }
54}
55
56package
57 Multiformats::CID::CIDv1 {
58 use Mojo::Base -base, -signatures;
59 use Multiformats::Multicodec qw/multicodec_wrap/;
60 use Multiformats::Multibase qw/multibase_encode/;
61 use Multiformats::Varint qw/varint_encode/;
62 use Multiformats::Multihash qw/multihash_wrap/;
63 use overload bool => sub {1}, '""' => sub { shift->to_str }, fallback => 1;
64
65 has [qw/version codec hash_function hash/] => undef;
66
67 sub to_str($self, $codec = 'base32') {
68 return multibase_encode($codec, $self->to_bytes);
69 }
70
71 sub to_bytes($self) {
72 my $hash = multihash_wrap($self->hash_function, $self->hash);
73 my $content = multicodec_wrap($self->codec, $hash);
74 my $version = varint_encode($self->version);
75 return $version . $content;
76 }
77}
78
79=pod
80
81=head1 NAME
82
83Multiformats::CID - CID handling
84
85=head1 SYNOPSIS
86
87 use Multiformats::CID qw/cid/;
88
89 # can use either the stringified representation or the raw binary representation
90 my $cid = cid('bafyreigngt2aslhuh7jbgpuliep4v4uvlantdmew2ojr7u3upknttpvqxa');
91
92=head1 FUNCTIONS
93
94=head2 cid(...)
95
96When given a string representation or binary representation of a CID will decode the version, codec, hash function, and hash value used and will return those wrapped in a C<Multiformats::CID::CIDv1> object.
97
98=head1 CIDv1 Object
99
100This object wraps a CID and has the following attributes and methods
101
102=head2 ATTRIBUTES
103
104=head3 version
105
106Returns the version of the CID (always 1)
107
108=head3 codec
109
110Returns the name of the multibase codec
111
112=head3 hash_function
113
114Returns the name of the hash function used
115
116=head3 hash
117
118Returns the binary hash (obtained via the hash function)
119
120=head2 METHODS
121
122=head3 to_str()
123
124Returns the stringified version of the CID. The CID object itself is overloaded to return this when used in string context.
125
126=head3 to_bytes()
127
128Returns the binary representation of the CID.
129
130=cut
131
1321;
133
134