Skip to main content

ytsaurus_yson/
attributes.rs

1use serde::{
2    Deserialize, Serialize,
3    de::{self, SeqAccess, Visitor},
4};
5use std::{
6    marker::PhantomData,
7    ops::{Deref, DerefMut},
8};
9
10/// Wrapper that pairs a value of type `T` with its associated YSON attributes of type `A`
11///
12/// Any value can have optional map of attributes
13///
14/// # Examples
15///
16/// ```
17/// use ytsaurus_yson::{WithAttributes, from_slice, YsonFormat};
18/// use std::collections::BTreeMap;
19///
20/// // YSON: <author="Alice">"Hello"
21/// let input = b"<author=\"Alice\">\"Hello\"";
22///
23/// // Define a value where attributes are a BTreeMap and the content is a String
24/// type MyNode = WithAttributes<String, BTreeMap<String, String>>;
25///
26/// let node: MyNode = from_slice(input, YsonFormat::Text).unwrap();
27///
28/// // Access attributes
29/// assert_eq!(node.attributes.get("author").unwrap(), "Alice");
30///
31/// // Access inner value directly via Deref or .value
32/// assert_eq!(node.value, "Hello");
33/// assert_eq!(*node, "Hello");
34/// ```
35#[derive(Debug, Clone, PartialEq, Eq, Default)]
36pub struct WithAttributes<T, A> {
37    /// The attributes associated with the value.
38    pub attributes: A,
39    /// Data content of the YSON node.
40    pub value: T,
41}
42
43impl<T: Serialize, A: Serialize> Serialize for WithAttributes<T, A> {
44    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
45        use serde::ser::SerializeStruct;
46        let mut state = serializer.serialize_struct("$__yson_attributes", 2)?;
47        state.serialize_field("$attributes", &self.attributes)?;
48        state.serialize_field("$value", &self.value)?;
49        state.end()
50    }
51}
52
53impl<'de, T, A> Deserialize<'de> for WithAttributes<T, A>
54where
55    T: Deserialize<'de>,
56    A: Deserialize<'de>,
57{
58    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
59        struct WAVisitor<T, A>(PhantomData<(T, A)>);
60
61        impl<'de, T, A> Visitor<'de> for WAVisitor<T, A>
62        where
63            T: Deserialize<'de>,
64            A: Deserialize<'de>,
65        {
66            type Value = WithAttributes<T, A>;
67
68            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
69                formatter.write_str("YSON node with optional attributes")
70            }
71
72            fn visit_seq<V: SeqAccess<'de>>(self, mut seq: V) -> Result<Self::Value, V::Error> {
73                let attributes = seq
74                    .next_element()?
75                    .ok_or_else(|| de::Error::custom("Missing attributes element"))?;
76
77                let value = seq
78                    .next_element()?
79                    .ok_or_else(|| de::Error::custom("Missing value element"))?;
80
81                Ok(WithAttributes { attributes, value })
82            }
83        }
84
85        deserializer.deserialize_struct(
86            "$__yson_attributes",
87            &["$attributes", "$value"],
88            WAVisitor(PhantomData),
89        )
90    }
91}
92
93impl<V, A> Deref for WithAttributes<V, A> {
94    type Target = V;
95
96    fn deref(&self) -> &Self::Target {
97        &self.value
98    }
99}
100
101impl<V, A> DerefMut for WithAttributes<V, A> {
102    fn deref_mut(&mut self) -> &mut Self::Target {
103        &mut self.value
104    }
105}