1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use crate::builtins::{Lazy, WasmbinCountable};
use crate::io::{Decode, DecodeError, Encode};
use crate::visit::Visit;
use arbitrary::Arbitrary;
#[derive(Debug, Arbitrary, PartialEq, Eq, Hash, Clone, Visit)]
pub struct RawBlob<T = Vec<u8>> {
pub contents: T,
}
impl<T: AsRef<[u8]>> Encode for RawBlob<T> {
fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
let bytes = self.contents.as_ref();
bytes.len().encode(w)?;
bytes.encode(w)
}
}
impl<T: Decode> Decode for RawBlob<T> {
fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
let size = u32::decode(r)?;
let mut taken = std::io::Read::take(r, size.into());
let contents = T::decode(&mut taken)?;
if taken.limit() != 0 {
return Err(DecodeError::UnrecognizedData);
}
Ok(RawBlob { contents })
}
}
impl<T: AsRef<[u8]>> AsRef<[u8]> for RawBlob<T> {
fn as_ref(&self) -> &[u8] {
self.contents.as_ref()
}
}
#[derive(Default, Arbitrary, PartialEq, Eq, Hash, Clone, Visit)]
pub struct Blob<T: Decode> {
contents: Lazy<T>,
}
impl<T: Decode> Blob<T> {
pub fn try_contents(&self) -> Result<&T, DecodeError> {
self.contents.try_contents()
}
pub fn try_contents_mut(&mut self) -> Result<&mut T, DecodeError> {
self.contents.try_contents_mut()
}
pub fn try_into_contents(self) -> Result<T, DecodeError> {
self.contents.try_into_contents()
}
}
impl<T: Decode + std::fmt::Debug> std::fmt::Debug for Blob<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.write_str("Blob(")?;
self.contents.fmt(f)?;
f.write_str(")")
}
}
impl<T: Decode + Encode> Encode for Blob<T> {
fn encode(&self, w: &mut impl std::io::Write) -> std::io::Result<()> {
let value = match self.contents.try_as_raw() {
Ok(raw) => return RawBlob { contents: raw }.encode(w),
Err(value) => value,
};
let mut buf;
buf = Vec::new();
value.encode(&mut buf)?;
RawBlob { contents: buf }.encode(w)
}
}
impl<T: Decode> Decode for Blob<T> {
fn decode(r: &mut impl std::io::Read) -> Result<Self, DecodeError> {
let contents: Lazy<T> = RawBlob::decode(r)?.contents;
Ok(Self { contents })
}
}
impl<T: Decode + WasmbinCountable> WasmbinCountable for Blob<T> {}
impl<T: Decode> From<T> for Blob<T> {
fn from(value: T) -> Self {
Blob {
contents: value.into(),
}
}
}