substrait/parse/
context.rsuse thiserror::Error;
use crate::parse::{
proto::extensions::SimpleExtensionUri, text::simple_extensions::SimpleExtensions, Anchor, Parse,
};
pub trait Context {
fn parse<T: Parse<Self>>(&mut self, item: T) -> Result<T::Parsed, T::Error>
where
Self: Sized,
{
item.parse(self)
}
fn add_simple_extension_uri(
&mut self,
simple_extension_uri: &SimpleExtensionUri,
) -> Result<&SimpleExtensions, ContextError>;
fn simple_extensions(
&self,
anchor: &Anchor<SimpleExtensionUri>,
) -> Result<&SimpleExtensions, ContextError>;
}
#[derive(Debug, Error, PartialEq)]
pub enum ContextError {
#[error("undefined reference to simple extension with anchor `{0}`")]
UndefinedSimpleExtension(Anchor<SimpleExtensionUri>),
#[error("duplicate anchor `{0}` for simple extension")]
DuplicateSimpleExtension(Anchor<SimpleExtensionUri>),
#[error("unsupported simple extension URI: {0}")]
UnsupportedURI(String),
}
#[cfg(test)]
pub(crate) mod tests {
use std::collections::{hash_map::Entry, HashMap};
use crate::parse::{
context::ContextError, proto::extensions::SimpleExtensionUri,
text::simple_extensions::SimpleExtensions, Anchor,
};
pub struct Context {
empty_simple_extensions: SimpleExtensions,
simple_extensions: HashMap<Anchor<SimpleExtensionUri>, SimpleExtensionUri>,
}
impl Default for Context {
fn default() -> Self {
Self {
empty_simple_extensions: SimpleExtensions {},
simple_extensions: Default::default(),
}
}
}
impl super::Context for Context {
fn add_simple_extension_uri(
&mut self,
simple_extension_uri: &crate::parse::proto::extensions::SimpleExtensionUri,
) -> Result<&SimpleExtensions, ContextError> {
match self.simple_extensions.entry(simple_extension_uri.anchor()) {
Entry::Occupied(_) => Err(ContextError::DuplicateSimpleExtension(
simple_extension_uri.anchor(),
)),
Entry::Vacant(entry) => {
if let "http" | "https" | "file" = simple_extension_uri.uri().scheme() {
entry.insert(simple_extension_uri.clone());
Ok(&self.empty_simple_extensions)
} else {
Err(ContextError::UnsupportedURI(format!(
"`{}` scheme not supported",
simple_extension_uri.uri().scheme()
)))
}
}
}
}
fn simple_extensions(
&self,
anchor: &Anchor<SimpleExtensionUri>,
) -> Result<&SimpleExtensions, ContextError> {
self.simple_extensions
.contains_key(anchor)
.then_some(&self.empty_simple_extensions)
.ok_or(ContextError::UndefinedSimpleExtension(*anchor))
}
}
}