bitpill 0.3.3

A personal medication management TUI application built in Rust.
Documentation
use std::sync::Mutex;

use crate::application::errors::StorageError;
use crate::application::ports::medication_repository_port::MedicationRepository;
use crate::domain::{entities::medication::Medication, value_objects::medication_id::MedicationId};

pub struct FakeMedicationRepository {
    medications: Mutex<Vec<Medication>>,
    fail_on_save: bool,
    deleted_count: Mutex<usize>,
}

impl Default for FakeMedicationRepository {
    fn default() -> Self {
        Self::new()
    }
}

impl FakeMedicationRepository {
    pub fn new() -> Self {
        Self {
            medications: Mutex::new(Vec::new()),
            fail_on_save: false,
            deleted_count: Mutex::new(0),
        }
    }

    pub fn with(medications: Vec<Medication>) -> Self {
        Self {
            medications: Mutex::new(medications),
            fail_on_save: false,
            deleted_count: Mutex::new(0),
        }
    }

    pub fn failing() -> Self {
        Self {
            medications: Mutex::new(Vec::new()),
            fail_on_save: true,
            deleted_count: Mutex::new(0),
        }
    }

    pub fn saved_count(&self) -> usize {
        self.medications.lock().unwrap().len()
    }

    pub fn deleted_count(&self) -> usize {
        *self.deleted_count.lock().unwrap()
    }
}

impl MedicationRepository for FakeMedicationRepository {
    fn save(&self, medication: &Medication) -> Result<(), StorageError> {
        if self.fail_on_save {
            return Err(StorageError("forced failure".into()));
        }
        self.medications.lock().unwrap().push(medication.clone());
        Ok(())
    }

    fn find_by_id(&self, id: &MedicationId) -> Result<Option<Medication>, StorageError> {
        Ok(self
            .medications
            .lock()
            .unwrap()
            .iter()
            .find(|m| m.id() == id)
            .cloned())
    }

    fn find_all(&self) -> Result<Vec<Medication>, StorageError> {
        Ok(self.medications.lock().unwrap().clone())
    }

    fn delete(&self, id: &MedicationId) -> Result<(), StorageError> {
        let mut meds = self.medications.lock().unwrap();
        let before = meds.len();
        meds.retain(|m| m.id() != id);
        let after = meds.len();
        let removed = before.saturating_sub(after);
        if removed > 0 {
            let mut cnt = self.deleted_count.lock().unwrap();
            *cnt += removed;
        }
        Ok(())
    }
}