///|
/// Primitive types defined by RFC 8927 section 2.2.3.
pub(all) enum JtdType {
BooleanType
Float32Type
Float64Type
Int8Type
Uint8Type
Int16Type
Uint16Type
Int32Type
Uint32Type
StringType
TimestampType
} derive(Eq, Debug)
///|
pub fn JtdType::name(self : JtdType) -> String {
match self {
BooleanType => "boolean"
Float32Type => "float32"
Float64Type => "float64"
Int8Type => "int8"
Uint8Type => "uint8"
Int16Type => "int16"
Uint16Type => "uint16"
Int32Type => "int32"
Uint32Type => "uint32"
StringType => "string"
TimestampType => "timestamp"
}
}
///|
pub fn JtdType::is_integer(self : JtdType) -> Bool {
match self {
Int8Type | Uint8Type | Int16Type | Uint16Type | Int32Type | Uint32Type =>
true
_ => false
}
}
///|
pub fn JtdType::is_signed(self : JtdType) -> Bool {
match self {
Int8Type | Int16Type | Int32Type => true
_ => false
}
}
///|
pub fn JtdType::is_numeric(self : JtdType) -> Bool {
self.is_integer() || self is Float32Type || self is Float64Type
}
///|
pub fn JtdType::minimum(self : JtdType) -> Double? {
match self {
Int8Type => Some(-128.0)
Uint8Type => Some(0.0)
Int16Type => Some(-32768.0)
Uint16Type => Some(0.0)
Int32Type => Some(-2147483648.0)
Uint32Type => Some(0.0)
_ => None
}
}
///|
pub fn JtdType::maximum(self : JtdType) -> Double? {
match self {
Int8Type => Some(127.0)
Uint8Type => Some(255.0)
Int16Type => Some(32767.0)
Uint16Type => Some(65535.0)
Int32Type => Some(2147483647.0)
Uint32Type => Some(4294967295.0)
_ => None
}
}
///|
pub fn jtd_type_from_name(name : String) -> JtdType? {
match name {
"boolean" => Some(BooleanType)
"float32" => Some(Float32Type)
"float64" => Some(Float64Type)
"int8" => Some(Int8Type)
"uint8" => Some(Uint8Type)
"int16" => Some(Int16Type)
"uint16" => Some(Uint16Type)
"int32" => Some(Int32Type)
"uint32" => Some(Uint32Type)
"string" => Some(StringType)
"timestamp" => Some(TimestampType)
_ => None
}
}
///|
/// The eight mutually exclusive schema forms from RFC 8927.
pub(all) enum SchemaForm {
EmptyForm
RefForm(String)
TypeForm(JtdType)
EnumForm(Array[String])
ElementsForm(Schema)
PropertiesForm(Map[String, Schema], Map[String, Schema], Bool)
ValuesForm(Schema)
DiscriminatorForm(String, Map[String, Schema])
} derive(Debug)
///|
/// A schema node. Metadata is retained without assigning it validation meaning.
pub(all) struct Schema {
form : SchemaForm
nullable : Bool
metadata : Map[String, Json]
} derive(Debug)
///|
pub fn Schema::new(form : SchemaForm) -> Schema {
{ form, nullable: false, metadata: Map([]), }
}
///|
pub fn Schema::with_nullable(self : Schema, nullable : Bool) -> Schema {
{ ..self, nullable, }
}
///|
pub fn Schema::with_metadata(
self : Schema,
metadata : Map[String, Json],
) -> Schema {
{ ..self, metadata, }
}
///|
pub fn Schema::form(self : Schema) -> SchemaForm {
self.form
}
///|
pub fn Schema::is_nullable(self : Schema) -> Bool {
self.nullable
}
///|
pub fn Schema::metadata(self : Schema) -> Map[String, Json] {
self.metadata.copy()
}
///|
pub fn Schema::form_name(self : Schema) -> String {
match self.form {
EmptyForm => "empty"
RefForm(_) => "ref"
TypeForm(_) => "type"
EnumForm(_) => "enum"
ElementsForm(_) => "elements"
PropertiesForm(_, _, _) => "properties"
ValuesForm(_) => "values"
DiscriminatorForm(_, _) => "discriminator"
}
}
///|
pub fn Schema::empty() -> Schema {
Schema::new(EmptyForm)
}
///|
pub fn Schema::reference(name : String) -> Schema {
Schema::new(RefForm(name))
}
///|
pub fn Schema::type_(kind : JtdType) -> Schema {
Schema::new(TypeForm(kind))
}
///|
pub fn Schema::enum_(values : Array[String]) -> Schema {
Schema::new(EnumForm(values))
}
///|
pub fn Schema::elements(element : Schema) -> Schema {
Schema::new(ElementsForm(element))
}
///|
pub fn Schema::properties(
required : Map[String, Schema],
optional : Map[String, Schema],
additional : Bool,
) -> Schema {
Schema::new(PropertiesForm(required, optional, additional))
}
///|
pub fn Schema::values(value : Schema) -> Schema {
Schema::new(ValuesForm(value))
}
///|
pub fn Schema::discriminator(
tag : String,
mapping : Map[String, Schema],
) -> Schema {
Schema::new(DiscriminatorForm(tag, mapping))
}
///|
pub fn Schema::ref_name(self : Schema) -> String? {
match self.form {
RefForm(name) => Some(name)
_ => None
}
}
///|
pub fn Schema::type_kind(self : Schema) -> JtdType? {
match self.form {
TypeForm(kind) => Some(kind)
_ => None
}
}
///|
pub fn Schema::enum_values(self : Schema) -> Array[String]? {
match self.form {
EnumForm(values) => Some(values.copy())
_ => None
}
}
///|
pub fn Schema::element_schema(self : Schema) -> Schema? {
match self.form {
ElementsForm(element) => Some(element)
_ => None
}
}
///|
pub fn Schema::value_schema(self : Schema) -> Schema? {
match self.form {
ValuesForm(value) => Some(value)
_ => None
}
}
///|
pub fn Schema::required_properties(self : Schema) -> Map[String, Schema]? {
match self.form {
PropertiesForm(required, _, _) => Some(required.copy())
_ => None
}
}
///|
pub fn Schema::optional_properties(self : Schema) -> Map[String, Schema]? {
match self.form {
PropertiesForm(_, optional, _) => Some(optional.copy())
_ => None
}
}
///|
pub fn Schema::allows_additional_properties(self : Schema) -> Bool {
match self.form {
PropertiesForm(_, _, additional) => additional
_ => false
}
}
///|
pub fn Schema::discriminator_tag(self : Schema) -> String? {
match self.form {
DiscriminatorForm(tag, _) => Some(tag)
_ => None
}
}
///|
pub fn Schema::discriminator_mapping(self : Schema) -> Map[String, Schema]? {
match self.form {
DiscriminatorForm(_, mapping) => Some(mapping.copy())
_ => None
}
}
///|
/// A complete JTD document. Only this root level may contain definitions.
pub(all) struct SchemaDocument {
root : Schema
definitions : Map[String, Schema]
} derive(Debug)
///|
pub fn SchemaDocument::new(
root : Schema,
definitions? : Map[String, Schema] = Map([]),
) -> SchemaDocument {
{ root, definitions, }
}
///|
pub fn SchemaDocument::root(self : SchemaDocument) -> Schema {
self.root
}
///|
pub fn SchemaDocument::definitions(
self : SchemaDocument,
) -> Map[String, Schema] {
self.definitions.copy()
}
///|
pub fn SchemaDocument::definition(
self : SchemaDocument,
name : String,
) -> Schema? {
self.definitions.get(name)
}
///|
pub fn SchemaDocument::has_definition(
self : SchemaDocument,
name : String,
) -> Bool {
self.definitions.contains(name)
}
///|
pub fn SchemaDocument::definition_count(self : SchemaDocument) -> Int {
self.definitions.length()
}
///|
pub fn SchemaDocument::definition_names(self : SchemaDocument) -> Array[String] {
let names : Array[String] = []
for name, _ in self.definitions {
names.push(name)
}
names
}