Absolute hinky bare-bones implementation of multiformats in Perl
at main 134 lines 4.3 kB view raw
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