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.
This commit is contained in:
KtorZ 2023-01-26 09:28:45 +01:00
parent 0e65fecf69
commit 3cefbd00af
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
2 changed files with 192 additions and 0 deletions

View File

@ -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<Box<Schema>>),
Map((Box<Schema>, Box<Schema>)),
Constructor(usize, Vec<Schema>),
}
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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
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<T> {
Singleton(T),
Many(Vec<T>),
}
impl<T: Serialize> Serialize for Item<T> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
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" }
}
]
}),
)
}
}

View File

@ -1,3 +1,4 @@
pub mod blueprint;
pub mod config;
pub mod deps;
pub mod docs;