use super::constraint::{vsf_type_name, TypeConstraint};
use super::validate::ValidationResult;
use crate::VsfType;
#[derive(Clone)]
pub struct FieldSchema {
pub name: String,
pub constraint: TypeConstraint,
pub required: bool,
pub description: Option<String>,
pub default: Option<VsfType>,
}
impl FieldSchema {
pub fn new(name: impl Into<String>, constraint: TypeConstraint) -> Self {
Self {
name: name.into(),
constraint,
required: false,
description: None,
default: None,
}
}
pub fn required(mut self) -> Self {
self.required = true;
self
}
pub fn description(mut self, desc: impl Into<String>) -> Self {
self.description = Some(desc.into());
self
}
pub fn default(mut self, value: VsfType) -> Self {
self.default = Some(value);
self.required = false;
self
}
pub fn validate(&self, value: &VsfType) -> ValidationResult<()> {
self.constraint.validate(value)
}
}
impl std::fmt::Debug for FieldSchema {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FieldSchema")
.field("name", &self.name)
.field("constraint", &self.constraint)
.field("required", &self.required)
.field("description", &self.description)
.field("default", &self.default.as_ref().map(vsf_type_name))
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_field_schema_creation() {
let field = FieldSchema::new("width", TypeConstraint::AnyUnsigned)
.required()
.description("Image width in pixels");
assert_eq!(field.name, "width");
assert!(field.required);
assert_eq!(field.description, Some("Image width in pixels".to_string()));
}
#[test]
fn test_field_validation() {
let field = FieldSchema::new("count", TypeConstraint::AnyUnsigned);
assert!(field.validate(&VsfType::u5(42)).is_ok());
assert!(field.validate(&VsfType::u3(10)).is_ok());
assert!(field.validate(&VsfType::f6(3.14)).is_err());
assert!(field.validate(&VsfType::x("hello".to_string())).is_err());
}
#[test]
fn test_field_with_default() {
let field =
FieldSchema::new("timeout", TypeConstraint::AnyUnsigned).default(VsfType::u5(30));
assert!(!field.required); assert!(field.default.is_some());
}
}