Skip to content

Commit 087527e

Browse files
authored
Extend string types (#293)
1 parent 2746996 commit 087527e

File tree

1 file changed

+111
-21
lines changed

1 file changed

+111
-21
lines changed

rosidl_runtime_rs/src/string.rs

Lines changed: 111 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -126,21 +126,6 @@ macro_rules! string_impl {
126126
) -> bool;
127127
}
128128

129-
impl Default for $string {
130-
fn default() -> Self {
131-
let mut msg = Self {
132-
data: std::ptr::null_mut(),
133-
size: 0,
134-
capacity: 0,
135-
};
136-
// SAFETY: Passing in a zeroed string is safe.
137-
if !unsafe { $init(&mut msg as *mut _) } {
138-
panic!("Sinit failed");
139-
}
140-
msg
141-
}
142-
}
143-
144129
impl Clone for $string {
145130
fn clone(&self) -> Self {
146131
let mut msg = Self::default();
@@ -158,6 +143,21 @@ macro_rules! string_impl {
158143
}
159144
}
160145

146+
impl Default for $string {
147+
fn default() -> Self {
148+
let mut msg = Self {
149+
data: std::ptr::null_mut(),
150+
size: 0,
151+
capacity: 0,
152+
};
153+
// SAFETY: Passing in a zeroed string is safe.
154+
if !unsafe { $init(&mut msg as *mut _) } {
155+
panic!("$init failed");
156+
}
157+
msg
158+
}
159+
}
160+
161161
// It's not guaranteed that there are no interior null bytes, hence no Deref to CStr.
162162
// This does not include the null byte at the end!
163163
impl Deref for $string {
@@ -200,15 +200,39 @@ macro_rules! string_impl {
200200

201201
impl Eq for $string {}
202202

203-
impl Hash for $string {
204-
fn hash<H: Hasher>(&self, state: &mut H) {
205-
self.deref().hash(state)
203+
impl Extend<char> for $string {
204+
fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
205+
let mut s = self.to_string();
206+
s.extend(iter);
207+
*self = Self::from(s.as_str());
206208
}
207209
}
208210

209-
impl PartialEq for $string {
210-
fn eq(&self, other: &Self) -> bool {
211-
self.deref().eq(other.deref())
211+
impl<'a> Extend<&'a char> for $string {
212+
fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
213+
self.extend(iter.into_iter().cloned());
214+
}
215+
}
216+
217+
impl FromIterator<char> for $string {
218+
fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> Self {
219+
let mut buf = <$string>::default();
220+
buf.extend(iter);
221+
buf
222+
}
223+
}
224+
225+
impl<'a> FromIterator<&'a char> for $string {
226+
fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> Self {
227+
let mut buf = <$string>::default();
228+
buf.extend(iter);
229+
buf
230+
}
231+
}
232+
233+
impl Hash for $string {
234+
fn hash<H: Hasher>(&self, state: &mut H) {
235+
self.deref().hash(state)
212236
}
213237
}
214238

@@ -218,6 +242,12 @@ macro_rules! string_impl {
218242
}
219243
}
220244

245+
impl PartialEq for $string {
246+
fn eq(&self, other: &Self) -> bool {
247+
self.deref().eq(other.deref())
248+
}
249+
}
250+
221251
impl PartialOrd for $string {
222252
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
223253
self.deref().partial_cmp(other.deref())
@@ -503,4 +533,64 @@ mod tests {
503533
s.as_str().try_into().unwrap()
504534
}
505535
}
536+
537+
#[test]
538+
fn string_from_char_iterator() {
539+
// Base char case
540+
let expected = String::from("abc");
541+
let actual = "abc".chars().collect::<String>();
542+
543+
assert_eq!(expected, actual);
544+
545+
// Empty case
546+
let expected = String::from("");
547+
let actual = "".chars().collect::<String>();
548+
549+
assert_eq!(expected, actual);
550+
551+
// Non-ascii char case
552+
let expected = String::from("Grüß Gott! 𝕊");
553+
let actual = "Grüß Gott! 𝕊".chars().collect::<String>();
554+
555+
assert_eq!(expected, actual);
556+
}
557+
558+
#[test]
559+
fn extend_string_with_char_iterator() {
560+
let expected = WString::from("abcdef");
561+
let mut actual = WString::from("abc");
562+
actual.extend("def".chars());
563+
564+
assert_eq!(expected, actual);
565+
}
566+
567+
#[test]
568+
fn wstring_from_char_iterator() {
569+
// Base char case
570+
let expected = WString::from("abc");
571+
let actual = "abc".chars().collect::<WString>();
572+
573+
assert_eq!(expected, actual);
574+
575+
// Empty case
576+
let expected = WString::from("");
577+
let actual = "".chars().collect::<WString>();
578+
579+
assert_eq!(expected, actual);
580+
581+
// Non-ascii char case
582+
let expected = WString::from("Grüß Gott! 𝕊");
583+
let actual = "Grüß Gott! 𝕊".chars().collect::<WString>();
584+
585+
assert_eq!(expected, actual);
586+
}
587+
588+
#[test]
589+
fn extend_wstring_with_char_iterator() {
590+
let expected = WString::from("abcdef");
591+
let mut actual = WString::from("abc");
592+
actual.extend("def".chars());
593+
594+
assert_eq!(expected, actual);
595+
}
506596
}

0 commit comments

Comments
 (0)