substrait/parse/text/simple_extensions/
extensions.rs1use indexmap::IndexMap;
9use std::collections::{HashMap, HashSet};
10use std::str::FromStr;
11
12use super::{
13 ExtensionFile, SimpleExtensionsError, scalar_functions::ScalarFunction, types::CustomType,
14};
15use crate::{
16 parse::{Context, Parse},
17 text::simple_extensions::SimpleExtensions as RawExtensions,
18 urn::Urn,
19};
20
21#[derive(Clone, Debug, Default)]
27pub struct SimpleExtensions {
28 types: HashMap<String, CustomType>,
30 scalar_functions: HashMap<String, ScalarFunction>,
34}
35
36impl SimpleExtensions {
37 pub fn add_type(&mut self, custom_type: &CustomType) -> Result<(), SimpleExtensionsError> {
39 if self.types.contains_key(&custom_type.name) {
40 return Err(SimpleExtensionsError::DuplicateTypeName {
41 name: custom_type.name.clone(),
42 });
43 }
44
45 self.types
46 .insert(custom_type.name.clone(), custom_type.clone());
47 Ok(())
48 }
49
50 pub fn get_type(&self, name: &str) -> Option<&CustomType> {
52 self.types.get(name)
53 }
54
55 pub fn types(&self) -> impl Iterator<Item = &CustomType> {
57 self.types.values()
58 }
59
60 pub(crate) fn into_types(self) -> HashMap<String, CustomType> {
62 self.types
63 }
64
65 pub(super) fn add_scalar_function(&mut self, scalar_function: ScalarFunction) {
72 use std::collections::hash_map::Entry;
73 match self.scalar_functions.entry(scalar_function.name.clone()) {
74 Entry::Vacant(e) => {
75 e.insert(scalar_function);
76 }
77 Entry::Occupied(mut e) => {
78 Self::merge_scalar_function(e.get_mut(), scalar_function);
79 }
80 }
81 }
82
83 fn merge_scalar_function(existing: &mut ScalarFunction, new: ScalarFunction) {
89 existing.impls.extend(new.impls);
90 existing.description = existing.description.take().or(new.description);
91 }
92
93 pub fn get_scalar_function(&self, name: &str) -> Option<&ScalarFunction> {
95 self.scalar_functions.get(name)
96 }
97
98 pub fn scalar_functions(&self) -> impl Iterator<Item = &ScalarFunction> {
100 self.scalar_functions.values()
101 }
102}
103
104#[derive(Debug, Default)]
106pub(crate) struct TypeContext {
107 known: HashSet<String>,
109 linked: HashSet<String>,
111}
112
113impl TypeContext {
114 pub fn found(&mut self, name: &str) {
116 self.linked.remove(name);
117 self.known.insert(name.to_string());
118 }
119
120 pub fn linked(&mut self, name: &str) {
123 if !self.known.contains(name) {
124 self.linked.insert(name.to_string());
125 }
126 }
127}
128
129impl Context for TypeContext {}
130
131impl Parse<TypeContext> for RawExtensions {
133 type Parsed = ExtensionFile;
137 type Error = super::SimpleExtensionsError;
138
139 fn parse(self, ctx: &mut TypeContext) -> Result<Self::Parsed, Self::Error> {
140 let RawExtensions {
141 urn,
142 types,
143 scalar_functions,
144 ..
145 } = self;
146 let urn = Urn::from_str(&urn)?;
147 let mut extension = SimpleExtensions::default();
148
149 for type_item in types {
150 let custom_type = Parse::parse(type_item, ctx)?;
151 extension.add_type(&custom_type)?;
152 }
153
154 for scalar_fn in scalar_functions {
155 match ScalarFunction::from_raw(scalar_fn, ctx) {
156 Ok(parsed_fn) => {
157 extension.add_scalar_function(parsed_fn);
158 }
159 Err(super::scalar_functions::ScalarFunctionError::NotYetImplemented(_)) => {
160 continue;
163 }
164 Err(e) => return Err(e.into()),
165 }
166 }
167
168 if let Some(missing) = ctx.linked.iter().next() {
169 return Err(super::SimpleExtensionsError::UnresolvedTypeReference {
171 type_name: missing.clone(),
172 });
173 }
174
175 Ok(ExtensionFile { urn, extension })
176 }
177}
178
179pub(super) fn to_raw_extensions(urn: Urn, extension: SimpleExtensions) -> RawExtensions {
186 let types = extension
187 .into_types()
188 .into_values()
189 .map(Into::into)
190 .collect();
191
192 RawExtensions {
193 urn: urn.to_string(),
194 aggregate_functions: vec![],
195 dependencies: IndexMap::new(),
196 metadata: Default::default(),
197 scalar_functions: vec![],
198 type_variations: vec![],
199 types,
200 window_functions: vec![],
201 }
202}