1use crate::attributes::{stunt_attribute, DecodeAttributeValue, EncodeAttributeValue};
2use crate::context::{AttributeDecoderContext, AttributeEncoderContext};
3use crate::error::{StunError, StunErrorType};
4use crate::strings;
5use crate::{Decode, Encode};
6use precis_core::profile::PrecisFastInvocation;
7use precis_profiles::OpaqueString;
8use std::convert::TryFrom;
9
10const USER_NAME: u16 = 0x0006;
11
12const MAX_ENCODED_SIZE: usize = 509;
13const MAX_DECODED_SIZE: usize = 763;
14
15#[derive(Debug, PartialEq, Eq, Clone)]
41pub struct UserName(String);
42
43impl UserName {
44 pub fn new<S>(value: S) -> Result<Self, StunError>
47 where
48 S: AsRef<str>,
49 {
50 let name = strings::opaque_string_prepapre(value.as_ref())?;
51 (name.len() < MAX_ENCODED_SIZE)
52 .then(|| UserName(String::from(name.as_ref())))
53 .ok_or_else(|| {
54 StunError::new(
55 StunErrorType::ValueTooLong,
56 format!(
57 "Name length {} > max. allowed size {}",
58 name.len(),
59 MAX_ENCODED_SIZE
60 ),
61 )
62 })
63 }
64
65 pub fn as_str(&self) -> &str {
67 self.0.as_str()
68 }
69}
70
71impl PartialEq<&str> for UserName {
72 fn eq(&self, other: &&str) -> bool {
73 OpaqueString::compare(self, *other).unwrap_or(false)
74 }
75}
76
77impl PartialEq<UserName> for &str {
78 fn eq(&self, other: &UserName) -> bool {
79 OpaqueString::compare(*self, other).unwrap_or(false)
80 }
81}
82
83impl PartialEq<str> for UserName {
84 fn eq(&self, other: &str) -> bool {
85 OpaqueString::compare(self, other).unwrap_or(false)
86 }
87}
88
89impl PartialEq<String> for UserName {
90 fn eq(&self, other: &String) -> bool {
91 OpaqueString::compare(self, other).unwrap_or(false)
92 }
93}
94
95impl PartialEq<UserName> for String {
96 fn eq(&self, other: &UserName) -> bool {
97 OpaqueString::compare(self, other).unwrap_or(false)
98 }
99}
100
101impl AsRef<str> for UserName {
102 fn as_ref(&self) -> &str {
103 self.as_str()
104 }
105}
106
107impl AsRef<String> for UserName {
108 fn as_ref(&self) -> &String {
109 &self.0
110 }
111}
112
113impl TryFrom<&str> for UserName {
114 type Error = StunError;
115
116 fn try_from(value: &str) -> Result<Self, Self::Error> {
117 UserName::new(value)
118 }
119}
120
121impl TryFrom<&String> for UserName {
122 type Error = StunError;
123
124 fn try_from(value: &String) -> Result<Self, Self::Error> {
125 UserName::new(value)
126 }
127}
128
129impl TryFrom<String> for UserName {
130 type Error = StunError;
131
132 fn try_from(value: String) -> Result<Self, Self::Error> {
133 UserName::new(value)
134 }
135}
136
137impl DecodeAttributeValue for UserName {
138 fn decode(ctx: AttributeDecoderContext) -> Result<(Self, usize), StunError> {
139 let (str, size) = <&'_ str as Decode<'_>>::decode(ctx.raw_value())?;
140
141 if size > MAX_DECODED_SIZE {
142 return Err(StunError::new(
143 StunErrorType::ValueTooLong,
144 format!(
145 "Value length {} > max. decoded size {}",
146 size, MAX_DECODED_SIZE
147 ),
148 ));
149 }
150
151 let name = strings::opaque_string_enforce(str)?;
152 Ok((UserName(String::from(name.as_ref())), size))
153 }
154}
155
156impl EncodeAttributeValue for UserName {
157 fn encode(&self, mut ctx: AttributeEncoderContext) -> Result<usize, StunError> {
158 if self.as_str().len() >= MAX_ENCODED_SIZE {
159 return Err(StunError::new(
160 StunErrorType::ValueTooLong,
161 format!(
162 "Value length {} >= max. encoded size {}",
163 self.as_str().len(),
164 MAX_ENCODED_SIZE
165 ),
166 ));
167 }
168 self.0.as_str().encode(ctx.raw_value_mut())
169 }
170}
171
172impl crate::attributes::AsVerifiable for UserName {}
173
174stunt_attribute!(UserName, USER_NAME);
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179 use crate::error::StunErrorType;
180 use crate::StunAttribute;
181
182 #[test]
183 fn user_name_constructor() {
184 let name = String::from("username");
185 let user_name = UserName::try_from(&name).expect("Can not create USERNAME attribute");
186 assert_eq!(user_name, "username");
188 assert_eq!("username", user_name);
189 assert_eq!(name, user_name);
190 assert_eq!(user_name, name);
191
192 let name = "x".repeat(MAX_ENCODED_SIZE - 1);
193 let user_name = UserName::try_from(&name).expect("Can not create USERNAME attribute");
194
195 let val: &String = user_name.as_ref();
196 assert!(name.eq(val));
197
198 let val: &str = user_name.as_ref();
199 assert!(name.eq(val));
200
201 let name = "x".repeat(MAX_ENCODED_SIZE);
202 let result = UserName::try_from(name);
204 assert_eq!(
205 result.expect_err("Error expected"),
206 StunErrorType::ValueTooLong
207 );
208
209 let result = UserName::try_from("");
211 assert_eq!(
212 result.expect_err("Error expected"),
213 StunErrorType::InvalidParam
214 );
215
216 let result = UserName::try_from("user\u{0009}name");
218 assert_eq!(
219 result.expect_err("Error expected"),
220 StunErrorType::InvalidParam
221 );
222 }
223
224 #[test]
225 fn decode_user_name() {
226 let dummy_msg = [];
227 let buffer = [0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65];
229 let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
230
231 let (user_name, size) = UserName::decode(ctx).expect("Can not decode USERNAME");
232 assert_eq!(size, 8);
233 assert_eq!(user_name.as_str(), "username");
234
235 let value = "x".repeat(MAX_DECODED_SIZE);
236 let ctx = AttributeDecoderContext::new(None, &dummy_msg, value.as_bytes());
237 let (_username, size) = UserName::decode(ctx).expect("Can not decode USERNAME");
238 assert_eq!(size, MAX_DECODED_SIZE);
239 }
240
241 #[test]
242 fn decode_error() {
243 let dummy_msg = [];
244
245 let buffer = [0x75, 0x73, 0x65, 0x09, 0x6e, 0x61, 0x6d, 0x65];
248 let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
249 let result = UserName::decode(ctx);
250 assert_eq!(
251 result.expect_err("Error expected"),
252 StunErrorType::InvalidParam
253 );
254
255 let buffer: [u8; 0] = [];
257 let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
258 let result = UserName::decode(ctx);
259 assert_eq!(
260 result.expect_err("Error expected"),
261 StunErrorType::InvalidParam
262 );
263
264 let value = "x".repeat(MAX_DECODED_SIZE + 1);
265 let ctx = AttributeDecoderContext::new(None, &dummy_msg, value.as_bytes());
266 assert_eq!(
267 UserName::decode(ctx).expect_err("Error expected"),
268 StunErrorType::ValueTooLong
269 );
270 }
271
272 #[test]
273 fn encode_user_name() {
274 let dummy_msg: [u8; 0] = [0x0; 0];
275 let user_name = UserName::try_from("username").expect("Can not create USERNAME attribute");
276
277 let mut buffer: [u8; 8] = [0x0; 8];
278 let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
279 let result = user_name.encode(ctx);
280 assert_eq!(result, Ok(8));
281
282 let cmp_buffer = [0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65];
283 assert_eq!(&buffer[..], &cmp_buffer[..]);
284
285 let mut buffer: [u8; 1000] = [0x0; 1000];
286 let name = "x".repeat(MAX_ENCODED_SIZE - 1);
287
288 let user_name =
289 UserName::try_from(name.as_str()).expect("Can not create USERNAME attribute");
290
291 let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
292 let result = user_name.encode(ctx);
293 assert_eq!(result, Ok(MAX_ENCODED_SIZE - 1));
294 }
295
296 #[test]
297 fn encode_user_name_error() {
298 let dummy_msg: [u8; 0] = [0x0; 0];
299
300 let user_name = UserName::try_from("username").expect("Can not create USERNAME attribute");
301
302 let mut buffer = [];
303 let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
304 let result = user_name.encode(ctx);
305 assert_eq!(
306 result.expect_err("Error expected"),
307 StunErrorType::SmallBuffer
308 );
309
310 let mut buffer: [u8; 7] = [0x0; 7];
311 let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
312 let result = user_name.encode(ctx);
313 assert_eq!(
314 result.expect_err("Error expected"),
315 StunErrorType::SmallBuffer
316 );
317
318 let mut buffer: [u8; MAX_ENCODED_SIZE] = [0x0; MAX_ENCODED_SIZE];
319 let value = "x".repeat(MAX_ENCODED_SIZE);
320 let user_name = UserName(value);
321 let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
322 let result = user_name.encode(ctx);
323 assert_eq!(
324 result.expect_err("Error expected"),
325 StunErrorType::ValueTooLong
326 );
327 }
328
329 #[test]
330 fn user_name_stunt_attribute() {
331 let attr = StunAttribute::UserName(
332 UserName::try_from("test").expect("Can not create UserName attribute"),
333 );
334 assert!(attr.is_user_name());
335 assert!(attr.as_user_name().is_ok());
336 assert!(attr.as_unknown().is_err());
337
338 assert!(attr.attribute_type().is_comprehension_required());
339 assert!(!attr.attribute_type().is_comprehension_optional());
340
341 let dbg_fmt = format!("{:?}", attr);
342 assert_eq!("UserName(UserName(\"test\"))", dbg_fmt);
343 }
344}