rjango 0.1.1

A full-stack Rust backend framework inspired by Django
Documentation
use super::FieldType;
use super::integer::validate_integer_range;
use super::mixins::{FieldCacheMixin, FieldValidationMixin};

/// A PositiveIntegerField stores non-negative 32-bit integers.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct PositiveIntegerField {
    pub min_value: i64,
}

impl PositiveIntegerField {
    #[must_use]
    pub fn new() -> Self {
        Self::default()
    }

    #[must_use]
    pub fn min_value(&self) -> i64 {
        self.min_value
    }

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

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

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

impl FieldValidationMixin for PositiveIntegerField {
    fn validate(&self, value: &str) -> Result<(), String> {
        let parsed = value
            .parse::<i64>()
            .map_err(|_| "Enter a valid integer.".to_string())?;
        validate_integer_range(parsed, &FieldType::PositiveInteger).map_err(|error| error.message)
    }
}

/// A PositiveBigIntegerField stores non-negative 64-bit integers.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct PositiveBigIntegerField {
    pub min_value: i64,
}

impl PositiveBigIntegerField {
    #[must_use]
    pub fn new() -> Self {
        Self::default()
    }

    #[must_use]
    pub fn min_value(&self) -> i64 {
        self.min_value
    }

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

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

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

impl FieldValidationMixin for PositiveBigIntegerField {
    fn validate(&self, value: &str) -> Result<(), String> {
        let parsed = value
            .parse::<i64>()
            .map_err(|_| "Enter a valid integer.".to_string())?;
        validate_integer_range(parsed, &FieldType::PositiveBigInteger)
            .map_err(|error| error.message)
    }
}

/// A PositiveSmallIntegerField stores non-negative 16-bit integers.
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct PositiveSmallIntegerField {
    pub min_value: i64,
}

impl PositiveSmallIntegerField {
    #[must_use]
    pub fn new() -> Self {
        Self::default()
    }

    #[must_use]
    pub fn min_value(&self) -> i64 {
        self.min_value
    }

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

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

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

impl FieldValidationMixin for PositiveSmallIntegerField {
    fn validate(&self, value: &str) -> Result<(), String> {
        let parsed = value
            .parse::<i64>()
            .map_err(|_| "Enter a valid integer.".to_string())?;
        validate_integer_range(parsed, &FieldType::PositiveSmallInteger)
            .map_err(|error| error.message)
    }
}

#[cfg(test)]
mod tests {
    use super::{PositiveBigIntegerField, PositiveIntegerField, PositiveSmallIntegerField};

    #[test]
    fn positive_integer_field_defaults_to_zero_minimum() {
        let field = PositiveIntegerField::default();

        assert_eq!(field.min_value(), 0);
        assert_eq!(field.db_type(), "INTEGER");
    }

    #[test]
    fn positive_big_and_small_integer_fields_use_non_negative_bounds() {
        let big = PositiveBigIntegerField::default();
        let small = PositiveSmallIntegerField::default();

        assert_eq!(big.min_value(), 0);
        assert_eq!(small.min_value(), 0);
        assert_eq!(big.db_type(), "BIGINT");
        assert_eq!(small.db_type(), "SMALLINT");
    }
}