rune/runtime/
range_from.rs

1use core::cmp::Ordering;
2use core::fmt;
3use core::ops;
4
5use crate as rune;
6use crate::alloc::clone::TryClone;
7use crate::Any;
8
9use super::{
10    EnvProtocolCaller, FromValue, Inline, ProtocolCaller, Repr, RuntimeError, ToValue, Value,
11    VmError, VmErrorKind,
12};
13
14/// Type for a from range expression `start..`.
15///
16/// # Examples
17///
18/// ```rune
19/// use std::ops::RangeFrom;
20///
21/// let range = 0..;
22///
23/// assert!(!range.contains(-10));
24/// assert!(range.contains(5));
25/// assert!(range.contains(10));
26/// assert!(range.contains(20));
27///
28/// assert!(range is RangeFrom);
29/// ```
30///
31/// Ranges can contain any type:
32///
33/// ```rune
34/// let range = 'a'..;
35/// assert_eq!(range.start, 'a');
36/// range.start = 'b';
37/// assert_eq!(range.start, 'b');
38/// ```
39///
40/// Certain ranges can be used as iterators:
41///
42/// ```rune
43/// let range = 'a'..;
44/// assert_eq!(range.iter().take(5).collect::<Vec>(), ['a', 'b', 'c', 'd', 'e']);
45/// ```
46///
47/// # Rust examples
48///
49/// ```rust
50/// use rune::runtime::RangeFrom;
51///
52/// let start = rune::to_value(1)?;
53/// let _ = RangeFrom::new(start);
54/// # Ok::<_, rune::support::Error>(())
55/// ```
56#[derive(Any, Clone, TryClone)]
57#[try_clone(crate)]
58#[rune(crate, constructor, item = ::std::ops)]
59pub struct RangeFrom {
60    /// The start value of the range.
61    #[rune(get, set)]
62    pub start: Value,
63}
64
65impl RangeFrom {
66    /// Construct a new range.
67    pub fn new(start: Value) -> Self {
68        Self { start }
69    }
70
71    /// Iterate over the range.
72    ///
73    /// # Panics
74    ///
75    /// This panics if the range is not a well-defined range.
76    ///
77    /// # Examples
78    ///
79    /// ```rune
80    /// let range = 'a'..;
81    /// assert_eq!(range.iter().take(5).collect::<Vec>(), ['a', 'b', 'c', 'd', 'e']);
82    /// ```
83    ///
84    /// Cannot construct an iterator over floats:
85    ///
86    /// ```rune,should_panic
87    /// let range = 1.0..;
88    /// range.iter()
89    /// ```
90    #[rune::function(keep)]
91    pub fn iter(&self) -> Result<Value, VmError> {
92        let value = match self.start.as_ref() {
93            Repr::Inline(Inline::Unsigned(start)) => crate::to_value(RangeFromIter::new(*start..))?,
94            Repr::Inline(Inline::Signed(start)) => crate::to_value(RangeFromIter::new(*start..))?,
95            Repr::Inline(Inline::Char(start)) => crate::to_value(RangeFromIter::new(*start..))?,
96            start => {
97                return Err(VmError::new(VmErrorKind::UnsupportedIterRangeFrom {
98                    start: start.type_info(),
99                }));
100            }
101        };
102
103        Ok(value)
104    }
105
106    /// Build an iterator over the range.
107    ///
108    /// # Panics
109    ///
110    /// This panics if the range is not a well-defined range.
111    ///
112    /// # Examples
113    ///
114    /// ```rune
115    /// let vec = [];
116    ///
117    /// for value in 'a'.. {
118    ///     vec.push(value);
119    ///
120    ///     if value == 'e' {
121    ///        break;
122    ///     }
123    /// }
124    ///
125    /// assert_eq!(vec, ['a', 'b', 'c', 'd', 'e']);
126    /// ```
127    ///
128    /// Cannot construct an iterator over floats:
129    ///
130    /// ```rune,should_panic
131    /// let range = 1.0..;
132    ///
133    /// for value in 1.0 .. {
134    /// }
135    /// ```
136    #[rune::function(keep, protocol = INTO_ITER)]
137    pub fn into_iter(&self) -> Result<Value, VmError> {
138        self.iter()
139    }
140
141    /// Test the range for partial equality.
142    ///
143    /// # Examples
144    ///
145    /// ```rune
146    /// let range = 'a'..;
147    /// assert!(range == ('a'..));
148    /// assert!(range != ('b'..));
149    ///
150    /// let range = 1.0..;
151    /// assert!(range == (1.0..));
152    /// assert!(range != (f64::NAN..));
153    /// assert!((f64::NAN..) != (f64::NAN..));
154    /// ```
155    #[rune::function(keep, protocol = PARTIAL_EQ)]
156    pub fn partial_eq(&self, other: &Self) -> Result<bool, VmError> {
157        self.partial_eq_with(other, &mut EnvProtocolCaller)
158    }
159
160    pub(crate) fn partial_eq_with(
161        &self,
162        b: &Self,
163        caller: &mut dyn ProtocolCaller,
164    ) -> Result<bool, VmError> {
165        Value::partial_eq_with(&self.start, &b.start, caller)
166    }
167
168    /// Test the range for total equality.
169    ///
170    /// # Examples
171    ///
172    /// ```rune
173    /// use std::ops::eq;
174    ///
175    /// let range = 'a'..;
176    /// assert!(eq(range, 'a'..));
177    /// assert!(!eq(range, 'b'..));
178    /// ```
179    #[rune::function(keep, protocol = EQ)]
180    pub fn eq(&self, other: &Self) -> Result<bool, VmError> {
181        self.eq_with(other, &mut EnvProtocolCaller)
182    }
183
184    pub(crate) fn eq_with(
185        &self,
186        b: &Self,
187        caller: &mut dyn ProtocolCaller,
188    ) -> Result<bool, VmError> {
189        Value::eq_with(&self.start, &b.start, caller)
190    }
191
192    /// Test the range for partial ordering.
193    ///
194    /// # Examples
195    ///
196    /// ```rune
197    /// assert!(('a'..) < ('b'..));
198    /// assert!(('c'..) > ('b'..));
199    /// assert!(!((f64::NAN..) > (f64::INFINITY..)));
200    /// assert!(!((f64::NAN..) < (f64::INFINITY..)));
201    /// ```
202    #[rune::function(keep, protocol = PARTIAL_CMP)]
203    pub fn partial_cmp(&self, other: &Self) -> Result<Option<Ordering>, VmError> {
204        self.partial_cmp_with(other, &mut EnvProtocolCaller)
205    }
206
207    pub(crate) fn partial_cmp_with(
208        &self,
209        b: &Self,
210        caller: &mut dyn ProtocolCaller,
211    ) -> Result<Option<Ordering>, VmError> {
212        Value::partial_cmp_with(&self.start, &b.start, caller)
213    }
214
215    /// Test the range for total ordering.
216    ///
217    /// # Examples
218    ///
219    /// ```rune
220    /// use std::ops::cmp;
221    /// use std::cmp::Ordering;
222    ///
223    /// assert_eq!(cmp('a'.., 'b'..), Ordering::Less);
224    /// assert_eq!(cmp('c'.., 'b'..), Ordering::Greater);
225    /// ```
226    #[rune::function(keep, protocol = CMP)]
227    pub fn cmp(&self, other: &Self) -> Result<Ordering, VmError> {
228        self.cmp_with(other, &mut EnvProtocolCaller)
229    }
230
231    pub(crate) fn cmp_with(
232        &self,
233        b: &Self,
234        caller: &mut dyn ProtocolCaller,
235    ) -> Result<Ordering, VmError> {
236        Value::cmp_with(&self.start, &b.start, caller)
237    }
238
239    /// Test if the range contains the given value.
240    ///
241    /// The check is performed using the [`PARTIAL_CMP`] protocol.
242    ///
243    /// # Examples
244    ///
245    /// ```rune
246    /// use std::ops::RangeFrom;
247    ///
248    /// let range = 0..;
249    ///
250    /// assert!(!range.contains(-10));
251    /// assert!(range.contains(5));
252    /// assert!(range.contains(10));
253    /// assert!(range.contains(20));
254    ///
255    /// assert!(range is RangeFrom);
256    /// ```
257    #[rune::function(keep)]
258    pub(crate) fn contains(&self, value: Value) -> Result<bool, VmError> {
259        self.contains_with(value, &mut EnvProtocolCaller)
260    }
261
262    pub(crate) fn contains_with(
263        &self,
264        value: Value,
265        caller: &mut dyn ProtocolCaller,
266    ) -> Result<bool, VmError> {
267        Ok(matches!(
268            Value::partial_cmp_with(&self.start, &value, caller)?,
269            Some(Ordering::Less | Ordering::Equal)
270        ))
271    }
272}
273
274impl fmt::Debug for RangeFrom {
275    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276        write!(f, "{:?}..", self.start)
277    }
278}
279
280impl<Idx> ToValue for ops::RangeFrom<Idx>
281where
282    Idx: ToValue,
283{
284    fn to_value(self) -> Result<Value, RuntimeError> {
285        let start = self.start.to_value()?;
286        let range = RangeFrom::new(start);
287        Ok(Value::new(range)?)
288    }
289}
290
291impl<Idx> FromValue for ops::RangeFrom<Idx>
292where
293    Idx: FromValue,
294{
295    #[inline]
296    fn from_value(value: Value) -> Result<Self, RuntimeError> {
297        let range = value.downcast::<RangeFrom>()?;
298        let start = Idx::from_value(range.start)?;
299        Ok(ops::RangeFrom { start })
300    }
301}
302
303range_iter!(RangeFrom, RangeFromIter<T>, {
304    #[rune::function(instance, keep, protocol = SIZE_HINT)]
305    #[inline]
306    pub(crate) fn size_hint(&self) -> (u64, Option<u64>) {
307        (u64::MAX, None)
308    }
309});