Skip to main content

surfer_translation_types/
variable_ref.rs

1use crate::ScopeRef;
2#[cfg(feature = "wasm_plugins")]
3use extism_convert::{FromBytes, Json, ToBytes};
4use serde::{Deserialize, Serialize};
5use std::hash::{Hash, Hasher};
6
7// FIXME: We'll be cloning these quite a bit, I wonder if a `Cow<&str>` or Rc/Arc would be better
8#[cfg_attr(feature = "wasm_plugins", derive(FromBytes, ToBytes))]
9#[cfg_attr(feature = "wasm_plugins", encoding(Json))]
10#[derive(Clone, Debug, Eq, Serialize, Deserialize)]
11pub struct VariableRef<VarId, ScopeId> {
12    /// Path in the scope hierarchy to where this variable resides.
13    pub path: ScopeRef<ScopeId>,
14    /// Name of the variable in its hierarchy.
15    pub name: String,
16    /// Backend specific numeric ID.
17    ///
18    /// Performance optimization.
19    pub id: VarId,
20    /// Index.
21    ///
22    /// Only used to point out a variable in an array of variables,
23    /// not variables that are arrays themselves, so only a single index required.
24    #[serde(default)]
25    pub index: Option<i64>,
26}
27
28impl<VarId, ScopeId> VariableRef<VarId, ScopeId> {
29    pub fn map_ids<VarId2, ScopeId2>(
30        self,
31        mut var_fn: impl FnMut(VarId) -> VarId2,
32        scope_fn: impl FnMut(ScopeId) -> ScopeId2,
33    ) -> VariableRef<VarId2, ScopeId2> {
34        VariableRef {
35            path: self.path.map_id(scope_fn),
36            name: self.name,
37            id: var_fn(self.id),
38            index: self.index,
39        }
40    }
41
42    pub fn full_path(&self) -> Vec<String> {
43        self.path
44            .strs
45            .iter()
46            .cloned()
47            .chain([self.name.clone()])
48            .collect()
49    }
50}
51
52impl<VarId, ScopeId> AsRef<VariableRef<VarId, ScopeId>> for VariableRef<VarId, ScopeId> {
53    fn as_ref(&self) -> &VariableRef<VarId, ScopeId> {
54        self
55    }
56}
57
58impl<VarId, ScopeId> Hash for VariableRef<VarId, ScopeId> {
59    fn hash<H: Hasher>(&self, state: &mut H) {
60        // id is intentionally not hashed, since it is only a performance hint
61        self.path.hash(state);
62        self.name.hash(state);
63    }
64}
65
66impl<VarId, ScopeId> PartialEq for VariableRef<VarId, ScopeId> {
67    fn eq(&self, other: &Self) -> bool {
68        // id is intentionally not compared, since it is only a performance hint
69        self.path.eq(&other.path) && self.name.eq(&other.name)
70    }
71}