inventory.rs en Rust
Un pequeño árbol de módulos con un builder, invariantes privados y sus propias pruebas.
mod store {
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub struct Item {
sku: String,
quantity: u32,
}
impl Item {
pub fn new(sku: &str, quantity: u32) -> Result<Item, String> {
if sku.is_empty() {
return Err("sku is required".to_string());
}
Ok(Item { sku: sku.to_string(), quantity })
}
pub fn sku(&self) -> &str {
&self.sku
}
pub fn quantity(&self) -> u32 {
self.quantity
}
}
#[derive(Default)]
pub struct Inventory {
items: HashMap<String, Item>,
}
impl Inventory {
pub fn add(&mut self, item: Item) {
self.items
.entry(item.sku().to_string())
.and_modify(|held| held.quantity += item.quantity())
.or_insert(item);
}
pub fn total(&self) -> u32 {
self.items.values().map(|i| i.quantity()).sum()
}
pub fn low_stock(&self, floor: u32) -> Vec<&str> {
let mut low: Vec<&str> = self
.items
.values()
.filter(|i| i.quantity() < floor)
.map(|i| i.sku())
.collect();
low.sort();
low
}
}
}
use store::{Inventory, Item};
fn main() {
let mut inventory = Inventory::default();
for (sku, qty) in [("TS-001", 5), ("TS-002", 1), ("TS-001", 3)] {
match Item::new(sku, qty) {
Ok(item) => inventory.add(item),
Err(e) => println!("skipped: {e}"),
}
}
println!("total units: {}", inventory.total());
println!("low stock: {:?}", inventory.low_stock(4));
println!("{:?}", Item::new("", 1));
}
#[cfg(test)]
mod tests {
use super::store::{Inventory, Item};
#[test]
fn merges_quantities_for_one_sku() {
let mut inv = Inventory::default();
inv.add(Item::new("A", 2).unwrap());
inv.add(Item::new("A", 3).unwrap());
assert_eq!(inv.total(), 5);
}
#[test]
fn rejects_an_empty_sku() {
assert!(Item::new("", 1).is_err());
}
}
Cómo funciona
- El módulo
storeposee los datos y mantiene privados sus campos. - Un builder arma los ítems, validando sobre la marcha.
- El módulo de pruebas ejercita el camino feliz y el que falla.
Palabras clave y builtins usados aquí
ErrOkResultStringVecfnforifimplinletmatchmodmutpubreturnselfstrstructsuperu32use
El intento, en números
- Líneas
- 89
- Caracteres a escribir
- 1633
- Tokens
- 556
- Ritmo de tres estrellas
- 115 tpm
Al ritmo de tres estrellas de 115 tokens por minuto, este intento toma unos 290 segundos.
Paso 1 de 1 en Bis; paso 12 de 12 en Módulos, pruebas y macros.