diff --git a/src/csv/serialize/commitment/collections.rs b/src/csv/serialize/commitment/collections.rs index 56ee058a..3e2b01c2 100644 --- a/src/csv/serialize/commitment/collections.rs +++ b/src/csv/serialize/commitment/collections.rs @@ -48,7 +48,7 @@ impl Commitment for Option where T: Commitment { /// In terms of commitment serialization, `Vec` is stored in form of usize-serialized length -/// (see `Commitemtn` implementation for `usize` type for serialization platform-independent +/// (see `Commitment` implementation for `usize` type for serialization platform-independent /// constant-length serialization rules) followed by a consequently-serialized vec items, /// according to their type. /// diff --git a/src/csv/serialize/network.rs b/src/csv/serialize/network.rs index 86afc214..b21b969e 100644 --- a/src/csv/serialize/network.rs +++ b/src/csv/serialize/network.rs @@ -42,6 +42,92 @@ macro_rules! network_serialize_from_commitment { }; } +macro_rules! network_serialize_list { + ( $encoder:ident; $($item:expr),+ ) => { + { + let mut len = 0usize; + $( + len += $item.network_serialize(&mut $encoder)?; + )+ + len + } + } +} + +impl Network for T where T: super::commitment::FromConsensus { + #[inline] + fn network_serialize(&self, mut e: E) -> Result { + Ok(self.consensus_encode(&mut e)?) + } + + #[inline] + fn network_deserialize(d: D) -> Result { + Ok(Self::consensus_decode(d)?) + } +} + +network_serialize_from_commitment!(usize); +network_serialize_from_commitment!(f32); +network_serialize_from_commitment!(f64); +network_serialize_from_commitment!(&[u8]); +network_serialize_from_commitment!(Box<[u8]>); +network_serialize_from_commitment!(&str); + + +/// In terms of network serialization, we interpret `Option` as a zero-length `Vec` +/// (for `Optional::None`) or single-item `Vec` (for `Optional::Some`). For deserialization +/// an attempt to read `Option` from a serialized non-0 or non-1 length Vec will result in +/// `Error::WrongOptionalEncoding`. +impl Network for Option where T: Network { + fn network_serialize(&self, mut e: E) -> Result { + Ok(match self { + None => network_serialize_list!(e; 0usize), + Some(val) => network_serialize_list!(e; 1usize, val), + }) + } + + fn network_deserialize(mut d: D) -> Result { + let mut vec = Vec::::network_deserialize(&mut d)?; + match vec.len() { + 0 => Ok(None), + 1 => Ok(Some( + vec.pop().expect("We are sure that there is a single item in the vec") + )), + _ => Err(Error::WrongOptionalEncoding), + } + } +} + + +/// In terms of network serialization, `Vec` is stored in form of usize-serialized length +/// (see `Commitment` implementation for `usize` type for serialization platform-independent +/// constant-length serialization rules) followed by a consequently-serialized vec items, +/// according to their type. +/// +/// An attempt to serialize `Vec` with more items than can fit in `usize` serialization rules +/// will result in `Error::OversizedVectorAllocation`. +impl Network for Vec where T: Network { + fn network_serialize(&self, mut e: E) -> Result { + let len = self.len() as usize; + let mut serialized = len.network_serialize(&mut e)?; + for item in self { + serialized += item.network_serialize(&mut e)?; + } + + Ok(serialized) + } + + fn network_deserialize(mut d: D) -> Result { + let len = usize::network_deserialize(&mut d)?; + let mut data = Vec::::with_capacity(len as usize); + for _ in 0..len { + data.push(T::network_deserialize(&mut d)?); + } + Ok(data) + } +} + + #[inline] pub fn network_serialize(data: &T) -> Result, Error> { let mut encoder = io::Cursor::new(vec![]); diff --git a/src/rgb/schema/schema.rs b/src/rgb/schema/schema.rs index fd270e3c..bb19b146 100644 --- a/src/rgb/schema/schema.rs +++ b/src/rgb/schema/schema.rs @@ -66,6 +66,8 @@ impl serialize::Commitment for Schema { } } +network_serialize_from_commitment!(Schema); + static MIDSTATE_SHEMAID: [u8; 32] = [ 25, 205, 224, 91, 171, 217, 131, 31, 140, 104, 5, 155, 127, 82, 14, 81, 58, 245, 79, 165, 114, 243, 110, 60, 133, 174, 103, 187, 103, 230, 9, 106 diff --git a/src/rgb/serialize.rs b/src/rgb/serialize.rs index e6ac2f4c..9e3c5462 100644 --- a/src/rgb/serialize.rs +++ b/src/rgb/serialize.rs @@ -148,7 +148,15 @@ impl csv::serialize::Commitment for rgb::Metadata { } } -// TODO: Implement network serialization +impl csv::serialize::Network for rgb::Metadata { + fn network_serialize(&self, mut e: E) -> Result { + self.as_ref().network_serialize(&mut e) + } + + fn network_deserialize(mut d: D) -> Result { + Vec::::network_deserialize(&mut d).map(Self::from_inner) + } +} /// ## Seal commitment serialization @@ -231,7 +239,25 @@ impl csv::serialize::Commitment for rgb::state::Partial { } } -// TODO: Implement network serialization for rgb::state::Partial +const TAG_COMMITMENT: u8 = 0x00u8; +const TAG_STATE: u8 = 0x01u8; + +impl csv::serialize::Network for rgb::state::Partial { + fn network_serialize(&self, mut e: E) -> Result { + Ok(match self { + Self::Commitment (cmt) => TAG_COMMITMENT.network_serialize(&mut e)? + cmt.network_serialize(&mut e)?, + Self::State(state) => TAG_STATE.network_serialize(&mut e)? + state.network_serialize(&mut e)?, + }) + } + + fn network_deserialize(mut d: D) -> Result { + Ok(match u8::network_deserialize(&mut d)? { + TAG_COMMITMENT => Self::Commitment(rgb::commit::StateCommitment::network_deserialize(&mut d)?), + TAG_STATE => Self::State(rgb::state::Bound::network_deserialize(&mut d)?), + _ => Err(csv::serialize::Error::ValueOutOfRange)?, + }) + } +} impl csv::serialize::Commitment for rgb::state::Bound { @@ -273,7 +299,15 @@ impl csv::serialize::Commitment for rgb::State { } } -// TODO: Implement network serialization +impl csv::serialize::Network for rgb::State { + fn network_serialize(&self, mut e: E) -> Result { + self.clone().into_inner().network_serialize(&mut e) + } + + fn network_deserialize(mut d: D) -> Result { + Vec::::network_deserialize(&mut d).map(Self::from_inner) + } +} /// ## Script commitment serialization @@ -314,10 +348,20 @@ impl csv::serialize::Commitment for rgb::Transition { } } -// TODO: Implement network serialization -/* Draft: -Ok(Self { - meta: Meta::commitment_deserialize(&mut d)?, - state: State::commitment_deserialize(&mut d)?, - script: Option::