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
3 changes: 3 additions & 0 deletions rust/catalyst-signed-doc-spec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ license.workspace = true
workspace = true

[dependencies]
catalyst-types = { version = "0.0.11", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.11" }
cbork-cddl-parser = { version = "0.0.3", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "cbork-cddl-parser/v0.0.3" }

serde_json = "1.0.142"
anyhow = "1.0.99"
serde = { version = "1.0.219", features = ["derive"] }
Expand Down
79 changes: 79 additions & 0 deletions rust/catalyst-signed-doc-spec/src/cddl_definitions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//! 'cddlDefinitions' field definition

use std::{collections::HashMap, fmt::Display};

use cbork_cddl_parser::validate_cddl;

#[derive(serde::Deserialize)]
pub struct CddlDefinitions(HashMap<CddlType, CddlDef>);

#[derive(Clone, serde::Deserialize, PartialEq, Eq, Hash)]
pub struct CddlType(String);

#[derive(serde::Deserialize)]
struct CddlDef {
def: String,
requires: Vec<CddlType>,
}

impl Display for CddlType {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
self.0.fmt(f)
}
}

impl CddlDef {
fn get_cddl_spec(
&self,
cddl_type: &CddlType,
) -> String {
format!("{cddl_type}={}\n", self.def)
}
}

impl CddlDefinitions {
fn find_cddl_def(
&self,
cddl_type: &CddlType,
) -> anyhow::Result<&CddlDef> {
self.0.get(cddl_type).ok_or(anyhow::anyhow!(
"Cannot find a cddl definition for the {cddl_type}"
))
}

/// Returns a full CDDL specification schema.
/// Performs
///
/// # Errors
/// - Cannot find a cddl definition
/// - Not a valid resulted CDDL spec
pub fn get_cddl_spec(
&self,
cddl_type: &CddlType,
) -> anyhow::Result<String> {
let def = self.find_cddl_def(cddl_type)?;

let spec = def.get_cddl_spec(cddl_type);
let mut requires = def.requires.clone();

let mut imports = HashMap::new();
while let Some(req) = requires.pop() {
let req_def = self.find_cddl_def(&req)?;
let req_spec = req_def.get_cddl_spec(&req);
if imports.insert(req, req_spec).is_none() {
requires.extend(req_def.requires.clone());
}
}

let mut spec = imports.values().fold(spec, |mut spec, import_spec| {
spec.push_str(import_spec);
spec
});

validate_cddl(&mut spec, &cbork_cddl_parser::Extension::CDDL)?;
Ok(spec)
}
}
10 changes: 7 additions & 3 deletions rust/catalyst-signed-doc-spec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

#![allow(missing_docs, clippy::missing_docs_in_private_items)]

pub mod copyright;
pub mod cddl_definitions;
mod copyright;
pub mod doc_types;
pub mod headers;
pub mod is_required;
Expand All @@ -15,16 +16,19 @@ use std::{collections::HashMap, fmt::Display, ops::Deref};
use build_info as build_info_lib;

use crate::{
copyright::Copyright, headers::Headers, metadata::Metadata, payload::Payload, signers::Signers,
cddl_definitions::CddlDefinitions, copyright::Copyright, headers::Headers, metadata::Metadata,
payload::Payload, signers::Signers,
};

build_info_lib::build_info!(pub(crate) fn build_info);

/// Catalyst Signed Document spec representation struct
#[derive(serde::Deserialize)]
pub struct CatalystSignedDocSpec {
pub docs: DocSpecs,
#[serde(rename = "cddlDefinitions")]
pub cddl_definitions: CddlDefinitions,
copyright: Copyright,
pub docs: DocSpecs,
}

#[derive(serde::Deserialize)]
Expand Down
33 changes: 32 additions & 1 deletion rust/catalyst-signed-doc-spec/src/payload.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,40 @@
//! `signed_doc.json` "payload" field JSON definition

use catalyst_types::json_schema::JsonSchema;
use serde::Deserialize;

use crate::cddl_definitions::CddlType;

/// `signed_doc.json` "payload" field JSON object
#[derive(serde::Deserialize)]
#[allow(clippy::missing_docs_in_private_items)]
pub struct Payload {
pub nil: bool,
pub schema: Option<serde_json::Value>,
pub schema: Option<Schema>,
}

pub enum Schema {
Cddl(CddlType),
Json(JsonSchema),
}

impl<'de> Deserialize<'de> for Schema {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: serde::Deserializer<'de> {
#[derive(serde::Deserialize)]
#[serde(untagged)]
pub enum SchemaSerde {
Cddl(CddlType),
Json(serde_json::Value),
}

match SchemaSerde::deserialize(deserializer)? {
SchemaSerde::Json(json) => {
JsonSchema::try_from(&json)
.map(Self::Json)
.map_err(serde::de::Error::custom)
},
SchemaSerde::Cddl(cddl_type) => Ok(Self::Cddl(cddl_type)),
}
}
}
2 changes: 1 addition & 1 deletion rust/signed_doc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ license.workspace = true
workspace = true

[dependencies]
catalyst-types = { version = "0.0.10", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.10" }
catalyst-types = { version = "0.0.11", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.11" }
cbork-utils = { version = "0.0.2", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "cbork-utils-v0.0.2" }

catalyst-signed-doc-macro = { version = "0.0.1", path = "../catalyst-signed-doc-macro" }
Expand Down
139 changes: 0 additions & 139 deletions rust/signed_doc/src/validator/json_schema.rs

This file was deleted.

1 change: 0 additions & 1 deletion rust/signed_doc/src/validator/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Catalyst Signed Documents validation logic

pub(crate) mod json_schema;
pub(crate) mod rules;

use std::{collections::HashMap, sync::LazyLock};
Expand Down
Loading
Loading