1use std::{
8 fmt,
9 io::{Read, Write},
10};
11
12use crate::{
13 encoding::{
14 process_decode_io_result, process_encode_io_result, write_i32, BinaryEncoder,
15 DecodingOptions, EncodingResult,
16 },
17 status_codes::StatusCode,
18};
19
20#[derive(Eq, PartialEq, Debug, Clone, Hash, Serialize, Deserialize)]
27pub struct UAString {
28 value: Option<String>,
29}
30
31impl fmt::Display for UAString {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 if let Some(ref value) = self.value {
34 write!(f, "{}", value)
35 } else {
36 write!(f, "[null]")
37 }
38 }
39}
40
41impl BinaryEncoder<UAString> for UAString {
42 fn byte_len(&self) -> usize {
43 4 + if self.value.is_none() {
45 0
46 } else {
47 self.value.as_ref().unwrap().len()
48 }
49 }
50
51 fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
52 if self.value.is_none() {
54 write_i32(stream, -1)
55 } else {
56 let value = self.value.as_ref().unwrap();
57 let mut size: usize = 0;
58 size += write_i32(stream, value.len() as i32)?;
59 let buf = value.as_bytes();
60 size += process_encode_io_result(stream.write(buf))?;
61 assert_eq!(size, self.byte_len());
62 Ok(size)
63 }
64 }
65
66 fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
67 let len = i32::decode(stream, decoding_options)?;
68 if len == -1 {
70 Ok(UAString::null())
71 } else if len < -1 {
72 error!("String buf length is a negative number {}", len);
73 Err(StatusCode::BadDecodingError)
74 } else if len as usize > decoding_options.max_string_length {
75 error!(
76 "String buf length {} exceeds decoding limit {}",
77 len, decoding_options.max_string_length
78 );
79 Err(StatusCode::BadDecodingError)
80 } else {
81 let mut buf = vec![0u8; len as usize];
83 process_decode_io_result(stream.read_exact(&mut buf))?;
84 let value = String::from_utf8(buf).map_err(|err| {
85 trace!("Decoded string was not valid UTF-8 - {}", err.to_string());
86 StatusCode::BadDecodingError
87 })?;
88 Ok(UAString::from(value))
89 }
90 }
91}
92
93impl From<UAString> for String {
94 fn from(value: UAString) -> Self {
95 value.as_ref().to_string()
96 }
97}
98
99impl AsRef<str> for UAString {
100 fn as_ref(&self) -> &str {
101 if self.is_null() {
102 ""
103 } else {
104 self.value.as_ref().unwrap()
105 }
106 }
107}
108
109impl<'a> From<&'a str> for UAString {
110 fn from(value: &'a str) -> Self {
111 Self::from(value.to_string())
112 }
113}
114
115impl From<&String> for UAString {
116 fn from(value: &String) -> Self {
117 UAString {
118 value: Some(value.clone()),
119 }
120 }
121}
122
123impl From<String> for UAString {
124 fn from(value: String) -> Self {
125 UAString { value: Some(value) }
126 }
127}
128
129impl Default for UAString {
130 fn default() -> Self {
131 UAString::null()
132 }
133}
134
135impl<'a, 'b> PartialEq<str> for UAString {
136 fn eq(&self, other: &str) -> bool {
137 match self.value {
138 None => false,
139 Some(ref v) => v.eq(other),
140 }
141 }
142}
143
144impl UAString {
145 pub fn value(&self) -> &Option<String> {
146 &self.value
147 }
148
149 pub fn set_value(&mut self, value: Option<String>) {
150 self.value = value;
151 }
152
153 pub fn is_empty(&self) -> bool {
155 if self.value.is_none() {
156 true
157 } else {
158 self.value.as_ref().unwrap().is_empty()
159 }
160 }
161
162 pub fn len(&self) -> isize {
164 if self.value.is_none() {
165 -1
166 } else {
167 self.value.as_ref().unwrap().len() as isize
168 }
169 }
170
171 pub fn null() -> UAString {
173 UAString { value: None }
174 }
175
176 pub fn is_null(&self) -> bool {
178 self.value.is_none()
179 }
180
181 pub fn substring(&self, min: usize, max: usize) -> Result<UAString, ()> {
186 if let Some(ref v) = self.value() {
187 if min >= v.len() {
188 Err(())
189 } else {
190 let max = if max >= v.len() { v.len() - 1 } else { max };
191 Ok(UAString::from(&v[min..=max]))
192 }
193 } else {
194 Err(())
195 }
196 }
197}
198
199#[test]
200fn string_null() {
201 let s = UAString::null();
202 assert!(s.is_null());
203 assert!(s.is_empty());
204 assert_eq!(s.len(), -1);
205}
206
207#[test]
208fn string_empty() {
209 let s = UAString::from("");
210 assert!(!s.is_null());
211 assert!(s.is_empty());
212 assert_eq!(s.len(), 0);
213}
214
215#[test]
216fn string_value() {
217 let v = "Mary had a little lamb";
218 let s = UAString::from(v);
219 assert!(!s.is_null());
220 assert!(!s.is_empty());
221 assert_eq!(s.as_ref(), v);
222}
223
224#[test]
225fn string_eq() {
226 let s = UAString::null();
227 assert!(!s.eq(""));
228
229 let s = UAString::from("");
230 assert!(s.eq(""));
231
232 let s = UAString::from("Sunshine");
233 assert!(s.ne("Moonshine"));
234 assert!(s.eq("Sunshine"));
235 assert!(!s.eq("Sunshine "));
236}
237
238#[test]
239fn string_substring() {
240 let a = "Mary had a little lamb";
241 let v = UAString::from(a);
242 let v2 = v.substring(0, 4).unwrap();
243 let a2 = v2.as_ref();
244 assert_eq!(a2, "Mary ");
245
246 let v2 = v.substring(2, 2).unwrap();
247 let a2 = v2.as_ref();
248 assert_eq!(a2, "r");
249
250 let v2 = v.substring(0, 2000).unwrap();
251 assert_eq!(v, v2);
252 assert_eq!(v2.as_ref(), a);
253
254 assert!(v.substring(22, 10000).is_err());
255
256 assert!(UAString::null().substring(0, 0).is_err());
257}
258
259pub type XmlElement = UAString;