use super::{ dectx::{DeCtx, DeCtxT}, *, }; /// Preferred way to parse [Point]s off of a [Serializer]. pub(super) struct Addresses { current: usize, } impl Addresses { /// Read the next [Address]. pub fn next<'a>( &mut self, deserializer: &'a mut dyn Deserializer, ) -> Result { let point = deserializer.read_n_const::()?; let address = Address { point, index: self.current, }; self.current += 1; Ok(address) } /// Start reading the [Address]es. fn start() -> Self { Addresses { current: 0 } } } pub(super) trait InliningAddresses: Stream { fn inext_address( self, addresses: &mut Addresses, err: impl FnOnce(&[u8]) -> E, ) -> Result<(Address, Self), E> { let (point, deserializer) = self.iread_n_const::(err)?; let address = Address { point, index: addresses.current, }; addresses.current += 1; Ok((address, deserializer)) } } impl InliningAddresses for D {} fn parse_slice<'a, Ctx: Context<'a>, F: FactoryParse<'a, Ctx>>( factory: &F, slice: &[u8], resolver: &Arc>, ) -> ParseResult<'a, F> { let mut deserializer = SliceDeserializer::from(slice); let mentionable = factory.deserialize(&mut DeCtxT { deserializer: &mut deserializer, resolver, addresses: &mut Addresses::start(), } as &mut dyn DeCtx<'a, Ctx>)?; let tail = deserializer.read_all(); if tail.is_empty() { Ok(mentionable) } else { factory.extend(mentionable, tail) } } impl<'a, Ctx: Context<'a>, F: FactoryParse<'a, Ctx>> FactoryExt<'a, Ctx> for F { fn parse_slice( &self, slice: &[u8], resolver: &Arc>, ) -> ParseResult<'a, Self> { parse_slice::(self, slice, resolver) } } #[cfg(test)] mod tests { use super::*; #[test] fn can_read_one_address() { let mut addresses = Addresses::start(); let point = b"A".repeat(HASH_SIZE); let mut deserializer = SliceDeserializer::from(point.as_slice()); let address = addresses.next(&mut deserializer).unwrap(); assert_eq!(address.point, point.as_slice()); assert_eq!(address.index, 0); } #[test] fn can_read_three_addresses_and_fail_on_extra_tail() { let mut addresses = Addresses::start(); let point0 = b"A".repeat(HASH_SIZE); let point1 = b"B".repeat(HASH_SIZE); let point2 = b"C".repeat(HASH_SIZE); let tail = b"tail"; let mut source = Vec::new(); source.extend(&point0); source.extend(&point1); source.extend(&point2); source.extend(tail); let mut deserializer = SliceDeserializer::from(source.as_slice()); let address = addresses.next(&mut deserializer).unwrap(); assert_eq!(address.point, point0.as_slice()); assert_eq!(address.index, 0); let address = addresses.next(&mut deserializer).unwrap(); assert_eq!(address.point, point1.as_slice()); assert_eq!(address.index, 1); let address = addresses.next(&mut deserializer).unwrap(); assert_eq!(address.point, point2.as_slice()); assert_eq!(address.index, 2); if tail.len() < HASH_SIZE { let err = addresses.next(&mut deserializer).unwrap_err(); assert_eq!(err, tail); } } }