Preliminary note: Here is just a curiousity question.
Is there a better way to implement impl From<Vec<String>> for Parts
given below?
For a "better way", I mean:
- Keeping the same performance or improving it;
- Cosmetics: avoiding repeating
strings.next().unwrap_or_default()
three times, without using macros; - Still passing all the given tests.
Here is the code:
#[derive(Debug, PartialEq)]
pub struct Parts {
left: String,
middle: String,
right: String,
}
impl From<Vec<String>> for Parts {
fn from(strings: Vec<String>) -> Parts {
// CODE REVIEW PART: ################################################################
let mut strings = strings.into_iter();
Parts {
left: strings.next().unwrap_or_default(),
middle: strings.next().unwrap_or_default(),
right: strings.next().unwrap_or_default(),
}
//###################################################################################
}
}
#[cfg(test)]
mod tests {
use super::*;
macro_rules! s { ($s:expr) => { String::from($s) } }
macro_rules! string_with_ptr {
($s:expr) => {{
let s = String::from($s);
let ptr = s.as_ptr();
(s, ptr)
}};
($($s:expr),*) => { ( $( string_with_ptr!($s), )* ) };
}
#[test]
fn test_empty_input() {
assert_eq!(
Parts::from(vec![]),
Parts { left: s!(""), middle: s!(""), right: s!("") }
);
}
#[test]
fn test_small_input() {
let (left_string, left_ptr) = string_with_ptr!("left");
// Object to test:
let parts = Parts::from(vec![left_string]);
// Test that strings has been moved, not cloned:
assert_eq!(left_ptr, parts.left.as_ptr());
// Test the behaviour:
assert_eq!(
parts,
Parts { left: s!("left"), middle: s!(""), right: s!("") }
);
}
#[test]
fn test_big_input() {
let (
( left_string, left_ptr),
(middle_string, middle_ptr),
( right_string, right_ptr),
) = string_with_ptr!("left", "middle", "right");
// Object to test:
let parts = Parts::from(vec![left_string, middle_string, right_string, s!("foo"), s!("bar")]);
// Test that strings has been moved, not cloned:
assert_eq!(left_ptr, parts.left.as_ptr());
assert_eq!(middle_ptr, parts.middle.as_ptr());
assert_eq!(right_ptr, parts.right.as_ptr());
// Test the behaviour:
assert_eq!(
parts,
Parts { left: s!("left"), middle: s!("middle"), right: s!("right") }
);
}
}