diff --git a/openzl-crypto/src/encryption/hybrid.rs b/openzl-crypto/src/encryption/hybrid.rs index ae94244a..669bf42a 100644 --- a/openzl-crypto/src/encryption/hybrid.rs +++ b/openzl-crypto/src/encryption/hybrid.rs @@ -359,6 +359,17 @@ where } } +#[component] +impl Hybrid { + type Header = E::Header where E: HeaderType; + type Ciphertext = Ciphertext where K: EphemeralPublicKeyType, E: CiphertextType; + type EncryptionKey = EncryptionKey where K: PublicKeyType; + type DecryptionKey = DecryptionKey where K: SecretKeyType; + type Plaintext = E::Plaintext where E: PlaintextType; + type Randomness = Randomness where K: EphemeralSecretKeyType, E: RandomnessType; + type DecryptedPlaintext = E::DecryptedPlaintext where E: DecryptedPlaintextType; +} + impl HeaderType for Hybrid where E: HeaderType, diff --git a/openzl-crypto/src/encryption/mod.rs b/openzl-crypto/src/encryption/mod.rs index ab5968bd..686e5060 100644 --- a/openzl-crypto/src/encryption/mod.rs +++ b/openzl-crypto/src/encryption/mod.rs @@ -142,15 +142,8 @@ where /// Encryption Types /// /// This `trait` encapsulates all the types required for [`Encrypt::encrypt`]. -pub trait EncryptionTypes: - CiphertextType + EncryptionKeyType + HeaderType + PlaintextType + RandomnessType -{ -} - -impl EncryptionTypes for T where - T: CiphertextType + EncryptionKeyType + HeaderType + PlaintextType + RandomnessType -{ -} +#[component] +pub type Encryption: Ciphertext + EncryptionKey + Header + Plaintext + Randomness; /// Encryption pub trait Encrypt: EncryptionTypes { @@ -203,15 +196,8 @@ where /// Decryption Types /// /// This `trait` encapsulates all the types required for [`Decrypt::decrypt`]. -pub trait DecryptionTypes: - CiphertextType + DecryptedPlaintextType + DecryptionKeyType + HeaderType -{ -} - -impl DecryptionTypes for T where - T: CiphertextType + DecryptedPlaintextType + DecryptionKeyType + HeaderType -{ -} +#[component] +pub type Decryption: Ciphertext + DecryptedPlaintext + DecryptionKey + Header; /// Decryption pub trait Decrypt: DecryptionTypes { diff --git a/openzl-derive/src/component.rs b/openzl-derive/src/component.rs index 6023c1f4..bd357148 100644 --- a/openzl-derive/src/component.rs +++ b/openzl-derive/src/component.rs @@ -1,14 +1,184 @@ //! `#[component]` Attribute Macro use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; use quote::{format_ident, quote}; use syn::{ + braced, parse::{Parse, ParseStream}, parse_macro_input, - token::{Semi, Type, Unsafe}, - Attribute, Ident, Result, Visibility, + punctuated::Punctuated, + Attribute, Ident, Result, Token, Type, Visibility, WhereClause, }; +/// Type Declaration +pub struct TypeDeclaration { + /// Attributes + attrs: Vec, + + /// Visibility + vis: Visibility, + + /// Unsafety + unsafety: Option, + + /// Identifier + ident: Ident, +} + +impl Parse for TypeDeclaration { + #[inline] + fn parse(input: ParseStream) -> Result { + let attrs = input.call(Attribute::parse_outer)?; + let vis = Visibility::parse(input)?; + let unsafety = Option::::parse(input)?; + ::parse(input)?; + let ident = Ident::parse(input)?; + Ok(Self { + attrs, + vis, + unsafety, + ident, + }) + } +} + +/// Single Component Implementation +pub struct SingleComponentImpl { + /// + ident: Ident, + + /// + body: Type, + + /// + where_clause: WhereClause, +} + +impl Parse for SingleComponentImpl { + #[inline] + fn parse(input: ParseStream) -> Result { + todo!() + } +} + +/// Component Implementation +pub struct ComponentImpl { + /// Outer Generics + outer_generics: Vec, + + /// Identifier + ident: Ident, + + /// Inner Generics + inner_generics: Vec, + + /// Components + components: Punctuated, +} + +impl Parse for ComponentImpl { + #[inline] + fn parse(input: ParseStream) -> Result { + ::parse(input)?; + let mut outer_generics = vec![]; + if Option::::parse(input)?.is_some() { + outer_generics.push(Ident::parse(input)?); + loop { + let lookahead = input.lookahead1(); + if lookahead.peek(Token![,]) { + ::parse(input)?; + outer_generics.push(Ident::parse(input)?); + } else if lookahead.peek(Token![>]) { + ]>::parse(input)?; + break; + } else { + return Err(lookahead.error()); + } + } + } + let ident = Ident::parse(input)?; + let mut inner_generics = vec![]; + if !outer_generics.is_empty() { + ::parse(input)?; + loop { + let lookahead = input.lookahead1(); + if lookahead.peek(Token![,]) { + ::parse(input)?; + inner_generics.push(Ident::parse(input)?); + } else if lookahead.peek(Token![>]) { + ]>::parse(input)?; + break; + } else { + return Err(lookahead.error()); + } + } + } + let content; + braced!(content in input); + let components = content.parse_terminated(SingleComponentImpl::parse)?; + Ok(Self { + outer_generics, + ident, + inner_generics, + components, + }) + } +} + +/// Component Macro Declaration +pub enum Component { + /// Basic Type Component + Type(TypeDeclaration), + + /// Extension Component + Extension { + /// Base Declaration + declaration: TypeDeclaration, + + /// Type Extensions + extensions: Vec, + }, + + /// Component Implementation + Impl(ComponentImpl), +} + +impl Parse for Component { + #[inline] + fn parse(input: ParseStream) -> Result { + let lookahead = input.lookahead1(); + if lookahead.peek(Token![impl]) { + Ok(Self::Impl(ComponentImpl::parse(input)?)) + } else { + let declaration = TypeDeclaration::parse(input)?; + if Option::::parse(input)?.is_some() { + let mut extensions = vec![]; + extensions.push(Ident::parse(input)?); + loop { + let lookahead = input.lookahead1(); + if lookahead.peek(Token![+]) { + ::parse(input)?; + extensions.push(Ident::parse(input)?); + } else if lookahead.peek(Token![;]) { + ::parse(input)?; + break; + } else { + return Err(lookahead.error()); + } + } + Ok(Self::Extension { + declaration, + extensions, + }) + } else { + ::parse(input)?; + Ok(Self::Type(declaration)) + } + } + } +} + /// Component Declaration pub struct Declaration { /// Attributes @@ -18,10 +188,13 @@ pub struct Declaration { vis: Visibility, /// Unsafety - unsafety: Option, + unsafety: Option, /// Identifier ident: Ident, + + /// Extension Identifiers + extensions: Vec, } impl Parse for Declaration { @@ -29,35 +202,50 @@ impl Parse for Declaration { fn parse(input: ParseStream) -> Result { let attrs = input.call(Attribute::parse_outer)?; let vis = Visibility::parse(input)?; - let unsafety = Option::::parse(input)?; + let unsafety = Option::::parse(input)?; Type::parse(input)?; let ident = Ident::parse(input)?; - Semi::parse(input)?; + let mut extensions = vec![]; + if Option::::parse(input)?.is_some() { + extensions.push(Ident::parse(input)?); + loop { + let lookahead = input.lookahead1(); + if lookahead.peek(Token![+]) { + ::parse(input)?; + extensions.push(Ident::parse(input)?); + } else if lookahead.peek(Token![;]) { + break; + } else { + return Err(lookahead.error()); + } + } + } + ::parse(input)?; Ok(Self { attrs, vis, unsafety, ident, + extensions, }) } } -/// Transforms `args` and `input` according to the macro definition. +/// Transforms a `declaration` component that has no extensions into the `trait` implementation. #[inline] -pub fn transform(args: TokenStream, input: TokenStream) -> TokenStream { - let _ = args; - let Declaration { +fn transform_type(declaration: TypeDeclaration) -> TokenStream { + let TypeDeclaration { attrs, vis, unsafety, ident, - } = parse_macro_input!(input as Declaration); + } = declaration; let trait_ident = format_ident!("{}Type", ident); let associated_type_doc = "Component Type"; let type_alias_doc = format!( "[`{ident}`]({trait_ident}::{ident}) Type Alias for the [`{trait_ident}`] Component", ); - TokenStream::from(quote!( + quote!( #(#attrs)* #vis #unsafety trait #trait_ident { #[doc = #associated_type_doc] @@ -77,5 +265,75 @@ pub fn transform(args: TokenStream, input: TokenStream) -> TokenStream { } #[doc = #type_alias_doc] #vis type #ident = ::#ident; + ) + .into() +} + +/// Transforms a `declaration` component with `extensions` into the `trait` implementation. +#[inline] +fn transform_extension(declaration: TypeDeclaration, extensions: Vec) -> TokenStream { + let TypeDeclaration { + attrs, + vis, + unsafety, + ident, + } = declaration; + let trait_ident = format_ident!("{}Types", ident); + let extensions = extensions + .into_iter() + .map(|e| format_ident!("{}Type", e)) + .collect::>(); + quote!( + #(#attrs)* + #vis #unsafety trait #trait_ident: #(#extensions)+* {} + impl #trait_ident for T + where + T: #(#extensions)+*, + { + } + ) + .into() +} + +/// +#[inline] +fn transform_impl(implementation: ComponentImpl) -> TokenStream { + let ComponentImpl { + outer_generics, + ident, + inner_generics, + components, + } = implementation; + + /* + TokenStream::from( + components + .into_iter() + .map(|component| quote!()) + .collect::(), + ) + */ + + /* + TokenStream::from(quote!( + #( + impl<#(#outer_generics),*> + ) )) + */ + todo!() +} + +/// Transforms `args` and `input` according to the macro definition. +#[inline] +pub fn transform(args: TokenStream, input: TokenStream) -> TokenStream { + let _ = args; + match parse_macro_input!(input as Component) { + Component::Type(declaration) => transform_type(declaration), + Component::Extension { + declaration, + extensions, + } => transform_extension(declaration, extensions), + Component::Impl(implementation) => transform_impl(implementation), + } }