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