lucet_module/
bindings.rs

1use crate::Error;
2use serde_json::{self, Map, Value};
3use std::collections::{hash_map::Entry, HashMap};
4use std::fs;
5use std::path::Path;
6
7#[derive(Debug, Clone)]
8pub struct Bindings {
9    bindings: HashMap<String, HashMap<String, String>>,
10}
11
12impl Bindings {
13    pub fn new(bindings: HashMap<String, HashMap<String, String>>) -> Bindings {
14        Self { bindings: bindings }
15    }
16
17    pub fn env(env: HashMap<String, String>) -> Bindings {
18        let mut bindings = HashMap::new();
19        bindings.insert("env".to_owned(), env);
20        Self::new(bindings)
21    }
22
23    pub fn empty() -> Bindings {
24        Self::new(HashMap::new())
25    }
26
27    pub fn from_json(v: &Value) -> Result<Bindings, Error> {
28        match v.as_object() {
29            Some(modules) => Self::parse_modules_json_obj(modules),
30            None => Err(Error::ParseJsonObjError)?,
31        }
32    }
33
34    pub fn from_str(s: &str) -> Result<Bindings, Error> {
35        let top: Value = serde_json::from_str(s)?;
36        Ok(Self::from_json(&top)?)
37    }
38
39    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Bindings, Error> {
40        let contents = fs::read_to_string(path.as_ref())?;
41        Ok(Self::from_str(&contents)?)
42    }
43
44    pub fn extend(&mut self, other: &Bindings) -> Result<(), Error> {
45        for (modname, othermodbindings) in other.bindings.iter() {
46            match self.bindings.entry(modname.clone()) {
47                Entry::Occupied(mut e) => {
48                    let existing = e.get_mut();
49                    for (bindname, binding) in othermodbindings {
50                        match existing.entry(bindname.clone()) {
51                            Entry::Vacant(e) => {
52                                e.insert(binding.clone());
53                            }
54                            Entry::Occupied(e) => {
55                                if binding != e.get() {
56                                    Err(Error::RebindError {
57                                        key: e.key().to_owned(),
58                                        binding: binding.to_owned(),
59                                        attempt: e.get().to_owned(),
60                                    })?;
61                                }
62                            }
63                        }
64                    }
65                }
66                Entry::Vacant(e) => {
67                    e.insert(othermodbindings.clone());
68                }
69            }
70        }
71        Ok(())
72    }
73
74    pub fn translate(&self, module: &str, symbol: &str) -> Result<&str, Error> {
75        match self.bindings.get(module) {
76            Some(m) => match m.get(symbol) {
77                Some(s) => Ok(s),
78                None => Err(Error::UnknownSymbol {
79                    module: module.to_owned(),
80                    symbol: symbol.to_owned(),
81                }),
82            },
83            None => Err(Error::UnknownModule {
84                module: module.to_owned(),
85                symbol: symbol.to_owned(),
86            }),
87        }
88    }
89
90    fn parse_modules_json_obj(m: &Map<String, Value>) -> Result<Self, Error> {
91        let mut res = HashMap::new();
92        for (modulename, values) in m {
93            match values.as_object() {
94                Some(methods) => {
95                    let methodmap = Self::parse_methods_json_obj(methods)?;
96                    res.insert(modulename.to_owned(), methodmap);
97                }
98                None => {
99                    Err(Error::ParseError {
100                        key: modulename.to_owned(),
101                        value: values.to_string(),
102                    })?;
103                }
104            }
105        }
106        Ok(Self::new(res))
107    }
108
109    fn parse_methods_json_obj(m: &Map<String, Value>) -> Result<HashMap<String, String>, Error> {
110        let mut res = HashMap::new();
111        for (method, i) in m {
112            match i.as_str() {
113                Some(importbinding) => {
114                    res.insert(method.to_owned(), importbinding.to_owned());
115                }
116                None => {
117                    Err(Error::ParseError {
118                        key: method.to_owned(),
119                        value: i.to_string(),
120                    })?;
121                }
122            }
123        }
124        Ok(res)
125    }
126
127    pub fn to_string(&self) -> Result<String, Error> {
128        let s = serde_json::to_string(&self.to_json())?;
129        Ok(s)
130    }
131
132    pub fn to_json(&self) -> Value {
133        Value::from(self.serialize_modules_json_obj())
134    }
135
136    fn serialize_modules_json_obj(&self) -> Map<String, Value> {
137        let mut m = Map::new();
138        for (modulename, values) in self.bindings.iter() {
139            m.insert(
140                modulename.to_owned(),
141                Value::from(Self::serialize_methods_json_obj(values)),
142            );
143        }
144        m
145    }
146
147    fn serialize_methods_json_obj(methods: &HashMap<String, String>) -> Map<String, Value> {
148        let mut m = Map::new();
149        for (methodname, symbol) in methods.iter() {
150            m.insert(methodname.to_owned(), Value::from(symbol.to_owned()));
151        }
152        m
153    }
154}