Skip to content

Commit

Permalink
Extend string types (#293)
Browse files Browse the repository at this point in the history
  • Loading branch information
maspe36 authored Nov 13, 2022
1 parent 2746996 commit 087527e
Showing 1 changed file with 111 additions and 21 deletions.
132 changes: 111 additions & 21 deletions rosidl_runtime_rs/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,6 @@ macro_rules! string_impl {
) -> bool;
}

impl Default for $string {
fn default() -> Self {
let mut msg = Self {
data: std::ptr::null_mut(),
size: 0,
capacity: 0,
};
// SAFETY: Passing in a zeroed string is safe.
if !unsafe { $init(&mut msg as *mut _) } {
panic!("Sinit failed");
}
msg
}
}

impl Clone for $string {
fn clone(&self) -> Self {
let mut msg = Self::default();
Expand All @@ -158,6 +143,21 @@ macro_rules! string_impl {
}
}

impl Default for $string {
fn default() -> Self {
let mut msg = Self {
data: std::ptr::null_mut(),
size: 0,
capacity: 0,
};
// SAFETY: Passing in a zeroed string is safe.
if !unsafe { $init(&mut msg as *mut _) } {
panic!("$init failed");
}
msg
}
}

// It's not guaranteed that there are no interior null bytes, hence no Deref to CStr.
// This does not include the null byte at the end!
impl Deref for $string {
Expand Down Expand Up @@ -200,15 +200,39 @@ macro_rules! string_impl {

impl Eq for $string {}

impl Hash for $string {
fn hash<H: Hasher>(&self, state: &mut H) {
self.deref().hash(state)
impl Extend<char> for $string {
fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
let mut s = self.to_string();
s.extend(iter);
*self = Self::from(s.as_str());
}
}

impl PartialEq for $string {
fn eq(&self, other: &Self) -> bool {
self.deref().eq(other.deref())
impl<'a> Extend<&'a char> for $string {
fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
self.extend(iter.into_iter().cloned());
}
}

impl FromIterator<char> for $string {
fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> Self {
let mut buf = <$string>::default();
buf.extend(iter);
buf
}
}

impl<'a> FromIterator<&'a char> for $string {
fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> Self {
let mut buf = <$string>::default();
buf.extend(iter);
buf
}
}

impl Hash for $string {
fn hash<H: Hasher>(&self, state: &mut H) {
self.deref().hash(state)
}
}

Expand All @@ -218,6 +242,12 @@ macro_rules! string_impl {
}
}

impl PartialEq for $string {
fn eq(&self, other: &Self) -> bool {
self.deref().eq(other.deref())
}
}

impl PartialOrd for $string {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.deref().partial_cmp(other.deref())
Expand Down Expand Up @@ -503,4 +533,64 @@ mod tests {
s.as_str().try_into().unwrap()
}
}

#[test]
fn string_from_char_iterator() {
// Base char case
let expected = String::from("abc");
let actual = "abc".chars().collect::<String>();

assert_eq!(expected, actual);

// Empty case
let expected = String::from("");
let actual = "".chars().collect::<String>();

assert_eq!(expected, actual);

// Non-ascii char case
let expected = String::from("Grüß Gott! 𝕊");
let actual = "Grüß Gott! 𝕊".chars().collect::<String>();

assert_eq!(expected, actual);
}

#[test]
fn extend_string_with_char_iterator() {
let expected = WString::from("abcdef");
let mut actual = WString::from("abc");
actual.extend("def".chars());

assert_eq!(expected, actual);
}

#[test]
fn wstring_from_char_iterator() {
// Base char case
let expected = WString::from("abc");
let actual = "abc".chars().collect::<WString>();

assert_eq!(expected, actual);

// Empty case
let expected = WString::from("");
let actual = "".chars().collect::<WString>();

assert_eq!(expected, actual);

// Non-ascii char case
let expected = WString::from("Grüß Gott! 𝕊");
let actual = "Grüß Gott! 𝕊".chars().collect::<WString>();

assert_eq!(expected, actual);
}

#[test]
fn extend_wstring_with_char_iterator() {
let expected = WString::from("abcdef");
let mut actual = WString::from("abc");
actual.extend("def".chars());

assert_eq!(expected, actual);
}
}

0 comments on commit 087527e

Please sign in to comment.