{-# LANGUAGE OverloadedStrings #-}
module Gram.Schema.Rust
( generateRustTypes
) where
import qualified Data.Text as T
import Data.Text (Text)
generateRustTypes :: Text
generateRustTypes :: Text
generateRustTypes = [Text] -> Text
T.unlines
[ Text
"//! Pattern<Subject> Rust Type Definitions"
, Text
"//! Generated from gram-hs canonical JSON Schema"
, Text
"//! Version: 0.1.0"
, Text
""
, Text
"use serde::{Deserialize, Serialize};"
, Text
"use std::collections::HashMap;"
, Text
""
, Text
"/// A pattern with a subject and optional nested pattern elements."
, Text
"///"
, Text
"/// Patterns are recursive: they can contain other patterns as elements."
, Text
"#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]"
, Text
"pub struct Pattern {"
, Text
" /// The subject of this pattern"
, Text
" pub subject: Subject,"
, Text
" /// Nested pattern elements"
, Text
" pub elements: Vec<Pattern>,"
, Text
"}"
, Text
""
, Text
"impl Pattern {"
, Text
" /// Create a new Pattern with a subject and elements"
, Text
" pub fn new(subject: Subject, elements: Vec<Pattern>) -> Self {"
, Text
" Self { subject, elements }"
, Text
" }"
, Text
""
, Text
" /// Create a new Pattern with a subject and no elements"
, Text
" pub fn leaf(subject: Subject) -> Self {"
, Text
" Self { subject, elements: Vec::new() }"
, Text
" }"
, Text
"}"
, Text
""
, Text
"/// A subject with identity, labels, and properties."
, Text
"#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]"
, Text
"pub struct Subject {"
, Text
" /// Identity symbol for the subject"
, Text
" pub identity: String,"
, Text
" /// Set of labels classifying the subject"
, Text
" pub labels: Vec<String>,"
, Text
" /// Map of property names to values"
, Text
" pub properties: HashMap<String, Value>,"
, Text
"}"
, Text
""
, Text
"impl Subject {"
, Text
" /// Create a new Subject with identity, labels, and properties"
, Text
" pub fn new(identity: String, labels: Vec<String>, properties: HashMap<String, Value>) -> Self {"
, Text
" Self { identity, labels, properties }"
, Text
" }"
, Text
""
, Text
" /// Create a new Subject with just an identity (no labels or properties)"
, Text
" pub fn simple(identity: String) -> Self {"
, Text
" Self {"
, Text
" identity,"
, Text
" labels: Vec::new(),"
, Text
" properties: HashMap::new(),"
, Text
" }"
, Text
" }"
, Text
"}"
, Text
""
, Text
"/// Symbol value with type discriminator"
, Text
"#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]"
, Text
"pub struct ValueSymbol {"
, Text
" #[serde(rename = \"type\")]"
, Text
" pub type_: String,"
, Text
" pub value: String,"
, Text
"}"
, Text
""
, Text
"impl ValueSymbol {"
, Text
" /// Create a new ValueSymbol"
, Text
" pub fn new(value: String) -> Self {"
, Text
" Self {"
, Text
" type_: \"symbol\".to_string(),"
, Text
" value,"
, Text
" }"
, Text
" }"
, Text
"}"
, Text
""
, Text
"/// Tagged string value (e.g., URL, JSON, code)"
, Text
"#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]"
, Text
"pub struct ValueTaggedString {"
, Text
" #[serde(rename = \"type\")]"
, Text
" pub type_: String,"
, Text
" pub tag: String,"
, Text
" pub content: String,"
, Text
"}"
, Text
""
, Text
"impl ValueTaggedString {"
, Text
" /// Create a new ValueTaggedString"
, Text
" pub fn new(tag: String, content: String) -> Self {"
, Text
" Self {"
, Text
" type_: \"tagged\".to_string(),"
, Text
" tag,"
, Text
" content,"
, Text
" }"
, Text
" }"
, Text
"}"
, Text
""
, Text
"/// Numeric range value with optional bounds"
, Text
"#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]"
, Text
"pub struct ValueRange {"
, Text
" #[serde(rename = \"type\")]"
, Text
" pub type_: String,"
, Text
" pub lower: Option<f64>,"
, Text
" pub upper: Option<f64>,"
, Text
"}"
, Text
""
, Text
"impl ValueRange {"
, Text
" /// Create a new ValueRange with both bounds"
, Text
" pub fn new(lower: Option<f64>, upper: Option<f64>) -> Self {"
, Text
" Self {"
, Text
" type_: \"range\".to_string(),"
, Text
" lower,"
, Text
" upper,"
, Text
" }"
, Text
" }"
, Text
""
, Text
" /// Create a closed range (both bounds present)"
, Text
" pub fn closed(lower: f64, upper: f64) -> Self {"
, Text
" Self::new(Some(lower), Some(upper))"
, Text
" }"
, Text
"}"
, Text
""
, Text
"/// Measurement value with unit and numeric value"
, Text
"#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]"
, Text
"pub struct ValueMeasurement {"
, Text
" #[serde(rename = \"type\")]"
, Text
" pub type_: String,"
, Text
" pub unit: String,"
, Text
" pub value: f64,"
, Text
"}"
, Text
""
, Text
"impl ValueMeasurement {"
, Text
" /// Create a new ValueMeasurement"
, Text
" pub fn new(unit: String, value: f64) -> Self {"
, Text
" Self {"
, Text
" type_: \"measurement\".to_string(),"
, Text
" unit,"
, Text
" value,"
, Text
" }"
, Text
" }"
, Text
"}"
, Text
""
, Text
"/// Value can be integer, number, boolean, string, symbol, tagged string,"
, Text
"/// array, map, range, or measurement."
, Text
"///"
, Text
"/// This uses serde's untagged enum for flexible JSON deserialization."
, Text
"/// Complex types use a 'type' field for discrimination."
, Text
"#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]"
, Text
"#[serde(untagged)]"
, Text
"pub enum Value {"
, Text
" /// Symbol value"
, Text
" Symbol(ValueSymbol),"
, Text
" /// Tagged string value"
, Text
" TaggedString(ValueTaggedString),"
, Text
" /// Range value"
, Text
" Range(ValueRange),"
, Text
" /// Measurement value"
, Text
" Measurement(ValueMeasurement),"
, Text
" /// Array of values"
, Text
" Array(Vec<Value>),"
, Text
" /// Map of string keys to values (plain object without 'type' field)"
, Text
" Map(HashMap<String, Value>),"
, Text
" /// Integer or floating-point number"
, Text
" Number(f64),"
, Text
" /// Boolean value"
, Text
" Boolean(bool),"
, Text
" /// String value"
, Text
" String(String),"
, Text
"}"
, Text
""
, Text
"impl Value {"
, Text
" /// Check if this value is a symbol"
, Text
" pub fn is_symbol(&self) -> bool {"
, Text
" matches!(self, Value::Symbol(_))"
, Text
" }"
, Text
""
, Text
" /// Check if this value is a tagged string"
, Text
" pub fn is_tagged_string(&self) -> bool {"
, Text
" matches!(self, Value::TaggedString(_))"
, Text
" }"
, Text
""
, Text
" /// Check if this value is a range"
, Text
" pub fn is_range(&self) -> bool {"
, Text
" matches!(self, Value::Range(_))"
, Text
" }"
, Text
""
, Text
" /// Check if this value is a measurement"
, Text
" pub fn is_measurement(&self) -> bool {"
, Text
" matches!(self, Value::Measurement(_))"
, Text
" }"
, Text
""
, Text
" /// Check if this value is an array"
, Text
" pub fn is_array(&self) -> bool {"
, Text
" matches!(self, Value::Array(_))"
, Text
" }"
, Text
""
, Text
" /// Check if this value is a map"
, Text
" pub fn is_map(&self) -> bool {"
, Text
" matches!(self, Value::Map(_))"
, Text
" }"
, Text
"}"
]