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