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