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