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 {
68 name: Cow::Borrowed("store"),
69 tag: 1,
70 kind: Kind::String,
71 cardinality: Cardinality::Required,
72 },
73 Field {
74 name: Cow::Borrowed("epoch"),
75 tag: 2,
76 kind: Kind::String,
77 cardinality: Cardinality::Required,
78 },
79 ];
80
81 const MARKER: &'static [u8] = &crate::schema::declaration::encode::<
82 { crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS) },
83 >(Self::NAME, Self::FIELDS);
84}
85
86impl Described for StorageCursor {
87 const NAME: &'static str = concat!(module_path!(), "::", stringify!(StorageCursor));
88 const FIELDS: &'static [Field] = &[
89 Field {
90 name: Cow::Borrowed("history"),
91 tag: 1,
92 kind: Kind::Message { definition: StoreHistory::DEFINITION },
93 cardinality: Cardinality::Required,
94 },
95 Field {
96 name: Cow::Borrowed("sequence"),
97 tag: 2,
98 kind: Kind::U64,
99 cardinality: Cardinality::Required,
100 },
101 ];
102
103 const MARKER: &'static [u8] = &crate::schema::declaration::encode::<
104 { crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS) },
105 >(Self::NAME, Self::FIELDS);
106}
107
108pub fn encode_bounded<T: Message>(value: &T, max_bytes: NonZeroUsize) -> Result<Vec<u8>> {
111 if value.encoded_size() > max_bytes.get() {
112 return Err(bound_error());
113 }
114 Ok(value.encode())
115}
116
117pub fn decode_bounded<T: Message + MemorySize>(bytes: &[u8], max_bytes: NonZeroUsize) -> Result<T> {
118 let required = T::decoding_memory(bytes).map_err(|_| Error::InvalidInput {
119 field: "storage native codec",
120 reason: "invalid encoding",
121 })?;
122 if required > max_bytes.get() {
123 return Err(bound_error());
124 }
125 let value = T::decode(bytes).map_err(|_| Error::InvalidInput {
126 field: "storage native codec",
127 reason: "invalid encoding",
128 })?;
129 if value.memory_size() > max_bytes.get() {
130 return Err(bound_error());
131 }
132 Ok(value)
133}
134
135fn bound_error() -> Error {
138 Error::InvalidInput {
139 field: "storage native codec",
140 reason: "value exceeds allowance",
141 }
142}
143
144