spectrusty_core/memory/
serde.rs1use core::fmt;
10use std::borrow::Cow;
11use std::rc::Rc;
12use std::convert::TryInto;
13#[cfg(feature = "compression")] use core::iter::FromIterator;
14#[cfg(feature = "compression")] use compression::prelude::*;
15#[cfg(feature = "compression")] use serde::ser;
16
17use serde::{
18 Serializer, Deserialize, Deserializer,
19 de::{self, Visitor}
20};
21
22pub fn serialize_mem<T, S>(mem: &T, serializer: S) -> Result<S::Ok, S::Error>
23 where S: Serializer,
24 T: MemSerExt
25{
26 #[cfg(not(feature = "compression"))]
27 {
28 serialize_mem_slice(mem.as_slice(), serializer)
29 }
30 #[cfg(feature = "compression")]
31 {
32 let compr = mem.as_slice().iter().copied()
33 .encode(&mut GZipEncoder::new(), Action::Finish)
34 .collect::<Result<Vec<_>, _>>()
35 .map_err(ser::Error::custom)?;
36 serialize_mem_slice(&compr, serializer)
37 }
38}
39
40pub fn serialize_mem_slice<S>(slice: &[u8], serializer: S) -> Result<S::Ok, S::Error>
41 where S: Serializer
42{
43 if serializer.is_human_readable() {
44 serializer.serialize_str(&base64::encode(slice))
45 }
46 else {
47 serializer.serialize_bytes(slice)
48 }
49}
50
51pub fn deserialize_mem<'de, T, D>(deserializer: D) -> Result<T, D::Error>
52 where T: MemDeExt,
53 D: Deserializer<'de>
54{
55 if deserializer.is_human_readable() {
56 Deserialize::deserialize(deserializer).and_then(|string: Cow<str>|
57 base64::decode(&*string).map_err(de::Error::custom)
58 )
59 .and_then(T::try_from_byte_buf)
60 }
61 else if T::PREFER_FROM_BYTE_BUF {
62 deserializer.deserialize_byte_buf(ByteBufVisitor)
63 .and_then(T::try_from_byte_buf)
64 }
65 else {
66 Deserialize::deserialize(deserializer)
67 .and_then(T::try_from_bytes)
68 }
69}
70
71pub trait MemSerExt: Sized {
72 fn as_slice(&self) -> &[u8];
73}
74
75pub trait MemDeExt: Sized {
76 const PREFER_FROM_BYTE_BUF: bool;
77 fn try_from_byte_buf<E: de::Error>(buf: Vec<u8>) -> Result<Self, E>;
78 fn try_from_bytes<E: de::Error>(slice: &[u8]) -> Result<Self, E>;
79}
80
81impl<const LEN: usize> MemSerExt for Box<[u8;LEN]> {
82 fn as_slice(&self) -> &[u8] {
83 &self[..]
84 }
85}
86
87impl<const LEN: usize> MemDeExt for Box<[u8;LEN]> {
88 const PREFER_FROM_BYTE_BUF: bool = true;
89
90 #[allow(unused_mut)]
91 fn try_from_byte_buf<E: de::Error>(mut buf: Vec<u8>) -> Result<Self, E> {
92 #[cfg(feature = "compression")]
93 {
94 if is_compressed(&buf) {
95 buf = decompress(&buf)?;
96 }
97 }
98 let buf = buf.into_boxed_slice();
99 buf.try_into().map_err(|buf: Box<[_]>|
100 de::Error::custom(
101 format!("failed to deserialize memory, {} bytes required, received: {}",
102 LEN, buf.len())))
103 }
104
105 fn try_from_bytes<E: de::Error>(slice: &[u8]) -> Result<Self, E> {
106 #[cfg(feature = "compression")]
107 {
108 if is_compressed(slice) {
109 return Self::try_from_byte_buf(decompress(slice)?)
110 }
111 }
112 Self::try_from_byte_buf(Vec::from(slice))
113 }
114}
115
116impl<const LEN: usize> MemDeExt for [u8;LEN] {
117 const PREFER_FROM_BYTE_BUF: bool = false;
118
119 fn try_from_byte_buf<E: de::Error>(buf: Vec<u8>) -> Result<Self, E> {
120 Self::try_from_bytes(&buf)
121 }
122
123 fn try_from_bytes<E: de::Error>(slice: &[u8]) -> Result<Self, E> {
124 slice.try_into().map_err(|_|
125 de::Error::custom(
126 format!("failed to deserialize a byte array, {} bytes required, received: {}",
127 LEN, slice.len())))
128 }
129}
130
131impl<'a, T: MemSerExt> MemSerExt for &'a T {
132 fn as_slice(&self) -> &[u8] {
133 T::as_slice(self)
134 }
135}
136
137impl MemSerExt for Rc<[u8]> {
138 fn as_slice(&self) -> &[u8] {
139 &self[..]
140 }
141}
142
143impl MemDeExt for Rc<[u8]> {
144 const PREFER_FROM_BYTE_BUF: bool = false;
145
146 fn try_from_byte_buf<E: de::Error>(buf: Vec<u8>) -> Result<Self, E> {
147 #[cfg(feature = "compression")]
148 {
149 if is_compressed(&buf) {
150 return decompress(&buf)
151 }
152 }
153 Ok(Rc::from(buf))
154 }
155
156 fn try_from_bytes<E: de::Error>(slice: &[u8]) -> Result<Self, E> {
157 #[cfg(feature = "compression")]
158 {
159 if is_compressed(slice) {
160 return decompress(slice)
161 }
162 }
163 Ok(Rc::from(slice))
164 }
165}
166
167struct ByteBufVisitor;
168
169impl Visitor<'_> for ByteBufVisitor {
170 type Value = Vec<u8>;
171
172 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
173 formatter.write_str("a byte array")
174 }
175
176 fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<Self::Value, E> {
177 Ok(v)
178 }
179
180 fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
181 Ok(Vec::from(v))
182 }
183
184 fn visit_string<E: de::Error>(self, v: String) -> Result<Self::Value, E> {
185 Ok(Vec::from(v))
186 }
187
188 fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
189 Ok(Vec::from(v))
190 }
191
192}
193
194#[cfg(feature = "compression")]
195fn is_compressed(data: &[u8]) -> bool {
196 match data.get(0..3) {
197 Some(&[0x1f, 0x8b, 0x08]) => true,
198 _ => false
200 }
201}
202
203#[cfg(feature = "compression")]
204fn decompress<T: FromIterator<u8>, E: de::Error>(data: &[u8]) -> Result<T, E> {
205 data.iter().copied()
206 .decode(&mut GZipDecoder::new())
207 .collect::<Result<T, _>>()
208 .map_err(de::Error::custom)
209}