refactor: Move prefix code from rust-cid to here
Using prefixes for creating CIDs is tightly coupled to Bitswap. Hence moving
this functionality from rust-cid [1] directly into bitswap.
[1]: fcb8ea3f48/src/prefix.rs
This commit is contained in:
parent
6cbf679644
commit
d9955928bb
@ -17,5 +17,7 @@ libipld = "0.1.0"
|
||||
libp2p-core = "0.16.0"
|
||||
libp2p-swarm = "0.16.1"
|
||||
log = "0.4.8"
|
||||
multihash = "0.10.1"
|
||||
prost = "0.6.1"
|
||||
thiserror = "1.0.11"
|
||||
unsigned-varint = "0.3.2"
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::bitswap_pb;
|
||||
use crate::block::Block;
|
||||
use crate::error::BitswapError;
|
||||
use crate::prefix::Prefix;
|
||||
use core::convert::TryFrom;
|
||||
use core::marker::PhantomData;
|
||||
use libipld::cid::{Cid, Prefix};
|
||||
use libipld::cid::Cid;
|
||||
use prost::Message as ProstMessage;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@ -168,7 +169,7 @@ impl Into<Vec<u8>> for &Message<O> {
|
||||
}
|
||||
for block in self.blocks() {
|
||||
let mut payload = bitswap_pb::message::Block::default();
|
||||
payload.prefix = block.cid().prefix().as_bytes();
|
||||
payload.prefix = Prefix::from(block.cid()).to_bytes();
|
||||
payload.data = block.data().to_vec();
|
||||
proto.payload.push(payload);
|
||||
}
|
||||
@ -204,8 +205,8 @@ impl TryFrom<&[u8]> for Message<I> {
|
||||
}
|
||||
}
|
||||
for payload in proto.payload {
|
||||
let prefix = Prefix::new_from_bytes(&payload.prefix)?;
|
||||
let cid = Cid::new_from_prefix(&prefix, &payload.data);
|
||||
let prefix = Prefix::new(&payload.prefix)?;
|
||||
let cid = prefix.to_cid(&payload.data)?;
|
||||
let block = Block {
|
||||
cid,
|
||||
data: payload.data.to_vec().into_boxed_slice(),
|
||||
|
@ -6,6 +6,7 @@ mod behaviour;
|
||||
mod block;
|
||||
mod error;
|
||||
mod ledger;
|
||||
mod prefix;
|
||||
mod protocol;
|
||||
mod strategy;
|
||||
|
||||
|
84
bitswap/src/prefix.rs
Normal file
84
bitswap/src/prefix.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use libipld::cid::{self, Cid, Codec, Version};
|
||||
use multihash::Code;
|
||||
use unsigned_varint::{decode as varint_decode, encode as varint_encode};
|
||||
|
||||
/// Prefix represents all metadata of a CID, without the actual content.
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub struct Prefix {
|
||||
/// The version of CID.
|
||||
pub version: Version,
|
||||
/// The codec of CID.
|
||||
pub codec: Codec,
|
||||
/// The multihash type of CID.
|
||||
pub mh_type: Code,
|
||||
/// The multihash length of CID.
|
||||
pub mh_len: usize,
|
||||
}
|
||||
|
||||
impl Prefix {
|
||||
/// Create a new prefix from encoded bytes.
|
||||
pub fn new(data: &[u8]) -> Result<Prefix, cid::Error> {
|
||||
let (raw_version, remain) = varint_decode::u64(data)?;
|
||||
let version = Version::try_from(raw_version)?;
|
||||
|
||||
let (raw_codec, remain) = varint_decode::u64(remain)?;
|
||||
let codec = Codec::try_from(raw_codec)?;
|
||||
|
||||
let (raw_mh_type, remain) = varint_decode::u64(remain)?;
|
||||
let mh_type = match multihash::Code::from_u64(raw_mh_type) {
|
||||
multihash::Code::Custom(_) => return Err(cid::Error::UnknownCodec),
|
||||
code => code,
|
||||
};
|
||||
|
||||
let (mh_len, _remain) = varint_decode::usize(remain)?;
|
||||
|
||||
Ok(Prefix {
|
||||
version,
|
||||
codec,
|
||||
mh_type,
|
||||
mh_len,
|
||||
})
|
||||
}
|
||||
|
||||
/// Convert the prefix to encoded bytes.
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut res = Vec::with_capacity(4);
|
||||
|
||||
let mut buf = varint_encode::u64_buffer();
|
||||
let version = varint_encode::u64(self.version.into(), &mut buf);
|
||||
res.extend_from_slice(version);
|
||||
let mut buf = varint_encode::u64_buffer();
|
||||
let codec = varint_encode::u64(self.codec.into(), &mut buf);
|
||||
res.extend_from_slice(codec);
|
||||
let mut buf = varint_encode::u64_buffer();
|
||||
let mh_type = varint_encode::u64(self.mh_type.to_u64(), &mut buf);
|
||||
res.extend_from_slice(mh_type);
|
||||
let mut buf = varint_encode::u64_buffer();
|
||||
let mh_len = varint_encode::u64(self.mh_len as u64, &mut buf);
|
||||
res.extend_from_slice(mh_len);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Create a CID out of the prefix and some data that will be hashed
|
||||
pub fn to_cid(&self, data: &[u8]) -> Result<Cid, cid::Error> {
|
||||
let mut hash = self.mh_type.hasher().unwrap().digest(data);
|
||||
if self.mh_len < hash.digest().len() {
|
||||
hash = multihash::wrap(hash.algorithm(), &hash.digest()[..self.mh_len]);
|
||||
}
|
||||
Cid::new(self.version, self.codec, hash)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Cid> for Prefix {
|
||||
fn from(cid: &Cid) -> Self {
|
||||
Self {
|
||||
version: cid.version(),
|
||||
codec: cid.codec(),
|
||||
mh_type: cid.hash().algorithm(),
|
||||
mh_len: cid.hash().digest().len(),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user