harmos_domain/model/storage/position/
codec.rs1use std::borrow::Cow;
18use std::num::NonZeroUsize;
19use super::{StorageCursor, StoreHistory};
23use crate::schema::declaration::{Field, Kind};
24use crate::schema::{Cardinality, Described};
25use crate::{Error, Identifier, MemorySize, Message, Result};
26
27impl StoreHistory {
42 pub fn encode_bounded(&self, max_bytes: NonZeroUsize) -> Result<Vec<u8>> {
43 encode_bounded(self, max_bytes)
44 }
45
46 pub fn decode_bounded(bytes: &[u8], max_bytes: NonZeroUsize) -> Result<Self> {
47 decode_bounded(bytes, max_bytes)
48 }
49}
50
51impl StorageCursor {
52 pub fn encode_bounded(&self, max_bytes: NonZeroUsize) -> Result<Vec<u8>> {
53 encode_bounded(self, max_bytes)
54 }
55
56 pub fn decode_bounded(bytes: &[u8], max_bytes: NonZeroUsize) -> Result<Self> {
57 decode_bounded(bytes, max_bytes)
58 }
59}
60
61crate::postcard_product!(StoreHistory { store: Identifier, epoch: Identifier });
62crate::postcard_product!(StorageCursor { history: StoreHistory, sequence: u64 });
63
64impl Described for StoreHistory {
65 const NAME: &'static str = concat!(module_path!(), "::", stringify!(StoreHistory));
66 const FIELDS: &'static [Field] = &[
67 Field { name: Cow::Borrowed("store"), tag: 1, kind: Kind::String, cardinality: Cardinality::Required },
68 Field { name: Cow::Borrowed("epoch"), tag: 2, kind: Kind::String, cardinality: Cardinality::Required },
69 ];
70
71 const MARKER: &'static [u8] = &crate::schema::declaration::encode::<
72 { crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS) },
73 >(Self::NAME, Self::FIELDS);
74}
75
76impl Described for StorageCursor {
77 const NAME: &'static str = concat!(module_path!(), "::", stringify!(StorageCursor));
78 const FIELDS: &'static [Field] = &[
79 Field {
80 name: Cow::Borrowed("history"),
81 tag: 1,
82 kind: Kind::Message { definition: StoreHistory::DEFINITION },
83 cardinality: Cardinality::Required,
84 },
85 Field { name: Cow::Borrowed("sequence"), tag: 2, kind: Kind::U64, cardinality: Cardinality::Required },
86 ];
87
88 const MARKER: &'static [u8] = &crate::schema::declaration::encode::<
89 { crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS) },
90 >(Self::NAME, Self::FIELDS);
91}
92
93pub fn encode_bounded<T: Message>(value: &T, max_bytes: NonZeroUsize) -> Result<Vec<u8>> {
96 if value.encoded_len() > max_bytes.get() {
97 return Err(bound_error());
98 }
99 Ok(value.encode_to_vec())
100}
101
102pub fn decode_bounded<T: Message + MemorySize>(bytes: &[u8], max_bytes: NonZeroUsize) -> Result<T> {
103 let required =
104 T::decoding_memory(bytes).map_err(|_| Error::InvalidInput { field: "storage native codec", reason: "invalid encoding" })?;
105 if required > max_bytes.get() {
106 return Err(bound_error());
107 }
108 let value = T::decode(bytes).map_err(|_| Error::InvalidInput { field: "storage native codec", reason: "invalid encoding" })?;
109 if value.memory_size() > max_bytes.get() {
110 return Err(bound_error());
111 }
112 Ok(value)
113}
114
115fn bound_error() -> Error {
118 Error::InvalidInput { field: "storage native codec", reason: "value exceeds allowance" }
119}
120
121