From d1ecc3e139c0348cf59862a5ef7646fdd4f74846 Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 4 Apr 2024 07:51:08 +0200 Subject: [PATCH 01/16] Save work --- src/parse/proto/extensions/mod.rs | 2 + .../extension_function.rs | 50 +++++++++++++++++ .../extension_type.rs | 49 +++++++++++++++++ .../extension_type_variation.rs | 53 +++++++++++++++++++ .../mapping_type.rs | 52 ++++++++++++++++++ .../simple_extension_declaration/mod.rs | 5 ++ .../simple_extension_declaration.rs | 41 ++++++++++++++ 7 files changed, 252 insertions(+) create mode 100644 src/parse/proto/extensions/simple_extension_declaration/extension_function.rs create mode 100644 src/parse/proto/extensions/simple_extension_declaration/extension_type.rs create mode 100644 src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs create mode 100644 src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs create mode 100644 src/parse/proto/extensions/simple_extension_declaration/mod.rs create mode 100644 src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs diff --git a/src/parse/proto/extensions/mod.rs b/src/parse/proto/extensions/mod.rs index 2527805..2e77959 100644 --- a/src/parse/proto/extensions/mod.rs +++ b/src/parse/proto/extensions/mod.rs @@ -2,5 +2,7 @@ //! Parsing of [proto::extensions] types. +mod simple_extension_declaration; mod simple_extension_uri; + pub use simple_extension_uri::SimpleExtensionUri; diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs new file mode 100644 index 0000000..432cc22 --- /dev/null +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs @@ -0,0 +1,50 @@ +use super::simple_extension_declaration::SimpleExtensionDeclarationError; +use crate::parse::{Anchor, Context, Parse}; +use crate::proto; + +#[derive(Clone, Debug, PartialEq)] +pub struct ExtensionFunction { + anchor: Anchor, + name: String, + extension_uri_reference: Anchor, +} + +impl Parse for proto::extensions::simple_extension_declaration::ExtensionFunction { + type Parsed = ExtensionFunction; + type Error = SimpleExtensionDeclarationError; + + fn parse(self, _ctx: &mut C) -> Result { + let proto::extensions::simple_extension_declaration::ExtensionFunction { + extension_uri_reference, + function_anchor, + name, + } = self; + + // Construct the parsed ExtensionFunction + let extension_function = ExtensionFunction { + extension_uri_reference: Anchor::new(extension_uri_reference), + name, + anchor: Anchor::new(function_anchor), + }; + + Ok(extension_function) + } +} + +impl From + for proto::extensions::simple_extension_declaration::ExtensionFunction +{ + fn from(value: ExtensionFunction) -> Self { + let ExtensionFunction { + anchor, + name, + extension_uri_reference, + } = value; + + Self { + extension_uri_reference: extension_uri_reference.into_inner(), + function_anchor: anchor.into_inner(), + name: name, + } + } +} diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs new file mode 100644 index 0000000..ecc1f78 --- /dev/null +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs @@ -0,0 +1,49 @@ +use crate::parse::{Anchor, Context, Parse}; +use crate::proto; + +use super::simple_extension_declaration::SimpleExtensionDeclarationError; + +#[derive(Clone, Debug, PartialEq)] +pub struct ExtensionType { + anchor: Anchor, + name: String, + extension_uri_reference: Anchor, +} + +impl Parse for proto::extensions::simple_extension_declaration::ExtensionType { + type Parsed = ExtensionType; + type Error = SimpleExtensionDeclarationError; + + fn parse(self, _ctx: &mut C) -> Result { + let proto::extensions::simple_extension_declaration::ExtensionType { + extension_uri_reference, + type_anchor, + name, + } = self; + + // Construct the parsed ExtensionType + let extension_type_variation = ExtensionType { + extension_uri_reference: Anchor::new(extension_uri_reference), + name, + anchor: Anchor::new(type_anchor), + }; + + Ok(extension_type_variation) + } +} + +impl From for proto::extensions::simple_extension_declaration::ExtensionType { + fn from(value: ExtensionType) -> Self { + let ExtensionType { + anchor, + name, + extension_uri_reference, + } = value; + + Self { + extension_uri_reference: extension_uri_reference.into_inner(), + type_anchor: anchor.into_inner(), + name: name, + } + } +} diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs new file mode 100644 index 0000000..98cbb77 --- /dev/null +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs @@ -0,0 +1,53 @@ +use crate::parse::{Anchor, Context, Parse}; +use crate::proto; + +use super::simple_extension_declaration::SimpleExtensionDeclarationError; + +#[derive(Clone, Debug, PartialEq)] +pub struct ExtensionTypeVariation { + anchor: Anchor, + name: String, + extension_uri_reference: Anchor, +} + +impl Parse + for proto::extensions::simple_extension_declaration::ExtensionTypeVariation +{ + type Parsed = ExtensionTypeVariation; + type Error = SimpleExtensionDeclarationError; + + fn parse(self, _ctx: &mut C) -> Result { + let proto::extensions::simple_extension_declaration::ExtensionTypeVariation { + extension_uri_reference, + type_variation_anchor, + name, + } = self; + + // Construct the parsed ExtensionTypeVariation + let extension_type_variation = ExtensionTypeVariation { + extension_uri_reference: Anchor::new(extension_uri_reference), + name, + anchor: Anchor::new(type_variation_anchor), + }; + + Ok(extension_type_variation) + } +} + +impl From + for proto::extensions::simple_extension_declaration::ExtensionTypeVariation +{ + fn from(value: ExtensionTypeVariation) -> Self { + let ExtensionTypeVariation { + anchor, + name, + extension_uri_reference, + } = value; + + Self { + extension_uri_reference: extension_uri_reference.into_inner(), + type_variation_anchor: anchor.into_inner(), + name: name, + } + } +} diff --git a/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs b/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs new file mode 100644 index 0000000..74782be --- /dev/null +++ b/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs @@ -0,0 +1,52 @@ +use crate::{ + parse::{Context, Parse}, + proto, +}; + +use super::{ + extension_function, extension_type, extension_type_variation, + simple_extension_declaration::SimpleExtensionDeclarationError, +}; + +/// MappingType +#[derive(Clone, Debug, PartialEq)] +pub enum MappingType { + ExtensionType(extension_type::ExtensionType), + ExtensionTypeVariation(extension_type_variation::ExtensionTypeVariation), + ExtensionFunction(extension_function::ExtensionFunction), +} + +impl Parse for proto::extensions::simple_extension_declaration::MappingType { + type Parsed = MappingType; + type Error = SimpleExtensionDeclarationError; + + fn parse(self, ctx: &mut C) -> Result { + Ok(match self { + proto::extensions::simple_extension_declaration::MappingType::ExtensionFunction(inner) => MappingType::ExtensionFunction(inner.parse(ctx)?), + proto::extensions::simple_extension_declaration::MappingType::ExtensionType(inner) => MappingType::ExtensionType(inner.parse(ctx)?), + proto::extensions::simple_extension_declaration::MappingType::ExtensionTypeVariation(inner) => MappingType::ExtensionTypeVariation(inner.parse(ctx)?), + }) + } +} + +impl From for proto::extensions::simple_extension_declaration::MappingType { + fn from(value: MappingType) -> Self { + match value { + MappingType::ExtensionFunction(inner) => { + proto::extensions::simple_extension_declaration::MappingType::ExtensionFunction( + inner.into(), + ) + } + MappingType::ExtensionType(inner) => { + proto::extensions::simple_extension_declaration::MappingType::ExtensionType( + inner.into(), + ) + } + MappingType::ExtensionTypeVariation(inner) => { + proto::extensions::simple_extension_declaration::MappingType::ExtensionTypeVariation( + inner.into(), + ) + } + } + } +} diff --git a/src/parse/proto/extensions/simple_extension_declaration/mod.rs b/src/parse/proto/extensions/simple_extension_declaration/mod.rs new file mode 100644 index 0000000..29f9ebc --- /dev/null +++ b/src/parse/proto/extensions/simple_extension_declaration/mod.rs @@ -0,0 +1,5 @@ +mod extension_function; +mod extension_type; +mod extension_type_variation; +mod mapping_type; +mod simple_extension_declaration; diff --git a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs b/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs new file mode 100644 index 0000000..b1bff78 --- /dev/null +++ b/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs @@ -0,0 +1,41 @@ +use crate::{ + parse::{Context, Parse}, + proto, +}; +use thiserror::Error; + +use super::mapping_type::MappingType; + +// SimpleExtensionDeclaration +#[derive(Clone, Debug, PartialEq)] +pub struct SimpleExtensionDeclaration { + pub mapping_type: Option, +} + +#[derive(Debug, PartialEq, Error)] +pub enum SimpleExtensionDeclarationError {} + +impl Parse for proto::extensions::SimpleExtensionDeclaration { + type Parsed = SimpleExtensionDeclaration; + type Error = SimpleExtensionDeclarationError; + + fn parse(self, ctx: &mut C) -> Result { + let proto::extensions::SimpleExtensionDeclaration { mapping_type } = self; + + Ok(SimpleExtensionDeclaration { + mapping_type: mapping_type + .map(|mapping_type| mapping_type.parse(ctx).ok()) + .flatten(), + }) + } +} + +impl From for proto::extensions::SimpleExtensionDeclaration { + fn from(declaration: SimpleExtensionDeclaration) -> Self { + let SimpleExtensionDeclaration { mapping_type } = declaration; + + proto::extensions::SimpleExtensionDeclaration { + mapping_type: mapping_type.map(|mapping_type| mapping_type.into()), + } + } +} From 68babd81d15d707988ef109b4434dd717da969ec Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Mon, 8 Apr 2024 05:37:23 +0200 Subject: [PATCH 02/16] Update src/parse/proto/extensions/simple_extension_declaration/extension_function.rs Co-authored-by: Matthijs Brobbel --- .../simple_extension_declaration/extension_function.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs index 432cc22..998dfc7 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs @@ -1,6 +1,5 @@ use super::simple_extension_declaration::SimpleExtensionDeclarationError; -use crate::parse::{Anchor, Context, Parse}; -use crate::proto; +use crate::{parse::{Anchor, Context, Parse}, proto}; #[derive(Clone, Debug, PartialEq)] pub struct ExtensionFunction { From 759847ffcf330a8ac1a72dbeba5c0020bd9cfbde Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Mon, 8 Apr 2024 05:37:41 +0200 Subject: [PATCH 03/16] Update src/parse/proto/extensions/simple_extension_declaration/extension_function.rs Co-authored-by: Matthijs Brobbel --- .../simple_extension_declaration/extension_function.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs index 998dfc7..e2ca3cd 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs @@ -5,7 +5,7 @@ use crate::{parse::{Anchor, Context, Parse}, proto}; pub struct ExtensionFunction { anchor: Anchor, name: String, - extension_uri_reference: Anchor, + extension_uri_reference: Anchor, } impl Parse for proto::extensions::simple_extension_declaration::ExtensionFunction { From 0d143a322dd76bd35e4dee0e424bc533d43028f0 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Mon, 8 Apr 2024 05:37:50 +0200 Subject: [PATCH 04/16] Update src/parse/proto/extensions/simple_extension_declaration/extension_function.rs Co-authored-by: Matthijs Brobbel --- .../simple_extension_declaration/extension_function.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs index e2ca3cd..1f3c5b4 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs @@ -4,7 +4,7 @@ use crate::{parse::{Anchor, Context, Parse}, proto}; #[derive(Clone, Debug, PartialEq)] pub struct ExtensionFunction { anchor: Anchor, - name: String, + name: Name, extension_uri_reference: Anchor, } From cfe8c77485eb10c03e02464a11008c61ba6094ff Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Mon, 8 Apr 2024 05:38:06 +0200 Subject: [PATCH 05/16] Update src/parse/proto/extensions/simple_extension_declaration/extension_type.rs Co-authored-by: Matthijs Brobbel --- .../extensions/simple_extension_declaration/extension_type.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs index ecc1f78..f060ed8 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs @@ -6,7 +6,7 @@ use super::simple_extension_declaration::SimpleExtensionDeclarationError; #[derive(Clone, Debug, PartialEq)] pub struct ExtensionType { anchor: Anchor, - name: String, + name: Name, extension_uri_reference: Anchor, } From 91d77244ccf082ce5ca0881a851ac695f535b023 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Mon, 8 Apr 2024 05:38:14 +0200 Subject: [PATCH 06/16] Update src/parse/proto/extensions/simple_extension_declaration/extension_type.rs Co-authored-by: Matthijs Brobbel --- .../extensions/simple_extension_declaration/extension_type.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs index f060ed8..5e57f2e 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs @@ -7,7 +7,7 @@ use super::simple_extension_declaration::SimpleExtensionDeclarationError; pub struct ExtensionType { anchor: Anchor, name: Name, - extension_uri_reference: Anchor, + extension_uri_reference: Anchor, } impl Parse for proto::extensions::simple_extension_declaration::ExtensionType { From c6e7e2c1dd45c6450656093d0b49eeba5f63c257 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Mon, 8 Apr 2024 05:38:22 +0200 Subject: [PATCH 07/16] Update src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs Co-authored-by: Matthijs Brobbel --- .../simple_extension_declaration/extension_type_variation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs index 98cbb77..aaaa196 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs @@ -7,7 +7,7 @@ use super::simple_extension_declaration::SimpleExtensionDeclarationError; pub struct ExtensionTypeVariation { anchor: Anchor, name: String, - extension_uri_reference: Anchor, + extension_uri_reference: Anchor, } impl Parse From 165568ccc1e105e55dc34973c8e030708de69c37 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Mon, 8 Apr 2024 05:38:28 +0200 Subject: [PATCH 08/16] Update src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs Co-authored-by: Matthijs Brobbel --- .../simple_extension_declaration/extension_type_variation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs index aaaa196..e642958 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs @@ -6,7 +6,7 @@ use super::simple_extension_declaration::SimpleExtensionDeclarationError; #[derive(Clone, Debug, PartialEq)] pub struct ExtensionTypeVariation { anchor: Anchor, - name: String, + name: Name, extension_uri_reference: Anchor, } From f05ea374335f6bb60492ee15ce1ae89ff8b83c52 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Mon, 8 Apr 2024 05:38:38 +0200 Subject: [PATCH 09/16] Update src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs Co-authored-by: Matthijs Brobbel --- .../extensions/simple_extension_declaration/mapping_type.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs b/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs index 74782be..1ad718f 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs @@ -33,17 +33,17 @@ impl From for proto::extensions::simple_extension_declaration::Mapp fn from(value: MappingType) -> Self { match value { MappingType::ExtensionFunction(inner) => { - proto::extensions::simple_extension_declaration::MappingType::ExtensionFunction( + Self::ExtensionFunction( inner.into(), ) } MappingType::ExtensionType(inner) => { - proto::extensions::simple_extension_declaration::MappingType::ExtensionType( + Self::ExtensionType( inner.into(), ) } MappingType::ExtensionTypeVariation(inner) => { - proto::extensions::simple_extension_declaration::MappingType::ExtensionTypeVariation( + Self::ExtensionTypeVariation( inner.into(), ) } From 204bc94c6cb035eccacf76bba2a243efd2e2d60a Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Mon, 8 Apr 2024 05:38:53 +0200 Subject: [PATCH 10/16] Update src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs Co-authored-by: Matthijs Brobbel --- .../simple_extension_declaration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs b/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs index b1bff78..06048d0 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs @@ -9,7 +9,7 @@ use super::mapping_type::MappingType; // SimpleExtensionDeclaration #[derive(Clone, Debug, PartialEq)] pub struct SimpleExtensionDeclaration { - pub mapping_type: Option, + mapping_type: MappingType, } #[derive(Debug, PartialEq, Error)] From dd1d7969aa90f065fadeff38964736f83f94d8f1 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Mon, 8 Apr 2024 05:38:59 +0200 Subject: [PATCH 11/16] Update src/parse/proto/extensions/simple_extension_declaration/mod.rs Co-authored-by: Matthijs Brobbel --- .../extensions/simple_extension_declaration/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/mod.rs b/src/parse/proto/extensions/simple_extension_declaration/mod.rs index 29f9ebc..31bbe37 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/mod.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/mod.rs @@ -1,5 +1,5 @@ -mod extension_function; -mod extension_type; -mod extension_type_variation; -mod mapping_type; -mod simple_extension_declaration; +pub mod extension_function; +pub mod extension_type; +pub mod extension_type_variation; +pub mod mapping_type; +pub mod simple_extension_declaration; From 4f56530553d1c8a73145924de883606220b05323 Mon Sep 17 00:00:00 2001 From: Cameron Date: Mon, 8 Apr 2024 06:21:18 +0200 Subject: [PATCH 12/16] Save work --- src/parse/context.rs | 30 +++++++++++++++++++ .../extension_function.rs | 10 +++++-- .../extension_type.rs | 5 +++- .../extension_type_variation.rs | 5 +++- .../mapping_type.rs | 16 ++-------- .../simple_extension_declaration.rs | 19 ++++++++---- 6 files changed, 63 insertions(+), 22 deletions(-) diff --git a/src/parse/context.rs b/src/parse/context.rs index fe3ff14..396557e 100644 --- a/src/parse/context.rs +++ b/src/parse/context.rs @@ -38,6 +38,36 @@ pub trait Context { &self, anchor: &Anchor, ) -> Result<&SimpleExtensions, ContextError>; + + /// Add a [ExtensionFunction] to this context. Must return an error for duplicate + /// anchors, when the URI is not supported or if the definition does not contain a matching function with the given name. + /// + /// This function must eagerly resolve and parse the simple extension, returning an + /// error if either fails. + fn add_extension_function( + &mut self, + extension_function: &ExtensionFunction, + ) -> Result<&SimpleExtensions, ContextError>; + + /// Add an [ExtensionType] to this context. Must return an error for duplicate + /// anchors, when the URI is not supported or if the definition does not contain a matching function with the given name. + /// + /// This function must eagerly resolve and parse the simple extension, returning an + /// error if either fails. + fn add_extension_type( + &mut self, + extension: &ExtensionType, + ) -> Result<&SimpleExtensions, ContextError>; + + /// Add a [ExtensionTypeVariation] to this context. Must return an error for duplicate + /// anchors, when the URI is not supported or if the definition does not contain a matching function with the given name. + /// + /// This function must eagerly resolve and parse the simple extension, returning an + /// error if either fails. + fn add_extension_type_variation( + &mut self, + extension_type_variation: &ExtensionTypeVariation, + ) -> Result<&SimpleExtensions, ContextError>; } /// Parse context errors. diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs index 1f3c5b4..12fb40b 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs @@ -1,5 +1,8 @@ use super::simple_extension_declaration::SimpleExtensionDeclarationError; -use crate::{parse::{Anchor, Context, Parse}, proto}; +use crate::{ + parse::{Anchor, Context, Parse}, + proto, +}; #[derive(Clone, Debug, PartialEq)] pub struct ExtensionFunction { @@ -19,13 +22,16 @@ impl Parse for proto::extensions::simple_extension_declaration::E name, } = self; - // Construct the parsed ExtensionFunction + // Construct the parsed ExtensionFunction. let extension_function = ExtensionFunction { extension_uri_reference: Anchor::new(extension_uri_reference), name, anchor: Anchor::new(function_anchor), }; + // Add the ExtensionFunction to the given context. + ctx.add_extension_function(&extension_function)?; + Ok(extension_function) } } diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs index 5e57f2e..5b0da08 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs @@ -21,13 +21,16 @@ impl Parse for proto::extensions::simple_extension_declaration::E name, } = self; - // Construct the parsed ExtensionType + // Construct the parsed ExtensionType. let extension_type_variation = ExtensionType { extension_uri_reference: Anchor::new(extension_uri_reference), name, anchor: Anchor::new(type_anchor), }; + // Add the ExtensionType to the given context. + ctx.add_extension_type(); + Ok(extension_type_variation) } } diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs index e642958..4c4e29a 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs @@ -23,13 +23,16 @@ impl Parse name, } = self; - // Construct the parsed ExtensionTypeVariation + // Construct the parsed ExtensionTypeVariation. let extension_type_variation = ExtensionTypeVariation { extension_uri_reference: Anchor::new(extension_uri_reference), name, anchor: Anchor::new(type_variation_anchor), }; + // Add the ExtensionTypeVariation to the given context. + ctx.add_extension_type_variation(&extension_type_variation)?; + Ok(extension_type_variation) } } diff --git a/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs b/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs index 1ad718f..c1cade7 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs @@ -32,20 +32,10 @@ impl Parse for proto::extensions::simple_extension_declaration::M impl From for proto::extensions::simple_extension_declaration::MappingType { fn from(value: MappingType) -> Self { match value { - MappingType::ExtensionFunction(inner) => { - Self::ExtensionFunction( - inner.into(), - ) - } - MappingType::ExtensionType(inner) => { - Self::ExtensionType( - inner.into(), - ) - } + MappingType::ExtensionFunction(inner) => Self::ExtensionFunction(inner.into()), + MappingType::ExtensionType(inner) => Self::ExtensionType(inner.into()), MappingType::ExtensionTypeVariation(inner) => { - Self::ExtensionTypeVariation( - inner.into(), - ) + Self::ExtensionTypeVariation(inner.into()) } } } diff --git a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs b/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs index 06048d0..cc4971e 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs @@ -9,11 +9,18 @@ use super::mapping_type::MappingType; // SimpleExtensionDeclaration #[derive(Clone, Debug, PartialEq)] pub struct SimpleExtensionDeclaration { - mapping_type: MappingType, + pub mapping_type: Option, } #[derive(Debug, PartialEq, Error)] -pub enum SimpleExtensionDeclarationError {} +pub enum SimpleExtensionDeclarationError { + #[error("No Mapping Type specified on Extension Declaration.")] + MissingMappingType, + + /// Context error + #[error(transparent)] + Context(#[from] ContextError), +} impl Parse for proto::extensions::SimpleExtensionDeclaration { type Parsed = SimpleExtensionDeclaration; @@ -23,9 +30,11 @@ impl Parse for proto::extensions::SimpleExtensionDeclaration { let proto::extensions::SimpleExtensionDeclaration { mapping_type } = self; Ok(SimpleExtensionDeclaration { - mapping_type: mapping_type - .map(|mapping_type| mapping_type.parse(ctx).ok()) - .flatten(), + mapping_type: Some( + mapping_type + .ok_or(SimpleExtensionDeclarationError::MissingMappingType)? + .parse(ctx)?, + ), }) } } From b424a1eca9d15d275bbecede5290a49635637c43 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Thu, 2 May 2024 12:28:33 +0200 Subject: [PATCH 13/16] Update src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs Co-authored-by: Matthijs Brobbel --- .../simple_extension_declaration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs b/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs index cc4971e..40d5eb7 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs @@ -44,7 +44,7 @@ impl From for proto::extensions::SimpleExtensionDecl let SimpleExtensionDeclaration { mapping_type } = declaration; proto::extensions::SimpleExtensionDeclaration { - mapping_type: mapping_type.map(|mapping_type| mapping_type.into()), + mapping_type: Some(mapping_type.into()), } } } From 00aa50d18532457196cbdb77ced3a3bc3eeef904 Mon Sep 17 00:00:00 2001 From: Cameron Harris Date: Thu, 2 May 2024 12:28:42 +0200 Subject: [PATCH 14/16] Update src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs Co-authored-by: Matthijs Brobbel --- .../simple_extension_declaration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs b/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs index 40d5eb7..cbed561 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs @@ -9,7 +9,7 @@ use super::mapping_type::MappingType; // SimpleExtensionDeclaration #[derive(Clone, Debug, PartialEq)] pub struct SimpleExtensionDeclaration { - pub mapping_type: Option, + pub mapping_type: MappingType, } #[derive(Debug, PartialEq, Error)] From fcc9797fb3989c96e61d549c59eff349d44d6f69 Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 2 May 2024 15:22:06 +0200 Subject: [PATCH 15/16] Save work --- src/parse/context.rs | 27 ++++++++++++++++++- src/parse/proto/extensions/mod.rs | 5 ++++ ...xtension_declaration.rs => declaration.rs} | 13 +++++---- .../extension_function.rs | 14 ++++++---- .../extension_type.rs | 20 +++++++++----- .../extension_type_variation.rs | 14 +++++++--- .../mapping_type.rs | 9 ++++--- .../simple_extension_declaration/mod.rs | 2 +- src/parse/typed.rs | 3 +++ 9 files changed, 79 insertions(+), 28 deletions(-) rename src/parse/proto/extensions/simple_extension_declaration/{simple_extension_declaration.rs => declaration.rs} (79%) diff --git a/src/parse/context.rs b/src/parse/context.rs index 396557e..508e3ab 100644 --- a/src/parse/context.rs +++ b/src/parse/context.rs @@ -5,7 +5,11 @@ use thiserror::Error; use crate::parse::{ - proto::extensions::SimpleExtensionUri, text::simple_extensions::SimpleExtensions, Anchor, Parse, + proto::extensions::{ + ExtensionFunction, ExtensionType, ExtensionTypeVariation, SimpleExtensionUri, + }, + text::simple_extensions::SimpleExtensions, + Anchor, Parse, }; /// A parse context. @@ -148,5 +152,26 @@ pub(crate) mod tests { .then_some(&self.empty_simple_extensions) .ok_or(ContextError::UndefinedSimpleExtension(*anchor)) } + + fn add_extension_function( + &mut self, + _extension_function: &crate::parse::proto::extensions::ExtensionFunction, + ) -> Result<&SimpleExtensions, ContextError> { + todo!() + } + + fn add_extension_type( + &mut self, + _extension: &crate::parse::proto::extensions::ExtensionType, + ) -> Result<&SimpleExtensions, ContextError> { + todo!() + } + + fn add_extension_type_variation( + &mut self, + _extension_type_variation: &crate::parse::proto::extensions::ExtensionTypeVariation, + ) -> Result<&SimpleExtensions, ContextError> { + todo!() + } } } diff --git a/src/parse/proto/extensions/mod.rs b/src/parse/proto/extensions/mod.rs index 2e77959..baca22e 100644 --- a/src/parse/proto/extensions/mod.rs +++ b/src/parse/proto/extensions/mod.rs @@ -5,4 +5,9 @@ mod simple_extension_declaration; mod simple_extension_uri; +pub use simple_extension_declaration::declaration::SimpleExtensionDeclaration; +pub use simple_extension_declaration::extension_function::ExtensionFunction; +pub use simple_extension_declaration::extension_type::ExtensionType; +pub use simple_extension_declaration::extension_type_variation::ExtensionTypeVariation; +pub use simple_extension_declaration::mapping_type::MappingType; pub use simple_extension_uri::SimpleExtensionUri; diff --git a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs b/src/parse/proto/extensions/simple_extension_declaration/declaration.rs similarity index 79% rename from src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs rename to src/parse/proto/extensions/simple_extension_declaration/declaration.rs index cbed561..0946f92 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/simple_extension_declaration.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/declaration.rs @@ -1,14 +1,15 @@ use crate::{ - parse::{Context, Parse}, + parse::{context::ContextError, Context, Parse}, proto, }; use thiserror::Error; use super::mapping_type::MappingType; -// SimpleExtensionDeclaration +/// A parsed [`SimpleExtensionDeclaration`]. #[derive(Clone, Debug, PartialEq)] pub struct SimpleExtensionDeclaration { + /// The underlying mapping type of this extension declaration pub mapping_type: MappingType, } @@ -30,11 +31,9 @@ impl Parse for proto::extensions::SimpleExtensionDeclaration { let proto::extensions::SimpleExtensionDeclaration { mapping_type } = self; Ok(SimpleExtensionDeclaration { - mapping_type: Some( - mapping_type - .ok_or(SimpleExtensionDeclarationError::MissingMappingType)? - .parse(ctx)?, - ), + mapping_type: mapping_type + .ok_or(SimpleExtensionDeclarationError::MissingMappingType)? + .parse(ctx)?, }) } } diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs index 12fb40b..25cfcbb 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs @@ -1,13 +1,17 @@ -use super::simple_extension_declaration::SimpleExtensionDeclarationError; +use super::declaration::SimpleExtensionDeclarationError; use crate::{ - parse::{Anchor, Context, Parse}, + parse::{proto::extensions::SimpleExtensionUri, typed::Name, Anchor, Context, Parse}, proto, }; +/// A parsed [`ExtensionFunction`] #[derive(Clone, Debug, PartialEq)] pub struct ExtensionFunction { + /// The parsed [`Anchor`] for this [`ExtensionFunction`] anchor: Anchor, + /// The parsed [`Name`] for this [`ExtensionFunction`] name: Name, + /// The parsed [`SimpleExtensionUri`] for this [`ExtensionFunction`] extension_uri_reference: Anchor, } @@ -15,7 +19,7 @@ impl Parse for proto::extensions::simple_extension_declaration::E type Parsed = ExtensionFunction; type Error = SimpleExtensionDeclarationError; - fn parse(self, _ctx: &mut C) -> Result { + fn parse(self, ctx: &mut C) -> Result { let proto::extensions::simple_extension_declaration::ExtensionFunction { extension_uri_reference, function_anchor, @@ -25,7 +29,7 @@ impl Parse for proto::extensions::simple_extension_declaration::E // Construct the parsed ExtensionFunction. let extension_function = ExtensionFunction { extension_uri_reference: Anchor::new(extension_uri_reference), - name, + name: Name::new(name), anchor: Anchor::new(function_anchor), }; @@ -49,7 +53,7 @@ impl From Self { extension_uri_reference: extension_uri_reference.into_inner(), function_anchor: anchor.into_inner(), - name: name, + name: name.into_inner(), } } } diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs index 5b0da08..9b3660e 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs @@ -1,12 +1,18 @@ +use crate::parse::proto::extensions::SimpleExtensionUri; +use crate::parse::typed::Name; use crate::parse::{Anchor, Context, Parse}; use crate::proto; -use super::simple_extension_declaration::SimpleExtensionDeclarationError; +use super::declaration::SimpleExtensionDeclarationError; +/// A parsed [`ExtensionType`] #[derive(Clone, Debug, PartialEq)] pub struct ExtensionType { + /// The parsed [`Anchor`] for this [`ExtensionType`] anchor: Anchor, + /// The parsed [`Name`] for this [`ExtensionType`] name: Name, + /// The parsed [`SimpleExtensionUri`] for this [`ExtensionType`] extension_uri_reference: Anchor, } @@ -14,7 +20,7 @@ impl Parse for proto::extensions::simple_extension_declaration::E type Parsed = ExtensionType; type Error = SimpleExtensionDeclarationError; - fn parse(self, _ctx: &mut C) -> Result { + fn parse(self, ctx: &mut C) -> Result { let proto::extensions::simple_extension_declaration::ExtensionType { extension_uri_reference, type_anchor, @@ -22,16 +28,16 @@ impl Parse for proto::extensions::simple_extension_declaration::E } = self; // Construct the parsed ExtensionType. - let extension_type_variation = ExtensionType { + let extension_type = ExtensionType { extension_uri_reference: Anchor::new(extension_uri_reference), - name, + name: Name::new(name), anchor: Anchor::new(type_anchor), }; // Add the ExtensionType to the given context. - ctx.add_extension_type(); + ctx.add_extension_type(&extension_type)?; - Ok(extension_type_variation) + Ok(extension_type) } } @@ -46,7 +52,7 @@ impl From for proto::extensions::simple_extension_declaration::Ex Self { extension_uri_reference: extension_uri_reference.into_inner(), type_anchor: anchor.into_inner(), - name: name, + name: name.into_inner(), } } } diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs index 4c4e29a..c4bd2de 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs @@ -1,12 +1,18 @@ +use crate::parse::proto::extensions::SimpleExtensionUri; +use crate::parse::typed::Name; use crate::parse::{Anchor, Context, Parse}; use crate::proto; -use super::simple_extension_declaration::SimpleExtensionDeclarationError; +use super::declaration::SimpleExtensionDeclarationError; +/// A parsed [`ExtensionTypeVariation`] #[derive(Clone, Debug, PartialEq)] pub struct ExtensionTypeVariation { + /// The parsed [`Anchor`] for this [`ExtensionTypeVariation`] anchor: Anchor, + /// The parsed [`Name`] for this [`ExtensionTypeVariation`] name: Name, + /// The parsed [`SimpleExtensionUri`] for this [`ExtensionTypeVariation`] extension_uri_reference: Anchor, } @@ -16,7 +22,7 @@ impl Parse type Parsed = ExtensionTypeVariation; type Error = SimpleExtensionDeclarationError; - fn parse(self, _ctx: &mut C) -> Result { + fn parse(self, ctx: &mut C) -> Result { let proto::extensions::simple_extension_declaration::ExtensionTypeVariation { extension_uri_reference, type_variation_anchor, @@ -26,7 +32,7 @@ impl Parse // Construct the parsed ExtensionTypeVariation. let extension_type_variation = ExtensionTypeVariation { extension_uri_reference: Anchor::new(extension_uri_reference), - name, + name: Name::new(name), anchor: Anchor::new(type_variation_anchor), }; @@ -50,7 +56,7 @@ impl From Self { extension_uri_reference: extension_uri_reference.into_inner(), type_variation_anchor: anchor.into_inner(), - name: name, + name: name.into_inner(), } } } diff --git a/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs b/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs index c1cade7..ed835a7 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs @@ -4,15 +4,18 @@ use crate::{ }; use super::{ - extension_function, extension_type, extension_type_variation, - simple_extension_declaration::SimpleExtensionDeclarationError, + declaration::SimpleExtensionDeclarationError, extension_function, extension_type, + extension_type_variation, }; -/// MappingType +/// A parse [`MappingType`] #[derive(Clone, Debug, PartialEq)] pub enum MappingType { + /// A parsed [`ExtensionType`] ExtensionType(extension_type::ExtensionType), + /// A parsed [`ExtensionTypeVariation`] ExtensionTypeVariation(extension_type_variation::ExtensionTypeVariation), + /// A parsed [`ExtensionFunction`] ExtensionFunction(extension_function::ExtensionFunction), } diff --git a/src/parse/proto/extensions/simple_extension_declaration/mod.rs b/src/parse/proto/extensions/simple_extension_declaration/mod.rs index 31bbe37..8a42f9b 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/mod.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/mod.rs @@ -1,5 +1,5 @@ +pub mod declaration; pub mod extension_function; pub mod extension_type; pub mod extension_type_variation; pub mod mapping_type; -pub mod simple_extension_declaration; diff --git a/src/parse/typed.rs b/src/parse/typed.rs index 991e7b5..a3a59c3 100644 --- a/src/parse/typed.rs +++ b/src/parse/typed.rs @@ -79,3 +79,6 @@ impl hash::Hash for Typed { /// A generic anchor new type for the anchor mechanism used in Substrait data. pub type Anchor = Typed; + +/// A generic Name type for the named things inside of Substrait. +pub type Name = Typed; From 013b50c64422f1b7e2779ee9584478b554baf7ae Mon Sep 17 00:00:00 2001 From: Cameron Date: Sun, 5 May 2024 16:27:29 +0200 Subject: [PATCH 16/16] Last bits of tests --- src/parse/context.rs | 91 +++++++++---- .../declaration.rs | 52 ++++++++ .../extension_function.rs | 91 ++++++++++++- .../extension_type.rs | 89 ++++++++++++- .../extension_type_variation.rs | 94 ++++++++++++- .../mapping_type.rs | 123 ++++++++++++++++++ 6 files changed, 509 insertions(+), 31 deletions(-) diff --git a/src/parse/context.rs b/src/parse/context.rs index 508e3ab..a717d8d 100644 --- a/src/parse/context.rs +++ b/src/parse/context.rs @@ -5,13 +5,11 @@ use thiserror::Error; use crate::parse::{ - proto::extensions::{ - ExtensionFunction, ExtensionType, ExtensionTypeVariation, SimpleExtensionUri, - }, - text::simple_extensions::SimpleExtensions, - Anchor, Parse, + proto::extensions::SimpleExtensionUri, text::simple_extensions::SimpleExtensions, Anchor, Parse, }; +use super::proto::extensions::{ExtensionFunction, ExtensionType, ExtensionTypeVariation}; + /// A parse context. /// /// Parsing Substrait data is context-sensitive. This trait provides methods @@ -51,17 +49,14 @@ pub trait Context { fn add_extension_function( &mut self, extension_function: &ExtensionFunction, - ) -> Result<&SimpleExtensions, ContextError>; + ) -> Result<(), ContextError>; /// Add an [ExtensionType] to this context. Must return an error for duplicate /// anchors, when the URI is not supported or if the definition does not contain a matching function with the given name. /// /// This function must eagerly resolve and parse the simple extension, returning an /// error if either fails. - fn add_extension_type( - &mut self, - extension: &ExtensionType, - ) -> Result<&SimpleExtensions, ContextError>; + fn add_extension_type(&mut self, extension: &ExtensionType) -> Result<(), ContextError>; /// Add a [ExtensionTypeVariation] to this context. Must return an error for duplicate /// anchors, when the URI is not supported or if the definition does not contain a matching function with the given name. @@ -71,7 +66,7 @@ pub trait Context { fn add_extension_type_variation( &mut self, extension_type_variation: &ExtensionTypeVariation, - ) -> Result<&SimpleExtensions, ContextError>; + ) -> Result<(), ContextError>; } /// Parse context errors. @@ -85,6 +80,18 @@ pub enum ContextError { #[error("duplicate anchor `{0}` for simple extension")] DuplicateSimpleExtension(Anchor), + /// Duplicate anchor for [ExtensionType]. + #[error("duplicate anchor `{0}` for extension_type")] + DuplicateExtensionType(Anchor), + + /// Duplicate anchor for [ExtensionFunction]. + #[error("duplicate anchor `{0}` for extension_function")] + DuplicateExtensionFunction(Anchor), + + /// Duplicate anchor for [ExtensionTypeVariation]. + #[error("duplicate anchor `{0}` for extension_type_variation")] + DuplicateExtensionTypeVariation(Anchor), + /// Unsupported simple extension URI. #[error("unsupported simple extension URI: {0}")] UnsupportedURI(String), @@ -95,8 +102,12 @@ pub(crate) mod tests { use std::collections::{hash_map::Entry, HashMap}; use crate::parse::{ - context::ContextError, proto::extensions::SimpleExtensionUri, - text::simple_extensions::SimpleExtensions, Anchor, + context::ContextError, + proto::extensions::{ + ExtensionFunction, ExtensionType, ExtensionTypeVariation, SimpleExtensionUri, + }, + text::simple_extensions::SimpleExtensions, + Anchor, }; /// A test context. @@ -106,6 +117,9 @@ pub(crate) mod tests { pub struct Context { empty_simple_extensions: SimpleExtensions, simple_extensions: HashMap, SimpleExtensionUri>, + extension_types: HashMap, ExtensionType>, + extension_functions: HashMap, ExtensionFunction>, + extension_type_variations: HashMap, ExtensionTypeVariation>, } impl Default for Context { @@ -113,6 +127,9 @@ pub(crate) mod tests { Self { empty_simple_extensions: SimpleExtensions {}, simple_extensions: Default::default(), + extension_types: Default::default(), + extension_functions: Default::default(), + extension_type_variations: Default::default(), } } } @@ -155,23 +172,53 @@ pub(crate) mod tests { fn add_extension_function( &mut self, - _extension_function: &crate::parse::proto::extensions::ExtensionFunction, - ) -> Result<&SimpleExtensions, ContextError> { - todo!() + extension_function: &crate::parse::proto::extensions::ExtensionFunction, + ) -> Result<(), ContextError> { + match self.extension_functions.entry(extension_function.anchor()) { + Entry::Occupied(_) => Err(ContextError::DuplicateExtensionFunction( + extension_function.anchor(), + )), + Entry::Vacant(entry) => { + entry.insert(extension_function.clone()); + + Ok(()) + } + } } fn add_extension_type( &mut self, - _extension: &crate::parse::proto::extensions::ExtensionType, - ) -> Result<&SimpleExtensions, ContextError> { - todo!() + extension_type: &crate::parse::proto::extensions::ExtensionType, + ) -> Result<(), ContextError> { + match self.extension_types.entry(extension_type.anchor()) { + Entry::Occupied(_) => Err(ContextError::DuplicateExtensionType( + extension_type.anchor(), + )), + Entry::Vacant(entry) => { + entry.insert(extension_type.clone()); + + Ok(()) + } + } } fn add_extension_type_variation( &mut self, - _extension_type_variation: &crate::parse::proto::extensions::ExtensionTypeVariation, - ) -> Result<&SimpleExtensions, ContextError> { - todo!() + extension_type_variation: &crate::parse::proto::extensions::ExtensionTypeVariation, + ) -> Result<(), ContextError> { + match self + .extension_type_variations + .entry(extension_type_variation.anchor()) + { + Entry::Occupied(_) => Err(ContextError::DuplicateExtensionTypeVariation( + extension_type_variation.anchor(), + )), + Entry::Vacant(entry) => { + entry.insert(extension_type_variation.clone()); + + Ok(()) + } + } } } } diff --git a/src/parse/proto/extensions/simple_extension_declaration/declaration.rs b/src/parse/proto/extensions/simple_extension_declaration/declaration.rs index 0946f92..99bcbce 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/declaration.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/declaration.rs @@ -47,3 +47,55 @@ impl From for proto::extensions::SimpleExtensionDecl } } } + +#[cfg(test)] +mod test { + + use super::*; + use crate::parse::{ + context::tests::Context, proto::extensions::ExtensionFunction, typed::Name, Anchor, + }; + + #[test] + fn parse_from_protobuf() -> Result<(), SimpleExtensionDeclarationError> { + let declaration = proto::extensions::SimpleExtensionDeclaration { + mapping_type: Some( + proto::extensions::simple_extension_declaration::MappingType::ExtensionFunction( + proto::extensions::simple_extension_declaration::ExtensionFunction { + extension_uri_reference: 1, + function_anchor: 1, + name: "test_name".to_string(), + }, + ), + ), + }; + let simple_extension = declaration.parse(&mut Context::default())?; + + assert!(matches!( + simple_extension.mapping_type, + MappingType::ExtensionFunction(_) + )); + + Ok(()) + } + + #[test] + fn convert_from_parsed() { + let declaration = SimpleExtensionDeclaration { + mapping_type: MappingType::ExtensionFunction(ExtensionFunction { + anchor: Anchor::new(1), + name: Name::new("test".to_string()), + extension_uri_reference: Anchor::new(1), + }), + }; + + let protobuf_declaration = proto::extensions::SimpleExtensionDeclaration::from(declaration); + + assert!(matches!( + protobuf_declaration + .mapping_type + .expect("No mapping_type returned from declaration conversion."), + proto::extensions::simple_extension_declaration::MappingType::ExtensionFunction(_) + )); + } +} diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs index 25cfcbb..973bea8 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_function.rs @@ -8,11 +8,34 @@ use crate::{ #[derive(Clone, Debug, PartialEq)] pub struct ExtensionFunction { /// The parsed [`Anchor`] for this [`ExtensionFunction`] - anchor: Anchor, + pub(crate) anchor: Anchor, /// The parsed [`Name`] for this [`ExtensionFunction`] - name: Name, + pub(crate) name: Name, /// The parsed [`SimpleExtensionUri`] for this [`ExtensionFunction`] - extension_uri_reference: Anchor, + pub(crate) extension_uri_reference: Anchor, +} + +impl ExtensionFunction { + /// Returns the name of this [ExtensionType] + /// + /// See [proto::extensions::simple_extension_declaration::ExtensionType::name]. + pub fn name(&self) -> &Name { + &self.name + } + + /// Returns the anchor value of this [ExtensionType]. + /// + /// See [proto::extensions::simple_extension_declaration::ExtensionType]. + pub fn anchor(&self) -> Anchor { + self.anchor + } + + /// Returns the Extension URI Reference of this [ExtensionType]. + /// + /// See [proto::extensions::simple_extension_declaration::ExtensionType::extension_uri_reference]. + pub fn uri(&self) -> Anchor { + self.extension_uri_reference + } } impl Parse for proto::extensions::simple_extension_declaration::ExtensionFunction { @@ -57,3 +80,65 @@ impl From } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::parse::{ + context::{tests::Context, ContextError}, + Context as _, + }; + + #[test] + fn parse_extension_function() -> Result<(), SimpleExtensionDeclarationError> { + let extension_type = proto::extensions::simple_extension_declaration::ExtensionFunction { + function_anchor: 1, + extension_uri_reference: 2, + name: "test_extension_function".to_string(), + }; + let extension_type: ExtensionFunction = extension_type.parse(&mut Context::default())?; + assert_eq!(extension_type.anchor(), Anchor::new(1)); + assert_eq!( + extension_type.name(), + &Name::new("test_extension_function".to_string()) + ); + assert_eq!(extension_type.uri(), Anchor::new(2)); + assert_eq!(extension_type.extension_uri_reference, Anchor::new(2)); + Ok(()) + } + + #[test] + fn duplicate_simple_extension_function() { + let mut ctx = Context::default(); + let extension_type = proto::extensions::simple_extension_declaration::ExtensionFunction { + extension_uri_reference: 1, + function_anchor: 2, + name: "test_extension_function".to_string(), + }; + assert!(ctx.parse(extension_type.clone()).is_ok()); + assert_eq!( + ctx.parse(extension_type.clone()), + Err(SimpleExtensionDeclarationError::Context( + ContextError::DuplicateExtensionFunction(Anchor::new(2)) + )) + ); + } + + #[test] + fn can_get_protobuf_from_struct() { + let extension_type = ExtensionFunction { + extension_uri_reference: Anchor::new(1), + anchor: Anchor::new(1), + name: Name::new("test_extension_function".to_string()), + }; + + let protobuf_extension_function = + proto::extensions::simple_extension_declaration::ExtensionFunction::from( + extension_type, + ); + + assert_eq!(protobuf_extension_function.extension_uri_reference, 1); + assert_eq!(protobuf_extension_function.function_anchor, 1); + assert_eq!(protobuf_extension_function.name, "test_extension_function"); + } +} diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs index 9b3660e..8f8eb78 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type.rs @@ -9,11 +9,34 @@ use super::declaration::SimpleExtensionDeclarationError; #[derive(Clone, Debug, PartialEq)] pub struct ExtensionType { /// The parsed [`Anchor`] for this [`ExtensionType`] - anchor: Anchor, + pub(crate) anchor: Anchor, /// The parsed [`Name`] for this [`ExtensionType`] - name: Name, + pub(crate) name: Name, /// The parsed [`SimpleExtensionUri`] for this [`ExtensionType`] - extension_uri_reference: Anchor, + pub(crate) extension_uri_reference: Anchor, +} + +impl ExtensionType { + /// Returns the name of this [ExtensionType] + /// + /// See [proto::extensions::simple_extension_declaration::ExtensionType::name]. + pub fn name(&self) -> &Name { + &self.name + } + + /// Returns the anchor value of this [ExtensionType]. + /// + /// See [proto::extensions::simple_extension_declaration::ExtensionType]. + pub fn anchor(&self) -> Anchor { + self.anchor + } + + /// Returns the Extension URI Reference of this [ExtensionType]. + /// + /// See [proto::extensions::simple_extension_declaration::ExtensionType::extension_uri_reference]. + pub fn uri(&self) -> Anchor { + self.extension_uri_reference + } } impl Parse for proto::extensions::simple_extension_declaration::ExtensionType { @@ -56,3 +79,63 @@ impl From for proto::extensions::simple_extension_declaration::Ex } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::parse::{ + context::{tests::Context, ContextError}, + Context as _, + }; + + #[test] + fn parse_extension_type() -> Result<(), SimpleExtensionDeclarationError> { + let extension_type = proto::extensions::simple_extension_declaration::ExtensionType { + type_anchor: 1, + extension_uri_reference: 2, + name: "test_extension_type".to_string(), + }; + let extension_type: ExtensionType = extension_type.parse(&mut Context::default())?; + assert_eq!(extension_type.anchor(), Anchor::new(1)); + assert_eq!( + extension_type.name(), + &Name::new("test_extension_type".to_string()) + ); + assert_eq!(extension_type.uri(), Anchor::new(2)); + assert_eq!(extension_type.extension_uri_reference, Anchor::new(2)); + Ok(()) + } + + #[test] + fn duplicate_simple_extension() { + let mut ctx = Context::default(); + let extension_type = proto::extensions::simple_extension_declaration::ExtensionType { + extension_uri_reference: 1, + type_anchor: 2, + name: "test_extension_type".to_string(), + }; + assert!(ctx.parse(extension_type.clone()).is_ok()); + assert_eq!( + ctx.parse(extension_type.clone()), + Err(SimpleExtensionDeclarationError::Context( + ContextError::DuplicateExtensionType(Anchor::new(2)) + )) + ); + } + + #[test] + fn can_get_protobuf_from_struct() { + let extension_type = ExtensionType { + extension_uri_reference: Anchor::new(1), + anchor: Anchor::new(1), + name: Name::new("test_extension_type".to_string()), + }; + + let protobuf_extension_type = + proto::extensions::simple_extension_declaration::ExtensionType::from(extension_type); + + assert_eq!(protobuf_extension_type.extension_uri_reference, 1); + assert_eq!(protobuf_extension_type.type_anchor, 1); + assert_eq!(protobuf_extension_type.name, "test_extension_type"); + } +} diff --git a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs index c4bd2de..b3078f8 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/extension_type_variation.rs @@ -9,11 +9,34 @@ use super::declaration::SimpleExtensionDeclarationError; #[derive(Clone, Debug, PartialEq)] pub struct ExtensionTypeVariation { /// The parsed [`Anchor`] for this [`ExtensionTypeVariation`] - anchor: Anchor, + pub(crate) anchor: Anchor, /// The parsed [`Name`] for this [`ExtensionTypeVariation`] - name: Name, + pub(crate) name: Name, /// The parsed [`SimpleExtensionUri`] for this [`ExtensionTypeVariation`] - extension_uri_reference: Anchor, + pub(crate) extension_uri_reference: Anchor, +} + +impl ExtensionTypeVariation { + /// Returns the name of this [ExtensionType] + /// + /// See [proto::extensions::simple_extension_declaration::ExtensionType::name]. + pub fn name(&self) -> &Name { + &self.name + } + + /// Returns the anchor value of this [ExtensionType]. + /// + /// See [proto::extensions::simple_extension_declaration::ExtensionType]. + pub fn anchor(&self) -> Anchor { + self.anchor + } + + /// Returns the Extension URI Reference of this [ExtensionType]. + /// + /// See [proto::extensions::simple_extension_declaration::ExtensionType::extension_uri_reference]. + pub fn uri(&self) -> Anchor { + self.extension_uri_reference + } } impl Parse @@ -60,3 +83,68 @@ impl From } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::parse::{ + context::{tests::Context, ContextError}, + Context as _, + }; + + #[test] + fn parse_extension_type_variation() -> Result<(), SimpleExtensionDeclarationError> { + let extension_type = + proto::extensions::simple_extension_declaration::ExtensionTypeVariation { + type_variation_anchor: 1, + extension_uri_reference: 2, + name: "test_extension_variation".to_string(), + }; + let extension_type: ExtensionTypeVariation = + extension_type.parse(&mut Context::default())?; + assert_eq!(extension_type.anchor(), Anchor::new(1)); + assert_eq!( + extension_type.name(), + &Name::new("test_extension_variation".to_string()) + ); + assert_eq!(extension_type.uri(), Anchor::new(2)); + assert_eq!(extension_type.extension_uri_reference, Anchor::new(2)); + Ok(()) + } + + #[test] + fn duplicate_simple_extension_variation() { + let mut ctx = Context::default(); + let extension_type = + proto::extensions::simple_extension_declaration::ExtensionTypeVariation { + extension_uri_reference: 1, + type_variation_anchor: 2, + name: "test_extension_var".to_string(), + }; + assert!(ctx.parse(extension_type.clone()).is_ok()); + assert_eq!( + ctx.parse(extension_type.clone()), + Err(SimpleExtensionDeclarationError::Context( + ContextError::DuplicateExtensionTypeVariation(Anchor::new(2)) + )) + ); + } + + #[test] + fn can_get_protobuf_from_struct() { + let extension_type = ExtensionTypeVariation { + extension_uri_reference: Anchor::new(1), + anchor: Anchor::new(1), + name: Name::new("test_extension_var".to_string()), + }; + + let protobuf_extension_type_variation = + proto::extensions::simple_extension_declaration::ExtensionTypeVariation::from( + extension_type, + ); + + assert_eq!(protobuf_extension_type_variation.extension_uri_reference, 1); + assert_eq!(protobuf_extension_type_variation.type_variation_anchor, 1); + assert_eq!(protobuf_extension_type_variation.name, "test_extension_var"); + } +} diff --git a/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs b/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs index ed835a7..894d24c 100644 --- a/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs +++ b/src/parse/proto/extensions/simple_extension_declaration/mapping_type.rs @@ -43,3 +43,126 @@ impl From for proto::extensions::simple_extension_declaration::Mapp } } } + +#[cfg(test)] +mod tests { + + use super::*; + use crate::parse::{ + context::tests::Context, + proto::extensions::{ExtensionFunction, ExtensionType, ExtensionTypeVariation}, + typed::Name, + Anchor, + }; + + #[test] + fn parse_extension_function_mapping_type() -> Result<(), SimpleExtensionDeclarationError> { + let exntesion_function = + proto::extensions::simple_extension_declaration::MappingType::ExtensionFunction( + proto::extensions::simple_extension_declaration::ExtensionFunction { + function_anchor: 1, + extension_uri_reference: 2, + name: "test_value".to_string(), + }, + ); + + assert!(matches!( + exntesion_function.parse(&mut Context::default())?, + MappingType::ExtensionFunction(_) + )); + + Ok(()) + } + + #[test] + fn parse_extension_type_mapping_type() -> Result<(), SimpleExtensionDeclarationError> { + let extension_type = + proto::extensions::simple_extension_declaration::MappingType::ExtensionType( + proto::extensions::simple_extension_declaration::ExtensionType { + type_anchor: 1, + extension_uri_reference: 2, + name: "test_value".to_string(), + }, + ); + + assert!(matches!( + extension_type.parse(&mut Context::default())?, + MappingType::ExtensionType(_) + )); + + Ok(()) + } + + #[test] + fn parse_extension_variation_mapping_type() -> Result<(), SimpleExtensionDeclarationError> { + let extension_type_variation = + proto::extensions::simple_extension_declaration::MappingType::ExtensionTypeVariation( + proto::extensions::simple_extension_declaration::ExtensionTypeVariation { + type_variation_anchor: 1, + extension_uri_reference: 2, + name: "test_value".to_string(), + }, + ); + + assert!(matches!( + extension_type_variation.parse(&mut Context::default())?, + MappingType::ExtensionTypeVariation(_) + )); + + Ok(()) + } + + #[test] + fn can_convert_extension_function_mapping_type_from_protobuf() { + let extension_function = MappingType::ExtensionFunction(ExtensionFunction { + extension_uri_reference: Anchor::new(1), + anchor: Anchor::new(1), + name: Name::new("test".to_string()), + }); + + let protobuf_extension_function = + proto::extensions::simple_extension_declaration::MappingType::from(extension_function); + + assert!(matches!( + protobuf_extension_function, + proto::extensions::simple_extension_declaration::MappingType::ExtensionFunction(_) + )); + } + + #[test] + fn can_convert_extension_type_mapping_type_from_protobuf() { + let extension_type = MappingType::ExtensionType(ExtensionType { + extension_uri_reference: Anchor::new(1), + anchor: Anchor::new(1), + name: Name::new("test".to_string()), + }); + + let protobuf_extension = + proto::extensions::simple_extension_declaration::MappingType::from(extension_type); + + assert!(matches!( + protobuf_extension, + proto::extensions::simple_extension_declaration::MappingType::ExtensionType(_) + )); + } + + #[test] + fn can_convert_extension_type_variation_mapping_type_from_protobuf() { + let extension_type_variation = + MappingType::ExtensionTypeVariation(ExtensionTypeVariation { + extension_uri_reference: Anchor::new(1), + anchor: Anchor::new(1), + name: Name::new("test".to_string()), + }); + + let protobuf_extension_type_variation = + proto::extensions::simple_extension_declaration::MappingType::from( + extension_type_variation, + ); + + assert!(matches!( + protobuf_extension_type_variation, + proto::extensions::simple_extension_declaration::MappingType::ExtensionTypeVariation(_) + )); + } +}