substrait_validator/output/extension/simple/
module.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Module for representing simple extension modules/files.
4
5use crate::output::extension;
6use std::collections::HashMap;
7
8/// Trait for structs that represent extension modules, providing functions for
9/// resolving names in them.
10pub trait Scope {
11    /// Resolves a to-be-resolved reference to a type class.
12    fn resolve_type_class<T>(&self, name: T) -> extension::simple::type_class::ResolutionResult
13    where
14        T: Into<extension::simple::type_class::UnresolvedReference>;
15
16    /// Resolves a to-be-resolved reference to a type variation.
17    fn resolve_type_variation<T>(
18        &self,
19        name: T,
20    ) -> extension::simple::type_variation::ResolutionResult
21    where
22        T: Into<extension::simple::type_variation::UnresolvedReference>;
23
24    /// Resolves a to-be-resolved reference to a function.
25    fn resolve_function<T>(&self, name: T) -> extension::simple::function::ResolutionResult
26    where
27        T: Into<extension::simple::function::UnresolvedReference>;
28}
29
30/// Same as [Scope], but object-safe.
31pub trait DynScope {
32    /// Resolves a to-be-resolved reference to a type class.
33    fn resolve_type_class_from_ref(
34        &self,
35        name: extension::simple::type_class::UnresolvedReference,
36    ) -> extension::simple::type_class::ResolutionResult;
37
38    /// Resolves a to-be-resolved reference to a type variation.
39    fn resolve_type_variation_from_ref(
40        &self,
41        name: extension::simple::type_variation::UnresolvedReference,
42    ) -> extension::simple::type_variation::ResolutionResult;
43
44    /// Resolves a to-be-resolved reference to a function.
45    fn resolve_function_from_ref(
46        &self,
47        name: extension::simple::function::UnresolvedReference,
48    ) -> extension::simple::function::ResolutionResult;
49}
50
51impl<T: Scope> DynScope for T {
52    fn resolve_type_class_from_ref(
53        &self,
54        name: extension::simple::type_class::UnresolvedReference,
55    ) -> extension::simple::type_class::ResolutionResult {
56        self.resolve_type_class(name)
57    }
58
59    fn resolve_type_variation_from_ref(
60        &self,
61        name: extension::simple::type_variation::UnresolvedReference,
62    ) -> extension::simple::type_variation::ResolutionResult {
63        self.resolve_type_variation(name)
64    }
65
66    fn resolve_function_from_ref(
67        &self,
68        name: extension::simple::function::UnresolvedReference,
69    ) -> extension::simple::function::ResolutionResult {
70        self.resolve_function(name)
71    }
72}
73
74/// A parsed simple extension module/file.
75#[derive(Clone, Debug, Default)]
76pub struct Definition {
77    /// Unique number within the tree that can be used to refer to this
78    /// extension when exporting in protobuf form.
79    pub extension_id: u64,
80
81    /// Description of the module.
82    pub description: String,
83
84    /// The URI that was actually used to resolve the module.
85    pub actual_uri: String,
86
87    /// Map with references to dependencies.
88    pub dependencies: HashMap<String, Reference>,
89
90    /// Reference to the namespace in which this module's type classes were
91    /// defined. Unlike the type variation and function implementation
92    /// namespaces, these should never be ambiguous, but we use the same
93    /// mechanism anyway.
94    pub type_classes: extension::simple::type_class::NamespaceReference,
95
96    /// Reference to the namespace in which this module's type variations were
97    /// defined. Note that variations are technically namespaced to the type
98    /// class they were defined for; however, this would make type variation
99    /// anchors very poorly defined. Instead, we pretend that they're all in
100    /// the same namespace, but allow multiple definitions with the same name
101    /// within our namespace system. Only when a type variation
102    /// anchor/reference pair is referred to in the plan and the type class is
103    /// known do we attempt to solve this ambiguity.
104    pub type_variations: extension::simple::type_variation::NamespaceReference,
105
106    /// Reference to the namespace in which this module's function
107    /// implementations were defined. Each implementation is mapped twice: once
108    /// for its simple function name, and once for its compound name. The
109    /// former will be ambiguous if multiple implementations exist for a
110    /// function, which we do indeed try to solve for using the type patterns,
111    /// even though Substrait explicitly disallows referring to a function by
112    /// its simple name if the function has multiple definitions. Likewise, we
113    /// also solve this if a compound name is ambigous, again despite Substrait
114    /// disallowing extensions from creating this situation.
115    pub function_impls: extension::simple::function::NamespaceReference,
116}
117
118impl Scope for Definition {
119    /// Resolves a to-be-resolved reference to a type class.
120    fn resolve_type_class<T>(&self, name: T) -> extension::simple::type_class::ResolutionResult
121    where
122        T: Into<extension::simple::type_class::UnresolvedReference>,
123    {
124        self.type_classes.resolve_public(name.into())
125    }
126
127    /// Resolves a to-be-resolved reference to a type variation.
128    fn resolve_type_variation<T>(
129        &self,
130        name: T,
131    ) -> extension::simple::type_variation::ResolutionResult
132    where
133        T: Into<extension::simple::type_variation::UnresolvedReference>,
134    {
135        self.type_variations.resolve_public(name.into())
136    }
137
138    /// Resolves a to-be-resolved reference to a function.
139    fn resolve_function<T>(&self, name: T) -> extension::simple::function::ResolutionResult
140    where
141        T: Into<extension::simple::function::UnresolvedReference>,
142    {
143        self.function_impls.resolve_public(name.into())
144    }
145}
146
147/// A potentially unresolved reference to a module. Includes the URI even if
148/// unresolved. The name fields of ExtensionReference are unused.
149pub type Reference = extension::Reference<Definition>;
150
151impl Scope for Reference {
152    /// Resolves a to-be-resolved reference to a type class.
153    fn resolve_type_class<T>(&self, name: T) -> extension::simple::type_class::ResolutionResult
154    where
155        T: Into<extension::simple::type_class::UnresolvedReference>,
156    {
157        let reference = name.into();
158        self.definition
159            .as_ref()
160            .map(|x| x.resolve_type_class(reference.clone()))
161            .unwrap_or_else(|| extension::simple::type_class::ResolutionResult::new(reference))
162    }
163
164    /// Resolves a to-be-resolved reference to a type variation.
165    fn resolve_type_variation<T>(
166        &self,
167        name: T,
168    ) -> extension::simple::type_variation::ResolutionResult
169    where
170        T: Into<extension::simple::type_variation::UnresolvedReference>,
171    {
172        let reference = name.into();
173        self.definition
174            .as_ref()
175            .map(|x| x.resolve_type_variation(reference.clone()))
176            .unwrap_or_else(|| extension::simple::type_variation::ResolutionResult::new(reference))
177    }
178
179    /// Resolves a to-be-resolved reference to a function.
180    fn resolve_function<T>(&self, name: T) -> extension::simple::function::ResolutionResult
181    where
182        T: Into<extension::simple::function::UnresolvedReference>,
183    {
184        let reference = name.into();
185        self.definition
186            .as_ref()
187            .map(|x| x.resolve_function(reference.clone()))
188            .unwrap_or_else(|| extension::simple::function::ResolutionResult::new(reference))
189    }
190}