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