1use std::{
8 fmt,
9 io::{Read, Write},
10};
11
12use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
13
14use crate::types::{
15 encoding::{
16 process_decode_io_result, process_encode_io_result, write_i32, BinaryEncoder,
17 DecodingOptions, EncodingResult,
18 },
19 status_codes::StatusCode,
20};
21
22#[derive(Eq, PartialEq, Debug, Clone, Hash)]
29pub struct UAString {
30 value: Option<String>,
31}
32
33impl fmt::Display for UAString {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 if let Some(ref value) = self.value {
36 write!(f, "{}", value)
37 } else {
38 write!(f, "[null]")
39 }
40 }
41}
42
43impl Serialize for UAString {
44 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
45 where
46 S: Serializer,
47 {
48 if let Some(s) = self.value.as_ref() {
49 serializer.serialize_str(&s)
50 } else {
51 serializer.serialize_none()
52 }
53 }
54}
55
56struct UAStringVisitor;
57
58impl<'de> serde::de::Visitor<'de> for UAStringVisitor {
59 type Value = UAString;
60 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
61 write!(formatter, "a string value or null")
62 }
63
64 fn visit_none<E>(self) -> Result<Self::Value, E>
65 where
66 E: de::Error,
67 {
68 Ok(Self::Value::null())
69 }
70
71 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
72 where
73 D: Deserializer<'de>,
74 {
75 deserializer.deserialize_str(self)
76 }
77
78 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
79 where
80 E: de::Error,
81 {
82 Ok(Self::Value::from(v))
83 }
84}
85
86impl<'de> Deserialize<'de> for UAString {
87 fn deserialize<D>(deserializer: D) -> Result<UAString, D::Error>
88 where
89 D: Deserializer<'de>,
90 {
91 deserializer.deserialize_option(UAStringVisitor)
92 }
93}
94
95impl BinaryEncoder<UAString> for UAString {
96 fn byte_len(&self) -> usize {
97 4 + if self.value.is_none() {
99 0
100 } else {
101 self.value.as_ref().unwrap().len()
102 }
103 }
104
105 fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
106 if self.value.is_none() {
108 write_i32(stream, -1)
109 } else {
110 let value = self.value.as_ref().unwrap();
111 let mut size: usize = 0;
112 size += write_i32(stream, value.len() as i32)?;
113 let buf = value.as_bytes();
114 size += process_encode_io_result(stream.write(buf))?;
115 assert_eq!(size, self.byte_len());
116 Ok(size)
117 }
118 }
119
120 fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
121 let len = i32::decode(stream, decoding_options)?;
122 if len == -1 {
124 Ok(UAString::null())
125 } else if len < -1 {
126 error!("String buf length is a negative number {}", len);
127 Err(StatusCode::BadDecodingError)
128 } else if len as usize > decoding_options.max_string_length {
129 error!(
130 "String buf length {} exceeds decoding limit {}",
131 len, decoding_options.max_string_length
132 );
133 Err(StatusCode::BadDecodingError)
134 } else {
135 let mut buf = vec![0u8; len as usize];
137 process_decode_io_result(stream.read_exact(&mut buf))?;
138 let value = String::from_utf8(buf).map_err(|err| {
139 trace!("Decoded string was not valid UTF-8 - {}", err.to_string());
140 StatusCode::BadDecodingError
141 })?;
142 Ok(UAString::from(value))
143 }
144 }
145}
146
147impl From<UAString> for String {
148 fn from(value: UAString) -> Self {
149 value.as_ref().to_string()
150 }
151}
152
153impl AsRef<str> for UAString {
154 fn as_ref(&self) -> &str {
155 if self.is_null() {
156 ""
157 } else {
158 self.value.as_ref().unwrap()
159 }
160 }
161}
162
163impl<'a> From<&'a str> for UAString {
164 fn from(value: &'a str) -> Self {
165 Self::from(value.to_string())
166 }
167}
168
169impl From<&String> for UAString {
170 fn from(value: &String) -> Self {
171 UAString {
172 value: Some(value.clone()),
173 }
174 }
175}
176
177impl From<String> for UAString {
178 fn from(value: String) -> Self {
179 UAString { value: Some(value) }
180 }
181}
182
183impl Default for UAString {
184 fn default() -> Self {
185 UAString::null()
186 }
187}
188
189impl<'a, 'b> PartialEq<str> for UAString {
190 fn eq(&self, other: &str) -> bool {
191 match self.value {
192 None => false,
193 Some(ref v) => v.eq(other),
194 }
195 }
196}
197
198impl UAString {
199 pub fn value(&self) -> &Option<String> {
200 &self.value
201 }
202
203 pub fn set_value(&mut self, value: Option<String>) {
204 self.value = value;
205 }
206
207 pub fn is_empty(&self) -> bool {
209 if self.value.is_none() {
210 true
211 } else {
212 self.value.as_ref().unwrap().is_empty()
213 }
214 }
215
216 pub fn len(&self) -> isize {
218 if self.value.is_none() {
219 -1
220 } else {
221 self.value.as_ref().unwrap().len() as isize
222 }
223 }
224
225 pub fn null() -> UAString {
227 UAString { value: None }
228 }
229
230 pub fn is_null(&self) -> bool {
232 self.value.is_none()
233 }
234
235 pub fn substring(&self, min: usize, max: usize) -> Result<UAString, ()> {
240 if let Some(ref v) = self.value() {
241 if min >= v.len() {
242 Err(())
243 } else {
244 let max = if max >= v.len() { v.len() - 1 } else { max };
245 Ok(UAString::from(&v[min..=max]))
246 }
247 } else {
248 Err(())
249 }
250 }
251}
252
253#[test]
254fn string_null() {
255 let s = UAString::null();
256 assert!(s.is_null());
257 assert!(s.is_empty());
258 assert_eq!(s.len(), -1);
259}
260
261#[test]
262fn string_empty() {
263 let s = UAString::from("");
264 assert!(!s.is_null());
265 assert!(s.is_empty());
266 assert_eq!(s.len(), 0);
267}
268
269#[test]
270fn string_value() {
271 let v = "Mary had a little lamb";
272 let s = UAString::from(v);
273 assert!(!s.is_null());
274 assert!(!s.is_empty());
275 assert_eq!(s.as_ref(), v);
276}
277
278#[test]
279fn string_eq() {
280 let s = UAString::null();
281 assert!(!s.eq(""));
282
283 let s = UAString::from("");
284 assert!(s.eq(""));
285
286 let s = UAString::from("Sunshine");
287 assert!(s.ne("Moonshine"));
288 assert!(s.eq("Sunshine"));
289 assert!(!s.eq("Sunshine "));
290}
291
292#[test]
293fn string_substring() {
294 let a = "Mary had a little lamb";
295 let v = UAString::from(a);
296 let v2 = v.substring(0, 4).unwrap();
297 let a2 = v2.as_ref();
298 assert_eq!(a2, "Mary ");
299
300 let v2 = v.substring(2, 2).unwrap();
301 let a2 = v2.as_ref();
302 assert_eq!(a2, "r");
303
304 let v2 = v.substring(0, 2000).unwrap();
305 assert_eq!(v, v2);
306 assert_eq!(v2.as_ref(), a);
307
308 assert!(v.substring(22, 10000).is_err());
309
310 assert!(UAString::null().substring(0, 0).is_err());
311}
312
313pub type XmlElement = UAString;