use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum FieldType {
String,
Text,
Integer,
Float,
Boolean,
Date,
DateTime,
Json,
Uuid,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Field {
pub name: String,
pub field_type: FieldType,
pub required: bool,
}
impl Field {
pub fn new(name: impl Into<String>, field_type: FieldType) -> Self {
Self {
name: name.into(),
field_type,
required: false,
}
}
pub fn required(mut self) -> Self {
self.required = true;
self
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Schema {
pub name: String,
pub table: String,
pub fields: Vec<Field>,
}
impl Schema {
pub fn new(name: impl Into<String>, table: impl Into<String>) -> Self {
Self {
name: name.into(),
table: table.into(),
fields: Vec::new(),
}
}
pub fn with_field(mut self, field: Field) -> Self {
self.fields.push(field);
self
}
}
pub trait SchemaDefinition {
fn schema() -> Schema;
}
#[cfg(test)]
mod tests {
use super::{Field, FieldType, Schema, SchemaDefinition};
#[test]
fn required_marks_field_as_required() {
let field = Field::new("title", FieldType::String).required();
assert_eq!(field.name, "title");
assert_eq!(field.field_type, FieldType::String);
assert!(field.required);
}
#[test]
fn schema_builder_collects_fields() {
let schema = Schema::new("Post", "posts")
.with_field(Field::new("id", FieldType::Integer).required())
.with_field(Field::new("title", FieldType::String));
assert_eq!(schema.name, "Post");
assert_eq!(schema.table, "posts");
assert_eq!(schema.fields.len(), 2);
assert_eq!(schema.fields[0].name, "id");
assert!(schema.fields[0].required);
}
#[test]
fn schema_definition_trait_can_expose_schema() {
struct PostSchema;
impl SchemaDefinition for PostSchema {
fn schema() -> Schema {
Schema::new("Post", "posts")
.with_field(Field::new("id", FieldType::Integer).required())
.with_field(Field::new("title", FieldType::String).required())
}
}
let schema = PostSchema::schema();
assert_eq!(schema.name, "Post");
assert_eq!(schema.fields.len(), 2);
assert!(schema.fields.iter().all(|field| field.required));
}
}