radn-rs/src/rcore/addresses.rs
parrrate 885a8732af
Some checks failed
buildbot/cargo fmt (1.72) Build done.
buildbot/cargo doc (1.72) Build done.
buildbot/cargo clippy (1.72) Build done.
buildbot/cargo test (1.65) Build done.
buildbot/cargo clippy (1.65) Build done.
remove InliningAddresses::inext_point
2024-08-30 21:41:26 +00:00

121 lines
3.5 KiB
Rust

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<Address, &'a [u8]> {
let point = deserializer.read_n_const::<HASH_SIZE>()?;
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<E>: Stream {
fn inext_address(
self,
addresses: &mut Addresses,
err: impl FnOnce(&[u8]) -> E,
) -> Result<(Address, Self), E> {
let (point, deserializer) = self.iread_n_const::<HASH_SIZE>(err)?;
let address = Address {
point,
index: addresses.current,
};
addresses.current += 1;
Ok((address, deserializer))
}
}
impl<E, D: ?Sized + Stream> InliningAddresses<E> for D {}
fn parse_slice<'a, Ctx: Context<'a>, F: FactoryParse<'a, Ctx>>(
factory: &F,
slice: &[u8],
resolver: &Arc<dyn Resolver<'a, Ctx>>,
) -> 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<dyn Resolver<'a, Ctx>>,
) -> ParseResult<'a, Self> {
parse_slice::<Ctx, _>(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);
}
}
}