// Generated by Molecule 0.8.0 #![allow(clippy::needless_lifetimes)] #![allow(clippy::needless_borrow)] #![allow(clippy::wrong_self_convention)] #![allow(clippy::if_same_then_else)] #![allow(clippy::derivable_impls)] #![allow(clippy::useless_conversion)] #![allow(clippy::write_literal)] #![allow(clippy::clone_on_copy)] #![allow(clippy::fallible_impl_from)] use molecule::prelude::*; #[derive(Clone)] pub struct VmIndex(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for VmIndex { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for VmIndex { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for VmIndex { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; let raw_data = hex_string(&self.raw_data()); write!(f, "{}(0x{})", Self::NAME, raw_data) } } impl ::core::default::Default for VmIndex { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); VmIndex::new_unchecked(v) } } impl VmIndex { const DEFAULT_VALUE: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; pub const TOTAL_SIZE: usize = 8; pub const ITEM_SIZE: usize = 1; pub const ITEM_COUNT: usize = 8; pub fn nth0(&self) -> Byte { Byte::new_unchecked(self.0.slice(0..1)) } pub fn nth1(&self) -> Byte { Byte::new_unchecked(self.0.slice(1..2)) } pub fn nth2(&self) -> Byte { Byte::new_unchecked(self.0.slice(2..3)) } pub fn nth3(&self) -> Byte { Byte::new_unchecked(self.0.slice(3..4)) } pub fn nth4(&self) -> Byte { Byte::new_unchecked(self.0.slice(4..5)) } pub fn nth5(&self) -> Byte { Byte::new_unchecked(self.0.slice(5..6)) } pub fn nth6(&self) -> Byte { Byte::new_unchecked(self.0.slice(6..7)) } pub fn nth7(&self) -> Byte { Byte::new_unchecked(self.0.slice(7..8)) } pub fn raw_data(&self) -> molecule::bytes::Bytes { self.as_bytes() } pub fn as_reader<'r>(&'r self) -> VmIndexReader<'r> { VmIndexReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for VmIndex { type Builder = VmIndexBuilder; const NAME: &'static str = "VmIndex"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { VmIndex(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { VmIndexReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { VmIndexReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder().set([ self.nth0(), self.nth1(), self.nth2(), self.nth3(), self.nth4(), self.nth5(), self.nth6(), self.nth7(), ]) } } #[derive(Clone, Copy)] pub struct VmIndexReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for VmIndexReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for VmIndexReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for VmIndexReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; let raw_data = hex_string(&self.raw_data()); write!(f, "{}(0x{})", Self::NAME, raw_data) } } impl<'r> VmIndexReader<'r> { pub const TOTAL_SIZE: usize = 8; pub const ITEM_SIZE: usize = 1; pub const ITEM_COUNT: usize = 8; pub fn nth0(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[0..1]) } pub fn nth1(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[1..2]) } pub fn nth2(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[2..3]) } pub fn nth3(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[3..4]) } pub fn nth4(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[4..5]) } pub fn nth5(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[5..6]) } pub fn nth6(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[6..7]) } pub fn nth7(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[7..8]) } pub fn raw_data(&self) -> &'r [u8] { self.as_slice() } } impl<'r> molecule::prelude::Reader<'r> for VmIndexReader<'r> { type Entity = VmIndex; const NAME: &'static str = "VmIndexReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { VmIndexReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len != Self::TOTAL_SIZE { return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); } Ok(()) } } #[derive(Clone)] pub struct VmIndexBuilder(pub(crate) [Byte; 8]); impl ::core::fmt::Debug for VmIndexBuilder { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:?})", Self::NAME, &self.0[..]) } } impl ::core::default::Default for VmIndexBuilder { fn default() -> Self { VmIndexBuilder([ Byte::default(), Byte::default(), Byte::default(), Byte::default(), Byte::default(), Byte::default(), Byte::default(), Byte::default(), ]) } } impl VmIndexBuilder { pub const TOTAL_SIZE: usize = 8; pub const ITEM_SIZE: usize = 1; pub const ITEM_COUNT: usize = 8; pub fn set(mut self, v: [Byte; 8]) -> Self { self.0 = v; self } pub fn nth0(mut self, v: Byte) -> Self { self.0[0] = v; self } pub fn nth1(mut self, v: Byte) -> Self { self.0[1] = v; self } pub fn nth2(mut self, v: Byte) -> Self { self.0[2] = v; self } pub fn nth3(mut self, v: Byte) -> Self { self.0[3] = v; self } pub fn nth4(mut self, v: Byte) -> Self { self.0[4] = v; self } pub fn nth5(mut self, v: Byte) -> Self { self.0[5] = v; self } pub fn nth6(mut self, v: Byte) -> Self { self.0[6] = v; self } pub fn nth7(mut self, v: Byte) -> Self { self.0[7] = v; self } } impl molecule::prelude::Builder for VmIndexBuilder { type Entity = VmIndex; const NAME: &'static str = "VmIndexBuilder"; fn expected_length(&self) -> usize { Self::TOTAL_SIZE } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { writer.write_all(self.0[0].as_slice())?; writer.write_all(self.0[1].as_slice())?; writer.write_all(self.0[2].as_slice())?; writer.write_all(self.0[3].as_slice())?; writer.write_all(self.0[4].as_slice())?; writer.write_all(self.0[5].as_slice())?; writer.write_all(self.0[6].as_slice())?; writer.write_all(self.0[7].as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); VmIndex::new_unchecked(inner.into()) } } impl From<[Byte; 8usize]> for VmIndex { fn from(value: [Byte; 8usize]) -> Self { Self::new_builder().set(value).build() } } impl ::core::convert::TryFrom<&[Byte]> for VmIndex { type Error = ::core::array::TryFromSliceError; fn try_from(value: &[Byte]) -> Result { Ok(Self::new_builder() .set(<&[Byte; 8usize]>::try_from(value)?.clone()) .build()) } } impl From for [Byte; 8usize] { #[track_caller] fn from(value: VmIndex) -> Self { [ value.nth0(), value.nth1(), value.nth2(), value.nth3(), value.nth4(), value.nth5(), value.nth6(), value.nth7(), ] } } impl From<[u8; 8usize]> for VmIndex { fn from(value: [u8; 8usize]) -> Self { VmIndexReader::new_unchecked(&value).to_entity() } } impl ::core::convert::TryFrom<&[u8]> for VmIndex { type Error = ::core::array::TryFromSliceError; fn try_from(value: &[u8]) -> Result { Ok(<[u8; 8usize]>::try_from(value)?.into()) } } impl From for [u8; 8usize] { #[track_caller] fn from(value: VmIndex) -> Self { ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() } } impl<'a> From> for &'a [u8; 8usize] { #[track_caller] fn from(value: VmIndexReader<'a>) -> Self { ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() } } impl<'a> From<&'a VmIndexReader<'a>> for &'a [u8; 8usize] { #[track_caller] fn from(value: &'a VmIndexReader<'a>) -> Self { ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() } } #[derive(Clone)] pub struct FdIndex(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for FdIndex { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for FdIndex { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for FdIndex { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; let raw_data = hex_string(&self.raw_data()); write!(f, "{}(0x{})", Self::NAME, raw_data) } } impl ::core::default::Default for FdIndex { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); FdIndex::new_unchecked(v) } } impl FdIndex { const DEFAULT_VALUE: [u8; 8] = [0, 0, 0, 0, 0, 0, 0, 0]; pub const TOTAL_SIZE: usize = 8; pub const ITEM_SIZE: usize = 1; pub const ITEM_COUNT: usize = 8; pub fn nth0(&self) -> Byte { Byte::new_unchecked(self.0.slice(0..1)) } pub fn nth1(&self) -> Byte { Byte::new_unchecked(self.0.slice(1..2)) } pub fn nth2(&self) -> Byte { Byte::new_unchecked(self.0.slice(2..3)) } pub fn nth3(&self) -> Byte { Byte::new_unchecked(self.0.slice(3..4)) } pub fn nth4(&self) -> Byte { Byte::new_unchecked(self.0.slice(4..5)) } pub fn nth5(&self) -> Byte { Byte::new_unchecked(self.0.slice(5..6)) } pub fn nth6(&self) -> Byte { Byte::new_unchecked(self.0.slice(6..7)) } pub fn nth7(&self) -> Byte { Byte::new_unchecked(self.0.slice(7..8)) } pub fn raw_data(&self) -> molecule::bytes::Bytes { self.as_bytes() } pub fn as_reader<'r>(&'r self) -> FdIndexReader<'r> { FdIndexReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for FdIndex { type Builder = FdIndexBuilder; const NAME: &'static str = "FdIndex"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { FdIndex(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { FdIndexReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { FdIndexReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder().set([ self.nth0(), self.nth1(), self.nth2(), self.nth3(), self.nth4(), self.nth5(), self.nth6(), self.nth7(), ]) } } #[derive(Clone, Copy)] pub struct FdIndexReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for FdIndexReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for FdIndexReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for FdIndexReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; let raw_data = hex_string(&self.raw_data()); write!(f, "{}(0x{})", Self::NAME, raw_data) } } impl<'r> FdIndexReader<'r> { pub const TOTAL_SIZE: usize = 8; pub const ITEM_SIZE: usize = 1; pub const ITEM_COUNT: usize = 8; pub fn nth0(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[0..1]) } pub fn nth1(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[1..2]) } pub fn nth2(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[2..3]) } pub fn nth3(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[3..4]) } pub fn nth4(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[4..5]) } pub fn nth5(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[5..6]) } pub fn nth6(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[6..7]) } pub fn nth7(&self) -> ByteReader<'r> { ByteReader::new_unchecked(&self.as_slice()[7..8]) } pub fn raw_data(&self) -> &'r [u8] { self.as_slice() } } impl<'r> molecule::prelude::Reader<'r> for FdIndexReader<'r> { type Entity = FdIndex; const NAME: &'static str = "FdIndexReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { FdIndexReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len != Self::TOTAL_SIZE { return ve!(Self, TotalSizeNotMatch, Self::TOTAL_SIZE, slice_len); } Ok(()) } } #[derive(Clone)] pub struct FdIndexBuilder(pub(crate) [Byte; 8]); impl ::core::fmt::Debug for FdIndexBuilder { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:?})", Self::NAME, &self.0[..]) } } impl ::core::default::Default for FdIndexBuilder { fn default() -> Self { FdIndexBuilder([ Byte::default(), Byte::default(), Byte::default(), Byte::default(), Byte::default(), Byte::default(), Byte::default(), Byte::default(), ]) } } impl FdIndexBuilder { pub const TOTAL_SIZE: usize = 8; pub const ITEM_SIZE: usize = 1; pub const ITEM_COUNT: usize = 8; pub fn set(mut self, v: [Byte; 8]) -> Self { self.0 = v; self } pub fn nth0(mut self, v: Byte) -> Self { self.0[0] = v; self } pub fn nth1(mut self, v: Byte) -> Self { self.0[1] = v; self } pub fn nth2(mut self, v: Byte) -> Self { self.0[2] = v; self } pub fn nth3(mut self, v: Byte) -> Self { self.0[3] = v; self } pub fn nth4(mut self, v: Byte) -> Self { self.0[4] = v; self } pub fn nth5(mut self, v: Byte) -> Self { self.0[5] = v; self } pub fn nth6(mut self, v: Byte) -> Self { self.0[6] = v; self } pub fn nth7(mut self, v: Byte) -> Self { self.0[7] = v; self } } impl molecule::prelude::Builder for FdIndexBuilder { type Entity = FdIndex; const NAME: &'static str = "FdIndexBuilder"; fn expected_length(&self) -> usize { Self::TOTAL_SIZE } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { writer.write_all(self.0[0].as_slice())?; writer.write_all(self.0[1].as_slice())?; writer.write_all(self.0[2].as_slice())?; writer.write_all(self.0[3].as_slice())?; writer.write_all(self.0[4].as_slice())?; writer.write_all(self.0[5].as_slice())?; writer.write_all(self.0[6].as_slice())?; writer.write_all(self.0[7].as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); FdIndex::new_unchecked(inner.into()) } } impl From<[Byte; 8usize]> for FdIndex { fn from(value: [Byte; 8usize]) -> Self { Self::new_builder().set(value).build() } } impl ::core::convert::TryFrom<&[Byte]> for FdIndex { type Error = ::core::array::TryFromSliceError; fn try_from(value: &[Byte]) -> Result { Ok(Self::new_builder() .set(<&[Byte; 8usize]>::try_from(value)?.clone()) .build()) } } impl From for [Byte; 8usize] { #[track_caller] fn from(value: FdIndex) -> Self { [ value.nth0(), value.nth1(), value.nth2(), value.nth3(), value.nth4(), value.nth5(), value.nth6(), value.nth7(), ] } } impl From<[u8; 8usize]> for FdIndex { fn from(value: [u8; 8usize]) -> Self { FdIndexReader::new_unchecked(&value).to_entity() } } impl ::core::convert::TryFrom<&[u8]> for FdIndex { type Error = ::core::array::TryFromSliceError; fn try_from(value: &[u8]) -> Result { Ok(<[u8; 8usize]>::try_from(value)?.into()) } } impl From for [u8; 8usize] { #[track_caller] fn from(value: FdIndex) -> Self { ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() } } impl<'a> From> for &'a [u8; 8usize] { #[track_caller] fn from(value: FdIndexReader<'a>) -> Self { ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() } } impl<'a> From<&'a FdIndexReader<'a>> for &'a [u8; 8usize] { #[track_caller] fn from(value: &'a FdIndexReader<'a>) -> Self { ::core::convert::TryFrom::try_from(value.as_slice()).unwrap() } } #[derive(Clone)] pub struct FdIndices(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for FdIndices { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for FdIndices { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for FdIndices { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} [", Self::NAME)?; for i in 0..self.len() { if i == 0 { write!(f, "{}", self.get_unchecked(i))?; } else { write!(f, ", {}", self.get_unchecked(i))?; } } write!(f, "]") } } impl ::core::default::Default for FdIndices { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); FdIndices::new_unchecked(v) } } impl FdIndices { const DEFAULT_VALUE: [u8; 4] = [0, 0, 0, 0]; pub const ITEM_SIZE: usize = 8; pub fn total_size(&self) -> usize { molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() } pub fn item_count(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn len(&self) -> usize { self.item_count() } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn get(&self, idx: usize) -> Option { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } pub fn get_unchecked(&self, idx: usize) -> FdIndex { let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; let end = start + Self::ITEM_SIZE; FdIndex::new_unchecked(self.0.slice(start..end)) } pub fn as_reader<'r>(&'r self) -> FdIndicesReader<'r> { FdIndicesReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for FdIndices { type Builder = FdIndicesBuilder; const NAME: &'static str = "FdIndices"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { FdIndices(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { FdIndicesReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { FdIndicesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder().extend(self.into_iter()) } } #[derive(Clone, Copy)] pub struct FdIndicesReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for FdIndicesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for FdIndicesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for FdIndicesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} [", Self::NAME)?; for i in 0..self.len() { if i == 0 { write!(f, "{}", self.get_unchecked(i))?; } else { write!(f, ", {}", self.get_unchecked(i))?; } } write!(f, "]") } } impl<'r> FdIndicesReader<'r> { pub const ITEM_SIZE: usize = 8; pub fn total_size(&self) -> usize { molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() } pub fn item_count(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn len(&self) -> usize { self.item_count() } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn get(&self, idx: usize) -> Option> { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } pub fn get_unchecked(&self, idx: usize) -> FdIndexReader<'r> { let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; let end = start + Self::ITEM_SIZE; FdIndexReader::new_unchecked(&self.as_slice()[start..end]) } } impl<'r> molecule::prelude::Reader<'r> for FdIndicesReader<'r> { type Entity = FdIndices; const NAME: &'static str = "FdIndicesReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { FdIndicesReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len < molecule::NUMBER_SIZE { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); } let item_count = molecule::unpack_number(slice) as usize; if item_count == 0 { if slice_len != molecule::NUMBER_SIZE { return ve!(Self, TotalSizeNotMatch, molecule::NUMBER_SIZE, slice_len); } return Ok(()); } let total_size = molecule::NUMBER_SIZE + Self::ITEM_SIZE * item_count; if slice_len != total_size { return ve!(Self, TotalSizeNotMatch, total_size, slice_len); } Ok(()) } } #[derive(Clone, Debug, Default)] pub struct FdIndicesBuilder(pub(crate) Vec); impl FdIndicesBuilder { pub const ITEM_SIZE: usize = 8; pub fn set(mut self, v: Vec) -> Self { self.0 = v; self } pub fn push(mut self, v: FdIndex) -> Self { self.0.push(v); self } pub fn extend>(mut self, iter: T) -> Self { for elem in iter { self.0.push(elem); } self } pub fn replace(&mut self, index: usize, v: FdIndex) -> Option { self.0 .get_mut(index) .map(|item| ::core::mem::replace(item, v)) } } impl molecule::prelude::Builder for FdIndicesBuilder { type Entity = FdIndices; const NAME: &'static str = "FdIndicesBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.0.len() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { writer.write_all(&molecule::pack_number(self.0.len() as molecule::Number))?; for inner in &self.0[..] { writer.write_all(inner.as_slice())?; } Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); FdIndices::new_unchecked(inner.into()) } } pub struct FdIndicesIterator(FdIndices, usize, usize); impl ::core::iter::Iterator for FdIndicesIterator { type Item = FdIndex; fn next(&mut self) -> Option { if self.1 >= self.2 { None } else { let ret = self.0.get_unchecked(self.1); self.1 += 1; Some(ret) } } } impl ::core::iter::ExactSizeIterator for FdIndicesIterator { fn len(&self) -> usize { self.2 - self.1 } } impl ::core::iter::IntoIterator for FdIndices { type Item = FdIndex; type IntoIter = FdIndicesIterator; fn into_iter(self) -> Self::IntoIter { let len = self.len(); FdIndicesIterator(self, 0, len) } } impl<'r> FdIndicesReader<'r> { pub fn iter<'t>(&'t self) -> FdIndicesReaderIterator<'t, 'r> { FdIndicesReaderIterator(&self, 0, self.len()) } } pub struct FdIndicesReaderIterator<'t, 'r>(&'t FdIndicesReader<'r>, usize, usize); impl<'t: 'r, 'r> ::core::iter::Iterator for FdIndicesReaderIterator<'t, 'r> { type Item = FdIndexReader<'t>; fn next(&mut self) -> Option { if self.1 >= self.2 { None } else { let ret = self.0.get_unchecked(self.1); self.1 += 1; Some(ret) } } } impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for FdIndicesReaderIterator<'t, 'r> { fn len(&self) -> usize { self.2 - self.1 } } impl ::core::iter::FromIterator for FdIndices { fn from_iter>(iter: T) -> Self { Self::new_builder().extend(iter).build() } } #[derive(Clone)] pub struct Bytes(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Bytes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for Bytes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for Bytes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; let raw_data = hex_string(&self.raw_data()); write!(f, "{}(0x{})", Self::NAME, raw_data) } } impl ::core::default::Default for Bytes { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); Bytes::new_unchecked(v) } } impl Bytes { const DEFAULT_VALUE: [u8; 4] = [0, 0, 0, 0]; pub const ITEM_SIZE: usize = 1; pub fn total_size(&self) -> usize { molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() } pub fn item_count(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn len(&self) -> usize { self.item_count() } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn get(&self, idx: usize) -> Option { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } pub fn get_unchecked(&self, idx: usize) -> Byte { let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; let end = start + Self::ITEM_SIZE; Byte::new_unchecked(self.0.slice(start..end)) } pub fn raw_data(&self) -> molecule::bytes::Bytes { self.0.slice(molecule::NUMBER_SIZE..) } pub fn as_reader<'r>(&'r self) -> BytesReader<'r> { BytesReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for Bytes { type Builder = BytesBuilder; const NAME: &'static str = "Bytes"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { Bytes(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { BytesReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { BytesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder().extend(self.into_iter()) } } #[derive(Clone, Copy)] pub struct BytesReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for BytesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for BytesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for BytesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; let raw_data = hex_string(&self.raw_data()); write!(f, "{}(0x{})", Self::NAME, raw_data) } } impl<'r> BytesReader<'r> { pub const ITEM_SIZE: usize = 1; pub fn total_size(&self) -> usize { molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.item_count() } pub fn item_count(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn len(&self) -> usize { self.item_count() } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn get(&self, idx: usize) -> Option> { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } pub fn get_unchecked(&self, idx: usize) -> ByteReader<'r> { let start = molecule::NUMBER_SIZE + Self::ITEM_SIZE * idx; let end = start + Self::ITEM_SIZE; ByteReader::new_unchecked(&self.as_slice()[start..end]) } pub fn raw_data(&self) -> &'r [u8] { &self.as_slice()[molecule::NUMBER_SIZE..] } } impl<'r> molecule::prelude::Reader<'r> for BytesReader<'r> { type Entity = Bytes; const NAME: &'static str = "BytesReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { BytesReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], _compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len < molecule::NUMBER_SIZE { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); } let item_count = molecule::unpack_number(slice) as usize; if item_count == 0 { if slice_len != molecule::NUMBER_SIZE { return ve!(Self, TotalSizeNotMatch, molecule::NUMBER_SIZE, slice_len); } return Ok(()); } let total_size = molecule::NUMBER_SIZE + Self::ITEM_SIZE * item_count; if slice_len != total_size { return ve!(Self, TotalSizeNotMatch, total_size, slice_len); } Ok(()) } } #[derive(Clone, Debug, Default)] pub struct BytesBuilder(pub(crate) Vec); impl BytesBuilder { pub const ITEM_SIZE: usize = 1; pub fn set(mut self, v: Vec) -> Self { self.0 = v; self } pub fn push(mut self, v: Byte) -> Self { self.0.push(v); self } pub fn extend>(mut self, iter: T) -> Self { for elem in iter { self.0.push(elem); } self } pub fn replace(&mut self, index: usize, v: Byte) -> Option { self.0 .get_mut(index) .map(|item| ::core::mem::replace(item, v)) } } impl molecule::prelude::Builder for BytesBuilder { type Entity = Bytes; const NAME: &'static str = "BytesBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE + Self::ITEM_SIZE * self.0.len() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { writer.write_all(&molecule::pack_number(self.0.len() as molecule::Number))?; for inner in &self.0[..] { writer.write_all(inner.as_slice())?; } Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); Bytes::new_unchecked(inner.into()) } } pub struct BytesIterator(Bytes, usize, usize); impl ::core::iter::Iterator for BytesIterator { type Item = Byte; fn next(&mut self) -> Option { if self.1 >= self.2 { None } else { let ret = self.0.get_unchecked(self.1); self.1 += 1; Some(ret) } } } impl ::core::iter::ExactSizeIterator for BytesIterator { fn len(&self) -> usize { self.2 - self.1 } } impl ::core::iter::IntoIterator for Bytes { type Item = Byte; type IntoIter = BytesIterator; fn into_iter(self) -> Self::IntoIter { let len = self.len(); BytesIterator(self, 0, len) } } impl ::core::iter::FromIterator for Bytes { fn from_iter>(iter: T) -> Self { Self::new_builder().extend(iter).build() } } impl ::core::iter::FromIterator for Bytes { fn from_iter>(iter: T) -> Self { Self::new_builder() .extend(iter.into_iter().map(Into::into)) .build() } } #[derive(Clone)] pub struct Pipe(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Pipe { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for Pipe { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for Pipe { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "vm", self.vm())?; write!(f, ", {}: {}", "read_fd", self.read_fd())?; write!(f, ", {}: {}", "write_fd", self.write_fd())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; } write!(f, " }}") } } impl ::core::default::Default for Pipe { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); Pipe::new_unchecked(v) } } impl Pipe { const DEFAULT_VALUE: [u8; 40] = [ 40, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; pub const FIELD_COUNT: usize = 3; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn field_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn count_extra_fields(&self) -> usize { self.field_count() - Self::FIELD_COUNT } pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } pub fn vm(&self) -> VmIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; VmIndex::new_unchecked(self.0.slice(start..end)) } pub fn read_fd(&self) -> FdIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; FdIndex::new_unchecked(self.0.slice(start..end)) } pub fn write_fd(&self) -> FdIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; FdIndex::new_unchecked(self.0.slice(start..end)) } else { FdIndex::new_unchecked(self.0.slice(start..)) } } pub fn as_reader<'r>(&'r self) -> PipeReader<'r> { PipeReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for Pipe { type Builder = PipeBuilder; const NAME: &'static str = "Pipe"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { Pipe(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { PipeReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { PipeReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder() .vm(self.vm()) .read_fd(self.read_fd()) .write_fd(self.write_fd()) } } #[derive(Clone, Copy)] pub struct PipeReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for PipeReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for PipeReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for PipeReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "vm", self.vm())?; write!(f, ", {}: {}", "read_fd", self.read_fd())?; write!(f, ", {}: {}", "write_fd", self.write_fd())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; } write!(f, " }}") } } impl<'r> PipeReader<'r> { pub const FIELD_COUNT: usize = 3; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn field_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn count_extra_fields(&self) -> usize { self.field_count() - Self::FIELD_COUNT } pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } pub fn vm(&self) -> VmIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; VmIndexReader::new_unchecked(&self.as_slice()[start..end]) } pub fn read_fd(&self) -> FdIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; FdIndexReader::new_unchecked(&self.as_slice()[start..end]) } pub fn write_fd(&self) -> FdIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; FdIndexReader::new_unchecked(&self.as_slice()[start..end]) } else { FdIndexReader::new_unchecked(&self.as_slice()[start..]) } } } impl<'r> molecule::prelude::Reader<'r> for PipeReader<'r> { type Entity = Pipe; const NAME: &'static str = "PipeReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { PipeReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len < molecule::NUMBER_SIZE { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); } let total_size = molecule::unpack_number(slice) as usize; if slice_len != total_size { return ve!(Self, TotalSizeNotMatch, total_size, slice_len); } if slice_len < molecule::NUMBER_SIZE * 2 { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); } let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { return ve!(Self, OffsetsNotMatch); } if slice_len < offset_first { return ve!(Self, HeaderIsBroken, offset_first, slice_len); } let field_count = offset_first / molecule::NUMBER_SIZE - 1; if field_count < Self::FIELD_COUNT { return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); } else if !compatible && field_count > Self::FIELD_COUNT { return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); }; let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] .chunks_exact(molecule::NUMBER_SIZE) .map(|x| molecule::unpack_number(x) as usize) .collect(); offsets.push(total_size); if offsets.windows(2).any(|i| i[0] > i[1]) { return ve!(Self, OffsetsNotMatch); } VmIndexReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; FdIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; FdIndexReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; Ok(()) } } #[derive(Clone, Debug, Default)] pub struct PipeBuilder { pub(crate) vm: VmIndex, pub(crate) read_fd: FdIndex, pub(crate) write_fd: FdIndex, } impl PipeBuilder { pub const FIELD_COUNT: usize = 3; pub fn vm(mut self, v: VmIndex) -> Self { self.vm = v; self } pub fn read_fd(mut self, v: FdIndex) -> Self { self.read_fd = v; self } pub fn write_fd(mut self, v: FdIndex) -> Self { self.write_fd = v; self } } impl molecule::prelude::Builder for PipeBuilder { type Entity = Pipe; const NAME: &'static str = "PipeBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.vm.as_slice().len() + self.read_fd.as_slice().len() + self.write_fd.as_slice().len() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); offsets.push(total_size); total_size += self.vm.as_slice().len(); offsets.push(total_size); total_size += self.read_fd.as_slice().len(); offsets.push(total_size); total_size += self.write_fd.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } writer.write_all(self.vm.as_slice())?; writer.write_all(self.read_fd.as_slice())?; writer.write_all(self.write_fd.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); Pipe::new_unchecked(inner.into()) } } #[derive(Clone)] pub struct Pipes(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Pipes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for Pipes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for Pipes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} [", Self::NAME)?; for i in 0..self.len() { if i == 0 { write!(f, "{}", self.get_unchecked(i))?; } else { write!(f, ", {}", self.get_unchecked(i))?; } } write!(f, "]") } } impl ::core::default::Default for Pipes { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); Pipes::new_unchecked(v) } } impl Pipes { const DEFAULT_VALUE: [u8; 4] = [4, 0, 0, 0]; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn item_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn len(&self) -> usize { self.item_count() } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn get(&self, idx: usize) -> Option { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } pub fn get_unchecked(&self, idx: usize) -> Pipe { let slice = self.as_slice(); let start_idx = molecule::NUMBER_SIZE * (1 + idx); let start = molecule::unpack_number(&slice[start_idx..]) as usize; if idx == self.len() - 1 { Pipe::new_unchecked(self.0.slice(start..)) } else { let end_idx = start_idx + molecule::NUMBER_SIZE; let end = molecule::unpack_number(&slice[end_idx..]) as usize; Pipe::new_unchecked(self.0.slice(start..end)) } } pub fn as_reader<'r>(&'r self) -> PipesReader<'r> { PipesReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for Pipes { type Builder = PipesBuilder; const NAME: &'static str = "Pipes"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { Pipes(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { PipesReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { PipesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder().extend(self.into_iter()) } } #[derive(Clone, Copy)] pub struct PipesReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for PipesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for PipesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for PipesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} [", Self::NAME)?; for i in 0..self.len() { if i == 0 { write!(f, "{}", self.get_unchecked(i))?; } else { write!(f, ", {}", self.get_unchecked(i))?; } } write!(f, "]") } } impl<'r> PipesReader<'r> { pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn item_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn len(&self) -> usize { self.item_count() } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn get(&self, idx: usize) -> Option> { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } pub fn get_unchecked(&self, idx: usize) -> PipeReader<'r> { let slice = self.as_slice(); let start_idx = molecule::NUMBER_SIZE * (1 + idx); let start = molecule::unpack_number(&slice[start_idx..]) as usize; if idx == self.len() - 1 { PipeReader::new_unchecked(&self.as_slice()[start..]) } else { let end_idx = start_idx + molecule::NUMBER_SIZE; let end = molecule::unpack_number(&slice[end_idx..]) as usize; PipeReader::new_unchecked(&self.as_slice()[start..end]) } } } impl<'r> molecule::prelude::Reader<'r> for PipesReader<'r> { type Entity = Pipes; const NAME: &'static str = "PipesReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { PipesReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len < molecule::NUMBER_SIZE { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); } let total_size = molecule::unpack_number(slice) as usize; if slice_len != total_size { return ve!(Self, TotalSizeNotMatch, total_size, slice_len); } if slice_len == molecule::NUMBER_SIZE { return Ok(()); } if slice_len < molecule::NUMBER_SIZE * 2 { return ve!( Self, TotalSizeNotMatch, molecule::NUMBER_SIZE * 2, slice_len ); } let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { return ve!(Self, OffsetsNotMatch); } if slice_len < offset_first { return ve!(Self, HeaderIsBroken, offset_first, slice_len); } let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] .chunks_exact(molecule::NUMBER_SIZE) .map(|x| molecule::unpack_number(x) as usize) .collect(); offsets.push(total_size); if offsets.windows(2).any(|i| i[0] > i[1]) { return ve!(Self, OffsetsNotMatch); } for pair in offsets.windows(2) { let start = pair[0]; let end = pair[1]; PipeReader::verify(&slice[start..end], compatible)?; } Ok(()) } } #[derive(Clone, Debug, Default)] pub struct PipesBuilder(pub(crate) Vec); impl PipesBuilder { pub fn set(mut self, v: Vec) -> Self { self.0 = v; self } pub fn push(mut self, v: Pipe) -> Self { self.0.push(v); self } pub fn extend>(mut self, iter: T) -> Self { for elem in iter { self.0.push(elem); } self } pub fn replace(&mut self, index: usize, v: Pipe) -> Option { self.0 .get_mut(index) .map(|item| ::core::mem::replace(item, v)) } } impl molecule::prelude::Builder for PipesBuilder { type Entity = Pipes; const NAME: &'static str = "PipesBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (self.0.len() + 1) + self .0 .iter() .map(|inner| inner.as_slice().len()) .sum::() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { let item_count = self.0.len(); if item_count == 0 { writer.write_all(&molecule::pack_number( molecule::NUMBER_SIZE as molecule::Number, ))?; } else { let (total_size, offsets) = self.0.iter().fold( ( molecule::NUMBER_SIZE * (item_count + 1), Vec::with_capacity(item_count), ), |(start, mut offsets), inner| { offsets.push(start); (start + inner.as_slice().len(), offsets) }, ); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } for inner in self.0.iter() { writer.write_all(inner.as_slice())?; } } Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); Pipes::new_unchecked(inner.into()) } } pub struct PipesIterator(Pipes, usize, usize); impl ::core::iter::Iterator for PipesIterator { type Item = Pipe; fn next(&mut self) -> Option { if self.1 >= self.2 { None } else { let ret = self.0.get_unchecked(self.1); self.1 += 1; Some(ret) } } } impl ::core::iter::ExactSizeIterator for PipesIterator { fn len(&self) -> usize { self.2 - self.1 } } impl ::core::iter::IntoIterator for Pipes { type Item = Pipe; type IntoIter = PipesIterator; fn into_iter(self) -> Self::IntoIter { let len = self.len(); PipesIterator(self, 0, len) } } impl<'r> PipesReader<'r> { pub fn iter<'t>(&'t self) -> PipesReaderIterator<'t, 'r> { PipesReaderIterator(&self, 0, self.len()) } } pub struct PipesReaderIterator<'t, 'r>(&'t PipesReader<'r>, usize, usize); impl<'t: 'r, 'r> ::core::iter::Iterator for PipesReaderIterator<'t, 'r> { type Item = PipeReader<'t>; fn next(&mut self) -> Option { if self.1 >= self.2 { None } else { let ret = self.0.get_unchecked(self.1); self.1 += 1; Some(ret) } } } impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for PipesReaderIterator<'t, 'r> { fn len(&self) -> usize { self.2 - self.1 } } impl ::core::iter::FromIterator for Pipes { fn from_iter>(iter: T) -> Self { Self::new_builder().extend(iter).build() } } #[derive(Clone)] pub struct Write(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Write { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for Write { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for Write { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "from", self.from())?; write!(f, ", {}: {}", "from_fd", self.from_fd())?; write!(f, ", {}: {}", "to", self.to())?; write!(f, ", {}: {}", "to_fd", self.to_fd())?; write!(f, ", {}: {}", "data", self.data())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; } write!(f, " }}") } } impl ::core::default::Default for Write { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); Write::new_unchecked(v) } } impl Write { const DEFAULT_VALUE: [u8; 60] = [ 60, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 40, 0, 0, 0, 48, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; pub const FIELD_COUNT: usize = 5; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn field_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn count_extra_fields(&self) -> usize { self.field_count() - Self::FIELD_COUNT } pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } pub fn from(&self) -> VmIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; VmIndex::new_unchecked(self.0.slice(start..end)) } pub fn from_fd(&self) -> FdIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; FdIndex::new_unchecked(self.0.slice(start..end)) } pub fn to(&self) -> VmIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; let end = molecule::unpack_number(&slice[16..]) as usize; VmIndex::new_unchecked(self.0.slice(start..end)) } pub fn to_fd(&self) -> FdIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[16..]) as usize; let end = molecule::unpack_number(&slice[20..]) as usize; FdIndex::new_unchecked(self.0.slice(start..end)) } pub fn data(&self) -> Bytes { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[20..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[24..]) as usize; Bytes::new_unchecked(self.0.slice(start..end)) } else { Bytes::new_unchecked(self.0.slice(start..)) } } pub fn as_reader<'r>(&'r self) -> WriteReader<'r> { WriteReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for Write { type Builder = WriteBuilder; const NAME: &'static str = "Write"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { Write(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { WriteReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { WriteReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder() .from(self.from()) .from_fd(self.from_fd()) .to(self.to()) .to_fd(self.to_fd()) .data(self.data()) } } #[derive(Clone, Copy)] pub struct WriteReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for WriteReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for WriteReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for WriteReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "from", self.from())?; write!(f, ", {}: {}", "from_fd", self.from_fd())?; write!(f, ", {}: {}", "to", self.to())?; write!(f, ", {}: {}", "to_fd", self.to_fd())?; write!(f, ", {}: {}", "data", self.data())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; } write!(f, " }}") } } impl<'r> WriteReader<'r> { pub const FIELD_COUNT: usize = 5; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn field_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn count_extra_fields(&self) -> usize { self.field_count() - Self::FIELD_COUNT } pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } pub fn from(&self) -> VmIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; VmIndexReader::new_unchecked(&self.as_slice()[start..end]) } pub fn from_fd(&self) -> FdIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; FdIndexReader::new_unchecked(&self.as_slice()[start..end]) } pub fn to(&self) -> VmIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; let end = molecule::unpack_number(&slice[16..]) as usize; VmIndexReader::new_unchecked(&self.as_slice()[start..end]) } pub fn to_fd(&self) -> FdIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[16..]) as usize; let end = molecule::unpack_number(&slice[20..]) as usize; FdIndexReader::new_unchecked(&self.as_slice()[start..end]) } pub fn data(&self) -> BytesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[20..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[24..]) as usize; BytesReader::new_unchecked(&self.as_slice()[start..end]) } else { BytesReader::new_unchecked(&self.as_slice()[start..]) } } } impl<'r> molecule::prelude::Reader<'r> for WriteReader<'r> { type Entity = Write; const NAME: &'static str = "WriteReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { WriteReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len < molecule::NUMBER_SIZE { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); } let total_size = molecule::unpack_number(slice) as usize; if slice_len != total_size { return ve!(Self, TotalSizeNotMatch, total_size, slice_len); } if slice_len < molecule::NUMBER_SIZE * 2 { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); } let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { return ve!(Self, OffsetsNotMatch); } if slice_len < offset_first { return ve!(Self, HeaderIsBroken, offset_first, slice_len); } let field_count = offset_first / molecule::NUMBER_SIZE - 1; if field_count < Self::FIELD_COUNT { return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); } else if !compatible && field_count > Self::FIELD_COUNT { return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); }; let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] .chunks_exact(molecule::NUMBER_SIZE) .map(|x| molecule::unpack_number(x) as usize) .collect(); offsets.push(total_size); if offsets.windows(2).any(|i| i[0] > i[1]) { return ve!(Self, OffsetsNotMatch); } VmIndexReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; FdIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; VmIndexReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; FdIndexReader::verify(&slice[offsets[3]..offsets[4]], compatible)?; BytesReader::verify(&slice[offsets[4]..offsets[5]], compatible)?; Ok(()) } } #[derive(Clone, Debug, Default)] pub struct WriteBuilder { pub(crate) from: VmIndex, pub(crate) from_fd: FdIndex, pub(crate) to: VmIndex, pub(crate) to_fd: FdIndex, pub(crate) data: Bytes, } impl WriteBuilder { pub const FIELD_COUNT: usize = 5; pub fn from(mut self, v: VmIndex) -> Self { self.from = v; self } pub fn from_fd(mut self, v: FdIndex) -> Self { self.from_fd = v; self } pub fn to(mut self, v: VmIndex) -> Self { self.to = v; self } pub fn to_fd(mut self, v: FdIndex) -> Self { self.to_fd = v; self } pub fn data(mut self, v: Bytes) -> Self { self.data = v; self } } impl molecule::prelude::Builder for WriteBuilder { type Entity = Write; const NAME: &'static str = "WriteBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.from.as_slice().len() + self.from_fd.as_slice().len() + self.to.as_slice().len() + self.to_fd.as_slice().len() + self.data.as_slice().len() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); offsets.push(total_size); total_size += self.from.as_slice().len(); offsets.push(total_size); total_size += self.from_fd.as_slice().len(); offsets.push(total_size); total_size += self.to.as_slice().len(); offsets.push(total_size); total_size += self.to_fd.as_slice().len(); offsets.push(total_size); total_size += self.data.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } writer.write_all(self.from.as_slice())?; writer.write_all(self.from_fd.as_slice())?; writer.write_all(self.to.as_slice())?; writer.write_all(self.to_fd.as_slice())?; writer.write_all(self.data.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); Write::new_unchecked(inner.into()) } } #[derive(Clone)] pub struct Writes(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Writes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for Writes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for Writes { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} [", Self::NAME)?; for i in 0..self.len() { if i == 0 { write!(f, "{}", self.get_unchecked(i))?; } else { write!(f, ", {}", self.get_unchecked(i))?; } } write!(f, "]") } } impl ::core::default::Default for Writes { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); Writes::new_unchecked(v) } } impl Writes { const DEFAULT_VALUE: [u8; 4] = [4, 0, 0, 0]; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn item_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn len(&self) -> usize { self.item_count() } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn get(&self, idx: usize) -> Option { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } pub fn get_unchecked(&self, idx: usize) -> Write { let slice = self.as_slice(); let start_idx = molecule::NUMBER_SIZE * (1 + idx); let start = molecule::unpack_number(&slice[start_idx..]) as usize; if idx == self.len() - 1 { Write::new_unchecked(self.0.slice(start..)) } else { let end_idx = start_idx + molecule::NUMBER_SIZE; let end = molecule::unpack_number(&slice[end_idx..]) as usize; Write::new_unchecked(self.0.slice(start..end)) } } pub fn as_reader<'r>(&'r self) -> WritesReader<'r> { WritesReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for Writes { type Builder = WritesBuilder; const NAME: &'static str = "Writes"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { Writes(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { WritesReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { WritesReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder().extend(self.into_iter()) } } #[derive(Clone, Copy)] pub struct WritesReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for WritesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for WritesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for WritesReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} [", Self::NAME)?; for i in 0..self.len() { if i == 0 { write!(f, "{}", self.get_unchecked(i))?; } else { write!(f, ", {}", self.get_unchecked(i))?; } } write!(f, "]") } } impl<'r> WritesReader<'r> { pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn item_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn len(&self) -> usize { self.item_count() } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn get(&self, idx: usize) -> Option> { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } pub fn get_unchecked(&self, idx: usize) -> WriteReader<'r> { let slice = self.as_slice(); let start_idx = molecule::NUMBER_SIZE * (1 + idx); let start = molecule::unpack_number(&slice[start_idx..]) as usize; if idx == self.len() - 1 { WriteReader::new_unchecked(&self.as_slice()[start..]) } else { let end_idx = start_idx + molecule::NUMBER_SIZE; let end = molecule::unpack_number(&slice[end_idx..]) as usize; WriteReader::new_unchecked(&self.as_slice()[start..end]) } } } impl<'r> molecule::prelude::Reader<'r> for WritesReader<'r> { type Entity = Writes; const NAME: &'static str = "WritesReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { WritesReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len < molecule::NUMBER_SIZE { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); } let total_size = molecule::unpack_number(slice) as usize; if slice_len != total_size { return ve!(Self, TotalSizeNotMatch, total_size, slice_len); } if slice_len == molecule::NUMBER_SIZE { return Ok(()); } if slice_len < molecule::NUMBER_SIZE * 2 { return ve!( Self, TotalSizeNotMatch, molecule::NUMBER_SIZE * 2, slice_len ); } let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { return ve!(Self, OffsetsNotMatch); } if slice_len < offset_first { return ve!(Self, HeaderIsBroken, offset_first, slice_len); } let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] .chunks_exact(molecule::NUMBER_SIZE) .map(|x| molecule::unpack_number(x) as usize) .collect(); offsets.push(total_size); if offsets.windows(2).any(|i| i[0] > i[1]) { return ve!(Self, OffsetsNotMatch); } for pair in offsets.windows(2) { let start = pair[0]; let end = pair[1]; WriteReader::verify(&slice[start..end], compatible)?; } Ok(()) } } #[derive(Clone, Debug, Default)] pub struct WritesBuilder(pub(crate) Vec); impl WritesBuilder { pub fn set(mut self, v: Vec) -> Self { self.0 = v; self } pub fn push(mut self, v: Write) -> Self { self.0.push(v); self } pub fn extend>(mut self, iter: T) -> Self { for elem in iter { self.0.push(elem); } self } pub fn replace(&mut self, index: usize, v: Write) -> Option { self.0 .get_mut(index) .map(|item| ::core::mem::replace(item, v)) } } impl molecule::prelude::Builder for WritesBuilder { type Entity = Writes; const NAME: &'static str = "WritesBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (self.0.len() + 1) + self .0 .iter() .map(|inner| inner.as_slice().len()) .sum::() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { let item_count = self.0.len(); if item_count == 0 { writer.write_all(&molecule::pack_number( molecule::NUMBER_SIZE as molecule::Number, ))?; } else { let (total_size, offsets) = self.0.iter().fold( ( molecule::NUMBER_SIZE * (item_count + 1), Vec::with_capacity(item_count), ), |(start, mut offsets), inner| { offsets.push(start); (start + inner.as_slice().len(), offsets) }, ); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } for inner in self.0.iter() { writer.write_all(inner.as_slice())?; } } Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); Writes::new_unchecked(inner.into()) } } pub struct WritesIterator(Writes, usize, usize); impl ::core::iter::Iterator for WritesIterator { type Item = Write; fn next(&mut self) -> Option { if self.1 >= self.2 { None } else { let ret = self.0.get_unchecked(self.1); self.1 += 1; Some(ret) } } } impl ::core::iter::ExactSizeIterator for WritesIterator { fn len(&self) -> usize { self.2 - self.1 } } impl ::core::iter::IntoIterator for Writes { type Item = Write; type IntoIter = WritesIterator; fn into_iter(self) -> Self::IntoIter { let len = self.len(); WritesIterator(self, 0, len) } } impl<'r> WritesReader<'r> { pub fn iter<'t>(&'t self) -> WritesReaderIterator<'t, 'r> { WritesReaderIterator(&self, 0, self.len()) } } pub struct WritesReaderIterator<'t, 'r>(&'t WritesReader<'r>, usize, usize); impl<'t: 'r, 'r> ::core::iter::Iterator for WritesReaderIterator<'t, 'r> { type Item = WriteReader<'t>; fn next(&mut self) -> Option { if self.1 >= self.2 { None } else { let ret = self.0.get_unchecked(self.1); self.1 += 1; Some(ret) } } } impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for WritesReaderIterator<'t, 'r> { fn len(&self) -> usize { self.2 - self.1 } } impl ::core::iter::FromIterator for Writes { fn from_iter>(iter: T) -> Self { Self::new_builder().extend(iter).build() } } #[derive(Clone)] pub struct Spawn(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Spawn { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for Spawn { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for Spawn { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "from", self.from())?; write!(f, ", {}: {}", "child", self.child())?; write!(f, ", {}: {}", "fds", self.fds())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; } write!(f, " }}") } } impl ::core::default::Default for Spawn { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); Spawn::new_unchecked(v) } } impl Spawn { const DEFAULT_VALUE: [u8; 36] = [ 36, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]; pub const FIELD_COUNT: usize = 3; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn field_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn count_extra_fields(&self) -> usize { self.field_count() - Self::FIELD_COUNT } pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } pub fn from(&self) -> VmIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; VmIndex::new_unchecked(self.0.slice(start..end)) } pub fn child(&self) -> VmIndex { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; VmIndex::new_unchecked(self.0.slice(start..end)) } pub fn fds(&self) -> FdIndices { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; FdIndices::new_unchecked(self.0.slice(start..end)) } else { FdIndices::new_unchecked(self.0.slice(start..)) } } pub fn as_reader<'r>(&'r self) -> SpawnReader<'r> { SpawnReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for Spawn { type Builder = SpawnBuilder; const NAME: &'static str = "Spawn"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { Spawn(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { SpawnReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { SpawnReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder() .from(self.from()) .child(self.child()) .fds(self.fds()) } } #[derive(Clone, Copy)] pub struct SpawnReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for SpawnReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for SpawnReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for SpawnReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "from", self.from())?; write!(f, ", {}: {}", "child", self.child())?; write!(f, ", {}: {}", "fds", self.fds())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; } write!(f, " }}") } } impl<'r> SpawnReader<'r> { pub const FIELD_COUNT: usize = 3; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn field_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn count_extra_fields(&self) -> usize { self.field_count() - Self::FIELD_COUNT } pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } pub fn from(&self) -> VmIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; VmIndexReader::new_unchecked(&self.as_slice()[start..end]) } pub fn child(&self) -> VmIndexReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; VmIndexReader::new_unchecked(&self.as_slice()[start..end]) } pub fn fds(&self) -> FdIndicesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; FdIndicesReader::new_unchecked(&self.as_slice()[start..end]) } else { FdIndicesReader::new_unchecked(&self.as_slice()[start..]) } } } impl<'r> molecule::prelude::Reader<'r> for SpawnReader<'r> { type Entity = Spawn; const NAME: &'static str = "SpawnReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { SpawnReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len < molecule::NUMBER_SIZE { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); } let total_size = molecule::unpack_number(slice) as usize; if slice_len != total_size { return ve!(Self, TotalSizeNotMatch, total_size, slice_len); } if slice_len < molecule::NUMBER_SIZE * 2 { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); } let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { return ve!(Self, OffsetsNotMatch); } if slice_len < offset_first { return ve!(Self, HeaderIsBroken, offset_first, slice_len); } let field_count = offset_first / molecule::NUMBER_SIZE - 1; if field_count < Self::FIELD_COUNT { return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); } else if !compatible && field_count > Self::FIELD_COUNT { return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); }; let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] .chunks_exact(molecule::NUMBER_SIZE) .map(|x| molecule::unpack_number(x) as usize) .collect(); offsets.push(total_size); if offsets.windows(2).any(|i| i[0] > i[1]) { return ve!(Self, OffsetsNotMatch); } VmIndexReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; VmIndexReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; FdIndicesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; Ok(()) } } #[derive(Clone, Debug, Default)] pub struct SpawnBuilder { pub(crate) from: VmIndex, pub(crate) child: VmIndex, pub(crate) fds: FdIndices, } impl SpawnBuilder { pub const FIELD_COUNT: usize = 3; pub fn from(mut self, v: VmIndex) -> Self { self.from = v; self } pub fn child(mut self, v: VmIndex) -> Self { self.child = v; self } pub fn fds(mut self, v: FdIndices) -> Self { self.fds = v; self } } impl molecule::prelude::Builder for SpawnBuilder { type Entity = Spawn; const NAME: &'static str = "SpawnBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.from.as_slice().len() + self.child.as_slice().len() + self.fds.as_slice().len() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); offsets.push(total_size); total_size += self.from.as_slice().len(); offsets.push(total_size); total_size += self.child.as_slice().len(); offsets.push(total_size); total_size += self.fds.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } writer.write_all(self.from.as_slice())?; writer.write_all(self.child.as_slice())?; writer.write_all(self.fds.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); Spawn::new_unchecked(inner.into()) } } #[derive(Clone)] pub struct Spawns(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Spawns { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for Spawns { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for Spawns { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} [", Self::NAME)?; for i in 0..self.len() { if i == 0 { write!(f, "{}", self.get_unchecked(i))?; } else { write!(f, ", {}", self.get_unchecked(i))?; } } write!(f, "]") } } impl ::core::default::Default for Spawns { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); Spawns::new_unchecked(v) } } impl Spawns { const DEFAULT_VALUE: [u8; 4] = [4, 0, 0, 0]; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn item_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn len(&self) -> usize { self.item_count() } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn get(&self, idx: usize) -> Option { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } pub fn get_unchecked(&self, idx: usize) -> Spawn { let slice = self.as_slice(); let start_idx = molecule::NUMBER_SIZE * (1 + idx); let start = molecule::unpack_number(&slice[start_idx..]) as usize; if idx == self.len() - 1 { Spawn::new_unchecked(self.0.slice(start..)) } else { let end_idx = start_idx + molecule::NUMBER_SIZE; let end = molecule::unpack_number(&slice[end_idx..]) as usize; Spawn::new_unchecked(self.0.slice(start..end)) } } pub fn as_reader<'r>(&'r self) -> SpawnsReader<'r> { SpawnsReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for Spawns { type Builder = SpawnsBuilder; const NAME: &'static str = "Spawns"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { Spawns(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { SpawnsReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { SpawnsReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder().extend(self.into_iter()) } } #[derive(Clone, Copy)] pub struct SpawnsReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for SpawnsReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for SpawnsReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for SpawnsReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} [", Self::NAME)?; for i in 0..self.len() { if i == 0 { write!(f, "{}", self.get_unchecked(i))?; } else { write!(f, ", {}", self.get_unchecked(i))?; } } write!(f, "]") } } impl<'r> SpawnsReader<'r> { pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn item_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn len(&self) -> usize { self.item_count() } pub fn is_empty(&self) -> bool { self.len() == 0 } pub fn get(&self, idx: usize) -> Option> { if idx >= self.len() { None } else { Some(self.get_unchecked(idx)) } } pub fn get_unchecked(&self, idx: usize) -> SpawnReader<'r> { let slice = self.as_slice(); let start_idx = molecule::NUMBER_SIZE * (1 + idx); let start = molecule::unpack_number(&slice[start_idx..]) as usize; if idx == self.len() - 1 { SpawnReader::new_unchecked(&self.as_slice()[start..]) } else { let end_idx = start_idx + molecule::NUMBER_SIZE; let end = molecule::unpack_number(&slice[end_idx..]) as usize; SpawnReader::new_unchecked(&self.as_slice()[start..end]) } } } impl<'r> molecule::prelude::Reader<'r> for SpawnsReader<'r> { type Entity = Spawns; const NAME: &'static str = "SpawnsReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { SpawnsReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len < molecule::NUMBER_SIZE { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); } let total_size = molecule::unpack_number(slice) as usize; if slice_len != total_size { return ve!(Self, TotalSizeNotMatch, total_size, slice_len); } if slice_len == molecule::NUMBER_SIZE { return Ok(()); } if slice_len < molecule::NUMBER_SIZE * 2 { return ve!( Self, TotalSizeNotMatch, molecule::NUMBER_SIZE * 2, slice_len ); } let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { return ve!(Self, OffsetsNotMatch); } if slice_len < offset_first { return ve!(Self, HeaderIsBroken, offset_first, slice_len); } let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] .chunks_exact(molecule::NUMBER_SIZE) .map(|x| molecule::unpack_number(x) as usize) .collect(); offsets.push(total_size); if offsets.windows(2).any(|i| i[0] > i[1]) { return ve!(Self, OffsetsNotMatch); } for pair in offsets.windows(2) { let start = pair[0]; let end = pair[1]; SpawnReader::verify(&slice[start..end], compatible)?; } Ok(()) } } #[derive(Clone, Debug, Default)] pub struct SpawnsBuilder(pub(crate) Vec); impl SpawnsBuilder { pub fn set(mut self, v: Vec) -> Self { self.0 = v; self } pub fn push(mut self, v: Spawn) -> Self { self.0.push(v); self } pub fn extend>(mut self, iter: T) -> Self { for elem in iter { self.0.push(elem); } self } pub fn replace(&mut self, index: usize, v: Spawn) -> Option { self.0 .get_mut(index) .map(|item| ::core::mem::replace(item, v)) } } impl molecule::prelude::Builder for SpawnsBuilder { type Entity = Spawns; const NAME: &'static str = "SpawnsBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (self.0.len() + 1) + self .0 .iter() .map(|inner| inner.as_slice().len()) .sum::() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { let item_count = self.0.len(); if item_count == 0 { writer.write_all(&molecule::pack_number( molecule::NUMBER_SIZE as molecule::Number, ))?; } else { let (total_size, offsets) = self.0.iter().fold( ( molecule::NUMBER_SIZE * (item_count + 1), Vec::with_capacity(item_count), ), |(start, mut offsets), inner| { offsets.push(start); (start + inner.as_slice().len(), offsets) }, ); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } for inner in self.0.iter() { writer.write_all(inner.as_slice())?; } } Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); Spawns::new_unchecked(inner.into()) } } pub struct SpawnsIterator(Spawns, usize, usize); impl ::core::iter::Iterator for SpawnsIterator { type Item = Spawn; fn next(&mut self) -> Option { if self.1 >= self.2 { None } else { let ret = self.0.get_unchecked(self.1); self.1 += 1; Some(ret) } } } impl ::core::iter::ExactSizeIterator for SpawnsIterator { fn len(&self) -> usize { self.2 - self.1 } } impl ::core::iter::IntoIterator for Spawns { type Item = Spawn; type IntoIter = SpawnsIterator; fn into_iter(self) -> Self::IntoIter { let len = self.len(); SpawnsIterator(self, 0, len) } } impl<'r> SpawnsReader<'r> { pub fn iter<'t>(&'t self) -> SpawnsReaderIterator<'t, 'r> { SpawnsReaderIterator(&self, 0, self.len()) } } pub struct SpawnsReaderIterator<'t, 'r>(&'t SpawnsReader<'r>, usize, usize); impl<'t: 'r, 'r> ::core::iter::Iterator for SpawnsReaderIterator<'t, 'r> { type Item = SpawnReader<'t>; fn next(&mut self) -> Option { if self.1 >= self.2 { None } else { let ret = self.0.get_unchecked(self.1); self.1 += 1; Some(ret) } } } impl<'t: 'r, 'r> ::core::iter::ExactSizeIterator for SpawnsReaderIterator<'t, 'r> { fn len(&self) -> usize { self.2 - self.1 } } impl ::core::iter::FromIterator for Spawns { fn from_iter>(iter: T) -> Self { Self::new_builder().extend(iter).build() } } #[derive(Clone)] pub struct Data(molecule::bytes::Bytes); impl ::core::fmt::LowerHex for Data { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl ::core::fmt::Debug for Data { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl ::core::fmt::Display for Data { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "spawns", self.spawns())?; write!(f, ", {}: {}", "pipes", self.pipes())?; write!(f, ", {}: {}", "writes", self.writes())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; } write!(f, " }}") } } impl ::core::default::Default for Data { fn default() -> Self { let v = molecule::bytes::Bytes::from_static(&Self::DEFAULT_VALUE); Data::new_unchecked(v) } } impl Data { const DEFAULT_VALUE: [u8; 28] = [ 28, 0, 0, 0, 16, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, ]; pub const FIELD_COUNT: usize = 3; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn field_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn count_extra_fields(&self) -> usize { self.field_count() - Self::FIELD_COUNT } pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } pub fn spawns(&self) -> Spawns { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; Spawns::new_unchecked(self.0.slice(start..end)) } pub fn pipes(&self) -> Pipes { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; Pipes::new_unchecked(self.0.slice(start..end)) } pub fn writes(&self) -> Writes { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; Writes::new_unchecked(self.0.slice(start..end)) } else { Writes::new_unchecked(self.0.slice(start..)) } } pub fn as_reader<'r>(&'r self) -> DataReader<'r> { DataReader::new_unchecked(self.as_slice()) } } impl molecule::prelude::Entity for Data { type Builder = DataBuilder; const NAME: &'static str = "Data"; fn new_unchecked(data: molecule::bytes::Bytes) -> Self { Data(data) } fn as_bytes(&self) -> molecule::bytes::Bytes { self.0.clone() } fn as_slice(&self) -> &[u8] { &self.0[..] } fn from_slice(slice: &[u8]) -> molecule::error::VerificationResult { DataReader::from_slice(slice).map(|reader| reader.to_entity()) } fn from_compatible_slice(slice: &[u8]) -> molecule::error::VerificationResult { DataReader::from_compatible_slice(slice).map(|reader| reader.to_entity()) } fn new_builder() -> Self::Builder { ::core::default::Default::default() } fn as_builder(self) -> Self::Builder { Self::new_builder() .spawns(self.spawns()) .pipes(self.pipes()) .writes(self.writes()) } } #[derive(Clone, Copy)] pub struct DataReader<'r>(&'r [u8]); impl<'r> ::core::fmt::LowerHex for DataReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { use molecule::hex_string; if f.alternate() { write!(f, "0x")?; } write!(f, "{}", hex_string(self.as_slice())) } } impl<'r> ::core::fmt::Debug for DataReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{}({:#x})", Self::NAME, self) } } impl<'r> ::core::fmt::Display for DataReader<'r> { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { write!(f, "{} {{ ", Self::NAME)?; write!(f, "{}: {}", "spawns", self.spawns())?; write!(f, ", {}: {}", "pipes", self.pipes())?; write!(f, ", {}: {}", "writes", self.writes())?; let extra_count = self.count_extra_fields(); if extra_count != 0 { write!(f, ", .. ({} fields)", extra_count)?; } write!(f, " }}") } } impl<'r> DataReader<'r> { pub const FIELD_COUNT: usize = 3; pub fn total_size(&self) -> usize { molecule::unpack_number(self.as_slice()) as usize } pub fn field_count(&self) -> usize { if self.total_size() == molecule::NUMBER_SIZE { 0 } else { (molecule::unpack_number(&self.as_slice()[molecule::NUMBER_SIZE..]) as usize / 4) - 1 } } pub fn count_extra_fields(&self) -> usize { self.field_count() - Self::FIELD_COUNT } pub fn has_extra_fields(&self) -> bool { Self::FIELD_COUNT != self.field_count() } pub fn spawns(&self) -> SpawnsReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[4..]) as usize; let end = molecule::unpack_number(&slice[8..]) as usize; SpawnsReader::new_unchecked(&self.as_slice()[start..end]) } pub fn pipes(&self) -> PipesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[8..]) as usize; let end = molecule::unpack_number(&slice[12..]) as usize; PipesReader::new_unchecked(&self.as_slice()[start..end]) } pub fn writes(&self) -> WritesReader<'r> { let slice = self.as_slice(); let start = molecule::unpack_number(&slice[12..]) as usize; if self.has_extra_fields() { let end = molecule::unpack_number(&slice[16..]) as usize; WritesReader::new_unchecked(&self.as_slice()[start..end]) } else { WritesReader::new_unchecked(&self.as_slice()[start..]) } } } impl<'r> molecule::prelude::Reader<'r> for DataReader<'r> { type Entity = Data; const NAME: &'static str = "DataReader"; fn to_entity(&self) -> Self::Entity { Self::Entity::new_unchecked(self.as_slice().to_owned().into()) } fn new_unchecked(slice: &'r [u8]) -> Self { DataReader(slice) } fn as_slice(&self) -> &'r [u8] { self.0 } fn verify(slice: &[u8], compatible: bool) -> molecule::error::VerificationResult<()> { use molecule::verification_error as ve; let slice_len = slice.len(); if slice_len < molecule::NUMBER_SIZE { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE, slice_len); } let total_size = molecule::unpack_number(slice) as usize; if slice_len != total_size { return ve!(Self, TotalSizeNotMatch, total_size, slice_len); } if slice_len < molecule::NUMBER_SIZE * 2 { return ve!(Self, HeaderIsBroken, molecule::NUMBER_SIZE * 2, slice_len); } let offset_first = molecule::unpack_number(&slice[molecule::NUMBER_SIZE..]) as usize; if offset_first % molecule::NUMBER_SIZE != 0 || offset_first < molecule::NUMBER_SIZE * 2 { return ve!(Self, OffsetsNotMatch); } if slice_len < offset_first { return ve!(Self, HeaderIsBroken, offset_first, slice_len); } let field_count = offset_first / molecule::NUMBER_SIZE - 1; if field_count < Self::FIELD_COUNT { return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); } else if !compatible && field_count > Self::FIELD_COUNT { return ve!(Self, FieldCountNotMatch, Self::FIELD_COUNT, field_count); }; let mut offsets: Vec = slice[molecule::NUMBER_SIZE..offset_first] .chunks_exact(molecule::NUMBER_SIZE) .map(|x| molecule::unpack_number(x) as usize) .collect(); offsets.push(total_size); if offsets.windows(2).any(|i| i[0] > i[1]) { return ve!(Self, OffsetsNotMatch); } SpawnsReader::verify(&slice[offsets[0]..offsets[1]], compatible)?; PipesReader::verify(&slice[offsets[1]..offsets[2]], compatible)?; WritesReader::verify(&slice[offsets[2]..offsets[3]], compatible)?; Ok(()) } } #[derive(Clone, Debug, Default)] pub struct DataBuilder { pub(crate) spawns: Spawns, pub(crate) pipes: Pipes, pub(crate) writes: Writes, } impl DataBuilder { pub const FIELD_COUNT: usize = 3; pub fn spawns(mut self, v: Spawns) -> Self { self.spawns = v; self } pub fn pipes(mut self, v: Pipes) -> Self { self.pipes = v; self } pub fn writes(mut self, v: Writes) -> Self { self.writes = v; self } } impl molecule::prelude::Builder for DataBuilder { type Entity = Data; const NAME: &'static str = "DataBuilder"; fn expected_length(&self) -> usize { molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1) + self.spawns.as_slice().len() + self.pipes.as_slice().len() + self.writes.as_slice().len() } fn write(&self, writer: &mut W) -> molecule::io::Result<()> { let mut total_size = molecule::NUMBER_SIZE * (Self::FIELD_COUNT + 1); let mut offsets = Vec::with_capacity(Self::FIELD_COUNT); offsets.push(total_size); total_size += self.spawns.as_slice().len(); offsets.push(total_size); total_size += self.pipes.as_slice().len(); offsets.push(total_size); total_size += self.writes.as_slice().len(); writer.write_all(&molecule::pack_number(total_size as molecule::Number))?; for offset in offsets.into_iter() { writer.write_all(&molecule::pack_number(offset as molecule::Number))?; } writer.write_all(self.spawns.as_slice())?; writer.write_all(self.pipes.as_slice())?; writer.write_all(self.writes.as_slice())?; Ok(()) } fn build(&self) -> Self::Entity { let mut inner = Vec::with_capacity(self.expected_length()); self.write(&mut inner) .unwrap_or_else(|_| panic!("{} build should be ok", Self::NAME)); Data::new_unchecked(inner.into()) } }