tc_transact/public/
generic.rs

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                    // no-op
126                }
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}