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. Performance optimization.
17    pub id: VarId,
18    /// Index
19    ///
20    /// Only used to point out a variable in an array of variables,
21    /// not variables that are arrays themselves, so only a single index required.
22    #[serde(default)]
23    pub index: Option<i64>,
24}
25
26impl<VarId, ScopeId> VariableRef<VarId, ScopeId> {
27    pub fn map_ids<VarId2, ScopeId2>(
28        self,
29        mut var_fn: impl FnMut(VarId) -> VarId2,
30        scope_fn: impl FnMut(ScopeId) -> ScopeId2,
31    ) -> VariableRef<VarId2, ScopeId2> {
32        VariableRef {
33            path: self.path.map_id(scope_fn),
34            name: self.name,
35            id: var_fn(self.id),
36            index: self.index,
37        }
38    }
39
40    pub fn full_path(&self) -> Vec<String> {
41        self.path
42            .strs
43            .iter()
44            .cloned()
45            .chain([self.name.clone()])
46            .collect()
47    }
48}
49
50impl<VarId, ScopeId> AsRef<VariableRef<VarId, ScopeId>> for VariableRef<VarId, ScopeId> {
51    fn as_ref(&self) -> &VariableRef<VarId, ScopeId> {
52        self
53    }
54}
55
56impl<VarId, ScopeId> Hash for VariableRef<VarId, ScopeId> {
57    fn hash<H: Hasher>(&self, state: &mut H) {
58        // id is intentionally not hashed, since it is only a performance hint
59        self.path.hash(state);
60        self.name.hash(state);
61    }
62}
63
64impl<VarId, ScopeId> PartialEq for VariableRef<VarId, ScopeId> {
65    fn eq(&self, other: &Self) -> bool {
66        // id is intentionally not compared, since it is only a performance hint
67        self.path.eq(&other.path) && self.name.eq(&other.name)
68    }
69}