Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 20 additions & 31 deletions rust/catalyst-signed-doc-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
//! spec.

mod error;
mod rules;
mod signed_doc_spec;
mod types_consts;

use proc_macro2::TokenStream;
use quote::quote;
use crate::error::process_error;

use crate::{error::process_error, signed_doc_spec::CatalystSignedDocSpec};

/// Defines consts for all Catalyst Signed Documents types values
/// e.g.
/// Defines consts for all Catalyst Signed Documents types values, which are
/// defined inside the `signed_doc.json` spec.
///
/// E.G.
/// ```ignore
/// pub const PROPOSAL: DocType = DocType::try_from_uuid(catalyst_types::uuid::uuid!(
/// "7808d2ba-d511-40af-84e8-c0d1625fdfdc"
Expand All @@ -20,33 +21,21 @@ use crate::{error::process_error, signed_doc_spec::CatalystSignedDocSpec};
pub fn catalyst_signed_documents_types_consts(
_: proc_macro::TokenStream
) -> proc_macro::TokenStream {
catalyst_signed_documents_types_consts_impl()
types_consts::catalyst_signed_documents_types_consts_impl()
.unwrap_or_else(process_error)
.into()
}

/// `catalyst_signed_documents_types_consts` macro implementation
fn catalyst_signed_documents_types_consts_impl() -> anyhow::Result<TokenStream> {
let spec = CatalystSignedDocSpec::load_signed_doc_spec()?;

let mut consts_definitions = Vec::new();
for (doc_name, doc_spec) in spec.docs {
let const_type_name_ident = doc_name.ident();
let doc_name = doc_name.name();
let type_uuid = doc_spec.doc_type;

let const_definition = quote! {
#[doc = #doc_name ]
#[doc = "type constant definition"]
pub const #const_type_name_ident: crate::DocType = match crate::DocType::try_from_uuid(catalyst_types::uuid::uuid!(#type_uuid)) {
Ok(v) => v,
Err(_) => panic!("invalid uuid v4 value"),
};
};
consts_definitions.push(const_definition);
}

Ok(quote! {
#(#consts_definitions)*
})
/// Defines `documents_rules` function which will return a defined
/// `catalyst_signed_doc::Rules` instances for each corresponding document type, which are
/// defined inside the `signed_doc.json` spec.
///
/// ```ignore
/// fn documents_rules() -> impl Iterator<Item = (DocType, Rules)>
/// ```
#[proc_macro]
pub fn catalyst_signed_documents_rules(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
rules::catalyst_signed_documents_rules_impl()
.unwrap_or_else(process_error)
.into()
}
54 changes: 54 additions & 0 deletions rust/catalyst-signed-doc-macro/src/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//! `catalyst_signed_documents_rules!` macro implementation

use proc_macro2::TokenStream;
use quote::quote;

use crate::signed_doc_spec::CatalystSignedDocSpec;

/// `catalyst_signed_documents_rules` macro implementation
pub(crate) fn catalyst_signed_documents_rules_impl() -> anyhow::Result<TokenStream> {
let spec = CatalystSignedDocSpec::load_signed_doc_spec()?;

let mut rules_definitions = Vec::new();
for (doc_name, _doc_spec) in spec.docs {
let const_type_name_ident = doc_name.ident();

// TODO: implement a proper initialization for all specific validation rules
let rules = quote! {
crate::validator::rules::Rules {
id: crate::validator::rules::IdRule,
ver: crate::validator::rules::VerRule,
content_type: crate::validator::rules::ContentTypeRule {
exp: ContentType::Json,
},
content_encoding: crate::validator::rules::ContentEncodingRule {
exp: ContentEncoding::Brotli,
optional: false,
},
content: crate::validator::rules::ContentRule::NotSpecified,
parameters: crate::validator::rules::ParametersRule::NotSpecified,
doc_ref: crate::validator::rules::RefRule::NotSpecified,
reply: crate::validator::rules::ReplyRule::NotSpecified,
section: crate::validator::rules::SectionRule::NotSpecified,
kid: crate::validator::rules::SignatureKidRule {
exp: &[],
},
signature: crate::validator::rules::SignatureRule {
mutlisig: false
},
}
};

let rule_definition = quote! {
(crate::doc_types::#const_type_name_ident, #rules),
};
rules_definitions.push(rule_definition);
}

Ok(quote! {
/// Returns an iterator with all defined Catalyst Signed Documents validation rules per corresponding document type
fn documents_rules() -> impl Iterator<Item = (crate::DocType, crate::validator::rules::Rules)> {
[ #(#rules_definitions)* ].into_iter()
}
})
}
32 changes: 32 additions & 0 deletions rust/catalyst-signed-doc-macro/src/types_consts.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! `catalyst_signed_documents_types_consts!` macro implementation

use proc_macro2::TokenStream;
use quote::quote;

use crate::signed_doc_spec::CatalystSignedDocSpec;

/// `catalyst_signed_documents_types_consts` macro implementation
pub(crate) fn catalyst_signed_documents_types_consts_impl() -> anyhow::Result<TokenStream> {
let spec = CatalystSignedDocSpec::load_signed_doc_spec()?;

let mut consts_definitions = Vec::new();
for (doc_name, doc_spec) in spec.docs {
let const_type_name_ident = doc_name.ident();
let doc_name = doc_name.name();
let type_uuid = doc_spec.doc_type;

let const_definition = quote! {
#[doc = #doc_name ]
#[doc = "type constant definition"]
pub const #const_type_name_ident: crate::DocType = match crate::DocType::try_from_uuid(catalyst_types::uuid::uuid!(#type_uuid)) {
Ok(v) => v,
Err(_) => panic!("invalid uuid v4 value"),
};
};
consts_definitions.push(const_definition);
}

Ok(quote! {
#(#consts_definitions)*
})
}
26 changes: 12 additions & 14 deletions rust/signed_doc/src/validator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
pub(crate) mod json_schema;
pub(crate) mod rules;

use std::{
collections::HashMap,
sync::{Arc, LazyLock},
};
use std::{collections::HashMap, sync::LazyLock};

use catalyst_signed_doc_macro;
use catalyst_types::catalyst_id::role_index::RoleId;
use rules::{
ContentEncodingRule, ContentRule, ContentSchema, ContentTypeRule, IdRule, ParametersRule,
Expand All @@ -25,8 +23,10 @@ use crate::{
CatalystSignedDocument, ContentEncoding, ContentType,
};

catalyst_signed_doc_macro::catalyst_signed_documents_rules!();

/// A table representing a full set or validation rules per document id.
static DOCUMENT_RULES: LazyLock<HashMap<DocType, Arc<Rules>>> = LazyLock::new(document_rules_init);
static DOCUMENT_RULES: LazyLock<HashMap<DocType, Rules>> = LazyLock::new(document_rules_init);

/// Proposal
/// Require field: type, id, ver, template, parameters
Expand Down Expand Up @@ -158,18 +158,16 @@ fn proposal_submission_action_rule() -> Rules {
}

/// `DOCUMENT_RULES` initialization function
fn document_rules_init() -> HashMap<DocType, Arc<Rules>> {
let mut document_rules_map = HashMap::new();

let proposal_rules = Arc::new(proposal_rule());
let comment_rules = Arc::new(proposal_comment_rule());
let action_rules = Arc::new(proposal_submission_action_rule());
fn document_rules_init() -> HashMap<DocType, Rules> {
let mut document_rules_map: HashMap<DocType, Rules> = documents_rules().collect();

document_rules_map.insert(PROPOSAL.clone(), Arc::clone(&proposal_rules));
document_rules_map.insert(PROPOSAL_COMMENT.clone(), Arc::clone(&comment_rules));
// TODO: remove this redefinitions of the validation rules after
// `catalyst_signed_documents_rules!` macro would be fully finished
document_rules_map.insert(PROPOSAL.clone(), proposal_rule());
document_rules_map.insert(PROPOSAL_COMMENT.clone(), proposal_comment_rule());
document_rules_map.insert(
PROPOSAL_SUBMISSION_ACTION.clone(),
Arc::clone(&action_rules),
proposal_submission_action_rule(),
);

document_rules_map
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! `template` rule type impl.

use std::fmt::Write;
use std::fmt::{Debug, Write};

use crate::{
metadata::ContentType,
Expand All @@ -16,7 +16,19 @@ pub(crate) enum ContentSchema {
Json(json_schema::JsonSchema),
}

impl Debug for ContentSchema {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
match self {
Self::Json(_) => writeln!(f, "JsonSchema"),
}
}
}

/// Document's content validation rule
#[derive(Debug)]
pub(crate) enum ContentRule {
/// Based on the 'template' field and loaded corresponding template document
Templated {
Expand Down
1 change: 1 addition & 0 deletions rust/signed_doc/src/validator/rules/content_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::{metadata::ContentEncoding, CatalystSignedDocument};

/// `content-encoding` field validation rule
#[derive(Debug)]
pub(crate) struct ContentEncodingRule {
/// expected `content-encoding` field
pub(crate) exp: ContentEncoding,
Expand Down
2 changes: 1 addition & 1 deletion rust/signed_doc/src/validator/rules/content_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use crate::{metadata::ContentType, CatalystSignedDocument};

/// `content-type` field validation rule
#[derive(Clone, Debug, PartialEq)]
#[derive(Debug)]
pub(crate) struct ContentTypeRule {
/// expected `content-type` field
pub(crate) exp: ContentType,
Expand Down
4 changes: 2 additions & 2 deletions rust/signed_doc/src/validator/rules/doc_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
};

/// `ref` field validation rule
#[derive(Clone, Debug, PartialEq)]
#[derive(Debug)]
pub(crate) enum RefRule {
/// Is 'ref' specified
Specified {
Expand Down Expand Up @@ -52,7 +52,7 @@ impl RefRule {
return Ok(false);
}
}
if &Self::NotSpecified == self {
if let Self::NotSpecified = self {
if let Some(doc_ref) = doc.doc_meta().doc_ref() {
doc.report().unknown_field(
"ref",
Expand Down
1 change: 1 addition & 0 deletions rust/signed_doc/src/validator/rules/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use anyhow::Context;
use crate::{providers::CatalystSignedDocumentProvider, CatalystSignedDocument};

/// Signed Document `id` field validation rule
#[derive(Debug)]
pub(crate) struct IdRule;

impl IdRule {
Expand Down
5 changes: 3 additions & 2 deletions rust/signed_doc/src/validator/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{
CatalystSignedDocument,
};

mod content;
mod content_encoding;
mod content_type;
mod doc_ref;
Expand All @@ -17,9 +18,9 @@ mod reply;
mod section;
mod signature;
mod signature_kid;
mod template;
mod ver;

pub(crate) use content::{ContentRule, ContentSchema};
pub(crate) use content_encoding::ContentEncodingRule;
pub(crate) use content_type::ContentTypeRule;
pub(crate) use doc_ref::RefRule;
Expand All @@ -29,10 +30,10 @@ pub(crate) use reply::ReplyRule;
pub(crate) use section::SectionRule;
pub(crate) use signature::SignatureRule;
pub(crate) use signature_kid::SignatureKidRule;
pub(crate) use template::{ContentRule, ContentSchema};
pub(crate) use ver::VerRule;

/// Struct represented a full collection of rules for all fields
#[derive(Debug)]
pub(crate) struct Rules {
/// 'id' field validation rule
pub(crate) id: IdRule,
Expand Down
2 changes: 1 addition & 1 deletion rust/signed_doc/src/validator/rules/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
};

/// `parameters` field validation rule
#[derive(Clone, Debug, PartialEq)]
#[derive(Debug)]
pub(crate) enum ParametersRule {
/// Is `parameters` specified
Specified {
Expand Down
2 changes: 1 addition & 1 deletion rust/signed_doc/src/validator/rules/reply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
};

/// `reply` field validation rule
#[derive(Clone, Debug, PartialEq)]
#[derive(Debug)]
pub(crate) enum ReplyRule {
/// Is 'reply' specified
Specified {
Expand Down
1 change: 1 addition & 0 deletions rust/signed_doc/src/validator/rules/section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::CatalystSignedDocument;

/// `section` field validation rule
#[derive(Debug)]
pub(crate) enum SectionRule {
/// Is 'section' specified
#[allow(dead_code)]
Expand Down
1 change: 1 addition & 0 deletions rust/signed_doc/src/validator/rules/signature_kid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use catalyst_types::catalyst_id::role_index::RoleId;
use crate::CatalystSignedDocument;

/// COSE signature `kid` (Catalyst Id) role validation
#[derive(Debug)]
pub(crate) struct SignatureKidRule {
/// expected `RoleId` values for the `kid` field
pub(crate) exp: &'static [RoleId],
Expand Down
1 change: 1 addition & 0 deletions rust/signed_doc/src/validator/rules/ver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::{providers::CatalystSignedDocumentProvider, CatalystSignedDocument};

/// Signed Document `ver` field validation rule
#[derive(Debug)]
pub(crate) struct VerRule;

impl VerRule {
Expand Down
Loading