1use std::convert::TryInto;
2use std::fmt;
3use std::iter::Cloned;
4use std::marker::PhantomData;
5use std::ops::{Bound, Deref};
6use std::str::FromStr;
7
8use futures::future::TryFutureExt;
9use futures::stream::{self, FuturesOrdered, StreamExt, TryStreamExt};
10use log::{debug, trace};
11use safecast::*;
12
13use tc_error::*;
14use tc_value::{Number, UInt, Value};
15use tcgeneric::{path_label, Id, Instance, Map, PathLabel, PathSegment, TCPathBuf, Tuple};
16
17use super::helpers::AttributeHandler;
18use super::{ClosureInstance, GetHandler, Handler, PostHandler, Public, Route, StateInstance};
19
20type Closure<State> = Box<dyn ClosureInstance<State>>;
21
22pub const COPY: PathLabel = path_label(&["copy"]);
23
24struct AppendHandler<'a, T: Clone> {
25 tuple: &'a Tuple<T>,
26}
27
28impl<'a, State, T> Handler<'a, State> for AppendHandler<'a, T>
29where
30 State: StateInstance + From<T>,
31 T: fmt::Debug + Clone + Send + Sync,
32{
33 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
34 where
35 'b: 'a,
36 {
37 Some(Box::new(|_txn, key| {
38 Box::pin(async move {
39 if self.tuple.is_empty() {
40 let key =
41 Tuple::<Value>::try_cast_from(key, |v| TCError::unexpected(v, "a Tuple"))?;
42
43 return Ok(Value::Tuple(key).into());
44 }
45
46 let suffix =
47 Tuple::<Value>::try_cast_from(key, |v| TCError::unexpected(v, "a Tuple"))?;
48
49 let items = self.tuple.iter().cloned().map(State::from);
50 let items = items.chain(suffix.into_iter().map(State::from));
51
52 Ok(State::from(items.collect::<Tuple<State>>()))
53 })
54 }))
55 }
56}
57
58struct ContainsHandler<'a, T> {
59 tuple: &'a Tuple<T>,
60}
61
62impl<'a, State, T> Handler<'a, State> for ContainsHandler<'a, T>
63where
64 State: StateInstance + From<T>,
65 T: Clone + Send + Sync,
66 Value: TryCastFrom<State>,
67{
68 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
69 where
70 'b: 'a,
71 {
72 Some(Box::new(|_txn, key| {
73 Box::pin(async move {
74 let present = self
75 .tuple
76 .iter()
77 .cloned()
78 .map(State::from)
79 .filter_map(Value::opt_cast_from)
80 .any(|item| item == key);
81
82 Ok(present.into())
83 })
84 }))
85 }
86}
87
88impl<'a, T> From<&'a Tuple<T>> for ContainsHandler<'a, T> {
89 fn from(tuple: &'a Tuple<T>) -> Self {
90 Self { tuple }
91 }
92}
93
94struct ForEachHandler<I> {
95 source: I,
96}
97
98impl<'a, State, I, T> Handler<'a, State> for ForEachHandler<I>
99where
100 State: StateInstance + From<T>,
101 I: IntoIterator<Item = T> + Send + 'a,
102 I::IntoIter: Send + 'a,
103 T: 'a,
104 Closure<State>: TryCastFrom<State>,
105{
106 fn post<'b>(self: Box<Self>) -> Option<PostHandler<'a, 'b, State::Txn, State>>
107 where
108 'b: 'a,
109 {
110 Some(Box::new(|txn, mut params| {
111 Box::pin(async move {
112 let op: State = params.require("op")?;
113 params.expect_empty()?;
114
115 let mut for_each = stream::iter(self.source)
116 .map(move |args| {
117 Closure::try_cast_from(op.clone(), |state| {
118 bad_request!("not a closure: {state:?}")
119 })
120 .map(|op| (op, args))
121 })
122 .and_then(|(op, args)| op.call(txn.clone(), State::from(args)));
123
124 while let Some(_step) = for_each.try_next().await? {
125 }
127
128 Ok(State::default())
129 })
130 }))
131 }
132}
133
134impl<I> From<I> for ForEachHandler<I> {
135 fn from(source: I) -> Self {
136 Self { source }
137 }
138}
139
140struct MapCopyHandler<'a, T> {
141 map: &'a Map<T>,
142}
143
144impl<'a, State, T> Handler<'a, State> for MapCopyHandler<'a, T>
145where
146 State: StateInstance,
147 T: Route<State> + Clone + Send + fmt::Debug + 'a,
148{
149 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
150 where
151 'b: 'a,
152 {
153 Some(Box::new(|txn, key| {
154 Box::pin(async move {
155 key.expect_none()?;
156
157 let path = TCPathBuf::from(COPY);
158 let mut copies: FuturesOrdered<_> = self
159 .map
160 .iter()
161 .map(|(key, item)| {
162 let key = key.clone();
163 let result = Public::get(item, txn, &path, Value::default());
164 result.map_ok(move |state| (key, state))
165 })
166 .collect();
167
168 let mut copy = Map::new();
169 while let Some((key, item)) = copies.try_next().await? {
170 copy.insert(key, item);
171 }
172
173 Ok(copy.into())
174 })
175 }))
176 }
177}
178
179impl<'a, T> From<&'a Map<T>> for MapCopyHandler<'a, T> {
180 fn from(map: &'a Map<T>) -> Self {
181 Self { map }
182 }
183}
184
185struct MapEqHandler<State, T> {
186 map: Map<T>,
187 state: PhantomData<State>,
188}
189
190impl<'a, State, T> Handler<'a, State> for MapEqHandler<State, T>
191where
192 State: StateInstance + From<T>,
193 T: fmt::Debug + Send + Sync + 'a,
194 Map<State>: TryCastFrom<State>,
195 Value: TryCastFrom<State>,
196{
197 fn post<'b>(self: Box<Self>) -> Option<PostHandler<'a, 'b, State::Txn, State>>
198 where
199 'b: 'a,
200 {
201 Some(Box::new(|_txn, mut params| {
202 Box::pin(async move {
203 let other: Map<State> = params.require("eq")?;
204 params.expect_empty()?;
205
206 if self.map.len() != other.len() {
207 return Ok(false.into());
208 }
209
210 let eq = self
211 .map
212 .into_iter()
213 .zip(other)
214 .map(|((this_id, this), (that_id, that))| {
215 if this_id != that_id {
216 return Ok(false);
217 }
218
219 let this = State::from(this);
220 let this =
221 Value::try_cast_from(this, |s| TCError::unexpected(s, "a Value"))?;
222
223 let that =
224 Value::try_cast_from(that, |s| TCError::unexpected(s, "a Value"))?;
225
226 Ok(this == that)
227 })
228 .collect::<TCResult<Vec<bool>>>()?;
229
230 Ok(eq.into_iter().all(|eq| eq).into())
231 })
232 }))
233 }
234}
235
236impl<State, T> From<Map<T>> for MapEqHandler<State, T> {
237 fn from(map: Map<T>) -> Self {
238 Self {
239 map,
240 state: PhantomData,
241 }
242 }
243}
244
245struct EqTupleHandler<T> {
246 tuple: Tuple<T>,
247}
248
249impl<'a, State, T> Handler<'a, State> for EqTupleHandler<T>
250where
251 T: fmt::Debug + Send + Sync + 'a,
252 State: StateInstance + From<T>,
253 Tuple<State>: TryCastFrom<State>,
254 Value: TryCastFrom<State>,
255{
256 fn post<'b>(self: Box<Self>) -> Option<PostHandler<'a, 'b, State::Txn, State>>
257 where
258 'b: 'a,
259 {
260 Some(Box::new(|_txn, mut params| {
261 Box::pin(async move {
262 let other: Tuple<State> = params.require("eq")?;
263 params.expect_empty()?;
264
265 if self.tuple.len() != other.len() {
266 return Ok(false.into());
267 }
268
269 let eq = self
270 .tuple
271 .into_iter()
272 .zip(other)
273 .map(|(this, that)| {
274 let this = State::from(this);
275
276 let this =
277 Value::try_cast_from(this, |s| TCError::unexpected(s, "a Value"))?;
278
279 let that =
280 Value::try_cast_from(that, |s| TCError::unexpected(s, "a Value"))?;
281
282 Ok(this == that)
283 })
284 .collect::<TCResult<Vec<bool>>>()?;
285
286 Ok(eq.into_iter().all(|eq| eq).into())
287 })
288 }))
289 }
290}
291
292impl<T> From<Tuple<T>> for EqTupleHandler<T> {
293 fn from(tuple: Tuple<T>) -> Self {
294 Self { tuple }
295 }
296}
297
298impl<'a, T: Clone> From<&'a Tuple<T>> for AppendHandler<'a, T> {
299 fn from(tuple: &'a Tuple<T>) -> Self {
300 Self { tuple }
301 }
302}
303
304struct MapHandler<'a, T: Clone> {
305 map: &'a Map<T>,
306}
307
308impl<'a, State, T> Handler<'a, State> for MapHandler<'a, T>
309where
310 State: StateInstance + From<T> + From<Map<T>>,
311 T: Instance + Clone,
312{
313 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
314 where
315 'b: 'a,
316 {
317 Some(Box::new(|_txn, key| {
318 Box::pin(async move {
319 if key.is_none() {
320 Ok(State::from(self.map.clone()))
321 } else {
322 let key = Id::try_cast_from(key, |v| TCError::unexpected(v, "an Id"))?;
323 self.map.get(&key).cloned().map(State::from).ok_or_else(|| {
324 let msg = format!(
325 "{} in Map with keys {}",
326 key,
327 self.map.keys().collect::<Tuple<&Id>>()
328 );
329
330 TCError::not_found(msg)
331 })
332 }
333 })
334 }))
335 }
336}
337
338impl<State, T> Route<State> for Map<T>
339where
340 State: StateInstance + From<T> + From<Map<T>> + From<Number>,
341 T: Instance + Route<State> + Clone + fmt::Debug,
342 Map<State>: TryCastFrom<State>,
343 Tuple<State>: TryCastFrom<State>,
344 Value: TryCastFrom<State>,
345{
346 fn route<'a>(&'a self, path: &'a [PathSegment]) -> Option<Box<dyn Handler<'a, State> + 'a>> {
347 if path.is_empty() {
348 Some(Box::new(MapHandler { map: self }))
349 } else if let Some(state) = self.deref().get(&path[0]) {
350 state.route(&path[1..])
351 } else if path.len() == 1 {
352 match path[0].as_str() {
353 "copy" => Some(Box::new(MapCopyHandler::from(self))),
354 "eq" => Some(Box::new(MapEqHandler::from(self.clone()))),
355 "len" => Some(Box::new(AttributeHandler::from(Number::UInt(UInt::U64(
356 self.len() as u64,
357 ))))),
358 _ => None,
359 }
360 } else {
361 None
362 }
363 }
364}
365
366struct TupleCopyHandler<'a, T> {
367 tuple: &'a Tuple<T>,
368}
369
370impl<'a, State, T> Handler<'a, State> for TupleCopyHandler<'a, T>
371where
372 State: StateInstance,
373 T: Route<State> + Clone + Send + fmt::Debug + 'a,
374{
375 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
376 where
377 'b: 'a,
378 {
379 Some(Box::new(|txn, key| {
380 Box::pin(async move {
381 key.expect_none()?;
382
383 let path = TCPathBuf::from(COPY);
384 let mut copies: FuturesOrdered<_> = self
385 .tuple
386 .iter()
387 .map(|item| Public::get(item, txn, &path, Value::default()))
388 .collect();
389
390 let mut copy = Vec::with_capacity(self.tuple.len());
391 while let Some(item) = copies.try_next().await? {
392 copy.push(item);
393 }
394
395 Ok(State::from(Tuple::from(copy)))
396 })
397 }))
398 }
399}
400
401impl<'a, T> From<&'a Tuple<T>> for TupleCopyHandler<'a, T> {
402 fn from(tuple: &'a Tuple<T>) -> Self {
403 Self { tuple }
404 }
405}
406
407struct TupleFoldHandler<'a, T> {
408 tuple: &'a Tuple<T>,
409}
410
411impl<'a, State, T> Handler<'a, State> for TupleFoldHandler<'a, T>
412where
413 State: StateInstance + From<T>,
414 T: Clone + Send + Sync + 'a,
415 Closure<State>: TryCastFrom<State>,
416 Id: TryCastFrom<State>,
417 Map<State>: TryFrom<State, Error = TCError>,
418{
419 fn post<'b>(self: Box<Self>) -> Option<PostHandler<'a, 'b, State::Txn, State>>
420 where
421 'b: 'a,
422 {
423 Some(Box::new(|txn, mut params| {
424 Box::pin(async move {
425 let item_name: Id = params.require("item_name")?;
426 let op: State = params.require("op")?;
427 let mut state: State = params.require("value")?;
428 params.expect_empty()?;
429
430 for item in self.tuple.iter().cloned() {
431 let mut params: Map<State> = state.try_into()?;
432 params.insert(item_name.clone(), item.into());
433
434 let op: Closure<State> = op
435 .clone()
436 .try_cast_into(|state| bad_request!("not a closure: {state:?}"))?;
437
438 state = op.call(txn.clone(), params.into()).await?;
439 }
440
441 Ok(state.into())
442 })
443 }))
444 }
445}
446
447impl<'a, T: Clone + 'a> From<&'a Tuple<T>> for TupleFoldHandler<'a, T> {
448 fn from(tuple: &'a Tuple<T>) -> Self {
449 Self { tuple }
450 }
451}
452
453struct MapOpHandler<I> {
454 len: usize,
455 items: I,
456}
457
458impl<'a, State, I> Handler<'a, State> for MapOpHandler<I>
459where
460 State: StateInstance + From<I::Item>,
461 I: IntoIterator + Send + 'a,
462 I::IntoIter: Send + 'a,
463 Closure<State>: TryCastFrom<State>,
464{
465 fn post<'b>(self: Box<Self>) -> Option<PostHandler<'a, 'b, State::Txn, State>>
466 where
467 'b: 'a,
468 {
469 Some(Box::new(|txn, mut params| {
470 Box::pin(async move {
471 let op: State = params.require("op")?;
472
473 let mut tuple = Vec::with_capacity(self.len);
474 let mut mapped = stream::iter(self.items)
475 .map(State::from)
476 .map(|state| {
477 Closure::try_cast_from(op.clone(), |state| {
478 bad_request!("not a closure: {state:?}")
479 })
480 .map(|op| op.call(txn.clone(), state))
481 })
482 .try_buffered(num_cpus::get());
483
484 while let Some(item) = mapped.try_next().await? {
485 tuple.push(item);
486 }
487
488 Ok(State::from(Tuple::from(tuple)))
489 })
490 }))
491 }
492}
493
494impl<'a, T: Clone + 'a> From<&'a Tuple<T>> for MapOpHandler<Cloned<std::slice::Iter<'a, T>>> {
495 fn from(tuple: &'a Tuple<T>) -> Self {
496 let len = tuple.len();
497 let items = tuple.iter().cloned();
498 Self { len, items }
499 }
500}
501
502struct TupleHandler<'a, T: Clone> {
503 tuple: &'a Tuple<T>,
504}
505
506impl<'a, State, T> Handler<'a, State> for TupleHandler<'a, T>
507where
508 State: StateInstance + From<T> + From<Tuple<T>>,
509 T: Instance + Clone + fmt::Debug,
510{
511 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
512 where
513 'b: 'a,
514 {
515 Some(Box::new(|_txn, key| {
516 Box::pin(async move {
517 debug!("get {key:?} from {this:?}", this = self.tuple);
518
519 let len = self.tuple.len() as i64;
520
521 match key {
522 Value::None => Ok(State::from(self.tuple.clone())),
523 Value::Tuple(range) if range.matches::<(Bound<Value>, Bound<Value>)>() => {
524 let range: (Bound<Value>, Bound<Value>) =
525 range.opt_cast_into().expect("range");
526
527 let (start, end) = cast_range(range, len)?;
528 let slice = self.tuple[start..end]
529 .iter()
530 .cloned()
531 .collect::<Tuple<State>>();
532
533 Ok(State::from(slice))
534 }
535 i if i.matches::<Number>() => {
536 let i = Number::opt_cast_from(i).expect("tuple index");
537 let i = i64::cast_from(i);
538 let i = if i < 0 { len + i } else { i };
539
540 self.tuple
541 .get(i as usize)
542 .cloned()
543 .map(State::from)
544 .ok_or_else(|| TCError::not_found(format!("no such index: {}", i)))
545 }
546 other => Err(TCError::unexpected(other, "a tuple index")),
547 }
548 })
549 }))
550 }
551}
552
553struct ZipHandler<'a, T: Clone> {
554 keys: &'a Tuple<T>,
555}
556
557impl<'a, State, T> Handler<'a, State> for ZipHandler<'a, T>
558where
559 State: StateInstance + From<T>,
560 T: Clone + Send + Sync,
561{
562 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
563 where
564 'b: 'a,
565 {
566 Some(Box::new(|_txn, key| {
567 Box::pin(async move {
568 let values: Tuple<Value> =
569 key.try_cast_into(|v| bad_request!("invalid values for Tuple/zip: {v:?}"))?;
570
571 if self.keys.len() != values.len() {
572 return Err(bad_request!(
573 "cannot zip {} keys with {} values",
574 self.keys.len(),
575 values.len()
576 ));
577 }
578
579 let zipped =
580 self.keys
581 .iter()
582 .cloned()
583 .zip(values.into_iter())
584 .map(|(key, value)| {
585 let key = State::from(key);
586 let value = State::from(value);
587 State::from(Tuple::from(vec![key, value]))
588 });
589
590 Ok(State::from(zipped.collect::<Tuple<State>>()))
591 })
592 }))
593 }
594}
595
596impl<'a, T: Clone> From<&'a Tuple<T>> for ZipHandler<'a, T> {
597 fn from(keys: &'a Tuple<T>) -> Self {
598 ZipHandler { keys }
599 }
600}
601
602impl<State, T> Route<State> for Tuple<T>
603where
604 State: StateInstance + From<T> + From<Tuple<T>>,
605 T: Instance + Route<State> + Clone + fmt::Debug + 'static,
606 Closure<State>: TryCastFrom<State>,
607 Id: TryCastFrom<State>,
608 Map<State>: TryFrom<State, Error = TCError>,
609 Tuple<State>: TryCastFrom<State>,
610 Value: TryCastFrom<State>,
611{
612 fn route<'a>(&'a self, path: &'a [PathSegment]) -> Option<Box<dyn Handler<'a, State> + 'a>> {
613 if path.is_empty() {
614 Some(Box::new(TupleHandler { tuple: self }))
615 } else if let Ok(i) = usize::from_str(path[0].as_str()) {
616 if let Some(state) = self.deref().get(i) {
617 state.route(&path[1..])
618 } else {
619 None
620 }
621 } else if path.len() == 1 {
622 match path[0].as_str() {
623 "append" => Some(Box::new(AppendHandler::from(self))),
624 "contains" => Some(Box::new(ContainsHandler::from(self))),
625 "copy" => Some(Box::new(TupleCopyHandler::from(self))),
626 "fold" => Some(Box::new(TupleFoldHandler::from(self))),
627 "for_each" => Some(Box::new(ForEachHandler::from(self.clone()))),
628 "len" => Some(Box::new(AttributeHandler::from(Number::UInt(UInt::U64(
629 self.len() as u64,
630 ))))),
631 "eq" => Some(Box::new(EqTupleHandler::from(self.clone()))),
632 "map" => Some(Box::new(MapOpHandler::from(self))),
633 "zip" => Some(Box::new(ZipHandler::from(self))),
634 _ => None,
635 }
636 } else {
637 None
638 }
639 }
640}
641
642struct CreateMapHandler;
643
644impl<'a, State: StateInstance> Handler<'a, State> for CreateMapHandler {
645 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
646 where
647 'b: 'a,
648 {
649 Some(Box::new(|_txn, key| {
650 Box::pin(async move {
651 let value =
652 Tuple::<(Id, Value)>::try_cast_from(key, |v| TCError::unexpected(v, "a Map"))?;
653
654 let map = value.into_iter().collect::<Map<State>>();
655
656 Ok(State::from(map))
657 })
658 }))
659 }
660}
661
662pub struct MapStatic;
663
664impl<State: StateInstance> Route<State> for MapStatic {
665 fn route<'a>(&'a self, path: &'a [PathSegment]) -> Option<Box<dyn Handler<'a, State> + 'a>> {
666 if path.is_empty() {
667 Some(Box::new(CreateMapHandler))
668 } else {
669 None
670 }
671 }
672}
673
674struct CreateTupleHandler;
675
676impl<'a, State> Handler<'a, State> for CreateTupleHandler
677where
678 State: StateInstance,
679{
680 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
681 where
682 'b: 'a,
683 {
684 Some(Box::new(|_txn, key| {
685 Box::pin(async move {
686 let value: Tuple<Value> = key.try_into()?;
687 Ok(State::from(value.into_iter().collect::<Tuple<State>>()))
688 })
689 }))
690 }
691}
692
693struct CreateRangeHandler;
694
695impl<'a, State> Handler<'a, State> for CreateRangeHandler
696where
697 State: StateInstance,
698{
699 fn get<'b>(self: Box<Self>) -> Option<GetHandler<'a, 'b, State::Txn, State>>
700 where
701 'b: 'a,
702 {
703 Some(Box::new(|_txn, key| {
704 Box::pin(async move {
705 debug!("construct range Tuple from {key:?}");
706
707 let (start, stop, step) = if key.matches::<(i64, i64, usize)>() {
708 key.opt_cast_into().expect("range")
709 } else if key.matches::<(i64, i64)>() {
710 let (start, stop) = key.opt_cast_into().expect("range");
711 (start, stop, 1)
712 } else if key.matches::<usize>() {
713 let stop = key.opt_cast_into().expect("range end");
714 (0, stop, 1)
715 } else {
716 return Err(bad_request!("invalid range: {key:?}"));
717 };
718
719 let tuple = if start <= stop {
720 let range = (start..stop).step_by(step).into_iter();
721 State::from(range.map(Number::from).collect::<Tuple<State>>())
722 } else {
723 let range = (stop..start).step_by(step).into_iter().rev();
724 State::from(range.map(Number::from).collect::<Tuple<State>>())
725 };
726
727 trace!("range is {tuple:?}");
728
729 Ok(tuple)
730 })
731 }))
732 }
733}
734
735struct ConcatenateHandler;
736
737impl<'a, State> Handler<'a, State> for ConcatenateHandler
738where
739 State: StateInstance,
740 Tuple<State>: TryCastFrom<State>,
741{
742 fn post<'b>(self: Box<Self>) -> Option<PostHandler<'a, 'b, State::Txn, State>>
743 where
744 'b: 'a,
745 {
746 Some(Box::new(|_txn, mut params| {
747 Box::pin(async move {
748 let l: Tuple<State> = params.require("l")?;
749 let r: Tuple<State> = params.require("r")?;
750 params.expect_empty()?;
751
752 let mut concat = l.into_inner();
753 concat.extend(r.into_inner());
754 Ok(State::from(Tuple::from(concat)))
755 })
756 }))
757 }
758}
759
760#[derive(Default)]
761pub struct TupleStatic;
762
763impl<State> Route<State> for TupleStatic
764where
765 State: StateInstance,
766 Tuple<State>: TryCastFrom<State>,
767{
768 fn route<'a>(&'a self, path: &'a [PathSegment]) -> Option<Box<dyn Handler<'a, State> + 'a>> {
769 if path.is_empty() {
770 Some(Box::new(CreateTupleHandler))
771 } else if path.len() == 1 {
772 match path[0].as_str() {
773 "concatenate" => Some(Box::new(ConcatenateHandler)),
774 "range" => Some(Box::new(CreateRangeHandler)),
775 _ => None,
776 }
777 } else {
778 None
779 }
780 }
781}
782
783#[inline]
784fn cast_range(range: (Bound<Value>, Bound<Value>), len: i64) -> TCResult<(usize, usize)> {
785 trace!("construct range from bounds {range:?} within {len}");
786
787 #[inline]
788 fn as_i64(v: Value) -> i64 {
789 let n = Number::opt_cast_from(v).expect("start index");
790 n.cast_into()
791 }
792
793 let start = match range.0 {
794 Bound::Included(v) if v.matches::<Number>() => {
795 let start = as_i64(v);
796 if start < 0 {
797 len + start
798 } else {
799 start
800 }
801 }
802 Bound::Excluded(v) if v.matches::<Number>() => {
803 let start = as_i64(v);
804 let start = if start < 0 { len + start } else { start };
805 start + 1
806 }
807 Bound::Unbounded => 0,
808 other => return Err(bad_request!("invalid start index {:?} for Tuple", other)),
809 };
810
811 let end = match range.1 {
812 Bound::Included(v) if v.matches::<Number>() => {
813 let end = as_i64(v);
814 let end = if end < 0 { len + end } else { end };
815 end + 1
816 }
817 Bound::Excluded(v) if v.matches::<Number>() => {
818 let end = as_i64(v);
819 if end < 0 {
820 len + end
821 } else {
822 end
823 }
824 }
825 Bound::Unbounded => len,
826 other => return Err(bad_request!("invalid end index {:?} for Tuple", other)),
827 };
828
829 if start >= len {
830 Err(bad_request!(
831 "start index {} is out of bounds for Tuple with length {}",
832 start,
833 len
834 ))
835 } else if end > len {
836 Err(bad_request!(
837 "end index {} is out of bounds for Tuple with length {}",
838 end,
839 len
840 ))
841 } else if start > end {
842 Err(bad_request!(
843 "invalid range for Tuple: {}",
844 Tuple::<i64>::from((start, end)),
845 ))
846 } else {
847 Ok((start as usize, end as usize))
848 }
849}