From 60dcd4ca4f929bfd850a15f28fddac3d5e99192d Mon Sep 17 00:00:00 2001 From: mriise Date: Tue, 12 Jul 2022 18:37:06 +0000 Subject: [PATCH] implement stack-based display and multibase encoding --- Cargo.toml | 6 ++--- src/cid.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 - 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f5ff23a..dddcdb1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,9 +10,9 @@ readme = "README.md" edition = "2018" [features] -default = ["std", "multihash/default"] +default = [ "multibase"] std = ["multihash/std", "unsigned-varint/std", "alloc", "multibase/std"] -alloc = ["multibase", "multihash/alloc", "core2/alloc", "serde/alloc"] +alloc = ["multibase/alloc", "multihash/alloc", "core2/alloc", "serde/alloc"] arb = ["quickcheck", "rand", "multihash/arb", "multihash/sha2", "arbitrary"] scale-codec = ["parity-scale-codec", "multihash/scale-codec"] serde-codec = ["alloc", "serde", "multihash/serde-codec", "serde_bytes"] @@ -21,7 +21,7 @@ serde-codec = ["alloc", "serde", "multihash/serde-codec", "serde_bytes"] multihash = { version = "0.16.2", default-features = false } unsigned-varint = { version = "0.7.0", default-features = false } -multibase = { version = "0.9.1", optional = true, default-features = false } +multibase = { version = "0.9.1", optional = true, default-features = false, git = "https://github.com/mriise/rust-multibase", branch = "stack" } parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"], optional = true } quickcheck = { version = "0.9.2", optional = true } rand = { version = "0.7.3", optional = true } diff --git a/src/cid.rs b/src/cid.rs index d6a852f..027abb0 100644 --- a/src/cid.rs +++ b/src/cid.rs @@ -7,6 +7,7 @@ //! import the `Cid` type from this module. use core::convert::TryFrom; +use multibase::{StackBase, StackVec, StackString}; #[cfg(feature = "alloc")] use multibase::{encode as base_encode, Base}; @@ -182,6 +183,26 @@ impl Cid { multibase::encode(Base::Base32Lower, self.to_bytes().as_slice()) } + fn to_stack_string_v0(&self) -> StackString { + let mut vec = StackVec::::default(); + { + let buf: &mut [u8] = &mut vec; + // unwraps because it assumes const was written to be generic over base + CID and thus should be correctly sized + self.hash.write(buf).unwrap(); + } + StackBase::<0, STR>::Base58BtcS.encode(vec).unwrap() + } + + fn to_stack_string_v1(&self) -> StackString { + let mut vec = StackVec::::default(); + { + let buf: &mut [u8] = &mut vec; + // unwraps because it assumes const was written to be generic over base + CID and thus should be correctly sized + self.write_bytes_v1(buf).unwrap(); + } + StackBase::<0, STR>::Base32Lower.encode(vec).unwrap() + } + /// Convert CID into a multibase encoded string /// /// # Example @@ -222,6 +243,55 @@ impl Default for Cid { } } +#[cfg(not(feature = "alloc"))] +/// takes a numerator of a fraction (magic number!) +/// and the input size to calculate the expected output size +/// +/// adds the buffer sizes of varint +/// +/// 58: 136566 +/// 10: 240824 +const fn encoded_size(size: usize, num: usize) -> usize { + let version_size = 1; + let codec_size = 4; + (size * num / 100000) + 1 + version_size + codec_size +} + +#[cfg(not(feature = "alloc"))] +macro_rules! stack_display { + ($($size:literal,)*) => { + $( + impl core::fmt::Display for Cid<$size> { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + + match self.version { + Version::V0 => write!(f, "{}", self.to_stack_string_v0::<{encoded_size($size, 136566)}>()), + Version::V1 => write!(f, "{}", self.to_stack_string_v1::<{encoded_size($size, 240824)}>()), + } + } + } + + impl core::fmt::Debug for Cid<$size> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + if f.alternate() { + f.debug_struct("Cid") + .field("version", &self.version()) + .field("codec", &self.codec()) + .field("hash", self.hash()) + .finish() + } else { + write!(f, "Cid({})", self) + } + } + } + + )* + }; +} + +#[cfg(not(feature = "alloc"))] +stack_display!(32, 64, 128, 256, 512, 1024, 2048,); + // TODO: remove the dependency on alloc by fixing // https://github.com/multiformats/rust-multibase/issues/33 #[cfg(feature = "alloc")] diff --git a/src/lib.rs b/src/lib.rs index ee839d1..1f72c89 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,6 @@ pub use self::cid::Cid as CidGeneric; pub use self::error::{Error, Result}; pub use self::version::Version; -#[cfg(feature = "alloc")] pub use multibase; pub use multihash;