use std::str::FromStr;
use thiserror::Error;
use crate::{
parse::{Anchor, Parse, context::ContextError, proto::ExtensionAnchors},
proto,
urn::{InvalidUrn, Urn},
};
#[derive(Clone, Debug, PartialEq)]
pub struct SimpleExtensionUrn {
urn: Urn,
anchor: Anchor<Self>,
}
impl SimpleExtensionUrn {
pub fn urn(&self) -> &Urn {
&self.urn
}
pub fn anchor(&self) -> Anchor<Self> {
self.anchor
}
}
#[derive(Debug, Error, PartialEq)]
pub enum SimpleExtensionUrnError {
#[error("invalid urn")]
InvalidUrn(#[from] InvalidUrn),
#[error(transparent)]
Context(#[from] ContextError),
}
impl Parse<ExtensionAnchors> for proto::extensions::SimpleExtensionUrn {
type Parsed = SimpleExtensionUrn;
type Error = SimpleExtensionUrnError;
fn parse(self, ctx: &mut ExtensionAnchors) -> Result<Self::Parsed, Self::Error> {
let proto::extensions::SimpleExtensionUrn {
extension_urn_anchor: anchor,
urn,
} = self;
let urn = Urn::from_str(&urn)?;
let simple_extension_urn = SimpleExtensionUrn {
urn,
anchor: Anchor::new(anchor),
};
ctx.add_simple_extension_urn(&simple_extension_urn)?;
Ok(simple_extension_urn)
}
}
impl From<SimpleExtensionUrn> for proto::extensions::SimpleExtensionUrn {
fn from(simple_extension_urn: SimpleExtensionUrn) -> Self {
let SimpleExtensionUrn { urn, anchor } = simple_extension_urn;
proto::extensions::SimpleExtensionUrn {
urn: urn.to_string(),
extension_urn_anchor: anchor.into_inner(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::parse::{Context as _, proto::ExtensionAnchors};
#[test]
fn parse() -> Result<(), SimpleExtensionUrnError> {
let simple_extension_urn = proto::extensions::SimpleExtensionUrn {
extension_urn_anchor: 1,
urn: "extension:substrait-rs:test".to_string(),
};
let simple_extension_urn = simple_extension_urn.parse(&mut ExtensionAnchors::default())?;
assert_eq!(simple_extension_urn.anchor(), Anchor::new(1));
assert_eq!(
simple_extension_urn.urn().to_string().as_str(),
"extension:substrait-rs:test"
);
Ok(())
}
#[test]
fn invalid_urn() {
let simple_extension_urn = proto::extensions::SimpleExtensionUrn::default();
assert_eq!(
simple_extension_urn.parse(&mut ExtensionAnchors::default()),
Err(SimpleExtensionUrnError::InvalidUrn(InvalidUrn))
);
let simple_extension_urn = proto::extensions::SimpleExtensionUrn {
extension_urn_anchor: 1,
urn: "urn::".to_string(),
};
assert_eq!(
simple_extension_urn.parse(&mut ExtensionAnchors::default()),
Err(SimpleExtensionUrnError::InvalidUrn(InvalidUrn))
);
}
#[test]
fn duplicate_simple_extension() {
let mut ctx = ExtensionAnchors::default();
let simple_extension_urn = proto::extensions::SimpleExtensionUrn {
extension_urn_anchor: 1,
urn: "extension:substrait-rs:test".to_string(),
};
assert!(ctx.parse(simple_extension_urn.clone()).is_ok());
assert_eq!(
ctx.parse(simple_extension_urn),
Err(SimpleExtensionUrnError::Context(
ContextError::DuplicateSimpleExtension(Anchor::new(1))
))
);
}
}