way-lib-rust 0.0.3

foundation for all Ampliway services
Documentation
use crate::id::v1::base::V1;
use once_cell::sync::Lazy;
use std::{
    collections::HashMap,
    sync::{LockResult, Mutex},
};

static mut MOCK_MAKE_VALUES: Lazy<Mutex<HashMap<String, Vec<String>>>> =
    Lazy::new(|| Mutex::new(HashMap::new()));
static mut MOCK_IS_VALID_VALUES: Lazy<Mutex<HashMap<String, Vec<String>>>> =
    Lazy::new(|| Mutex::new(HashMap::new()));

#[derive(Debug)]
pub struct Mock {
    id: String,
}

impl Mock {
    pub fn new() -> Self {
        Mock::new_options(ulid::Ulid::new().to_string())
    }

    pub fn new_options(id: String) -> Self {
        Mock {
            id: id.to_lowercase(),
        }
    }

    pub fn expected_make(&self, value: String) {
        unsafe {
            let value = value.to_lowercase();

            let mut mock_make_values = MOCK_MAKE_VALUES.lock().ignore_poison();

            if !mock_make_values.contains_key(&self.id) {
                mock_make_values.insert(self.id.clone(), vec![]);
            }

            mock_make_values
                .get_mut(&self.id)
                .unwrap()
                .push(value.clone());

            let mut mock_is_valid_values = MOCK_IS_VALID_VALUES.lock().ignore_poison();

            if !mock_is_valid_values.contains_key(&self.id) {
                mock_is_valid_values.insert(self.id.clone(), vec![]);
            }

            mock_is_valid_values
                .get_mut(&self.id)
                .unwrap()
                .push(value.clone());
        }
    }
}

impl V1 for Mock {
    fn make(&self) -> String {
        unsafe {
            let mut mock_make_values = MOCK_MAKE_VALUES.lock().ignore_poison();

            let values = match mock_make_values.get_mut(&self.id) {
                Some(result) => result,
                None => panic!("no values were found for this mock instance ({}), you did'nt initialize the mock correctly, to do so use the 'new' function as shown below: Mock::new()", self.id)
            };

            let value = match values.pop() {
                Some(result) => result,
                None => panic!("no value found for the requested mock instance ({}), you must set the value expected by the mock using the 'expected_make' function as shown below: mock_instance.expected_make(\"my_value\".to_string())", self.id)
            };

            value
        }
    }

    fn is_valid(&self, value: String) -> bool {
        unsafe {
            let mock_is_valid_values = MOCK_IS_VALID_VALUES.lock().ignore_poison();

            let values = match mock_is_valid_values.get(&self.id) {
                None => return false,
                Some(result) => result,
            };

            values.contains(&value)
        }
    }
}

pub trait LockResultExt {
    type Guard;

    fn ignore_poison(self) -> Self::Guard;
}

impl<Guard> LockResultExt for LockResult<Guard> {
    type Guard = Guard;

    fn ignore_poison(self) -> Guard {
        self.unwrap_or_else(|e| e.into_inner())
    }
}