-
Notifications
You must be signed in to change notification settings - Fork 159
Extend string types #293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extend string types #293
Changes from 6 commits
661558c
d173928
4d5c052
955003a
99945e6
0885dd7
55a4334
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ use std::ffi::CStr; | |
use std::fmt::{self, Debug, Display}; | ||
use std::hash::{Hash, Hasher}; | ||
use std::ops::{Deref, DerefMut}; | ||
use std::ptr; | ||
|
||
#[cfg(feature = "serde")] | ||
mod serde; | ||
|
@@ -112,7 +113,7 @@ pub struct StringExceedsBoundsError { | |
|
||
// There is a lot of redundancy between String and WString, which this macro aims to reduce. | ||
macro_rules! string_impl { | ||
($string:ty, $char_type:ty, $unsigned_char_type:ty, $string_conversion_func:ident, $init:ident, $fini:ident, $assignn:ident, $sequence_init:ident, $sequence_fini:ident, $sequence_copy:ident) => { | ||
($string:ty, $char_type:ty, $unsigned_char_type:ty, $string_conversion_func:ident, $encoding_func:ident, $init:ident, $fini:ident, $assignn:ident, $sequence_init:ident, $sequence_fini:ident, $sequence_copy:ident) => { | ||
maspe36 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#[link(name = "rosidl_runtime_c")] | ||
extern "C" { | ||
fn $init(s: *mut $string) -> bool; | ||
|
@@ -135,7 +136,7 @@ macro_rules! string_impl { | |
}; | ||
// SAFETY: Passing in a zeroed string is safe. | ||
if !unsafe { $init(&mut msg as *mut _) } { | ||
panic!("Sinit failed"); | ||
panic!("$init failed"); | ||
maspe36 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
msg | ||
} | ||
|
@@ -224,6 +225,42 @@ macro_rules! string_impl { | |
} | ||
} | ||
|
||
impl From<&std::string::String> for $string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the existing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's correct, though using |
||
fn from(s: &std::string::String) -> Self { | ||
Self::from(s.as_str()) | ||
} | ||
} | ||
|
||
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 Extend<char> for $string { | ||
maspe36 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) { | ||
let mut s = self.to_string(); | ||
s.extend(iter); | ||
*self = Self::from(&s); | ||
} | ||
} | ||
|
||
impl<'a> Extend<&'a char> for $string { | ||
fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) { | ||
self.extend(iter.into_iter().cloned()); | ||
} | ||
} | ||
|
||
// SAFETY: A string is a simple data structure, and therefore not thread-specific. | ||
unsafe impl Send for $string {} | ||
// SAFETY: A string does not have interior mutability, so it can be shared. | ||
|
@@ -251,6 +288,7 @@ string_impl!( | |
std::os::raw::c_char, | ||
u8, | ||
from_utf8_lossy, | ||
encode_utf8, | ||
rosidl_runtime_c__String__init, | ||
rosidl_runtime_c__String__fini, | ||
rosidl_runtime_c__String__assignn, | ||
|
@@ -263,6 +301,7 @@ string_impl!( | |
std::os::raw::c_ushort, | ||
u16, | ||
from_utf16_lossy, | ||
encode_utf16, | ||
rosidl_runtime_c__U16String__init, | ||
rosidl_runtime_c__U16String__fini, | ||
rosidl_runtime_c__U16String__assignn, | ||
|
@@ -274,7 +313,7 @@ string_impl!( | |
impl From<&str> for String { | ||
fn from(s: &str) -> Self { | ||
let mut msg = Self { | ||
data: std::ptr::null_mut(), | ||
data: ptr::null_mut(), | ||
size: 0, | ||
capacity: 0, | ||
}; | ||
|
@@ -304,7 +343,7 @@ impl String { | |
impl From<&str> for WString { | ||
fn from(s: &str) -> Self { | ||
let mut msg = Self { | ||
data: std::ptr::null_mut(), | ||
data: ptr::null_mut(), | ||
size: 0, | ||
capacity: 0, | ||
}; | ||
|
@@ -503,4 +542,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); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.