RustCurious.com
Rust explained carefully.

Lesson 7

Arrays and Slices

Rust has distinct types for fixed-length arrays, dynamic arrays, and slices. A slice is a borrowed reference into a sequence of elements owned by some other variable.

Coding Practice

Exercise: Stack

Open in playground

// https://rustcurious.com/7

// Exercise: Stack
//
// Implement the methods to pass the unit tests.
//
// Yes you could use a Vec as a stack, but that
// would be cheating. In this exercise we use a
// fixed-length array as a buffer, with a separate
// integer field to track the number of items.

/// A first-in-last-out container of up to 25 chars.
pub struct Stack {
    buf: [char; 25],
    len: usize,
}

impl Stack {
    /// Returns an empty Stack.
    pub fn new() -> Stack {
        todo!()
    }

    /// Returns the current number of items (chars) held.
    pub fn len(&self) -> usize {
        todo!()
    }

    /// Pushes the item `c` onto the stack.
    ///
    /// Panics if already at full capacity.
    /// (You don't need to write code to explicitly panic,
    /// the bounds check on array access will do it for you.)
    pub fn push(&mut self, c: char) {
        todo!()
    }

    /// Removes the top item from the stack and returns it.
    ///
    /// Returns None if the stack is empty.
    pub fn pop(&mut self) -> Option<char> {
        todo!()
    }

    /// Returns a shared reference to the top item.
    ///
    /// Returns None if the stack is empty.
    pub fn peek(&self) -> Option<&char> {
        todo!()
    }

    /// Returns a mutable reference to the top item.
    ///
    /// Returns None if the stack is empty.
    pub fn peek_mut(&mut self) -> Option<&mut char> {
        todo!()
    }

    /// Returns the content of the stack as a shared
    /// array slice. The most recently pushed item
    /// is the last element in the slice.
    pub fn as_slice(&self) -> &[char] {
        todo!()
    }

    /// Returns the content of the stack as a mutable
    /// array slice. The most recently pushed item
    /// is the last element in the slice.
    pub fn as_mut_slice(&mut self) -> &mut [char] {
        todo!()
    }
}

// -------------------------------------------------------
// No need to change anything below this line.

#[test]
fn test_len_push_pop() {
    let mut stack = Stack::new();
    assert_eq!(0, stack.len());
    assert_eq!(None, stack.pop());
    stack.push('a');
    stack.push('b');
    stack.push('c');
    assert_eq!(3, stack.len());
    assert_eq!(Some('c'), stack.pop());
    assert_eq!(Some('b'), stack.pop());
    assert_eq!(Some('a'), stack.pop());
    assert_eq!(0, stack.len());
    assert_eq!(None, stack.pop());
}

#[test]
fn test_push_full() {
    let mut stack = Stack::new();
    for c in 'a'..='y' {
        stack.push(c);
    }
    for c in ('a'..='y').rev() {
        assert_eq!(Some(c), stack.pop());
    }
    assert_eq!(None, stack.pop());
}

#[should_panic(expected="index out of bounds")]
#[test]
fn test_push_overflow() {
    let mut stack = Stack::new();
    for c in 'a'..='z' {
        stack.push(c);
    }
}

#[test]
fn test_peek() {
    let mut stack = Stack::new();
    assert_eq!(None, stack.peek());
    stack.push('a');
    stack.push('b');
    stack.push('c');
    assert_eq!(Some(&'c'), stack.peek());
    assert_eq!(Some('c'), stack.pop());
    assert_eq!(Some(&'b'), stack.peek());
    assert_eq!(Some('b'), stack.pop());
    assert_eq!(Some(&'a'), stack.peek());
    assert_eq!(Some('a'), stack.pop());
    assert_eq!(None, stack.peek());
}

#[test]
fn test_peek_mut() {
    let mut stack = Stack::new();
    assert_eq!(None, stack.peek_mut());
    stack.push('a');
    stack.push('b');
    stack.push('c');
    stack.peek_mut().unwrap().make_ascii_uppercase();
    assert_eq!(Some('C'), stack.pop());
    stack.peek_mut().unwrap().make_ascii_uppercase();
    assert_eq!(Some('B'), stack.pop());
    stack.peek_mut().unwrap().make_ascii_uppercase();
    assert_eq!(Some('A'), stack.pop());
    assert_eq!(None, stack.peek_mut());
}

#[test]
fn test_slices() {
    let mut stack = Stack::new();
    assert_eq!(stack.as_slice(), &[]);
    assert_eq!(stack.as_mut_slice(), &[]);
    stack.push('a');
    stack.push('b');
    stack.push('c');
    assert_eq!(stack.as_slice(), &['a', 'b', 'c']);
    assert_eq!(stack.as_mut_slice(), &['a', 'b', 'c']);
    stack.as_mut_slice()[1] = 'B';
    assert_eq!(stack.as_slice(), &['a', 'B', 'c']);
    assert_eq!(stack.as_mut_slice(), &['a', 'B', 'c']);
    stack.pop();
    assert_eq!(stack.as_slice(), &['a', 'B']);
    stack.pop();
    stack.pop();
    assert_eq!(stack.as_slice(), &[]);
    assert_eq!(stack.as_mut_slice(), &[]);
}