eure_document/
data_model.rs

1use crate::prelude_internal::*;
2use crate::value::Map;
3
4/// Data model of a document or a value in a document. Corresponds to the `$data-model` extension.
5#[derive(Debug, Clone, Copy, PartialEq, Default)]
6pub enum DataModel {
7    /// Serde compatible data model.
8    Rust,
9    /// JSON compatible data model.
10    Json,
11    /// Eure full data model including path.
12    #[default]
13    Eure,
14}
15
16#[derive(Debug, Clone, PartialEq, Default)]
17pub struct DataModelConfig {
18    pub data_model: DataModel,
19    pub variant_repr: VariantRepr,
20    pub number_key_repr: NumberKeyRepr,
21    pub tuple_key_repr: TupleKeyRepr,
22    pub boolean_key_repr: BooleanKeyRepr,
23    pub tuple_repr: TupleRepr,
24}
25
26#[derive(Debug, Clone, PartialEq, Default)]
27/// How to represent numeric keys in a data model that does not support numbers as object keys. Corresponds to the `$number-key-repr` extension.
28pub enum NumberKeyRepr {
29    /// Represent number as string.
30    String,
31    /// Error on conversion.
32    #[default]
33    Error,
34}
35
36#[derive(Debug, Clone, PartialEq, Default)]
37/// How to represent tuple keys in a data model that does not support tuples as object keys. Corresponds to the `$tuple-key-repr` extension.
38pub enum TupleKeyRepr {
39    /// Represent tuple as string. e.g. "(1,2,3)".
40    String,
41    /// Error on conversion.
42    #[default]
43    Error,
44}
45
46#[derive(Debug, Clone, PartialEq, Default)]
47/// How to represent boolean keys in a data model that does not support booleans as object keys. Corresponds to the `$boolean-key-repr` extension.
48pub enum BooleanKeyRepr {
49    /// Represent boolean as string. e.g. "true" or "false".
50    String,
51    /// Error on conversion.
52    #[default]
53    Error,
54}
55
56#[derive(Debug, Clone, PartialEq, Default)]
57/// How to represent tuples in a data model that does not support tuples. Corresponds to the `$tuple-repr` extension.
58pub enum TupleRepr {
59    /// Represent tuple as array. e.g. "[1,2,3]".
60    Array,
61    /// Represent tuple as number indexed object. e.g. `{0: 1, 1: 2, 2: 3}`. `{"0": 1, "1": 2, "2": 3}` if `NumberKeyRepr` is `String`.
62    NumberIndexedObject,
63    /// Error on conversion.
64    #[default]
65    Error,
66}
67
68#[derive(Debug, Clone, PartialEq, Default)]
69/// How to represent variant in a data model. Corresponds to the `$variant-repr` extension.
70pub enum VariantRepr {
71    /// Default representation: {"variant-name": {...}}
72    #[default]
73    External,
74
75    /// Internal tagging: {"type": "variant-name", ...fields...}
76    Internal { tag: String },
77
78    /// Adjacent tagging: {"type": "variant-name", "content": {...}}
79    Adjacent { tag: String, content: String },
80
81    /// Untagged: just the content without variant information
82    Untagged,
83}
84
85impl VariantRepr {
86    /// Create a VariantRepr from $variant-repr annotation value
87    pub fn from_annotation(value: &Value) -> Option<Self> {
88        match value {
89            Value::Primitive(PrimitiveValue::Text(t)) if t.as_str() == "untagged" => {
90                Some(VariantRepr::Untagged)
91            }
92            Value::Map(Map(map)) => {
93                let tag = map
94                    .get(&ObjectKey::String("tag".to_string()))
95                    .and_then(|v| match v {
96                        Value::Primitive(PrimitiveValue::Text(t)) => Some(t.as_str().to_string()),
97                        _ => None,
98                    });
99
100                let content = map
101                    .get(&ObjectKey::String("content".to_string()))
102                    .and_then(|v| match v {
103                        Value::Primitive(PrimitiveValue::Text(t)) => Some(t.as_str().to_string()),
104                        _ => None,
105                    });
106
107                match (tag, content) {
108                    (Some(tag), Some(content)) => Some(VariantRepr::Adjacent { tag, content }),
109                    (Some(tag), None) => Some(VariantRepr::Internal { tag }),
110                    _ => None,
111                }
112            }
113            _ => None,
114        }
115    }
116}
117
118/// How to represent text with non-plaintext language in a data model.
119///
120/// This controls how `Text` values with `Language::Other(lang)` are serialized
121/// to formats that don't natively support language-tagged text.
122///
123/// Corresponds to the `$text-repr` extension (formerly `$code-repr`).
124#[derive(Debug, Clone, PartialEq, Default)]
125pub enum TextRepr {
126    /// Markdown code block string.
127    /// e.g. "```rust\nfn main() { println!(\"Hello, world!\"); }\n```".
128    Markdown,
129    /// Content only string, discarding language information.
130    /// e.g. "fn main() { println!(\"Hello, world!\"); }".
131    String,
132    /// Object with language and content fields.
133    /// e.g. `{"language": "rust", "content": "fn main() { println!(\"Hello, world!\"); }"}`.
134    Object {
135        language_key: String,
136        content_key: String,
137    },
138    /// Error on conversion.
139    #[default]
140    Error,
141}