Skip to content

Commit

Permalink
🚧 Continue working on validators and migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
rster2002 committed Nov 6, 2023
1 parent 0b91dc5 commit 386da8c
Show file tree
Hide file tree
Showing 16 changed files with 599 additions and 66 deletions.
10 changes: 0 additions & 10 deletions src/field.rs

This file was deleted.

3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod field;
pub mod schema;
pub mod schema_type;
pub mod traits;
pub mod migration;

mod shared;
18 changes: 18 additions & 0 deletions src/migration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pub mod migration_op;

use std::collections::HashMap;
use json_search::json_path::JsonPath;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged, rename_all = "camelCase")]
pub enum Migration {
Ref(JsonPath),
Array(Vec<Migration>),
Object(HashMap<String, Migration>),
}

#[cfg(test)]
mod tests {

}
7 changes: 7 additions & 0 deletions src/migration/migration_op.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "$", rename_all = "camelCase")]
pub enum MigrationOp {

}
40 changes: 21 additions & 19 deletions src/schema.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use serde::{Deserialize, Deserializer};
pub mod schema_change;

use serde::{Deserialize, Deserializer, Serialize};
use serde_json::Value;
use thiserror::Error;
use crate::schema::schema_change::SchemaChange;
use crate::schema_type::SchemaType;

#[derive(Debug, Error)]
pub enum SchemaValidationError {
Expand All @@ -9,29 +13,27 @@ pub enum SchemaValidationError {
}

/// A schema encapsulates multiple version of the schema which are updated through migrations.
#[derive(Debug)]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Schema {
inner: Value,
version: u32,
initial: SchemaType,
changes: Vec<SchemaChange>,
}

impl<'de> Deserialize<'de> for Schema {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let inner = Value::deserialize(deserializer)?;

Ok(Schema { inner })
impl Schema {
pub fn add_change(&mut self, change: SchemaChange) {
self.version += 1;
self.changes.push(change);
}
}

#[cfg(test)]
mod tests {
use crate::schema::Schema;
use serde_json::json;

#[test]
fn root_type_schema_validates_value_correctly() {
let _schema: Schema = serde_json::from_value(json!("string")).unwrap();
impl From<SchemaType> for Schema {
fn from(value: SchemaType) -> Self {
Schema {
version: 0,
initial: value,
changes: vec![],
}
}
}
8 changes: 8 additions & 0 deletions src/schema/schema_change.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use serde::{Deserialize, Serialize};
use crate::schema_type::SchemaType;

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SchemaChange {
new_schema: SchemaType,
}
96 changes: 88 additions & 8 deletions src/schema_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ use serde_json::Value;
use std::collections::HashMap;
use std::fmt::{Debug, Display, Formatter};
use thiserror::Error;
use crate::schema_type::advanced_type::advanced_string_type::AdvancedStringType;
use crate::schema_type::advanced_type::any_of_type::AnyOfType;
use crate::schema_type::advanced_type::array_type::ArrayType;
use crate::schema_type::advanced_type::object_type::ObjectType;
use crate::schema_type::advanced_type::optional_type::OptionalType;
use crate::schema_type::advanced_type::tuple_type::TupleType;
use crate::schema_type::field::Field;

pub mod advanced_type;
pub mod basic_type;
pub mod field;

#[derive(Debug, Error, PartialEq)]
pub enum SchemaTypeValidationError {
Expand All @@ -27,6 +32,7 @@ pub enum SchemaTypeValidationError {
#[serde(untagged, rename_all = "camelCase")]
pub enum SchemaType {
Basic(BasicType),
Field(Field),
Advanced(AdvancedType),
Array((Box<SchemaType>,)),
Tuple(Vec<SchemaType>),
Expand All @@ -37,6 +43,7 @@ impl Display for SchemaType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
SchemaType::Basic(basic_type) => Display::fmt(basic_type, f),
SchemaType::Field(field) => Display::fmt(field, f),
SchemaType::Advanced(advanced_type) => Display::fmt(advanced_type, f),
SchemaType::Array(item) => {
write!(f, "array filled with '{}'", item.0)
Expand All @@ -61,6 +68,7 @@ impl Validator for SchemaType {
fn validate(&self, value: &Value) -> Result<(), Self::E> {
match self {
SchemaType::Basic(basic_type) => Ok(basic_type.validate(value)?),
SchemaType::Field(field) => field.validate(value),
SchemaType::Advanced(advanced_type) => Ok(advanced_type.validate(value)?),
SchemaType::Array(item) => {
let array_type = ArrayType {
Expand Down Expand Up @@ -91,6 +99,78 @@ impl Validator for SchemaType {
}
}

impl From<BasicType> for SchemaType {
fn from(value: BasicType) -> Self {
SchemaType::Basic(value)
}
}

impl From<AdvancedType> for SchemaType {
fn from(value: AdvancedType) -> Self {
SchemaType::Advanced(value)
}
}

impl From<Field> for SchemaType {
fn from(value: Field) -> Self {
SchemaType::Field(value)
}
}

impl From<(SchemaType,)> for SchemaType {
fn from(value: (SchemaType, )) -> Self {
SchemaType::Array((Box::new(value.0),))
}
}

impl From<Vec<SchemaType>> for SchemaType {
fn from(value: Vec<SchemaType>) -> Self {
SchemaType::Tuple(value)
}
}

impl From<HashMap<String, SchemaType>> for SchemaType {
fn from(value: HashMap<String, SchemaType>) -> Self {
SchemaType::Object(value)
}
}

impl From<AdvancedStringType> for SchemaType {
fn from(value: AdvancedStringType) -> Self {
SchemaType::Advanced(value.into())
}
}

impl From<AnyOfType> for SchemaType {
fn from(value: AnyOfType) -> Self {
SchemaType::Advanced(value.into())
}
}

impl From<TupleType> for SchemaType {
fn from(value: TupleType) -> Self {
SchemaType::Advanced(value.into())
}
}

impl From<ArrayType> for SchemaType {
fn from(value: ArrayType) -> Self {
SchemaType::Advanced(value.into())
}
}

impl From<ObjectType> for SchemaType {
fn from(value: ObjectType) -> Self {
SchemaType::Advanced(value.into())
}
}

impl From<OptionalType> for SchemaType {
fn from(value: OptionalType) -> Self {
SchemaType::Advanced(value.into())
}
}

#[cfg(test)]
mod tests {
use crate::schema_type::advanced_type::advanced_string_type::AdvancedStringType;
Expand All @@ -116,10 +196,10 @@ mod tests {

assert_eq!(
value,
SchemaType::Advanced(AdvancedType::String(AdvancedStringType {
AdvancedStringType {
min_length: Some(10),
..Default::default()
}))
}.into()
);

let result = serde_json::from_value::<SchemaType>(json!({ "minLength": 10 }));
Expand All @@ -135,10 +215,10 @@ mod tests {

assert_eq!(
value,
SchemaType::Object(HashMap::from([(
HashMap::from([(
"name".to_string(),
SchemaType::Basic(BasicType::String)
)]))
)]).into()
);
}

Expand All @@ -158,10 +238,10 @@ mod tests {

assert_eq!(
value,
SchemaType::Tuple(vec![
vec![
SchemaType::Basic(BasicType::String),
SchemaType::Basic(BasicType::Number),
])
].into()
);
}

Expand Down Expand Up @@ -253,10 +333,10 @@ mod tests {

assert_eq!(
value,
SchemaType::Object(HashMap::from([
HashMap::from([
("$".to_string(), SchemaType::Basic(BasicType::Number)),
("name".to_string(), SchemaType::Basic(BasicType::String)),
]))
]).into()
);
}

Expand Down
58 changes: 47 additions & 11 deletions src/schema_type/advanced_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,42 @@ impl Validator for AdvancedType {
}
}

impl From<AdvancedStringType> for AdvancedType {
fn from(value: AdvancedStringType) -> Self {
AdvancedType::String(value)
}
}

impl From<AnyOfType> for AdvancedType {
fn from(value: AnyOfType) -> Self {
AdvancedType::AnyOf(value)
}
}

impl From<TupleType> for AdvancedType {
fn from(value: TupleType) -> Self {
AdvancedType::Tuple(value)
}
}

impl From<ArrayType> for AdvancedType {
fn from(value: ArrayType) -> Self {
AdvancedType::Array(value)
}
}

impl From<ObjectType> for AdvancedType {
fn from(value: ObjectType) -> Self {
AdvancedType::Object(value)
}
}

impl From<OptionalType> for AdvancedType {
fn from(value: OptionalType) -> Self {
AdvancedType::Optional(value)
}
}

#[cfg(test)]
mod tests {
use crate::schema_type::advanced_type::advanced_string_type::AdvancedStringType;
Expand Down Expand Up @@ -131,12 +167,12 @@ mod tests {

assert_eq!(
advanced_type,
AdvancedType::AnyOf(AnyOfType {
AnyOfType {
variants: vec![
SchemaType::Basic(BasicType::String),
SchemaType::Basic(BasicType::Number),
BasicType::String.into(),
BasicType::Number.into(),
],
})
}.into()
);
}

Expand All @@ -153,12 +189,12 @@ mod tests {

assert_eq!(
advanced_type,
AdvancedType::Tuple(TupleType {
TupleType {
items: vec![
SchemaType::Basic(BasicType::String),
SchemaType::Basic(BasicType::Number),
BasicType::String.into(),
BasicType::Number.into(),
],
})
}.into()
);
}

Expand All @@ -172,9 +208,9 @@ mod tests {

assert_eq!(
advanced_type,
AdvancedType::Optional(OptionalType {
kind: Box::new(SchemaType::Basic(BasicType::String))
})
OptionalType {
kind: Box::new(BasicType::String.into())
}.into()
);
}
}
11 changes: 8 additions & 3 deletions src/schema_type/advanced_type/advanced_string_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,15 @@ pub enum StringValidationError {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AdvancedStringType {
/// If this is set to true, the string cannot have a length of zero.
#[serde(default = "default_true")]
pub(crate) require_filled: bool,
pub(crate) min_length: Option<usize>,
pub(crate) max_length: Option<usize>,
pub require_filled: bool,

/// If set, ensures the string is at least n number of characters long.
pub min_length: Option<usize>,

/// If set, ensures the string is less of equal to n characters long.
pub max_length: Option<usize>,
}

impl Display for AdvancedStringType {
Expand Down
Loading

0 comments on commit 386da8c

Please sign in to comment.