jeff/reader/
module.rs

1//! Top-level module definition in a jeff program.
2use crate::capnp::jeff_capnp;
3
4use super::function::FunctionId;
5use super::metadata::sealed::HasMetadataSealed;
6use super::string_table::StringTable;
7use super::Function;
8
9/// Top-level module definition in a jeff program.
10#[derive(Clone, Copy, Debug)]
11pub struct Module<'a> {
12    /// Internal capnproto module definition.
13    module: jeff_capnp::module::Reader<'a>,
14}
15
16impl<'a> Module<'a> {
17    /// Create a new module view from a capnp reader.
18    pub(crate) fn read_capnp(module: jeff_capnp::module::Reader<'a>) -> Self {
19        Self { module }
20    }
21
22    /// Version of the jeff protocol used in this module.
23    pub fn version(&self) -> u32 {
24        self.module.get_version()
25    }
26
27    /// Returns the internal reader over the module's functions.
28    fn functions_reader(&self) -> capnp::struct_list::Reader<'a, jeff_capnp::function::Owned> {
29        self.module
30            .get_functions()
31            .expect("Functions should be present")
32    }
33
34    /// Returns an iterator over the functions defined in this module.
35    pub fn functions(&self) -> impl Iterator<Item = Function<'a>> {
36        let string_table = self.strings();
37        self.functions_reader()
38            .iter()
39            .map(move |f| Function::read_capnp(f, string_table))
40    }
41
42    /// Returns the number of functions defined in this module.
43    pub fn function_count(&self) -> usize {
44        self.functions_reader().len() as usize
45    }
46
47    /// Returns the `n`-th function defined in this module.
48    ///
49    /// # Panics
50    ///
51    /// Panics if `n` is equal or greater than [`Module::function_count`].
52    pub fn function(&self, n: FunctionId) -> Function<'a> {
53        Function::read_capnp(self.functions_reader().get(n), self.strings())
54    }
55
56    /// Returns the `n`-th function defined in this module.
57    pub fn try_function(&self, n: FunctionId) -> Option<Function<'a>> {
58        let f = self.functions_reader().try_get(n)?;
59        Some(Function::read_capnp(f, self.strings()))
60    }
61
62    /// Returns the internal storage of strings.
63    pub fn strings(&self) -> StringTable<'a> {
64        StringTable::read_capnp(
65            self.module
66                .get_strings()
67                .expect("Strings should be present"),
68        )
69    }
70
71    /// Returns the [FunctionId] of the entrypoint function for this module.
72    pub fn entrypoint_id(&self) -> FunctionId {
73        self.module.get_entrypoint() as FunctionId
74    }
75
76    /// Returns the entrypoint function for this module.
77    ///
78    /// # Panics
79    ///
80    /// Panics if the entrypoint id in the jeff definition is out of range.
81    pub fn entrypoint(&self) -> Function<'a> {
82        self.functions().nth(self.entrypoint_id() as usize).unwrap()
83    }
84
85    /// Returns the tool name used to generate this program.
86    ///
87    /// See [`Module::tool_version`].
88    pub fn tool(&self) -> &str {
89        self.module
90            .get_tool()
91            .ok()
92            .and_then(|r| r.to_str().ok())
93            .unwrap_or("")
94    }
95
96    /// Returns the tool version used to generate this program.
97    ///
98    /// See [`Module::tool`].
99    pub fn tool_version(&self) -> &str {
100        self.module
101            .get_tool_version()
102            .ok()
103            .and_then(|r| r.to_str().ok())
104            .unwrap_or("")
105    }
106}
107
108impl<'a> HasMetadataSealed for Module<'a> {
109    fn strings(&self) -> StringTable<'a> {
110        self.strings()
111    }
112
113    fn metadata_reader(&self) -> capnp::struct_list::Reader<'a, jeff_capnp::meta::Owned> {
114        self.module
115            .get_metadata()
116            .expect("Metadata should be present")
117    }
118}