Skip to content

Commit 7b033ca

Browse files
committed
Improve efficiency of deserializing strings
1 parent 37de108 commit 7b033ca

File tree

1 file changed

+89
-4
lines changed

1 file changed

+89
-4
lines changed

rosidl_runtime_rs/src/string/serde.rs

+89-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,98 @@
1-
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
1+
use std::fmt;
22

3-
use super::{BoundedString, BoundedWString, String, WString};
3+
use serde::{
4+
de::{Error, SeqAccess, Visitor},
5+
Deserialize, Deserializer, Serialize, Serializer,
6+
};
7+
8+
use super::{
9+
rosidl_runtime_c__String__assignn, rosidl_runtime_c__U16String__assignn, BoundedString,
10+
BoundedWString, String, WString,
11+
};
12+
13+
struct StringVisitor;
14+
struct WStringVisitor;
15+
16+
impl<'de> Visitor<'de> for StringVisitor {
17+
type Value = String;
18+
19+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
20+
formatter.write_str("a string")
21+
}
22+
23+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
24+
where
25+
E: Error,
26+
{
27+
Ok(String::from(v))
28+
}
29+
30+
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
31+
where
32+
E: Error,
33+
{
34+
let mut msg = String {
35+
data: std::ptr::null_mut(),
36+
size: 0,
37+
capacity: 0,
38+
};
39+
// SAFETY: This is doing the same thing as rosidl_runtime_c__String__copy.
40+
unsafe {
41+
rosidl_runtime_c__String__assignn(&mut msg, v.as_ptr() as *const _, v.len());
42+
}
43+
Ok(msg)
44+
}
45+
46+
// We don't implement visit_bytes_buf, since the data in a string must always be managed by C.
47+
}
48+
49+
impl<'de> Visitor<'de> for WStringVisitor {
50+
type Value = WString;
51+
52+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
53+
formatter.write_str("a string")
54+
}
55+
56+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
57+
where
58+
E: Error,
59+
{
60+
Ok(WString::from(v))
61+
}
62+
63+
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
64+
where
65+
A: SeqAccess<'de>,
66+
{
67+
let mut buf = if let Some(size) = seq.size_hint() {
68+
Vec::with_capacity(size)
69+
} else {
70+
Vec::new()
71+
};
72+
while let Some(el) = seq.next_element::<u16>()? {
73+
buf.push(el);
74+
}
75+
let mut msg = WString {
76+
data: std::ptr::null_mut(),
77+
size: 0,
78+
capacity: 0,
79+
};
80+
// SAFETY: This is doing the same thing as rosidl_runtime_c__U16String__copy.
81+
unsafe {
82+
rosidl_runtime_c__U16String__assignn(&mut msg, buf.as_ptr(), buf.len());
83+
}
84+
Ok(msg)
85+
}
86+
87+
// We don't implement visit_bytes_buf, since the data in a string must always be managed by C.
88+
}
489

590
impl<'de> Deserialize<'de> for String {
691
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
792
where
893
D: Deserializer<'de>,
994
{
10-
std::string::String::deserialize(deserializer).map(|s| Self::from(s.as_str()))
95+
deserializer.deserialize_string(StringVisitor)
1196
}
1297
}
1398

@@ -29,7 +114,7 @@ impl<'de> Deserialize<'de> for WString {
29114
where
30115
D: Deserializer<'de>,
31116
{
32-
std::string::String::deserialize(deserializer).map(|s| Self::from(s.as_str()))
117+
deserializer.deserialize_string(WStringVisitor)
33118
}
34119
}
35120

0 commit comments

Comments
 (0)