aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMelody Horn <melody@boringcactus.com>2022-03-26 19:57:57 -0600
committerMelody Horn <melody@boringcactus.com>2022-03-26 19:57:57 -0600
commit26a20cf4f3a71ccdd7c6abb06cffd4c12d08395e (patch)
tree046d933b8847545a7bf392a250d3305c031bc344 /src
parent6f5772173e49f198a18652454ead2a02f8a942af (diff)
downloadkdl-schema-26a20cf4f3a71ccdd7c6abb06cffd4c12d08395e.tar.gz
kdl-schema-26a20cf4f3a71ccdd7c6abb06cffd4c12d08395e.zip
parse schemas with knuffel
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs264
-rw-r--r--src/schema_schema.rs794
2 files changed, 1052 insertions, 6 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 1b4a90c..7f0966b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,8 +1,260 @@
-#[cfg(test)]
-mod tests {
- #[test]
- fn it_works() {
- let result = 2 + 2;
- assert_eq!(result, 4);
+#[cfg(feature = "knuffel")]
+use knuffel::Decode;
+
+pub trait BuildFromRef {
+ fn ref_to(query: impl Into<String>) -> Self;
+}
+
+#[derive(Debug, PartialEq, Eq, Default)]
+#[cfg_attr(feature = "knuffel", derive(Decode))]
+pub struct Schema {
+ #[cfg_attr(feature = "knuffel", knuffel(child))]
+ pub document: Document,
+}
+
+#[derive(Debug, PartialEq, Eq, Default)]
+#[cfg_attr(feature = "knuffel", derive(Decode))]
+pub struct Document {
+ #[cfg_attr(feature = "knuffel", knuffel(child))]
+ pub info: Info,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "node")))]
+ pub nodes: Vec<Node>,
+}
+
+pub use info::Info;
+
+pub mod info {
+ use super::*;
+
+ #[derive(Debug, PartialEq, Eq, Default)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub struct Info {
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "title")))]
+ pub title: Vec<TextValue>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "description")))]
+ pub description: Vec<TextValue>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "author")))]
+ pub authors: Vec<Person>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "contributor")))]
+ pub contributors: Vec<Person>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "link")))]
+ pub links: Vec<Link>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "license")))]
+ pub licenses: Vec<License>,
+ #[cfg_attr(feature = "knuffel", knuffel(child))]
+ pub published: Option<Date>,
+ #[cfg_attr(feature = "knuffel", knuffel(child))]
+ pub modified: Option<Date>,
+ }
+
+ #[derive(Debug, PartialEq, Eq)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub struct TextValue {
+ #[cfg_attr(feature = "knuffel", knuffel(argument))]
+ pub text: String,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub lang: Option<String>,
+ }
+
+ #[derive(Debug, PartialEq, Eq)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub struct Person {
+ #[cfg_attr(feature = "knuffel", knuffel(argument))]
+ pub name: String,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub orcid: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "link")))]
+ pub links: Vec<Link>,
+ }
+
+ #[derive(Debug, PartialEq, Eq)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub struct Link {
+ #[cfg_attr(feature = "knuffel", knuffel(argument))]
+ pub iri: String,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub rel: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub lang: Option<String>,
+ }
+
+ #[derive(Debug, PartialEq, Eq)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub struct License {
+ #[cfg_attr(feature = "knuffel", knuffel(argument))]
+ pub name: String,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub spdx: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "link")))]
+ pub link: Vec<Link>,
+ }
+
+ #[derive(Debug, PartialEq, Eq)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub struct Date {
+ #[cfg_attr(feature = "knuffel", knuffel(argument))]
+ pub date: String,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub time: Option<String>,
+ }
+}
+
+pub use node::Node;
+
+pub mod node {
+ use super::*;
+
+ #[derive(Debug, PartialEq, Eq, Default)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub struct Node {
+ #[cfg_attr(feature = "knuffel", knuffel(argument))]
+ pub name: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub id: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub description: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub ref_: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(child, unwrap(argument)))]
+ pub min: Option<usize>,
+ #[cfg_attr(feature = "knuffel", knuffel(child, unwrap(argument)))]
+ pub max: Option<usize>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "prop")))]
+ pub props: Vec<Prop>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "value")))]
+ pub values: Vec<Value>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "children")))]
+ pub children: Vec<Children>,
+ }
+
+ impl BuildFromRef for Node {
+ fn ref_to(query: impl Into<String>) -> Self {
+ Self {
+ ref_: Some(query.into()),
+ ..Self::default()
+ }
+ }
+ }
+
+ #[derive(Debug, PartialEq, Eq, Default)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub struct Prop {
+ #[cfg_attr(feature = "knuffel", knuffel(argument))]
+ pub key: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub id: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub description: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub ref_: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(child))]
+ pub required: bool,
+ #[cfg_attr(feature = "knuffel", knuffel(children))]
+ pub validations: Vec<Validation>,
+ }
+
+ impl BuildFromRef for Prop {
+ fn ref_to(query: impl Into<String>) -> Self {
+ Self {
+ ref_: Some(query.into()),
+ ..Self::default()
+ }
+ }
+ }
+
+ #[derive(Debug, PartialEq, Eq, Default)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub struct Value {
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub id: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub description: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub ref_: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(child, unwrap(argument)))]
+ pub min: Option<usize>,
+ #[cfg_attr(feature = "knuffel", knuffel(child, unwrap(argument)))]
+ pub max: Option<usize>,
+ #[cfg_attr(feature = "knuffel", knuffel(children))]
+ pub validations: Vec<Validation>,
+ }
+
+ impl BuildFromRef for Value {
+ fn ref_to(query: impl Into<String>) -> Self {
+ Self {
+ ref_: Some(query.into()),
+ ..Self::default()
+ }
+ }
+ }
+
+ #[derive(Debug, PartialEq, Eq, Default)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub struct Children {
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub id: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub description: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(property))]
+ pub ref_: Option<String>,
+ #[cfg_attr(feature = "knuffel", knuffel(children(name = "node")))]
+ pub nodes: Vec<Node>,
+ }
+
+ impl BuildFromRef for Children {
+ fn ref_to(query: impl Into<String>) -> Self {
+ Self {
+ ref_: Some(query.into()),
+ ..Self::default()
+ }
+ }
+ }
+
+ pub use validation::Validation;
+
+ pub mod validation {
+ #[cfg(feature = "knuffel")]
+ use knuffel::{Decode, DecodeScalar};
+
+ #[derive(Debug, PartialEq, Eq)]
+ #[cfg_attr(feature = "knuffel", derive(Decode))]
+ pub enum Validation {
+ Type(#[cfg_attr(feature = "knuffel", knuffel(argument))] String),
+ Enum(#[cfg_attr(feature = "knuffel", knuffel(arguments))] Vec<String>),
+ Pattern(#[cfg_attr(feature = "knuffel", knuffel(argument))] String),
+ Format(#[cfg_attr(feature = "knuffel", knuffel(arguments))] Vec<Format>),
+ }
+
+ #[derive(Debug, PartialEq, Eq)]
+ #[cfg_attr(feature = "knuffel", derive(DecodeScalar))]
+ pub enum Format {
+ DateTime,
+ Date,
+ Time,
+ Duration,
+ Decimal,
+ Currency,
+ Country2,
+ Country3,
+ CountrySubdivision,
+ Email,
+ IdnEmail,
+ Hostname,
+ IdnHostname,
+ Ipv4,
+ Ipv6,
+ Url,
+ UrlReference,
+ Irl,
+ IrlReference,
+ UrlTemplate,
+ Uuid,
+ Regex,
+ Base64,
+ KdlQuery,
+ }
}
}
+
+mod schema_schema;
+pub use schema_schema::SCHEMA_SCHEMA;
diff --git a/src/schema_schema.rs b/src/schema_schema.rs
new file mode 100644
index 0000000..d548f5a
--- /dev/null
+++ b/src/schema_schema.rs
@@ -0,0 +1,794 @@
+use lazy_static::lazy_static;
+
+use super::node::validation::*;
+use super::node::*;
+use super::*;
+
+lazy_static! {
+ pub static ref SCHEMA_SCHEMA: Schema = make_schema_schema();
+}
+
+fn s<T: From<String>>(text: &str) -> T {
+ T::from(text.to_string())
+}
+
+fn ref_to_id<T: BuildFromRef>(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")],
+ ..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![info::TextValue {
+ text: s("KDL Schema"),
+ lang: s("en"),
+ }],
+ description: vec![info::TextValue {
+ text: s("KDL Schema KDL schema in KDL"),
+ lang: s("en"),
+ }],
+ authors: vec![info::Person {
+ name: s("Kat Marchán"),
+ orcid: None,
+ links: vec![info::Link {
+ iri: s("https://github.com/zkat"),
+ rel: s("self"),
+ lang: None,
+ }],
+ }],
+ contributors: vec![info::Person {
+ name: s("Lars Willighagen"),
+ orcid: None,
+ links: vec![info::Link {
+ iri: s("https://github.com/larsgw"),
+ rel: s("self"),
+ lang: None,
+ }],
+ }],
+ links: vec![info::Link {
+ iri: s("https://github.com/zkat/kdl"),
+ rel: s("documentation"),
+ lang: None,
+ }],
+ licenses: vec![info::License {
+ name: s("Creative Commons Attribution-ShareAlike 4.0 International License"),
+ spdx: s("CC-BY-SA-4.0"),
+ link: vec![info::Link {
+ iri: s("https://creativecommons.org/licenses/by-sa/4.0/"),
+ rel: None,
+ lang: s("en"),
+ }],
+ }],
+ published: Some(info::Date {
+ date: s("2021-08-31"),
+ time: None,
+ }),
+ modified: Some(info::Date {
+ date: s("2021-09-01"),
+ time: None,
+ }),
+ }
+}