1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use super::{
    dectx::{DeCtx, DeCtxT},
    *,
};

/// Preferred way to parse [Point]s off of a [Serializer].
pub(super) struct Addresses {
    current: usize,
}

impl Addresses {
    /// 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: 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, _) = deserializer
            .inext_address(&mut addresses, |_| unreachable!())
            .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, _) = deserializer
            .inext_address(&mut addresses, |_| unreachable!())
            .unwrap();
        assert_eq!(address.point, point0.as_slice());
        assert_eq!(address.index, 0);
        let (address, _) = deserializer
            .inext_address(&mut addresses, |_| unreachable!())
            .unwrap();
        assert_eq!(address.point, point1.as_slice());
        assert_eq!(address.index, 1);
        let (address, _) = deserializer
            .inext_address(&mut addresses, |_| unreachable!())
            .unwrap();
        assert_eq!(address.point, point2.as_slice());
        assert_eq!(address.index, 2);
        if tail.len() < HASH_SIZE {
            let err = deserializer
                .inext_address(&mut addresses, |e| e.to_vec())
                .unwrap_err();
            assert_eq!(err, tail);
        }
    }
}