opcua/types/
byte_string.rs1use std::{
8 convert::TryFrom,
9 fmt,
10 io::{Read, Write},
11};
12
13use base64::{engine::general_purpose::STANDARD, Engine};
14use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
15
16use crate::types::{
17 encoding::{
18 process_decode_io_result, process_encode_io_result, write_i32, BinaryEncoder,
19 DecodingOptions, EncodingResult,
20 },
21 status_codes::StatusCode,
22 Guid,
23};
24
25#[derive(Eq, PartialEq, Debug, Clone, Hash)]
27pub struct ByteString {
28 pub value: Option<Vec<u8>>,
29}
30
31impl AsRef<[u8]> for ByteString {
32 fn as_ref(&self) -> &[u8] {
33 if self.value.is_none() {
34 &[]
35 } else {
36 self.value.as_ref().unwrap()
37 }
38 }
39}
40
41impl Serialize for ByteString {
42 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
43 where
44 S: Serializer,
45 {
46 if self.value.is_some() {
47 serializer.serialize_str(&self.as_base64())
48 } else {
49 serializer.serialize_none()
50 }
51 }
52}
53struct ByteStringVisitor;
54
55impl<'de> serde::de::Visitor<'de> for ByteStringVisitor {
56 type Value = ByteString;
57 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
58 write!(formatter, "a base64 encoded string value or null")
59 }
60
61 fn visit_none<E>(self) -> Result<Self::Value, E>
62 where
63 E: de::Error,
64 {
65 Ok(Self::Value::null())
66 }
67
68 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
69 where
70 D: Deserializer<'de>,
71 {
72 deserializer.deserialize_str(self)
73 }
74
75 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
76 where
77 E: de::Error,
78 {
79 Self::Value::from_base64(v)
80 .ok_or_else(|| de::Error::custom("Cannot decode base64 bytestring"))
81 }
82}
83
84impl<'de> Deserialize<'de> for ByteString {
85 fn deserialize<D>(deserializer: D) -> Result<ByteString, D::Error>
86 where
87 D: Deserializer<'de>,
88 {
89 deserializer.deserialize_option(ByteStringVisitor)
90 }
91}
92
93impl BinaryEncoder<ByteString> for ByteString {
94 fn byte_len(&self) -> usize {
95 4 + if self.value.is_none() {
97 0
98 } else {
99 self.value.as_ref().unwrap().len()
100 }
101 }
102
103 fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
104 if self.value.is_none() {
106 write_i32(stream, -1)
107 } else {
108 let mut size: usize = 0;
109 let value = self.value.as_ref().unwrap();
110 size += write_i32(stream, value.len() as i32)?;
111 size += process_encode_io_result(stream.write(value))?;
112 assert_eq!(size, self.byte_len());
113 Ok(size)
114 }
115 }
116
117 fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
118 let len = i32::decode(stream, decoding_options)?;
119 if len == -1 {
121 Ok(ByteString::null())
122 } else if len < -1 {
123 error!("ByteString buf length is a negative number {}", len);
124 Err(StatusCode::BadDecodingError)
125 } else if len as usize > decoding_options.max_byte_string_length {
126 error!(
127 "ByteString length {} exceeds decoding limit {}",
128 len, decoding_options.max_string_length
129 );
130 Err(StatusCode::BadDecodingError)
131 } else {
132 let mut buf: Vec<u8> = vec![0u8; len as usize];
134 process_decode_io_result(stream.read_exact(&mut buf))?;
135 Ok(ByteString { value: Some(buf) })
136 }
137 }
138}
139
140impl<'a, T> From<&'a T> for ByteString
141where
142 T: AsRef<[u8]> + ?Sized,
143{
144 fn from(value: &'a T) -> Self {
145 Self::from(value.as_ref().to_vec())
146 }
147}
148
149impl From<Vec<u8>> for ByteString {
150 fn from(value: Vec<u8>) -> Self {
151 ByteString { value: Some(value) }
153 }
154}
155
156impl From<Guid> for ByteString {
157 fn from(value: Guid) -> Self {
158 ByteString::from(value.as_bytes().to_vec())
159 }
160}
161
162impl TryFrom<&ByteString> for Guid {
163 type Error = ();
164
165 fn try_from(value: &ByteString) -> Result<Self, Self::Error> {
166 if value.is_null_or_empty() {
167 Err(())
168 } else {
169 let bytes = value.as_ref();
170 if bytes.len() != 16 {
171 Err(())
172 } else {
173 let mut guid = [0u8; 16];
174 guid.copy_from_slice(bytes);
175 Ok(Guid::from_bytes(guid))
176 }
177 }
178 }
179}
180
181impl Into<String> for ByteString {
182 fn into(self) -> String {
183 self.as_base64()
184 }
185}
186
187impl Default for ByteString {
188 fn default() -> Self {
189 ByteString::null()
190 }
191}
192
193impl ByteString {
194 pub fn null() -> ByteString {
196 ByteString { value: None }
197 }
198
199 pub fn is_null(&self) -> bool {
201 self.value.is_none()
202 }
203
204 pub fn is_empty(&self) -> bool {
206 if let Some(v) = &self.value {
207 v.is_empty()
208 } else {
209 false
210 }
211 }
212
213 pub fn is_null_or_empty(&self) -> bool {
215 self.is_null() || self.is_empty()
216 }
217
218 pub fn from_base64(data: &str) -> Option<ByteString> {
220 if let Ok(bytes) = STANDARD.decode(data) {
221 Some(Self::from(bytes))
222 } else {
223 None
224 }
225 }
226
227 pub fn as_base64(&self) -> String {
229 if let Some(ref value) = self.value {
231 STANDARD.encode(value)
232 } else {
233 STANDARD.encode("")
234 }
235 }
236
237 pub fn substring(&self, min: usize, max: usize) -> Result<ByteString, ()> {
242 if let Some(ref v) = self.value {
243 if min >= v.len() {
244 Err(())
245 } else {
246 let max = if max >= v.len() { v.len() - 1 } else { max };
247 let v = v[min..=max].to_vec();
248 Ok(ByteString::from(v))
249 }
250 } else {
251 Err(())
252 }
253 }
254}
255
256#[test]
257fn bytestring_null() {
258 let v = ByteString::null();
259 assert!(v.is_null());
260}
261
262#[test]
263fn bytestring_empty() {
264 let v = ByteString::from(&[]);
265 assert!(!v.is_null());
266 assert!(v.is_null_or_empty());
267 assert!(v.is_empty());
268}
269
270#[test]
271fn bytestring_bytes() {
272 let a = [0x1u8, 0x2u8, 0x3u8, 0x4u8];
273 let v = ByteString::from(&a);
274 assert!(!v.is_null());
275 assert!(!v.is_empty());
276 assert_eq!(v.value.as_ref().unwrap(), &a);
277}
278
279#[test]
280fn bytestring_substring() {
281 let a = [0x1u8, 0x2u8, 0x3u8, 0x4u8];
282 let v = ByteString::from(&a);
283 let v2 = v.substring(2, 10000).unwrap();
284 let a2 = v2.value.as_ref().unwrap().as_slice();
285 assert_eq!(a2, &a[2..]);
286
287 let v2 = v.substring(2, 2).unwrap();
288 let a2 = v2.value.as_ref().unwrap().as_slice();
289 assert_eq!(a2, &a[2..3]);
290
291 let v2 = v.substring(0, 2000).unwrap();
292 assert_eq!(v, v2);
293 assert_eq!(v2.value.as_ref().unwrap(), &a);
294
295 assert!(v.substring(4, 10000).is_err());
296 assert!(ByteString::null().substring(0, 0).is_err());
297}