harmos_storage/
schema_encoding.rs1use serde::de::{DeserializeSeed, Error as _, IntoDeserializer, MapAccess, Visitor};
20use serde::ser::SerializeStruct;
21use serde::{Deserialize, Deserializer, Serialize, Serializer};
22use super::manager::encoded_size;
24use super::{SchemaKey, StorageCursor, StorageSchema};
25use crate::{Error, Result};
26
27struct Input<A> {
36 map: A,
37 position: Option<StorageCursor>,
38 key: Option<SchemaKey>,
39 encoding: Option<Encoding>,
40}
41
42struct StorageVisitor;
43
44#[derive(Deserialize)]
47#[serde(rename_all = "snake_case")]
48enum Encoding {
49 GraphV1,
50}
51
52impl StorageSchema {
57 pub(super) fn encoded_bytes(&self) -> Result<usize> {
58 self.schema.preparation(&harmos_domain::config::SchemaSettings::default()).map_err(|_| invalid())?;
59 encoded_size(self)
60 }
61}
62
63impl Serialize for StorageSchema {
64 fn serialize<S: Serializer>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error> {
65 let mut output = serializer.serialize_struct("StorageSchema", 5)?;
66 output.serialize_field("position", &self.position)?;
67 output.serialize_field("key", &self.key)?;
68 output.serialize_field("encoding", "graph_v1")?;
69 output.serialize_field("root", &self.schema.root)?;
70 output.serialize_field("definitions", &self.schema.definitions)?;
71 output.end()
72 }
73}
74
75impl<'de> Deserialize<'de> for StorageSchema {
76 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> std::result::Result<Self, D::Error> {
77 deserializer.deserialize_map(StorageVisitor).map_err(|error| D::Error::custom(format!(
78 "invalid graph_v1 storage schema: {error}; inline metadata is unsupported; retain the original data and select a fresh storage root",
79 )))
80 }
81}
82
83impl<'de> Visitor<'de> for StorageVisitor {
84 type Value = StorageSchema;
85 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
86 formatter.write_str("bounded graph_v1 storage metadata")
87 }
88 fn visit_map<A: MapAccess<'de>>(self, map: A) -> std::result::Result<Self::Value, A::Error> {
89 let mut input = Input {
90 map,
91 position: None,
92 key: None,
93 encoding: None,
94 };
95 let schema = crate::schema::graph::Seed {
98 settings: &harmos_domain::config::SchemaSettings::default(),
99 }
100 .deserialize(serde::de::value::MapAccessDeserializer::new(&mut input))?;
101 let Encoding::GraphV1 = input.encoding.ok_or_else(|| A::Error::missing_field("encoding"))?;
102 Ok(StorageSchema::new(
103 input.position.ok_or_else(|| A::Error::missing_field("position"))?,
104 input.key.ok_or_else(|| A::Error::missing_field("key"))?,
105 schema,
106 ))
107 }
108}
109
110impl<'de, A: MapAccess<'de>> MapAccess<'de> for Input<A> {
111 type Error = A::Error;
112 fn next_key_seed<K: DeserializeSeed<'de>>(&mut self, seed: K) -> std::result::Result<Option<K::Value>, A::Error> {
113 while let Some(key) = self.map.next_key::<String>()? {
114 match key.as_str() {
115 "position" => {
116 if self.position.is_some() {
117 return Err(A::Error::duplicate_field("position"));
118 }
119 self.position = Some(self.map.next_value()?);
120 }
121 "key" => {
122 if self.key.is_some() {
123 return Err(A::Error::duplicate_field("key"));
124 }
125 self.key = Some(self.map.next_value()?);
126 }
127 "encoding" => {
128 if self.encoding.is_some() {
129 return Err(A::Error::duplicate_field("encoding"));
130 }
131 self.encoding = Some(self.map.next_value()?);
132 }
133 _ => return seed.deserialize(key.into_deserializer()).map(Some),
134 }
135 }
136 Ok(None)
137 }
138 fn next_value_seed<V: DeserializeSeed<'de>>(&mut self, seed: V) -> std::result::Result<V::Value, A::Error> {
139 self.map.next_value_seed(seed)
140 }
141}
142
143fn invalid() -> Error {
148 Error::InvalidInput {
149 field: "storage schema",
150 reason: "invalid shared schema preparation",
151 }
152}
153
154