harmos_domain/metadata/
codec.rs1use std::borrow::Cow;
18use super::{Identifier, Metadata};
22use crate::MessageError;
23use crate::message::{PostcardReader as Reader, PostcardValue, decoding_add};
24use crate::schema::declaration::{Definition, Field, Kind};
25use crate::schema::{Cardinality, Described};
26use crate::value::codec::{
27 ENTRY_DEFINITION, TIMESTAMP_DEFINITION, VALUE_DEPTH, entries_memory, entries_size, read_entries, read_timestamp, timestamp_size,
28 write_entries, write_timestamp,
29};
30
31const IDENTIFIER_FIELDS: &[Field] = &[Field {
34 name: Cow::Borrowed("value"),
35 tag: 1,
36 kind: Kind::String,
37 cardinality: Cardinality::Required,
38}];
39
40const METADATA_FIELDS: &[Field] = &[
41 field("identifier", 1, Kind::String, Cardinality::Required),
42 field("label", 2, Kind::String, Cardinality::Required),
43 field("description", 3, Kind::String, Cardinality::Optional),
44 field("tags", 4, Kind::String, Cardinality::Repeated),
45 field("attributes", 5, message(ENTRY_DEFINITION), Cardinality::Repeated),
46 field("created_at", 6, message(TIMESTAMP_DEFINITION), Cardinality::Optional),
47 field("updated_at", 7, message(TIMESTAMP_DEFINITION), Cardinality::Optional),
48];
49
50impl Described for Identifier {
63 const NAME: &'static str = "harmos::Identifier";
64 const FIELDS: &'static [Field] = IDENTIFIER_FIELDS;
65 const MARKER: &'static [u8] = &crate::schema::declaration::encode::<
66 { crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS) },
67 >(Self::NAME, Self::FIELDS);
68}
69
70impl Described for Metadata {
71 const NAME: &'static str = "harmos::Metadata";
72 const FIELDS: &'static [Field] = METADATA_FIELDS;
73 const MARKER: &'static [u8] = &crate::schema::declaration::encode::<
74 { crate::schema::declaration::encoded_len(Self::NAME, Self::FIELDS) },
75 >(Self::NAME, Self::FIELDS);
76}
77
78impl PostcardValue for Metadata {
79 fn write(&self, bytes: &mut Vec<u8>) {
80 self.identifier.write(bytes);
81 self.label.write(bytes);
82 self.description.write(bytes);
83 self.tags.write(bytes);
84 write_entries(&self.attributes, bytes);
85 write_instant(self.created_at, bytes);
86 write_instant(self.updated_at, bytes);
87 }
88
89 fn size(&self) -> usize {
90 self.identifier
91 .size()
92 .saturating_add(self.label.size())
93 .saturating_add(self.description.size())
94 .saturating_add(self.tags.size())
95 .saturating_add(entries_size(&self.attributes))
96 .saturating_add(instant_size(self.created_at))
97 .saturating_add(instant_size(self.updated_at))
98 }
99
100 fn memory(input: &mut Reader<'_>) -> Result<usize, MessageError> {
101 input.nested(|input| {
102 let mut owned = std::mem::size_of::<Self>();
103 for allocation in [
104 Identifier::memory(input)?.saturating_sub(std::mem::size_of::<Identifier>()),
105 String::memory(input)?.saturating_sub(std::mem::size_of::<String>()),
106 Option::<String>::memory(input)?.saturating_sub(std::mem::size_of::<Option<String>>()),
107 Vec::<String>::memory(input)?.saturating_sub(std::mem::size_of::<Vec<String>>()),
108 entries_memory(input, VALUE_DEPTH)?,
109 ] {
110 owned = decoding_add(owned, allocation)?;
111 }
112 read_instant(input)?;
113 read_instant(input)?;
114 Ok(owned)
115 })
116 }
117
118 fn read(input: &mut Reader<'_>) -> Result<Self, MessageError> {
119 input.nested(|input| {
120 let identifier = Identifier::read(input)?;
121 let label = String::read(input)?;
122 let description = Option::<String>::read(input)?;
123 let tags = Vec::<String>::read(input)?;
124 let attributes = read_entries(input, VALUE_DEPTH)?;
125 let created_at = read_instant(input)?;
126 let updated_at = read_instant(input)?;
127 let mut metadata = Self::definition(identifier, label, description, tags);
128 metadata.tags.shrink_to_fit();
129 metadata.attributes = attributes;
130 metadata.created_at = created_at;
131 metadata.updated_at = updated_at;
132 Ok(metadata)
133 })
134 }
135}
136
137const fn field(name: &'static str, tag: u32, kind: Kind, cardinality: Cardinality) -> Field {
142 Field {
143 name: Cow::Borrowed(name),
144 tag,
145 kind,
146 cardinality,
147 }
148}
149
150const fn message(definition: Definition) -> Kind {
151 Kind::Message { definition }
152}
153
154fn write_instant(value: Option<time::OffsetDateTime>, bytes: &mut Vec<u8>) {
155 value.is_some().write(bytes);
156 if let Some(value) = value {
157 write_timestamp(value, bytes);
158 }
159}
160
161fn instant_size(value: Option<time::OffsetDateTime>) -> usize {
162 1usize.saturating_add(value.map_or(0, timestamp_size))
163}
164
165fn read_instant(input: &mut Reader<'_>) -> Result<Option<time::OffsetDateTime>, MessageError> {
166 if bool::read(input)? { read_timestamp(input).map(Some) } else { Ok(None) }
167}
168
169