#![allow(clippy::too_many_lines, clippy::wildcard_imports)] use lazy_static::lazy_static; use super::*; lazy_static! { /// the schema schema defined by [the canonical `kdl-schema.kdl`](https://github.com/kdl-org/kdl/blob/cc1da35435abbe2f7d0138310f89b18c55a292e7/examples/kdl-schema.kdl) pub static ref SCHEMA_SCHEMA: Schema = make_schema_schema(); } fn s>(text: &str) -> T { T::from(text.to_string()) } fn ref_to_id(id: &str) -> T { T::ref_to(format!(r#"[id="{}"]"#, id)) } fn make_schema_schema() -> Schema { Schema { document: Document { info: make_schema_info(), nodes: vec![make_document_node()], }, } } fn make_document_node() -> Node { Node { name: s("document"), min: Some(1), max: Some(1), children: vec![Children { id: s("node-children"), nodes: vec![ Node { name: s("node-names"), id: s("node-names-node"), description: s( "Validations to apply specifically to arbitrary node names", ), children: vec![ref_to_id("validations")], ..Node::default() }, Node { name: s("other-nodes-allowed"), id: s("other-nodes-allowed-node"), description: s("Whether to allow child nodes other than the ones explicitly listed. Defaults to 'false'."), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("boolean"))], ..Value::default() }], ..Node::default() }, Node { name: s("tag-names"), description: s("Validations to apply specifically to arbitrary type tag names"), children: vec![ref_to_id("validations")], ..Node::default() }, Node { name: s("other-tags-allowed"), description: s("Whether to allow child node tags other than the ones explicitly listed. Defaults to 'false'."), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("boolean"))], ..Value::default() }], ..Node::default() }, make_info_node(), Node { name: s("tag"), id: s("tag-node"), description: s("A tag belonging to a child node of `document` or another node."), values: vec![Value { description: s("The name of the tag. If a tag name is not supplied, the node rules apply to _all_ nodes belonging to the parent."), max: Some(1), validations: vec![Validation::Type(s("string"))], ..Value::default() }], props: vec![ Prop { key: s("description"), description: s("A description of this node's purpose."), validations: vec![Validation::Type(s("string"))], ..Prop::default() }, Prop { key: s("id"), description: s("A globally-unique ID for this node."), validations: vec![Validation::Type(s("string"))], ..Prop::default() }, Prop { key: s("ref"), description: s("A globally unique reference to another node."), validations: vec![ Validation::Type(s("string")), Validation::Format(vec![Format::KdlQuery]), ], ..Prop::default() } ], children: vec![Children { nodes: vec![ ref_to_id("node-names-node"), ref_to_id("other-nodes-allowed-node"), ref_to_id("node-node"), ], ..Children::default() }], ..Node::default() }, make_node_node(), Node { name: s("definitions"), description: s("Definitions to reference in parts of the top-level nodes"), children: vec![Children { nodes: vec![ ref_to_id("node-node"), ref_to_id("value-node"), ref_to_id("prop-node"), ref_to_id("children-node"), ref_to_id("tag-node"), ], ..Children::default() }], ..Node::default() } ], ..Children::default() }], ..Node::default() } } fn make_node_node() -> Node { Node { name: s("node"), id: s("node-node"), description: s("A child node belonging either to `document` or to another `node`. Nodes may be anonymous."), values: vec![Value { description: s("The name of the node. If a node name is not supplied, the node rules apply to _all_ nodes belonging to the parent."), max: Some(1), validations: vec![Validation::Type(s("string"))], ..Value::default() }], props: vec![ Prop { key: s("description"), description: s("A description of this node's purpose."), validations: vec![Validation::Type(s("string"))], ..Prop::default() }, Prop { key: s("id"), description: s("A globally-unique ID for this node."), validations: vec![Validation::Type(s("string"))], ..Prop::default() }, Prop { key: s("ref"), description: s("A globally unique reference to another node."), validations: vec![ Validation::Type(s("string")), Validation::Format(vec![Format::KdlQuery]), ], ..Prop::default() } ], children: vec![Children { nodes: vec![ Node { name: s("prop-names"), description: s("Validations to apply specifically to arbitrary property names"), children: vec![ref_to_id("validations")], ..Node::default() }, Node { name: s("other-props-allowed"), description: s("Whether to allow properties other than the ones explicitly listed. Defaults to 'false'."), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("boolean"))], ..Value::default() }], ..Node::default() }, Node { name: s("min"), description: s("minimum number of instances of this node in its parent's children."), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, Node { name: s("max"), description: s("maximum number of instances of this node in its parent's children."), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, ref_to_id("value-tag-node"), Node { name: s("prop"), id: s("prop-node"), description: s("A node property key/value pair."), values: vec![Value { description: s("The property key."), validations: vec![Validation::Type(s("string"))], ..Value::default() }], props: vec![ Prop { key: s("id"), description: s("A globally-unique ID of this property."), validations: vec![Validation::Type(s("string"))], ..Prop::default() }, Prop { key: s("ref"), description: s("A globally unique reference to another property node."), validations: vec![ Validation::Type(s("string")), Validation::Format(vec![Format::KdlQuery]), ], ..Prop::default() }, Prop { key: s("description"), description: s("A description of this property's purpose."), validations: vec![Validation::Type(s("string"))], ..Prop::default() }, ], children: vec![ Children { description: s("Property-specific validations."), nodes: vec![Node { name: s("required"), description: s("Whether this property is required if its parent is present."), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("boolean"))], ..Value::default() }], ..Node::default() }], ..Children::default() }, make_validations_children() ], ..Node::default() }, Node { name: s("value"), id: s("value-node"), description: s("one or more direct node values"), props: vec![ Prop { key: s("id"), description: s("A globally-unique ID of this value."), validations: vec![Validation::Type(s("string"))], ..Prop::default() }, Prop { key: s("ref"), description: s("A globally unique reference to another value node."), validations: vec![ Validation::Type(s("string")), Validation::Format(vec![Format::KdlQuery]), ], ..Prop::default() }, Prop { key: s("description"), description: s("A description of this property's purpose."), // TODO report bug in original document validations: vec![Validation::Type(s("string"))], ..Prop::default() }, ], children: vec![ ref_to_id("validations"), Children { description: s("Node value-specific validations"), nodes: vec![ Node { name: s("min"), description: s("minimum number of values for this node."), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, Node { name: s("max"), description: s("maximum number of values for this node."), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, ], ..Children::default() } ], ..Node::default() }, Node { name: s("children"), id: s("children-node"), props: vec![ Prop { key: s("id"), description: s("A globally-unique ID of this children node."), validations: vec![Validation::Type(s("string"))], ..Prop::default() }, Prop { key: s("ref"), description: s("A globally unique reference to another children node."), validations: vec![ Validation::Type(s("string")), Validation::Format(vec![Format::KdlQuery]), ], ..Prop::default() }, Prop { key: s("description"), description: s("A description of this these children's purpose."), // TODO report bug in original document validations: vec![Validation::Type(s("string"))], ..Prop::default() }, ], children: vec![ref_to_id("node-children")], ..Node::default() } ], ..Children::default() }], ..Node::default() } } fn make_validations_children() -> Children { Children { id: s("validations"), description: s("General value validations."), nodes: vec![ Node { name: s("tag"), id: s("value-tag-node"), description: s("The tags associated with this value"), max: Some(1), children: vec![ref_to_id("validations")], ..Node::default() }, Node { name: s("type"), description: s("The type for this prop's value."), max: Some(1), values: vec![Value { min: Some(1), validations: vec![Validation::Type(s("string"))], ..Value::default() }], ..Node::default() }, Node { name: s("enum"), description: s("An enumeration of possible values"), max: Some(1), values: vec![Value { description: s("Enumeration choices"), min: Some(1), ..Value::default() }], ..Node::default() }, Node { name: s("pattern"), description: s("PCRE (Regex) pattern or patterns to test prop values against."), values: vec![Value { min: Some(1), validations: vec![Validation::Type(s("string"))], ..Value::default() }], ..Node::default() }, Node { name: s("min-length"), description: s("Minimum length of prop value, if it's a string."), max: Some(1), values: vec![Value { min: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, Node { name: s("max-length"), description: s("Maximum length of prop value, if it's a string."), max: Some(1), values: vec![Value { min: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, Node { name: s("format"), description: s("Intended data format."), max: Some(1), values: vec![Value { min: Some(1), validations: vec![ Validation::Type(s("string")), Validation::Enum(vec![ s("date-time"), s("date"), s("time"), s("duration"), s("decimal"), s("currency"), s("country-2"), s("country-3"), s("country-subdivision"), s("email"), s("idn-email"), s("hostname"), s("idn-hostname"), s("ipv4"), s("ipv6"), s("url"), s("url-reference"), s("irl"), s("irl-reference"), s("url-template"), s("regex"), s("uuid"), s("kdl-query"), s("i8"), s("i16"), s("i32"), s("i64"), s("u8"), s("u16"), s("u32"), s("u64"), s("isize"), s("usize"), s("f32"), s("f64"), s("decimal64"), s("decimal128"), ]) ], ..Value::default() }], ..Node::default() }, Node { name: s("%"), description: s("Only used for numeric values. Constrains them to be multiples of the given number(s)"), max: Some(1), values: vec![Value { min: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, Node { name: s(">"), description: s("Only used for numeric values. Constrains them to be greater than the given number(s)"), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, Node { name: s(">="), description: s("Only used for numeric values. Constrains them to be greater than or equal to the given number(s)"), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, Node { name: s("<"), description: s("Only used for numeric values. Constrains them to be less than the given number(s)"), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, Node { name: s("<="), description: s("Only used for numeric values. Constrains them to be less than or equal to the given number(s)"), max: Some(1), values: vec![Value { min: Some(1), max: Some(1), validations: vec![Validation::Type(s("number"))], ..Value::default() }], ..Node::default() }, ], ..Children::default() } } fn make_info_node() -> Node { Node { name: s("info"), description: s("A child node that describes the schema itself."), children: vec![Children { nodes: vec![ Node { name: s("title"), description: s("The title of the schema or the format it describes"), values: vec![Value { description: s("The title text"), min: Some(1), max: Some(1), validations: vec![Validation::Type(s("string"))], ..Value::default() }], props: vec![Prop { key: s("lang"), id: s("info-lang"), description: s("The language of the text"), validations: vec![Validation::Type(s("string"))], ..Prop::default() }], ..Node::default() }, Node { name: s("description"), description: s("A description of the schema or the format it describes"), values: vec![Value { description: s("The description text"), min: Some(1), max: Some(1), validations: vec![Validation::Type(s("string"))], ..Value::default() }], props: vec![ref_to_id("info-lang")], ..Node::default() }, Node { name: s("author"), description: s("Author of the schema"), values: vec![Value { id: s("info-person-name"), description: s("Person name"), min: Some(1), max: Some(1), validations: vec![Validation::Type(s("string"))], ..Value::default() }], props: vec![Prop { key: s("orcid"), id: s("info-orcid"), description: s("The ORCID of the person"), validations: vec![ Validation::Type(s("string")), Validation::Pattern(s(r"\d{4}-\d{4}-\d{4}-\d{4}")), ], ..Prop::default() }], children: vec![Children { nodes: vec![ref_to_id("info-link")], ..Children::default() }], ..Node::default() }, Node { name: s("contributor"), description: s("Contributor to the schema"), values: vec![ref_to_id("info-person-name")], props: vec![ref_to_id("info-orcid")], children: vec![Children { nodes: vec![ref_to_id("info-link")], ..Children::default() }], ..Node::default() }, Node { name: s("link"), id: s("info-link"), description: s("Links to itself, and to sources describing it"), values: vec![Value { description: s("A URL that the link points to"), min: Some(1), max: Some(1), validations: vec![ Validation::Type(s("string")), Validation::Format(vec![Format::Url, Format::Irl]), ], ..Value::default() }], props: vec![ Prop { key: s("rel"), description: s("The relation between the current entity and the URL"), validations: vec![ Validation::Type(s("string")), Validation::Enum(vec![s("self"), s("documentation")]), ], ..Prop::default() }, ref_to_id("info-lang"), ], ..Node::default() }, Node { name: s("license"), description: s("The license(s) that the schema is licensed under"), values: vec![Value { description: s("Name of the used license"), min: Some(1), max: Some(1), validations: vec![Validation::Type(s("string"))], ..Value::default() }], props: vec![Prop { key: s("spdx"), description: s("An SPDX license identifier"), validations: vec![Validation::Type(s("string"))], ..Prop::default() }], children: vec![Children { nodes: vec![ref_to_id("info-link")], ..Children::default() }], ..Node::default() }, Node { name: s("published"), description: s("When the schema was published"), values: vec![Value { description: s("Publication date"), min: Some(1), max: Some(1), validations: vec![ Validation::Type(s("string")), Validation::Format(vec![Format::Date]), ], ..Value::default() }], props: vec![Prop { key: s("time"), id: s("info-time"), description: s("A time to accompany the date"), validations: vec![ Validation::Type(s("string")), Validation::Format(vec![Format::Time]), ], ..Prop::default() }], ..Node::default() }, Node { name: s("modified"), description: s("When the schema was last modified"), values: vec![Value { description: s("Modification date"), min: Some(1), max: Some(1), validations: vec![ Validation::Type(s("string")), Validation::Format(vec![Format::Date]), ], ..Value::default() }], props: vec![ref_to_id("info-time")], ..Node::default() }, Node { name: s("version"), description: s("The version number of this version of the schema"), values: vec![Value { description: s("Semver version number"), min: Some(1), max: Some(1), validations: vec![ Validation::Type(s("string")), Validation::Pattern(s( r"^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", )), ], ..Value::default() }], ..Node::default() }, ], ..Children::default() }], ..Node::default() } } fn make_schema_info() -> Info { Info { title: vec![TextValue { text: s("KDL Schema"), lang: s("en"), }], description: vec![TextValue { text: s("KDL Schema KDL schema in KDL"), lang: s("en"), }], authors: vec![Person { name: s("Kat Marchán"), orcid: None, links: vec![Link { iri: s("https://github.com/zkat"), rel: s("self"), lang: None, }], }], contributors: vec![Person { name: s("Lars Willighagen"), orcid: None, links: vec![Link { iri: s("https://github.com/larsgw"), rel: s("self"), lang: None, }], }], links: vec![Link { iri: s("https://github.com/zkat/kdl"), rel: s("documentation"), lang: None, }], licenses: vec![License { name: s("Creative Commons Attribution-ShareAlike 4.0 International License"), spdx: s("CC-BY-SA-4.0"), link: vec![Link { iri: s("https://creativecommons.org/licenses/by-sa/4.0/"), rel: None, lang: s("en"), }], }], published: Some(Date { date: s("2021-08-31"), time: None, }), modified: Some(Date { date: s("2021-09-01"), time: None, }), } }