Skip to main content

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) -> semver::Version {
24        let major = self.module.get_version() as u64;
25        let minor = self.module.get_version_minor() as u64;
26        let patch = self.module.get_version_patch() as u64;
27        semver::Version::new(major, minor, patch)
28    }
29
30    /// Returns the internal reader over the module's functions.
31    fn functions_reader(&self) -> capnp::struct_list::Reader<'a, jeff_capnp::function::Owned> {
32        self.module
33            .get_functions()
34            .expect("Functions should be present")
35    }
36
37    /// Returns an iterator over the functions defined in this module.
38    pub fn functions(&self) -> impl Iterator<Item = Function<'a>> {
39        let string_table = self.strings();
40        self.functions_reader()
41            .iter()
42            .map(move |f| Function::read_capnp(f, string_table))
43    }
44
45    /// Returns the number of functions defined in this module.
46    pub fn function_count(&self) -> usize {
47        self.functions_reader().len() as usize
48    }
49
50    /// Returns the `n`-th function defined in this module.
51    ///
52    /// # Panics
53    ///
54    /// Panics if `n` is equal or greater than [`Module::function_count`].
55    pub fn function(&self, n: FunctionId) -> Function<'a> {
56        Function::read_capnp(self.functions_reader().get(n), self.strings())
57    }
58
59    /// Returns the `n`-th function defined in this module.
60    pub fn try_function(&self, n: FunctionId) -> Option<Function<'a>> {
61        let f = self.functions_reader().try_get(n)?;
62        Some(Function::read_capnp(f, self.strings()))
63    }
64
65    /// Returns the internal storage of strings.
66    pub fn strings(&self) -> StringTable<'a> {
67        StringTable::read_capnp(
68            self.module
69                .get_strings()
70                .expect("Strings should be present"),
71        )
72    }
73
74    /// Returns the [FunctionId] of the entrypoint function for this module.
75    pub fn entrypoint_id(&self) -> FunctionId {
76        self.module.get_entrypoint() as FunctionId
77    }
78
79    /// Returns the entrypoint function for this module.
80    ///
81    /// # Panics
82    ///
83    /// Panics if the entrypoint id in the jeff definition is out of range.
84    pub fn entrypoint(&self) -> Function<'a> {
85        self.functions().nth(self.entrypoint_id() as usize).unwrap()
86    }
87
88    /// Returns the tool name used to generate this program.
89    ///
90    /// See [`Module::tool_version`].
91    pub fn tool(&self) -> &str {
92        self.module
93            .get_tool()
94            .ok()
95            .and_then(|r| r.to_str().ok())
96            .unwrap_or("")
97    }
98
99    /// Returns the tool version used to generate this program.
100    ///
101    /// See [`Module::tool`].
102    pub fn tool_version(&self) -> &str {
103        self.module
104            .get_tool_version()
105            .ok()
106            .and_then(|r| r.to_str().ok())
107            .unwrap_or("")
108    }
109}
110
111impl<'a> HasMetadataSealed for Module<'a> {
112    fn strings(&self) -> StringTable<'a> {
113        self.strings()
114    }
115
116    fn metadata_reader(&self) -> capnp::struct_list::Reader<'a, jeff_capnp::meta::Owned> {
117        self.module
118            .get_metadata()
119            .expect("Metadata should be present")
120    }
121}