opcua_types/
byte_string.rs1use std::convert::TryFrom;
8use std::io::{Read, Write};
9
10use crate::{
11 encoding::{
12 process_decode_io_result, process_encode_io_result, write_i32, BinaryEncoder,
13 DecodingOptions, EncodingResult,
14 },
15 status_codes::StatusCode,
16 Guid,
17};
18
19#[derive(Eq, PartialEq, Debug, Clone, Hash, Serialize, Deserialize)]
21pub struct ByteString {
22 pub value: Option<Vec<u8>>,
23}
24
25impl AsRef<[u8]> for ByteString {
26 fn as_ref(&self) -> &[u8] {
27 if self.value.is_none() {
28 &[]
29 } else {
30 self.value.as_ref().unwrap()
31 }
32 }
33}
34
35impl BinaryEncoder<ByteString> for ByteString {
36 fn byte_len(&self) -> usize {
37 4 + if self.value.is_none() {
39 0
40 } else {
41 self.value.as_ref().unwrap().len()
42 }
43 }
44
45 fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
46 if self.value.is_none() {
48 write_i32(stream, -1)
49 } else {
50 let mut size: usize = 0;
51 let value = self.value.as_ref().unwrap();
52 size += write_i32(stream, value.len() as i32)?;
53 size += process_encode_io_result(stream.write(value))?;
54 assert_eq!(size, self.byte_len());
55 Ok(size)
56 }
57 }
58
59 fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
60 let len = i32::decode(stream, decoding_options)?;
61 if len == -1 {
63 Ok(ByteString::null())
64 } else if len < -1 {
65 error!("ByteString buf length is a negative number {}", len);
66 Err(StatusCode::BadDecodingError)
67 } else if len as usize > decoding_options.max_byte_string_length {
68 error!(
69 "ByteString length {} exceeds decoding limit {}",
70 len, decoding_options.max_string_length
71 );
72 Err(StatusCode::BadDecodingError)
73 } else {
74 let mut buf: Vec<u8> = vec![0u8; len as usize];
76 process_decode_io_result(stream.read_exact(&mut buf))?;
77 Ok(ByteString { value: Some(buf) })
78 }
79 }
80}
81
82impl<'a, T> From<&'a T> for ByteString
83where
84 T: AsRef<[u8]> + ?Sized,
85{
86 fn from(value: &'a T) -> Self {
87 Self::from(value.as_ref().to_vec())
88 }
89}
90
91impl From<Vec<u8>> for ByteString {
92 fn from(value: Vec<u8>) -> Self {
93 ByteString { value: Some(value) }
95 }
96}
97
98impl From<Guid> for ByteString {
99 fn from(value: Guid) -> Self {
100 ByteString::from(value.as_bytes().to_vec())
101 }
102}
103
104impl TryFrom<&ByteString> for Guid {
105 type Error = ();
106
107 fn try_from(value: &ByteString) -> Result<Self, Self::Error> {
108 if value.is_null_or_empty() {
109 Err(())
110 } else {
111 let bytes = value.as_ref();
112 if bytes.len() != 16 {
113 Err(())
114 } else {
115 let mut guid = [0u8; 16];
116 guid.copy_from_slice(bytes);
117 Ok(Guid::from_bytes(guid))
118 }
119 }
120 }
121}
122
123impl Into<String> for ByteString {
124 fn into(self) -> String {
125 self.as_base64()
126 }
127}
128
129impl Default for ByteString {
130 fn default() -> Self {
131 ByteString::null()
132 }
133}
134
135impl ByteString {
136 pub fn null() -> ByteString {
138 ByteString { value: None }
139 }
140
141 pub fn is_null(&self) -> bool {
143 self.value.is_none()
144 }
145
146 pub fn is_empty(&self) -> bool {
148 if let Some(v) = &self.value {
149 v.is_empty()
150 } else {
151 false
152 }
153 }
154
155 pub fn is_null_or_empty(&self) -> bool {
157 self.is_null() || self.is_empty()
158 }
159
160 pub fn from_base64(data: &str) -> Option<ByteString> {
162 if let Ok(bytes) = base64::decode(data) {
163 Some(Self::from(bytes))
164 } else {
165 None
166 }
167 }
168
169 pub fn as_base64(&self) -> String {
171 if let Some(ref value) = self.value {
173 base64::encode(value)
174 } else {
175 base64::encode("")
176 }
177 }
178
179 pub fn substring(&self, min: usize, max: usize) -> Result<ByteString, ()> {
184 if let Some(ref v) = self.value {
185 if min >= v.len() {
186 Err(())
187 } else {
188 let max = if max >= v.len() { v.len() - 1 } else { max };
189 let v = v[min..=max].to_vec();
190 Ok(ByteString::from(v))
191 }
192 } else {
193 Err(())
194 }
195 }
196}
197
198#[test]
199fn bytestring_null() {
200 let v = ByteString::null();
201 assert!(v.is_null());
202}
203
204#[test]
205fn bytestring_empty() {
206 let v = ByteString::from(&[]);
207 assert!(!v.is_null());
208 assert!(v.is_null_or_empty());
209 assert!(v.is_empty());
210}
211
212#[test]
213fn bytestring_bytes() {
214 let a = [0x1u8, 0x2u8, 0x3u8, 0x4u8];
215 let v = ByteString::from(&a);
216 assert!(!v.is_null());
217 assert!(!v.is_empty());
218 assert_eq!(v.value.as_ref().unwrap(), &a);
219}
220
221#[test]
222fn bytestring_substring() {
223 let a = [0x1u8, 0x2u8, 0x3u8, 0x4u8];
224 let v = ByteString::from(&a);
225 let v2 = v.substring(2, 10000).unwrap();
226 let a2 = v2.value.as_ref().unwrap().as_slice();
227 assert_eq!(a2, &a[2..]);
228
229 let v2 = v.substring(2, 2).unwrap();
230 let a2 = v2.value.as_ref().unwrap().as_slice();
231 assert_eq!(a2, &a[2..3]);
232
233 let v2 = v.substring(0, 2000).unwrap();
234 assert_eq!(v, v2);
235 assert_eq!(v2.value.as_ref().unwrap(), &a);
236
237 assert!(v.substring(4, 10000).is_err());
238 assert!(ByteString::null().substring(0, 0).is_err());
239}