//! Your task is to implement the methods for `Crate`. use std::{iter::Sum, ops::Add}; #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] struct Kilograms(f32); impl From for Kilograms { fn from(kilos: f32) -> Self { Self(kilos) } } impl From for Kilograms { fn from(kilos: i32) -> Self { Self(kilos as f32) } } impl Add for Kilograms { type Output = Self; fn add(self, rhs: Self) -> Self::Output { Kilograms::from(self.0 + rhs.0) } } impl Sum for Kilograms { fn sum>(iter: I) -> Self { iter.fold(0.0.into(), |acc, next| acc + next) } } #[derive(Debug, Clone, PartialEq, PartialOrd)] enum Crate { Empty, WithStuff(Kilograms), Multiple(Vec), } impl Default for Crate { fn default() -> Self { Self::Empty } } #[derive(Debug, Clone, PartialEq)] enum Error { /// Tried to fill a crate with stuff but there were other crates inside FillMultiple, /// Tried to unbox an empty crate EmptyCrate, } impl Crate { fn new() -> Self { Self::default() } /// Returns the total mass of the crate's contents. fn mass(&self) -> Kilograms { todo!() } /// Fills the crate with `mass` kilograms of _stuff_. /// /// # Errors /// /// If the crate contains multiple crates there's no way to fill it and an /// [`Error::FillMultiple`] is returned. fn fill(&mut self, mass: Kilograms) -> Result<(), Error> { todo!() } /// Unboxes the crate returing the mass of all the _stuff_. Every unboxed /// crate becomes empty and stays in their parent crate. If the crate /// contains empty crates and no _stuff_ the unboxing is successful. /// /// # Errors /// /// If the top-most crate is empty an [`Error::EmptyCrate`] is returned. fn unbox(&mut self) -> Result { todo!() } /// Inserts an `other` crate inside `self`. If the crate has _stuff_ inside, /// its mass is returned. If the crate has other crates inside, the `other` /// crate just joins them. fn insert(&mut self, other: Self) -> Option { todo!() } } #[test] fn mass() { let heavy_crate = Crate::WithStuff(12.into()); let loota = Crate::Multiple(vec![ heavy_crate.clone(), Crate::Multiple(vec![heavy_crate.clone(), Crate::new()]), ]); assert_eq!(loota.mass(), 24.into()); } #[test] fn fill() { let mut loota = Crate::Empty; loota.fill(5.into()); assert_eq!(loota.mass(), 5.into()); let mut loota = Crate::WithStuff(2.into()); loota.fill(5.into()); assert_eq!(loota.mass(), 7.into()); } #[test] fn unbox() { let mut loota = Crate::Empty; assert_eq!(loota.unbox(), Err(Error::EmptyCrate)); assert_eq!(loota, Crate::Empty); let mut loota = Crate::Multiple(vec![Crate::Empty, Crate::Multiple(vec![Crate::Empty])]); assert_eq!(loota.unbox(), Ok(0.into())); let iso_loota = Crate::WithStuff(20.into()); let mut loota = Crate::Multiple(vec![ iso_loota.clone(), Crate::Multiple(vec![iso_loota.clone(), Crate::new()]), iso_loota.clone(), Crate::new(), ]); assert_eq!(loota.unbox(), Ok(60.into())); assert_eq!( loota, Crate::Multiple(vec![ Crate::Empty, Crate::Multiple(vec![Crate::Empty, Crate::Empty]), Crate::Empty, Crate::Empty ]) ); } #[test] fn insert() { let pieni_loota = Crate::WithStuff(2.into()); let iso_loota = Crate::Multiple(vec![ pieni_loota.clone(), Crate::Multiple(vec![pieni_loota.clone(), Crate::new()]), pieni_loota.clone(), ]); let mut loota = Crate::Empty; assert_eq!(loota.insert(iso_loota.clone()), None); assert_eq!(loota, Crate::Multiple(vec![iso_loota.clone()])); let mut loota = Crate::Multiple(vec![ pieni_loota.clone(), Crate::Multiple(vec![Crate::Empty]), ]); assert_eq!(loota.insert(iso_loota.clone()), None); assert_eq!(loota.mass(), 8.into()); let mut loota = Crate::WithStuff(10.into()); assert_eq!(loota.insert(iso_loota), Some(10.into())); assert_eq!(loota.mass(), 6.into()); }