68 lines
2.3 KiB
Rust
68 lines
2.3 KiB
Rust
#[derive(Debug, PartialEq)]
|
|
pub struct EmptyListError;
|
|
|
|
// implementing Error for my error to satisfy Box<dyn std::error::Error>
|
|
// not needed ATM
|
|
// impl std::error::Error for EmptyListError {}
|
|
|
|
// so we can pass EmptyListError to println!
|
|
impl std::fmt::Display for EmptyListError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
write!(f, "Error: list must not be empty")
|
|
}
|
|
}
|
|
|
|
// Result<...,Box<dyn std::error::Error>> is overkill
|
|
// this is intuitive enough for caller error detection
|
|
// actually probably should use Option instead, but this is better for extension
|
|
pub fn min_and_max(list: &[u32]) -> Result<(u32, u32), EmptyListError> {
|
|
if list.is_empty() {
|
|
return Err(EmptyListError);
|
|
}
|
|
let mut min:u32 = 100;
|
|
let mut max:u32 = 0;
|
|
for i in list {
|
|
if *i > max {
|
|
max = *i;
|
|
}
|
|
if *i < min {
|
|
min = *i;
|
|
}
|
|
}
|
|
Ok((min,max))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*; // need access to functions above
|
|
|
|
#[test]
|
|
fn test_arrays() {
|
|
// empty array
|
|
let empty = [];
|
|
let empty_min_and_max = min_and_max(&empty);
|
|
assert!(empty_min_and_max.as_ref().is_err()); // as_ref() so we don't perform move
|
|
assert!(*(empty_min_and_max.as_ref().err().unwrap()) == EmptyListError);
|
|
println!("Expected: {}", *(empty_min_and_max.as_ref().err().unwrap()));
|
|
|
|
// array - contiguous, entirely on the stack, fixed at compile time, no pointer indirection
|
|
let l = [ 1, 2, 10, 100, 50, 75, 36, 21];
|
|
let l_min_and_max = min_and_max(&l);
|
|
assert!(l_min_and_max.as_ref().unwrap().0 == 1);
|
|
assert!(l_min_and_max.as_ref().unwrap().1 == 100);
|
|
|
|
// vec - stack: ptr, len, cap; ptr -> heap: contiguous allocation of capacity
|
|
// when variable goes out of scope drop() is called to deallocate the heap
|
|
let v = vec![1,2,3];
|
|
let v_min_and_max = min_and_max(&v);
|
|
assert!(v_min_and_max.as_ref().unwrap().0 == 1);
|
|
assert!(v_min_and_max.as_ref().unwrap().1 == 3);
|
|
|
|
let s = String::from("hello");
|
|
let r = &s;
|
|
println!("{}", *r); // works because there is no implicit move
|
|
// let thing = *r; // doesn't work because String does not implement Copy trait
|
|
|
|
}
|
|
}
|