syntax_parser_generator/readers/
address_based.rs

1use std::marker::PhantomData;
2
3use crate::readers::Reader;
4
5/// A sequence of items that can be accessed by conceptual addresses.
6///
7/// The first item's address should be 0.
8pub trait AddressSpace<T> {
9    /// Get the item in a given address.
10    ///
11    /// If no item is available at that address, [None] is returned.
12    fn read_at(&self, address: usize) -> Option<T>;
13}
14
15/// A [Reader] implementation that's based on an [AddressSpace] of the read items.
16pub struct AddressBasedReader<T, AddressSpaceType>
17where
18    AddressSpaceType: AddressSpace<T>,
19{
20    address_space: AddressSpaceType,
21    head_address: usize,
22    tail_address: usize,
23    cursor_address: usize,
24    phantom_data: PhantomData<T>,
25}
26
27impl<T, AddressSpaceType> AddressBasedReader<T, AddressSpaceType>
28where
29    AddressSpaceType: AddressSpace<T>,
30{
31    /// Create a new reader over the items in the given address space.
32    pub fn raw_new(address_space: AddressSpaceType) -> Self {
33        Self {
34            address_space,
35            head_address: 0,
36            tail_address: 0,
37            cursor_address: 0,
38            phantom_data: Default::default(),
39        }
40    }
41}
42
43impl<T, AddressSpaceType> Reader<T> for AddressBasedReader<T, AddressSpaceType>
44where
45    AddressSpaceType: AddressSpace<T>,
46{
47    fn read_next(&mut self) -> Option<T> {
48        let result = self.address_space.read_at(self.cursor_address)?;
49        self.cursor_address += 1;
50        Some(result)
51    }
52
53    fn set_head(&mut self) {
54        self.head_address = self.cursor_address;
55    }
56
57    fn set_tail(&mut self) {
58        self.tail_address = self.cursor_address;
59    }
60
61    fn move_cursor_to_tail(&mut self) {
62        self.cursor_address = self.tail_address;
63    }
64
65    fn get_sequence(&self) -> impl Iterator<Item=T> {
66        (self.head_address..self.tail_address)
67            .map(|address| self.address_space.read_at(address))
68            .map(|optional_item| {
69                optional_item.expect("Sequence of Reader items between head & tail should exist")
70            })
71    }
72}