substrait/parse/
context.rs1use thiserror::Error;
6
7use crate::parse::{
8 proto::extensions::SimpleExtensionUri, text::simple_extensions::SimpleExtensions, Anchor, Parse,
9};
10
11pub trait Context {
16 fn parse<T: Parse<Self>>(&mut self, item: T) -> Result<T::Parsed, T::Error>
20 where
21 Self: Sized,
22 {
23 item.parse(self)
24 }
25
26 fn add_simple_extension_uri(
32 &mut self,
33 simple_extension_uri: &SimpleExtensionUri,
34 ) -> Result<&SimpleExtensions, ContextError>;
35
36 fn simple_extensions(
38 &self,
39 anchor: &Anchor<SimpleExtensionUri>,
40 ) -> Result<&SimpleExtensions, ContextError>;
41}
42
43#[derive(Debug, Error, PartialEq)]
45pub enum ContextError {
46 #[error("undefined reference to simple extension with anchor `{0}`")]
48 UndefinedSimpleExtension(Anchor<SimpleExtensionUri>),
49
50 #[error("duplicate anchor `{0}` for simple extension")]
52 DuplicateSimpleExtension(Anchor<SimpleExtensionUri>),
53
54 #[error("unsupported simple extension URI: {0}")]
56 UnsupportedURI(String),
57}
58
59#[cfg(test)]
60pub(crate) mod tests {
61 use std::collections::{hash_map::Entry, HashMap};
62
63 use crate::parse::{
64 context::ContextError, proto::extensions::SimpleExtensionUri,
65 text::simple_extensions::SimpleExtensions, Anchor,
66 };
67
68 pub struct Context {
73 empty_simple_extensions: SimpleExtensions,
74 simple_extensions: HashMap<Anchor<SimpleExtensionUri>, SimpleExtensionUri>,
75 }
76
77 impl Default for Context {
78 fn default() -> Self {
79 Self {
80 empty_simple_extensions: SimpleExtensions {},
81 simple_extensions: Default::default(),
82 }
83 }
84 }
85
86 impl super::Context for Context {
87 fn add_simple_extension_uri(
88 &mut self,
89 simple_extension_uri: &crate::parse::proto::extensions::SimpleExtensionUri,
90 ) -> Result<&SimpleExtensions, ContextError> {
91 match self.simple_extensions.entry(simple_extension_uri.anchor()) {
92 Entry::Occupied(_) => Err(ContextError::DuplicateSimpleExtension(
93 simple_extension_uri.anchor(),
94 )),
95 Entry::Vacant(entry) => {
96 if let "http" | "https" | "file" = simple_extension_uri.uri().scheme() {
99 entry.insert(simple_extension_uri.clone());
100 Ok(&self.empty_simple_extensions)
102 } else {
103 Err(ContextError::UnsupportedURI(format!(
104 "`{}` scheme not supported",
105 simple_extension_uri.uri().scheme()
106 )))
107 }
108 }
109 }
110 }
111
112 fn simple_extensions(
113 &self,
114 anchor: &Anchor<SimpleExtensionUri>,
115 ) -> Result<&SimpleExtensions, ContextError> {
116 self.simple_extensions
117 .contains_key(anchor)
118 .then_some(&self.empty_simple_extensions)
119 .ok_or(ContextError::UndefinedSimpleExtension(*anchor))
120 }
121 }
122}