From 3cefbd00afa3ec4553fa8362e981f44b6b604779 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Thu, 26 Jan 2023 09:28:45 +0100 Subject: [PATCH] Draft basic Blueprint schema type definition. This doesn't include validations yet. Let's start simple and try to get some basic schema generated already. --- crates/aiken-project/src/blueprint.rs | 191 ++++++++++++++++++++++++++ crates/aiken-project/src/lib.rs | 1 + 2 files changed, 192 insertions(+) create mode 100644 crates/aiken-project/src/blueprint.rs diff --git a/crates/aiken-project/src/blueprint.rs b/crates/aiken-project/src/blueprint.rs new file mode 100644 index 00000000..9a4c35ef --- /dev/null +++ b/crates/aiken-project/src/blueprint.rs @@ -0,0 +1,191 @@ +use serde::ser::{Serialize, SerializeStruct, Serializer}; +use serde_json; +use std::fmt::{self, Display}; + +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum Schema { + Integer, + Bytes, + List(Item>), + Map((Box, Box)), + Constructor(usize, Vec), +} + +impl Display for Schema { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s = serde_json::to_string_pretty(self).map_err(|_| fmt::Error)?; + f.write_str(&s) + } +} + +impl Serialize for Schema { + fn serialize(&self, serializer: S) -> Result { + match self { + Schema::Integer => { + let mut s = serializer.serialize_struct("Integer", 1)?; + s.serialize_field("dataType", "integer")?; + s.end() + } + Schema::Bytes => { + let mut s = serializer.serialize_struct("Bytes", 1)?; + s.serialize_field("dataType", "bytes")?; + s.end() + } + Schema::List(items) => { + let mut s = serializer.serialize_struct("List", 2)?; + s.serialize_field("dataType", "list")?; + s.serialize_field("items", &items)?; + s.end() + } + Schema::Map(elements) => { + let mut s = serializer.serialize_struct("Map", 2)?; + s.serialize_field("dataType", "map")?; + s.serialize_field("elements", &elements)?; + s.end() + } + _ => { + todo!() + } + } + } +} + +// Represent a items list in a JSON schema. Can be either a singleton (i.e. a single schema) when +// all elements in the list are uniform or a list of schemas. +#[derive(Debug, PartialEq, Eq, Clone)] +pub enum Item { + Singleton(T), + Many(Vec), +} + +impl Serialize for Item { + fn serialize(&self, serializer: S) -> Result { + match self { + Item::Singleton(elem) => Serialize::serialize(elem, serializer), + Item::Many(elems) => Serialize::serialize(elems, serializer), + } + } +} + +pub mod test { + use super::*; + #[allow(unused_imports)] + use serde_json::{self, json, Value}; + + pub fn assert_json(schema: &Schema, expected: Value) { + assert_eq!(serde_json::to_value(schema).unwrap(), expected); + } + + #[test] + fn serialize_integer() { + let schema = Schema::Integer; + assert_json( + &schema, + json!({ + "dataType": "integer" + }), + ); + } + + #[test] + fn serialize_bytes() { + let schema = Schema::Bytes; + assert_json( + &schema, + json!({ + "dataType": "bytes" + }), + ); + } + + #[test] + fn serialize_list_1() { + let schema = Schema::List(Item::Many(vec![])); + assert_json( + &schema, + json!({ + "dataType": "list", + "items": [] + }), + ); + } + + #[test] + fn serialize_list_2() { + let schema = Schema::List(Item::Singleton(Box::new(Schema::Integer))); + assert_json( + &schema, + json!({ + "dataType": "list", + "items": { + "dataType": "integer" + } + }), + ); + } + + #[test] + fn serialize_list_3() { + let schema = Schema::List(Item::Many(vec![ + Box::new(Schema::Bytes), + Box::new(Schema::List(Item::Singleton(Box::new(Schema::Integer)))), + ])); + assert_json( + &schema, + json!({ + "dataType": "list", + "items": [ + { + "dataType": "bytes" + }, + { + "dataType": "list", + "items": { "dataType": "integer" } + } + ] + }), + ); + } + + #[test] + fn serialize_map_1() { + let schema = Schema::Map((Box::new(Schema::Integer), Box::new(Schema::Bytes))); + assert_json( + &schema, + json!({ + "dataType": "map", + "elements": [ + { + "dataType": "integer" + }, + { + "dataType": "bytes" + } + ] + }), + ) + } + + #[test] + fn serialize_map_2() { + let schema = Schema::Map(( + Box::new(Schema::Bytes), + Box::new(Schema::List(Item::Singleton(Box::new(Schema::Integer)))), + )); + assert_json( + &schema, + json!({ + "dataType": "map", + "elements": [ + { + "dataType": "bytes" + }, + { + "dataType": "list", + "items": { "dataType": "integer" } + } + ] + }), + ) + } +} diff --git a/crates/aiken-project/src/lib.rs b/crates/aiken-project/src/lib.rs index 86c3ca7c..fd23d11e 100644 --- a/crates/aiken-project/src/lib.rs +++ b/crates/aiken-project/src/lib.rs @@ -1,3 +1,4 @@ +pub mod blueprint; pub mod config; pub mod deps; pub mod docs;