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});