godot_core/meta/
signed_range.rs1use std::collections::Bound;
9use std::ops::RangeBounds;
10
11struct WrappedRange {
15 lower_bound: i64,
16 upper_bound: Option<i64>,
17}
18
19pub fn wrapped<T>(signed_range: impl RangeBounds<T>) -> impl SignedRange
30where
31 T: Copy + Into<i64>,
32{
33 let lower_bound = lower_bound(signed_range.start_bound().map(|v| (*v).into())).unwrap_or(0);
34 let upper_bound = upper_bound(signed_range.end_bound().map(|v| (*v).into()));
35
36 WrappedRange {
37 lower_bound,
38 upper_bound,
39 }
40}
41
42fn lower_bound(bound: Bound<i64>) -> Option<i64> {
43 match bound {
44 Bound::Included(n) => Some(n),
45 Bound::Excluded(n) => Some(n + 1),
46 Bound::Unbounded => None,
47 }
48}
49
50fn upper_bound(bound: Bound<i64>) -> Option<i64> {
51 match bound {
52 Bound::Included(n) => Some(n + 1),
53 Bound::Excluded(n) => Some(n),
54 Bound::Unbounded => None,
55 }
56}
57
58mod sealed {
59 pub trait SealedRange {}
60}
61
62pub trait SignedRange: sealed::SealedRange {
67 #[doc(hidden)]
72 fn signed(&self) -> (i64, Option<i64>);
73}
74
75impl sealed::SealedRange for WrappedRange {}
76impl SignedRange for WrappedRange {
77 fn signed(&self) -> (i64, Option<i64>) {
78 (self.lower_bound, self.upper_bound)
79 }
80}
81
82impl<R> sealed::SealedRange for R where R: RangeBounds<usize> {}
83impl<R> SignedRange for R
84where
85 R: RangeBounds<usize>,
86{
87 fn signed(&self) -> (i64, Option<i64>) {
88 let lower_bound = lower_bound(self.start_bound().map(|v| *v as i64)).unwrap_or(0);
89 let upper_bound = upper_bound(self.end_bound().map(|v| *v as i64));
90
91 (lower_bound, upper_bound)
92 }
93}
94
95pub(crate) fn to_godot_range_fromto(range: impl SignedRange) -> (i64, i64) {
100 match range.signed() {
101 (from, Some(to)) => {
102 crate::sys::strict_assert!(from <= to, "range: start ({from}) > end ({to})");
103 (from, to)
104 }
105 (from, None) => (from, 0),
106 }
107}
108
109pub(crate) fn to_godot_range_fromlen(range: impl SignedRange, unbounded: i64) -> (i64, i64) {
114 match range.signed() {
115 (from, Some(to)) => {
116 crate::sys::strict_assert!(from <= to, "range: start ({from}) > end ({to})");
117 (from, to - from)
118 }
119 (from, None) => (from, unbounded),
120 }
121}