1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use crate::value::Primitive;
use derive_new::new;
use nu_errors::ShellError;
use nu_source::{DbgDocBldr, DebugDocBuilder, Spanned};
use serde::{Deserialize, Serialize};

/// The two types of ways to include a range end. Inclusive means to include the value (eg 1..3 inclusive would include the 3 value).
/// Exclusive excludes the value (eg 1..3 exclusive does not include 3 value)
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
pub enum RangeInclusion {
    Inclusive,
    Exclusive,
}

impl RangeInclusion {
    /// Get a RangeInclusion left bracket ready for pretty printing
    pub fn debug_left_bracket(self) -> DebugDocBuilder {
        DbgDocBldr::delimiter(match self {
            RangeInclusion::Exclusive => "(",
            RangeInclusion::Inclusive => "[",
        })
    }

    /// Get a RangeInclusion right bracket ready for pretty printing
    pub fn debug_right_bracket(self) -> DebugDocBuilder {
        DbgDocBldr::delimiter(match self {
            RangeInclusion::Exclusive => ")",
            RangeInclusion::Inclusive => "]",
        })
    }
}

/// The range definition, holding the starting and end point of the range
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize, new)]
pub struct Range {
    pub from: (Spanned<Primitive>, RangeInclusion),
    pub to: (Spanned<Primitive>, RangeInclusion),
}

impl Range {
    pub fn min_u64(&self) -> Result<u64, ShellError> {
        let (from, range_incl) = &self.from;

        let minval = if let Primitive::Nothing = from.item {
            u64::MIN
        } else {
            from.item.as_u64(from.span)?
        };

        match range_incl {
            RangeInclusion::Inclusive => Ok(minval),
            RangeInclusion::Exclusive => Ok(minval.saturating_add(1)),
        }
    }

    pub fn max_u64(&self) -> Result<u64, ShellError> {
        let (to, range_incl) = &self.to;

        let maxval = if let Primitive::Nothing = to.item {
            u64::MAX
        } else {
            to.item.as_u64(to.span)?
        };

        match range_incl {
            RangeInclusion::Inclusive => Ok(maxval),
            RangeInclusion::Exclusive => Ok(maxval.saturating_sub(1)),
        }
    }

    pub fn min_usize(&self) -> Result<usize, ShellError> {
        let (from, range_incl) = &self.from;

        let minval = if let Primitive::Nothing = from.item {
            usize::MIN
        } else {
            from.item.as_usize(from.span)?
        };

        match range_incl {
            RangeInclusion::Inclusive => Ok(minval),
            RangeInclusion::Exclusive => Ok(minval.saturating_add(1)),
        }
    }

    pub fn max_usize(&self) -> Result<usize, ShellError> {
        let (to, range_incl) = &self.to;

        let maxval = if let Primitive::Nothing = to.item {
            usize::MAX
        } else {
            to.item.as_usize(to.span)?
        };

        match range_incl {
            RangeInclusion::Inclusive => Ok(maxval),
            RangeInclusion::Exclusive => Ok(maxval.saturating_sub(1)),
        }
    }

    pub fn min_f64(&self) -> Result<f64, ShellError> {
        let from = &self.from.0;

        if let Primitive::Nothing = from.item {
            Ok(f64::MIN)
        } else {
            Ok(from.item.as_f64(from.span)?)
        }

        // How would inclusive vs. exclusive range work here?
    }

    pub fn max_f64(&self) -> Result<f64, ShellError> {
        let to = &self.to.0;

        if let Primitive::Nothing = to.item {
            Ok(f64::MAX)
        } else {
            Ok(to.item.as_f64(to.span)?)
        }

        // How would inclusive vs. exclusive range work here?
    }
}