rjango 0.1.1

A full-stack Rust backend framework inspired by Django
Documentation
use crate::core::validators::{DecimalValidator, Validator};

use super::mixins::{FieldCacheMixin, FieldValidationMixin};

/// A DecimalField stores fixed-precision numbers.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DecimalField {
    pub max_digits: u32,
    pub decimal_places: u32,
}

impl Default for DecimalField {
    fn default() -> Self {
        Self {
            max_digits: 10,
            decimal_places: 2,
        }
    }
}

impl DecimalField {
    #[must_use]
    pub fn new(max_digits: u32, decimal_places: u32) -> Self {
        Self {
            max_digits,
            decimal_places,
        }
    }

    #[must_use]
    pub fn max_digits(&self) -> u32 {
        self.max_digits
    }

    #[must_use]
    pub fn decimal_places(&self) -> u32 {
        self.decimal_places
    }

    #[must_use]
    pub fn db_type(&self) -> &str {
        "DECIMAL"
    }
}

impl FieldCacheMixin for DecimalField {
    fn get_cache_name(&self) -> String {
        "decimal_field".to_string()
    }

    fn is_cached(&self) -> bool {
        false
    }
}

impl FieldValidationMixin for DecimalField {
    fn validate(&self, value: &str) -> Result<(), String> {
        DecimalValidator::new(self.max_digits as usize, self.decimal_places as usize)
            .validate(&value)
            .map_err(|error| error.message)
    }
}

#[cfg(test)]
mod tests {
    use super::DecimalField;

    #[test]
    fn decimal_field_default_precision_is_10_2() {
        let field = DecimalField::default();

        assert_eq!(field.max_digits, 10);
        assert_eq!(field.decimal_places, 2);
    }

    #[test]
    fn decimal_field_exposes_max_digits() {
        let field = DecimalField::new(12, 4);

        assert_eq!(field.max_digits(), 12);
    }

    #[test]
    fn decimal_field_exposes_decimal_places() {
        let field = DecimalField::new(12, 4);

        assert_eq!(field.decimal_places(), 4);
        assert_eq!(field.db_type(), "DECIMAL");
    }
}