bt_obex/header/
obex_string.rs
1use crate::error::PacketError;
6
7#[derive(Clone, Debug, PartialEq)]
11pub struct ObexString(pub String);
12
13impl ObexString {
14 pub fn len(&self) -> usize {
15 self.to_be_bytes().len()
16 }
17
18 pub fn to_be_bytes(&self) -> Vec<u8> {
19 let mut encoded_buf: Vec<u16> = self.0.encode_utf16().collect();
20 encoded_buf.push(0); encoded_buf.into_iter().map(|v| v.to_be_bytes()).flatten().collect()
22 }
23}
24
25impl From<String> for ObexString {
26 fn from(src: String) -> ObexString {
27 ObexString(src)
28 }
29}
30
31impl From<&str> for ObexString {
32 fn from(src: &str) -> ObexString {
33 ObexString(src.to_string())
34 }
35}
36
37impl TryFrom<&[u8]> for ObexString {
38 type Error = PacketError;
39
40 fn try_from(src: &[u8]) -> Result<Self, Self::Error> {
41 if src.len() == 0 {
42 return Ok(Self(String::new()));
43 }
44
45 let unicode_array = src
46 .chunks_exact(2)
47 .into_iter()
48 .map(|a| u16::from_be_bytes([a[0], a[1]]))
49 .collect::<Vec<u16>>();
50 let mut text = String::from_utf16(&unicode_array).map_err(PacketError::external)?;
51 if !text.ends_with('\0') {
53 return Err(PacketError::data("text missing null terminator"));
54 }
55
56 let _ = text.pop();
57 Ok(Self(text))
58 }
59}
60
61impl ToString for ObexString {
62 fn to_string(&self) -> String {
63 self.0.clone()
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 use assert_matches::assert_matches;
72
73 fn expect_strings_equal(s1: ObexString, s2: String) {
74 assert_eq!(s1.0, s2);
75 }
76
77 #[fuchsia::test]
78 fn obex_string_from_bytes() {
79 let converted = ObexString::try_from(&[][..]).expect("can convert to String");
81 expect_strings_equal(converted, "".to_string());
82
83 let buf = [0x00, 0x00];
85 let converted = ObexString::try_from(&buf[..]).expect("can convert to String");
86 expect_strings_equal(converted, "".to_string());
87
88 let buf = [0x00, 0x68, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x00];
90 let converted = ObexString::try_from(&buf[..]).expect("can convert to String");
91 expect_strings_equal(converted, "hello".to_string());
92
93 let buf = [0x00, 0x62, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00];
95 let converted = ObexString::try_from(&buf[..]).expect("can convert to String");
96 expect_strings_equal(converted, "bob\0".to_string());
97 }
98
99 #[fuchsia::test]
100 fn obex_string_missing_terminator_is_error() {
101 let buf =
103 [0x00, 0x66, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x78, 0x00, 0x74];
104 let converted = ObexString::try_from(&buf[..]);
105 assert_matches!(converted, Err(PacketError::Data(_)));
106 }
107
108 #[fuchsia::test]
109 fn obex_string_invalid_utf16_is_error() {
110 let buf =
112 [0xd8, 0x34, 0xdd, 0x1e, 0x00, 0x6d, 0x00, 0x75, 0xd8, 0x00, 0x00, 0x69, 0x00, 0x63];
113 let converted = ObexString::try_from(&buf[..]);
114 assert_matches!(converted, Err(PacketError::Other(_)));
115 }
116}