plotnik_lib/engine/
value.rs

1//! Types for representing query results.
2
3use super::effect_stream::{CapturedNode, VerboseNode};
4use crate::ir::{CompiledQuery, DataFieldId, VariantTagId};
5use serde::Serialize;
6use serde::ser::{SerializeMap, SerializeSeq, SerializeStruct};
7use std::collections::BTreeMap;
8
9/// A structured value produced by a query.
10#[derive(Debug, Clone, PartialEq, Serialize)]
11#[serde(untagged)]
12pub enum Value<'tree> {
13    /// Represents a missing optional value. Serializes to `null`.
14    Null,
15    /// An AST node capture.
16    Node(CapturedNode<'tree>),
17    /// A string, typically from a `:: string` conversion.
18    String(String),
19    /// A list of values, from a `*` or `+` capture.
20    Array(Vec<Value<'tree>>),
21    /// A map of field names to values, from a `{...}` capture.
22    Object(BTreeMap<DataFieldId, Value<'tree>>),
23    /// A tagged union, from a `[...]` capture with labels.
24    Variant {
25        tag: VariantTagId,
26        value: Box<Value<'tree>>,
27    },
28}
29
30/// Wrapper for verbose serialization of a Value.
31/// Nodes include full positional information (bytes + line/column).
32pub struct VerboseValue<'a, 'tree>(pub &'a Value<'tree>);
33
34impl Serialize for VerboseValue<'_, '_> {
35    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36    where
37        S: serde::Serializer,
38    {
39        match self.0 {
40            Value::Null => serializer.serialize_none(),
41            Value::Node(node) => VerboseNode(node).serialize(serializer),
42            Value::String(s) => serializer.serialize_str(s),
43            Value::Array(arr) => {
44                let mut seq = serializer.serialize_seq(Some(arr.len()))?;
45                for item in arr {
46                    seq.serialize_element(&VerboseValue(item))?;
47                }
48                seq.end()
49            }
50            Value::Object(obj) => {
51                let mut map = serializer.serialize_map(Some(obj.len()))?;
52                for (k, v) in obj {
53                    map.serialize_entry(&k, &VerboseValue(v))?;
54                }
55                map.end()
56            }
57            Value::Variant { tag, value } => {
58                let mut state = serializer.serialize_struct("Variant", 2)?;
59                state.serialize_field("$tag", tag)?;
60                state.serialize_field("$data", &VerboseValue(value))?;
61                state.end()
62            }
63        }
64    }
65}
66
67/// Wrapper for serialization that resolves string IDs to actual strings.
68/// Object field names and variant tags are resolved via CompiledQuery.
69pub struct ResolvedValue<'a, 'tree>(pub &'a Value<'tree>, pub &'a CompiledQuery);
70
71impl Serialize for ResolvedValue<'_, '_> {
72    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
73    where
74        S: serde::Serializer,
75    {
76        let ResolvedValue(value, query) = self;
77        match value {
78            Value::Null => serializer.serialize_none(),
79            Value::Node(node) => node.serialize(serializer),
80            Value::String(s) => serializer.serialize_str(s),
81            Value::Array(arr) => {
82                let mut seq = serializer.serialize_seq(Some(arr.len()))?;
83                for item in arr {
84                    seq.serialize_element(&ResolvedValue(item, query))?;
85                }
86                seq.end()
87            }
88            Value::Object(obj) => {
89                let mut map = serializer.serialize_map(Some(obj.len()))?;
90                for (k, v) in obj {
91                    let key = query.string(*k);
92                    map.serialize_entry(key, &ResolvedValue(v, query))?;
93                }
94                map.end()
95            }
96            Value::Variant { tag, value } => {
97                let mut state = serializer.serialize_struct("Variant", 2)?;
98                let tag_str = query.string(*tag);
99                state.serialize_field("$tag", tag_str)?;
100                state.serialize_field("$data", &ResolvedValue(value, query))?;
101                state.end()
102            }
103        }
104    }
105}
106
107/// Wrapper for verbose serialization with resolved string IDs.
108/// Combines VerboseValue (full node positions) with ResolvedValue (string resolution).
109pub struct VerboseResolvedValue<'a, 'tree>(pub &'a Value<'tree>, pub &'a CompiledQuery);
110
111impl Serialize for VerboseResolvedValue<'_, '_> {
112    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
113    where
114        S: serde::Serializer,
115    {
116        let VerboseResolvedValue(value, query) = self;
117        match value {
118            Value::Null => serializer.serialize_none(),
119            Value::Node(node) => VerboseNode(node).serialize(serializer),
120            Value::String(s) => serializer.serialize_str(s),
121            Value::Array(arr) => {
122                let mut seq = serializer.serialize_seq(Some(arr.len()))?;
123                for item in arr {
124                    seq.serialize_element(&VerboseResolvedValue(item, query))?;
125                }
126                seq.end()
127            }
128            Value::Object(obj) => {
129                let mut map = serializer.serialize_map(Some(obj.len()))?;
130                for (k, v) in obj {
131                    let key = query.string(*k);
132                    map.serialize_entry(key, &VerboseResolvedValue(v, query))?;
133                }
134                map.end()
135            }
136            Value::Variant { tag, value } => {
137                let mut state = serializer.serialize_struct("Variant", 2)?;
138                let tag_str = query.string(*tag);
139                state.serialize_field("$tag", tag_str)?;
140                state.serialize_field("$data", &VerboseResolvedValue(value, query))?;
141                state.end()
142            }
143        }
144    }
145}