Skip to main content

jeff/reader/
value.rs

1//! "Values" represent wire types in the jeff language with associated metadata.
2//!
3//! There are two types of values:
4//!
5//! - [`WireValue`]s that correspond to typed hyperedges in dataflow regions.
6//! - [`FunctionIOValue`]s, describing the inputs and outputs of a function.
7//!
8//! All regions inside a function share a single [`ValueTable`] listing all the
9//! hyperedges in the function. These are indexed by their [`ValueId`]s.
10
11mod function_io;
12mod wire_value;
13
14pub use function_io::FunctionIOValue;
15pub use wire_value::WireValue;
16
17use crate::capnp::jeff_capnp;
18
19use super::string_table::StringTable;
20use super::ReadError;
21
22/// The ID of a value hyperedge in the function's value table.
23pub type ValueId = u32;
24
25/// Table of values / typed hyperedges contained in a function.
26#[derive(Clone, Copy, Debug)]
27pub struct ValueTable<'a> {
28    /// Internal capnproto value table.
29    values: capnp::struct_list::Reader<'a, jeff_capnp::value::Owned>,
30    /// Module-level register of reused strings.
31    strings: StringTable<'a>,
32}
33
34impl<'a> ValueTable<'a> {
35    /// Create a new value table view from a capnp reader.
36    pub(crate) fn read_capnp(
37        values: capnp::struct_list::Reader<'a, jeff_capnp::value::Owned>,
38        strings: StringTable<'a>,
39    ) -> Self {
40        Self { values, strings }
41    }
42
43    /// Returns the wire value at the given index.
44    ///
45    /// # Errors
46    ///
47    /// - [`ReadError::ValueOutOfBounds`] if the index is out of bounds.
48    pub fn get(&self, idx: ValueId) -> Result<WireValue<'a>, ReadError> {
49        let value = self
50            .values
51            .try_get(idx)
52            .ok_or_else(|| ReadError::ValueOutOfBounds {
53                idx,
54                count: self.len(),
55            })?;
56
57        Ok(WireValue::read_capnp(idx, value, self.strings))
58    }
59
60    /// Returns an iterator over the wire values in this table.
61    pub fn iter(&self) -> impl Iterator<Item = (ValueId, WireValue<'a>)> + '_ {
62        self.values.iter().enumerate().map(move |(idx, value)| {
63            (
64                idx as ValueId,
65                WireValue::read_capnp(idx as ValueId, value, self.strings),
66            )
67        })
68    }
69
70    /// Returns the number of strings in this table.
71    pub fn len(&self) -> usize {
72        self.values.len() as usize
73    }
74
75    /// Returns `true` if the table is empty.
76    pub fn is_empty(&self) -> bool {
77        self.values.len() == 0
78    }
79}