Skip to content

Instantly share code, notes, and snippets.

@hjr3
Created October 27, 2016 04:15
Show Gist options
  • Select an option

  • Save hjr3/a77ee17c792890bed37b270d3dbd1b97 to your computer and use it in GitHub Desktop.

Select an option

Save hjr3/a77ee17c792890bed37b270d3dbd1b97 to your computer and use it in GitHub Desktop.

Revisions

  1. hjr3 created this gist Oct 27, 2016.
    181 changes: 181 additions & 0 deletions exercise2.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,181 @@
    use std::borrow::{Borrow, BorrowMut, Cow};
    use std::mem;

    #[derive(Eq, PartialEq, Debug, Clone)]
    pub struct NameString {
    inner: String,
    }

    impl NameString {
    pub fn from_str(s: &str) -> NameString {
    NameString {
    inner: s.to_string()
    }
    }

    pub fn uppercase(&mut self) {
    self.inner = self.inner.to_uppercase();
    }

    // TODO: Write a lowercase function to be used by `NameStr::to_lowercase`.
    pub fn lowercase(&mut self) {
    unimplemented!()
    }
    }

    impl Borrow<NameStr> for NameString {
    fn borrow(&self) -> &NameStr {
    unsafe { mem::transmute(& *self.inner) }
    }
    }

    impl BorrowMut<NameStr> for NameString {
    fn borrow_mut(&mut self) -> &mut NameStr {
    unsafe { mem::transmute(&mut *self.inner) }
    }
    }

    #[derive(Eq, PartialEq, Debug)]
    pub struct NameStr {
    // allowed per https://doc.rust-lang.org/book/unsized-types.html
    inner: str,
    }

    impl NameStr {
    pub fn new(name: &str) -> &NameStr {
    unsafe { mem::transmute(name) }
    }

    pub fn to_name_string(&self) -> NameString {
    NameString {
    inner: self.inner.to_string()
    }
    }

    pub fn to_uppercase(&self) -> Cow<NameStr> {
    if self.inner.chars().all(|b| b.is_uppercase()) {
    Cow::Borrowed(self)
    } else {
    let mut name_string = self.to_name_string();
    name_string.uppercase();
    Cow::Owned(name_string)
    }
    }

    // TODO: Write a `NameStr::to_lowercase` function.
    pub fn to_lowercase(&self) -> Cow<NameStr> {
    unimplemented!()
    }
    }

    impl ToOwned for NameStr {
    type Owned = NameString;

    fn to_owned(&self) -> NameString {
    self.to_name_string()
    }
    }

    #[derive(Debug, Eq, PartialEq)]
    pub struct Roster<'a> {
    pub names: Vec<Cow<'a, NameStr>>,
    }

    impl<'a> Roster<'a> {
    pub fn new() -> Roster<'a> {
    Roster {
    names: Vec::new(),
    }
    }

    // TODO: Implement `Roster::with_names()`.
    pub fn with_names(names: Vec<&'a NameStr>) -> Roster<'a> {
    unimplemented!()
    }

    pub fn add_name(&mut self, name: &'a NameStr) {
    self.names.push(name.to_uppercase())
    }
    }

    #[derive(Debug, Eq, PartialEq)]
    pub struct Student {
    name: NameString,
    seat: usize,
    }

    impl Student {
    pub fn new<I>(name: I, seat: usize) -> Student
    where I: Into<NameString>
    {
    Student {
    name: name.into(),
    seat: seat,
    }
    }

    pub fn name(&self) -> &NameString {
    &self.name
    }
    }

    pub struct InClass<T> {
    inner: T,
    }

    impl<T> InClass<T> {
    pub fn rest(self) -> Home<T> {
    // TODO: Implement a new function for the `InClass` struct called `rest`
    // that changes a student to a new state caled `Home`.
    unimplemented!()
    }
    }



    #[cfg(test)]
    mod tests {
    use super::*;
    use std::borrow::Cow;

    #[test]
    fn test_name_string_lowercase() {
    let expected = NameString::from_str("name");
    let mut given = NameString:: from_str("Name");
    given.lowercase();
    assert_eq!(expected, given);
    }

    #[test]
    fn test_name_str_to_lowercase() {
    let lc_name_str = NameStr::new("name");

    assert_eq!(Cow::Borrowed(lc_name_str), lc_name_str.to_lowercase());

    let uc_name_string: Cow<NameStr> = Cow::Owned(lc_name_str.to_owned());
    let mixed_case_name_str = NameStr::new("Name");

    assert_eq!(uc_name_string, mixed_case_name_str.to_lowercase());
    }

    #[test]
    fn test_roster_with_names() {
    let names = vec![NameStr::new("Grace Hopper"), NameStr::new("Ada Lovelace")];

    let given = Roster::with_names(names);

    let mut expected = Roster::new();
    expected.add_name(NameStr::new("Grace Hopper"));
    expected.add_name(NameStr::new("Ada Lovelace"));

    assert_eq!(expected, given);
    }

    #[test]
    fn test_student_state_change_home() {
    let me = Student::new(NameString::from_str("Herman"), 0);
    let me_in_class = InClass { inner: me };
    let me_at_home = me_in_class.rest();
    let _me_back_in_class = me_at_home.learn();
    }
    }