ant_protocol/storage/
header.rs1use crate::error::Error;
10use crate::PrettyPrintRecordKey;
11use bytes::{BufMut, Bytes, BytesMut};
12use libp2p::kad::Record;
13use prometheus_client::encoding::EncodeLabelValue;
14use rmp_serde::Serializer;
15use serde::{Deserialize, Serialize};
16use std::fmt::Display;
17use xor_name::XorName;
18
19#[derive(EncodeLabelValue, Debug, Serialize, Deserialize, Clone, Copy, Eq, PartialEq, Hash)]
21pub enum DataTypes {
22 Chunk,
23 GraphEntry,
24 Pointer,
25 Scratchpad,
26}
27
28impl DataTypes {
29 pub fn get_index(&self) -> u32 {
30 match self {
31 Self::Chunk => 0,
32 Self::GraphEntry => 1,
33 Self::Pointer => 2,
34 Self::Scratchpad => 3,
35 }
36 }
37
38 pub fn from_index(index: u32) -> Option<Self> {
39 match index {
40 0 => Some(Self::Chunk),
41 1 => Some(Self::GraphEntry),
42 2 => Some(Self::Pointer),
43 3 => Some(Self::Scratchpad),
44 _ => None,
45 }
46 }
47}
48
49#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
53pub enum ValidationType {
54 Chunk,
55 NonChunk(XorName),
56}
57
58#[derive(Debug, Serialize, Deserialize)]
59pub struct RecordHeader {
60 pub kind: RecordKind,
61}
62
63#[derive(Debug, Eq, PartialEq, Clone, Copy)]
65pub enum RecordKind {
66 DataOnly(DataTypes),
67 DataWithPayment(DataTypes),
68}
69
70pub const RECORD_KIND_PAYMENT_STARTING_INDEX: u32 = 10;
72
73impl Serialize for RecordKind {
74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75 where
76 S: serde::Serializer,
77 {
78 let index = match self {
79 Self::DataOnly(ref data_types) => data_types.get_index(),
80 Self::DataWithPayment(ref data_types) => {
81 RECORD_KIND_PAYMENT_STARTING_INDEX + data_types.get_index()
82 }
83 };
84 serializer.serialize_u32(index)
85 }
86}
87
88impl<'de> Deserialize<'de> for RecordKind {
89 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
90 where
91 D: serde::Deserializer<'de>,
92 {
93 let num = u32::deserialize(deserializer)?;
94 let data_type_index = if num < RECORD_KIND_PAYMENT_STARTING_INDEX {
95 num
96 } else {
97 num - RECORD_KIND_PAYMENT_STARTING_INDEX
98 };
99
100 if let Some(data_type) = DataTypes::from_index(data_type_index) {
101 if num < RECORD_KIND_PAYMENT_STARTING_INDEX {
102 Ok(Self::DataOnly(data_type))
103 } else {
104 Ok(Self::DataWithPayment(data_type))
105 }
106 } else {
107 Err(serde::de::Error::custom(format!(
108 "Unexpected index {num} for RecordKind variant",
109 )))
110 }
111 }
112}
113impl Display for RecordKind {
114 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115 write!(f, "RecordKind({self:?})")
116 }
117}
118
119impl RecordHeader {
120 pub const SIZE: usize = 2;
121
122 pub fn try_serialize(self) -> Result<BytesMut, Error> {
123 let bytes = BytesMut::new();
124 let mut buf = bytes.writer();
125
126 self.serialize(&mut Serializer::new(&mut buf))
127 .map_err(|err| {
128 error!("Failed to serialized RecordHeader {self:?} with error: {err:?}");
129 Error::RecordHeaderParsingFailed
130 })?;
131
132 let b = buf.into_inner();
133
134 Ok(b)
135 }
136
137 pub fn try_deserialize(bytes: &[u8]) -> Result<Self, Error> {
138 rmp_serde::from_slice(bytes).map_err(|err| {
139 error!("Failed to deserialize RecordHeader with error: {err:?}");
140 Error::RecordHeaderParsingFailed
141 })
142 }
143
144 pub fn from_record(record: &Record) -> Result<Self, Error> {
145 if record.value.len() < RecordHeader::SIZE + 1 {
146 return Err(Error::RecordHeaderParsingFailed);
147 }
148 Self::try_deserialize(&record.value[..RecordHeader::SIZE + 1])
149 }
150
151 pub fn is_record_of_type_chunk(record: &Record) -> Result<bool, Error> {
152 let kind = Self::from_record(record)?.kind;
153 Ok(kind == RecordKind::DataOnly(DataTypes::Chunk))
154 }
155
156 pub fn get_data_type(record: &Record) -> Result<DataTypes, Error> {
157 let kind = Self::from_record(record)?.kind;
158 match kind {
159 RecordKind::DataOnly(data_type) | RecordKind::DataWithPayment(data_type) => {
160 Ok(data_type)
161 }
162 }
163 }
164}
165
166pub fn try_deserialize_record<T: serde::de::DeserializeOwned>(record: &Record) -> Result<T, Error> {
169 let bytes = if record.value.len() > RecordHeader::SIZE {
170 &record.value[RecordHeader::SIZE..]
171 } else {
172 return Err(Error::RecordParsingFailed);
173 };
174 rmp_serde::from_slice(bytes).map_err(|err| {
175 error!(
176 "Failed to deserialized record {} with error: {err:?}",
177 PrettyPrintRecordKey::from(&record.key)
178 );
179 Error::RecordParsingFailed
180 })
181}
182
183pub fn try_serialize_record<T: serde::Serialize>(
186 data: &T,
187 record_kind: RecordKind,
188) -> Result<Bytes, Error> {
189 let mut buf = RecordHeader { kind: record_kind }.try_serialize()?.writer();
190 data.serialize(&mut Serializer::new(&mut buf))
191 .map_err(|err| {
192 error!("Failed to serialized Records with error: {err:?}");
193 Error::RecordParsingFailed
194 })?;
195 let bytes = buf.into_inner();
196 Ok(bytes.freeze())
197}
198
199#[cfg(test)]
200mod tests {
201 use super::*;
202 use crate::error::Result;
203
204 #[test]
205 fn verify_record_header_encoded_size() -> Result<()> {
206 let chunk_with_payment = RecordHeader {
207 kind: RecordKind::DataWithPayment(DataTypes::Chunk),
208 }
209 .try_serialize()?;
210 assert_eq!(chunk_with_payment.len(), RecordHeader::SIZE);
211
212 let chunk = RecordHeader {
213 kind: RecordKind::DataOnly(DataTypes::Chunk),
214 }
215 .try_serialize()?;
216 assert_eq!(chunk.len(), RecordHeader::SIZE);
217
218 let graphentry = RecordHeader {
219 kind: RecordKind::DataOnly(DataTypes::GraphEntry),
220 }
221 .try_serialize()?;
222 assert_eq!(graphentry.len(), RecordHeader::SIZE);
223
224 let scratchpad = RecordHeader {
225 kind: RecordKind::DataOnly(DataTypes::Scratchpad),
226 }
227 .try_serialize()?;
228 assert_eq!(scratchpad.len(), RecordHeader::SIZE);
229
230 let scratchpad_with_payment = RecordHeader {
231 kind: RecordKind::DataWithPayment(DataTypes::Scratchpad),
232 }
233 .try_serialize()?;
234 assert_eq!(scratchpad_with_payment.len(), RecordHeader::SIZE);
235
236 let pointer = RecordHeader {
237 kind: RecordKind::DataOnly(DataTypes::Pointer),
238 }
239 .try_serialize()?;
240 assert_eq!(pointer.len(), RecordHeader::SIZE);
241
242 let pointer_with_payment = RecordHeader {
243 kind: RecordKind::DataWithPayment(DataTypes::Pointer),
244 }
245 .try_serialize()?;
246 assert_eq!(pointer_with_payment.len(), RecordHeader::SIZE);
247
248 Ok(())
249 }
250
251 #[test]
252 fn test_record_kind_serialization() -> Result<()> {
253 let kinds = vec![
254 RecordKind::DataOnly(DataTypes::Chunk),
255 RecordKind::DataWithPayment(DataTypes::Chunk),
256 RecordKind::DataOnly(DataTypes::GraphEntry),
257 RecordKind::DataWithPayment(DataTypes::GraphEntry),
258 RecordKind::DataOnly(DataTypes::Scratchpad),
259 RecordKind::DataWithPayment(DataTypes::Scratchpad),
260 RecordKind::DataOnly(DataTypes::Pointer),
261 RecordKind::DataWithPayment(DataTypes::Pointer),
262 ];
263
264 for kind in kinds {
265 let header = RecordHeader { kind };
266 let header2 = RecordHeader { kind };
267
268 let serialized = header.try_serialize()?;
269 let deserialized = RecordHeader::try_deserialize(&serialized)?;
270 assert_eq!(header2.kind, deserialized.kind);
271 }
272
273 Ok(())
274 }
275}