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, StepsBetween,
11 ToValue, Value, VmError, VmErrorKind,
12};
13
14#[derive(Any, Clone, TryClone)]
58#[try_clone(crate)]
59#[rune(crate, constructor, item = ::std::ops)]
60pub struct Range {
61 #[rune(get, set)]
63 pub start: Value,
64 #[rune(get, set)]
66 pub end: Value,
67}
68
69impl Range {
70 pub fn new(start: Value, end: Value) -> Self {
72 Self { start, end }
73 }
74
75 #[rune::function(keep)]
95 pub fn iter(&self) -> Result<Value, VmError> {
96 let value = match (self.start.as_ref(), self.end.as_ref()) {
97 (Repr::Inline(Inline::Unsigned(start)), Repr::Inline(end)) => {
98 let end = end.as_integer::<u64>()?;
99 rune::to_value(RangeIter::new(*start..end))?
100 }
101 (Repr::Inline(Inline::Signed(start)), Repr::Inline(end)) => {
102 let end = end.as_integer::<i64>()?;
103 rune::to_value(RangeIter::new(*start..end))?
104 }
105 (Repr::Inline(Inline::Char(start)), Repr::Inline(Inline::Char(end))) => {
106 rune::to_value(RangeIter::new(*start..*end))?
107 }
108 (start, end) => {
109 return Err(VmError::from(VmErrorKind::UnsupportedIterRange {
110 start: start.type_info(),
111 end: end.type_info(),
112 }))
113 }
114 };
115
116 Ok(value)
117 }
118
119 #[rune::function(keep, protocol = INTO_ITER)]
144 pub fn into_iter(&self) -> Result<Value, VmError> {
145 self.iter()
146 }
147
148 #[rune::function(keep, protocol = PARTIAL_EQ)]
163 pub fn partial_eq(&self, other: &Self) -> Result<bool, VmError> {
164 self.partial_eq_with(other, &mut EnvProtocolCaller)
165 }
166
167 pub(crate) fn partial_eq_with(
168 &self,
169 b: &Self,
170 caller: &mut dyn ProtocolCaller,
171 ) -> Result<bool, VmError> {
172 if !Value::partial_eq_with(&self.start, &b.start, caller)? {
173 return Ok(false);
174 }
175
176 Value::partial_eq_with(&self.end, &b.end, caller)
177 }
178
179 #[rune::function(keep, protocol = EQ)]
191 pub fn eq(&self, other: &Self) -> Result<bool, VmError> {
192 self.eq_with(other, &mut EnvProtocolCaller)
193 }
194
195 pub(crate) fn eq_with(
196 &self,
197 b: &Self,
198 caller: &mut dyn ProtocolCaller,
199 ) -> Result<bool, VmError> {
200 if !Value::eq_with(&self.start, &b.start, caller)? {
201 return Ok(false);
202 }
203
204 Value::eq_with(&self.end, &b.end, caller)
205 }
206
207 #[rune::function(keep, protocol = PARTIAL_CMP)]
218 pub fn partial_cmp(&self, other: &Self) -> Result<Option<Ordering>, VmError> {
219 self.partial_cmp_with(other, &mut EnvProtocolCaller)
220 }
221
222 pub(crate) fn partial_cmp_with(
223 &self,
224 b: &Self,
225 caller: &mut dyn ProtocolCaller,
226 ) -> Result<Option<Ordering>, VmError> {
227 match Value::partial_cmp_with(&self.start, &b.start, caller)? {
228 Some(Ordering::Equal) => (),
229 other => return Ok(other),
230 }
231
232 Value::partial_cmp_with(&self.end, &b.end, caller)
233 }
234
235 #[rune::function(keep, protocol = CMP)]
247 pub fn cmp(&self, other: &Self) -> Result<Ordering, VmError> {
248 self.cmp_with(other, &mut EnvProtocolCaller)
249 }
250
251 pub(crate) fn cmp_with(
252 &self,
253 b: &Self,
254 caller: &mut dyn ProtocolCaller,
255 ) -> Result<Ordering, VmError> {
256 match Value::cmp_with(&self.start, &b.start, caller)? {
257 Ordering::Equal => (),
258 other => return Ok(other),
259 }
260
261 Value::cmp_with(&self.end, &b.end, caller)
262 }
263
264 #[rune::function(keep)]
281 pub(crate) fn contains(&self, value: Value) -> Result<bool, VmError> {
282 self.contains_with(value, &mut EnvProtocolCaller)
283 }
284
285 pub(crate) fn contains_with(
286 &self,
287 value: Value,
288 caller: &mut dyn ProtocolCaller,
289 ) -> Result<bool, VmError> {
290 match Value::partial_cmp_with(&self.start, &value, caller)? {
291 Some(Ordering::Less | Ordering::Equal) => {}
292 _ => return Ok(false),
293 }
294
295 Ok(matches!(
296 Value::partial_cmp_with(&self.end, &value, caller)?,
297 Some(Ordering::Greater)
298 ))
299 }
300}
301
302impl fmt::Debug for Range {
303 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
304 write!(f, "{:?}..{:?}", self.start, self.end)
305 }
306}
307
308impl<Idx> ToValue for ops::Range<Idx>
309where
310 Idx: ToValue,
311{
312 fn to_value(self) -> Result<Value, RuntimeError> {
313 let start = self.start.to_value()?;
314 let end = self.end.to_value()?;
315 let range = Range::new(start, end);
316 Ok(Value::new(range)?)
317 }
318}
319
320impl<Idx> FromValue for ops::Range<Idx>
321where
322 Idx: FromValue,
323{
324 #[inline]
325 fn from_value(value: Value) -> Result<Self, RuntimeError> {
326 let range = value.downcast::<Range>()?;
327 let start = Idx::from_value(range.start)?;
328 let end = Idx::from_value(range.end)?;
329 Ok(ops::Range { start, end })
330 }
331}
332
333double_ended_range_iter!(Range, RangeIter<T>, {
334 #[rune::function(instance, keep, protocol = SIZE_HINT)]
335 #[inline]
336 pub(crate) fn size_hint(&self) -> (usize, Option<usize>) {
337 self.iter.size_hint()
338 }
339
340 #[rune::function(instance, keep, protocol = LEN)]
341 #[inline]
342 pub(crate) fn len(&self) -> Result<usize, VmError>
343 where
344 T: Copy + StepsBetween + fmt::Debug,
345 {
346 let Some(result) = T::steps_between(self.iter.start, self.iter.end) else {
347 return Err(VmError::panic(format!(
348 "could not calculate length of range {:?}..={:?}",
349 self.iter.start, self.iter.end
350 )));
351 };
352
353 Ok(result)
354 }
355});