substrait_validator/output/extension/
reference.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Module for representing anchor-based references to extensions.
4
5use crate::output::path;
6use crate::util;
7use std::sync::Arc;
8
9/// Represents an identifier that was used to reference something. It is
10/// stored along with a resolution result to retain information about the
11/// reference even if the resolution failed, and is generally only used for
12/// identity/equality checks and diagnostic information.
13#[derive(Clone, Debug, Default)]
14pub struct Identifier {
15    /// The name of the object being referred to, if known. Always stored using
16    /// the case convention used by the reference.
17    name: Option<String>,
18
19    /// If this name is also abstracted by an integer anchor number in the
20    /// plan, this is set to the path to the node that defined it, if known.
21    anchor_path: Option<path::PathBuf>,
22}
23
24impl PartialEq for Identifier {
25    fn eq(&self, other: &Self) -> bool {
26        self.name == other.name
27    }
28}
29
30impl Eq for Identifier {}
31
32impl std::hash::Hash for Identifier {
33    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
34        self.name.hash(state);
35    }
36}
37
38impl std::fmt::Display for Identifier {
39    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40        if let Some(name) = &self.name {
41            write!(f, "{}", util::string::as_ident_or_string(name))
42        } else {
43            write!(f, "?")
44        }
45    }
46}
47
48impl From<String> for Identifier {
49    fn from(name: String) -> Self {
50        Identifier {
51            name: Some(name),
52            anchor_path: None,
53        }
54    }
55}
56
57impl From<&str> for Identifier {
58    fn from(name: &str) -> Self {
59        Identifier {
60            name: Some(name.to_string()),
61            anchor_path: None,
62        }
63    }
64}
65
66impl Identifier {
67    /// Create a new anchor-based reference.
68    pub fn new<S: ToString>(
69        name: Option<S>,
70        anchor_path: Option<path::PathBuf>,
71    ) -> Arc<Identifier> {
72        Arc::new(Identifier {
73            name: name.map(|x| x.to_string()),
74            anchor_path,
75        })
76    }
77
78    /// Create a new named reference.
79    pub fn new_by_name<S: ToString>(name: S) -> Arc<Identifier> {
80        Arc::new(Identifier {
81            name: Some(name.to_string()),
82            anchor_path: None,
83        })
84    }
85
86    /// Create a new unknown reference.
87    pub fn new_unknown() -> Arc<Identifier> {
88        Arc::default()
89    }
90
91    /// Returns the name, if known.
92    pub fn name(&self) -> Option<&str> {
93        self.name.as_ref().map(|s| &s[..])
94    }
95
96    /// Returns the path to the anchor, if known.
97    pub fn anchor_path(&self) -> Option<&path::PathBuf> {
98        self.anchor_path.as_ref()
99    }
100}
101
102/// Named/namespaced reference to a particular named extension within a
103/// particular URI-referenced extension.
104#[derive(Debug)]
105pub struct Data<T> {
106    /// The name of the type, type variation, or function. If we're referring
107    /// to a module, this is unused (both name and anchor are set to None)
108    pub name: Arc<Identifier>,
109
110    /// The URI of the YAML file that defined this extension.
111    pub uri: Arc<Identifier>,
112
113    /// Extension definition information, specific to this type of extension,
114    /// if we managed to resolve the reference.
115    pub definition: Option<Arc<T>>,
116}
117
118impl<T> Clone for Data<T> {
119    fn clone(&self) -> Self {
120        Self {
121            name: self.name.clone(),
122            uri: self.uri.clone(),
123            definition: self.definition.clone(),
124        }
125    }
126}
127
128impl<T> Default for Data<T> {
129    fn default() -> Self {
130        Self {
131            name: Default::default(),
132            uri: Default::default(),
133            definition: Default::default(),
134        }
135    }
136}
137
138impl<T> PartialEq for Data<T> {
139    /// References are equal if they refer to the same thing, regardless of how
140    /// they refer to it. If we're not sure because either reference is
141    /// (partially) unresolved, return false pessimistically.
142    fn eq(&self, other: &Self) -> bool {
143        self.name == other.name && self.uri == other.uri
144    }
145}
146
147impl<T> Eq for Data<T> {}
148
149impl<T> std::hash::Hash for Data<T> {
150    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
151        self.name.hash(state);
152        self.uri.hash(state);
153    }
154}
155
156impl<T> std::fmt::Display for Data<T> {
157    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158        write!(f, "{}::{}", self.uri, self.name)
159    }
160}
161
162impl<T> From<String> for Data<T> {
163    fn from(name: String) -> Self {
164        Data {
165            name: Arc::new(name.into()),
166            uri: Arc::default(),
167            definition: None,
168        }
169    }
170}
171
172impl<T> From<&str> for Data<T> {
173    fn from(name: &str) -> Self {
174        Data {
175            name: Arc::new(name.into()),
176            uri: Arc::default(),
177            definition: None,
178        }
179    }
180}
181
182/// References are stored in Arcs, so they can be (somewhat) efficiently
183/// copied.
184pub type Reference<T> = Arc<Data<T>>;