aws_smithy_types/
blob.rs
1#[derive(Debug, Default, PartialEq, Eq, Hash, Clone)]
10pub struct Blob {
11 inner: Vec<u8>,
12}
13
14impl Blob {
15 pub fn new<T: Into<Vec<u8>>>(input: T) -> Self {
17 Blob {
18 inner: input.into(),
19 }
20 }
21
22 pub fn into_inner(self) -> Vec<u8> {
24 self.inner
25 }
26}
27
28impl AsRef<[u8]> for Blob {
29 fn as_ref(&self) -> &[u8] {
30 &self.inner
31 }
32}
33
34impl From<Vec<u8>> for Blob {
35 fn from(value: Vec<u8>) -> Self {
36 Blob::new(value)
37 }
38}
39
40impl From<Blob> for Vec<u8> {
41 fn from(value: Blob) -> Self {
42 value.into_inner()
43 }
44}
45
46impl From<&[u8]> for Blob {
47 fn from(value: &[u8]) -> Self {
48 Blob::new(value)
49 }
50}
51
52#[cfg(all(aws_sdk_unstable, feature = "serde-serialize"))]
53mod serde_serialize {
54 use super::*;
55 use serde::Serialize;
56
57 impl Serialize for Blob {
58 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
59 where
60 S: serde::Serializer,
61 {
62 if serializer.is_human_readable() {
63 serializer.serialize_str(&crate::base64::encode(&self.inner))
64 } else {
65 serializer.serialize_bytes(&self.inner)
66 }
67 }
68 }
69}
70
71#[cfg(all(aws_sdk_unstable, feature = "serde-deserialize"))]
72mod serde_deserialize {
73 use super::*;
74 use serde::{de::Visitor, Deserialize};
75
76 struct HumanReadableBlobVisitor;
77 impl<'de> Visitor<'de> for HumanReadableBlobVisitor {
78 type Value = Blob;
79 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 formatter.write_str("expected base64 encoded string")
81 }
82
83 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
84 where
85 E: serde::de::Error,
86 {
87 match crate::base64::decode(v) {
88 Ok(inner) => Ok(Blob { inner }),
89 Err(e) => Err(E::custom(e)),
90 }
91 }
92 }
93
94 struct NotHumanReadableBlobVisitor;
95 impl<'de> Visitor<'de> for NotHumanReadableBlobVisitor {
96 type Value = Blob;
97 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98 formatter.write_str("expected bytes")
99 }
100
101 fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
102 where
103 E: serde::de::Error,
104 {
105 Ok(Blob { inner: v })
106 }
107 }
108
109 impl<'de> Deserialize<'de> for Blob {
110 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
111 where
112 D: serde::Deserializer<'de>,
113 {
114 if deserializer.is_human_readable() {
115 deserializer.deserialize_str(HumanReadableBlobVisitor)
116 } else {
117 deserializer.deserialize_byte_buf(NotHumanReadableBlobVisitor)
118 }
119 }
120 }
121}
122
123#[cfg(test)]
124mod test {
125 use crate::Blob;
126
127 #[test]
128 fn blob_conversion() {
129 let my_bytes: &[u8] = &[1u8, 2u8, 3u8];
130 let my_vec = vec![1u8, 2u8, 3u8];
131 let orig_vec = my_vec.clone();
132
133 let blob1: Blob = my_bytes.into();
134 let vec1: Vec<u8> = blob1.into();
135 assert_eq!(orig_vec, vec1);
136
137 let blob2: Blob = my_vec.into();
138 let vec2: Vec<u8> = blob2.into();
139 assert_eq!(orig_vec, vec2);
140 }
141}
142
143#[cfg(all(
144 aws_sdk_unstable,
145 feature = "serde-serialize",
146 feature = "serde-deserialize"
147))]
148mod test_serde {
149 use crate::Blob;
150 use serde::{Deserialize, Serialize};
151 use std::collections::HashMap;
152
153 #[derive(Deserialize, Serialize, Debug, PartialEq)]
154 struct ForTest {
155 blob: Blob,
156 }
157
158 #[test]
159 fn human_readable_blob() {
160 let aws_in_base64 = r#"{"blob":"QVdT"}"#;
161 let for_test = ForTest {
162 blob: Blob {
163 inner: vec![b'A', b'W', b'S'],
164 },
165 };
166 assert_eq!(for_test, serde_json::from_str(aws_in_base64).unwrap());
167 assert_eq!(serde_json::to_string(&for_test).unwrap(), aws_in_base64);
168 }
169
170 #[test]
171 fn not_human_readable_blob() {
172 use std::ffi::CString;
173
174 let for_test = ForTest {
175 blob: Blob {
176 inner: vec![b'A', b'W', b'S'],
177 },
178 };
179 let mut buf = vec![];
180 let res = ciborium::ser::into_writer(&for_test, &mut buf);
181 assert!(res.is_ok());
182
183 let n: HashMap<String, CString> =
185 ciborium::de::from_reader(std::io::Cursor::new(buf.clone())).unwrap();
186 assert!(n.get("blob").is_some());
187 assert!(n.get("blob") == CString::new([65, 87, 83]).ok().as_ref());
188
189 let de: ForTest = ciborium::de::from_reader(std::io::Cursor::new(buf)).unwrap();
190 assert_eq!(for_test, de);
191 }
192}