koto_runtime/types/
tuple.rs1use crate::{Ptr, Result, prelude::*};
2use std::ops::{Deref, Range};
3
4#[derive(Clone)]
6pub struct KTuple(Inner);
7
8#[derive(Clone)]
10enum Inner {
11 Full(Ptr<Vec<KValue>>),
12 Slice(TupleSlice16),
13 SliceLarge(Ptr<TupleSlice>),
14}
15
16impl KTuple {
17 pub fn make_sub_tuple(&self, mut new_bounds: Range<usize>) -> Option<Self> {
23 let slice = match &self.0 {
24 Inner::Full(data) => TupleSlice::from(data.clone()),
25 Inner::SliceLarge(slice) => slice.deref().clone(),
26 Inner::Slice(slice) => TupleSlice::from(slice.clone()),
27 };
28
29 new_bounds.start += slice.bounds.start;
30 new_bounds.end += slice.bounds.start;
31
32 if new_bounds.end <= slice.bounds.end && slice.get(new_bounds.clone()).is_some() {
33 let result = TupleSlice {
34 data: slice.data.clone(),
35 bounds: new_bounds,
36 };
37 Some(result.into())
38 } else {
39 None
40 }
41 }
42
43 pub fn data(&self) -> &[KValue] {
45 self.deref()
46 }
47
48 pub fn is_hashable(&self) -> bool {
50 self.iter().all(KValue::is_hashable)
51 }
52
53 pub fn pop_front(&mut self) -> Option<KValue> {
58 match &mut self.0 {
59 Inner::Full(data) => {
60 if let Some(value) = data.first().cloned() {
61 *self = Self::from(TupleSlice {
62 data: data.clone(),
63 bounds: 1..data.len(),
64 });
65 Some(value)
66 } else {
67 None
68 }
69 }
70 Inner::SliceLarge(slice) => {
71 if let Some(value) = slice.first().cloned() {
72 Ptr::make_mut(slice).bounds.start += 1;
73 Some(value)
74 } else {
75 None
76 }
77 }
78 Inner::Slice(slice) => {
79 if let Some(value) = slice.first().cloned() {
80 slice.bounds.start += 1;
81 Some(value)
82 } else {
83 None
84 }
85 }
86 }
87 }
88
89 pub fn pop_back(&mut self) -> Option<KValue> {
94 match &mut self.0 {
95 Inner::Full(data) => {
96 if let Some(value) = data.last().cloned() {
97 *self = Self::from(TupleSlice {
98 data: data.clone(),
99 bounds: 0..data.len() - 1,
100 });
101 Some(value)
102 } else {
103 None
104 }
105 }
106 Inner::SliceLarge(slice) => {
107 if let Some(value) = slice.last().cloned() {
108 Ptr::make_mut(slice).bounds.end -= 1;
109 Some(value)
110 } else {
111 None
112 }
113 }
114 Inner::Slice(slice) => {
115 if let Some(value) = slice.last().cloned() {
116 slice.bounds.end -= 1;
117 Some(value)
118 } else {
119 None
120 }
121 }
122 }
123 }
124
125 pub fn is_same_instance(&self, other: &Self) -> bool {
127 let ptr_and_bounds = |tuple: &Self| match &tuple.0 {
128 Inner::Full(data) => (Ptr::address(data), 0..data.len()),
129 Inner::Slice(slice) => (
130 Ptr::address(&slice.data),
131 slice.bounds.start as usize..slice.bounds.end as usize,
132 ),
133 Inner::SliceLarge(slice) => (Ptr::address(&slice.data), slice.bounds.clone()),
134 };
135
136 let (ptr_a, bounds_a) = ptr_and_bounds(self);
137 let (ptr_b, bounds_b) = ptr_and_bounds(other);
138
139 ptr_a == ptr_b && bounds_a == bounds_b
140 }
141
142 pub fn display(&self, ctx: &mut DisplayContext) -> Result<()> {
144 let id = Ptr::address(match &self.0 {
145 Inner::Full(data) => data,
146 Inner::SliceLarge(slice) => &slice.data,
147 Inner::Slice(slice) => &slice.data,
148 });
149 ctx.push_container(id);
150 ctx.append('(');
151
152 for (i, value) in self.iter().enumerate() {
153 if i > 0 {
154 ctx.append(", ");
155 }
156 value.display(ctx)?;
157 }
158
159 ctx.append(')');
160 ctx.pop_container();
161
162 Ok(())
163 }
164}
165
166impl Deref for KTuple {
167 type Target = [KValue];
168
169 fn deref(&self) -> &[KValue] {
170 match &self.0 {
171 Inner::Full(data) => data,
172 Inner::Slice(slice) => slice.deref(),
173 Inner::SliceLarge(slice) => slice.deref(),
174 }
175 }
176}
177
178thread_local! {
179 static EMPTY_TUPLE: Ptr<Vec<KValue>> = Vec::new().into();
180}
181
182impl Default for KTuple {
183 fn default() -> Self {
184 Self::from(EMPTY_TUPLE.with(|x| x.clone()))
185 }
186}
187
188impl From<Ptr<Vec<KValue>>> for KTuple {
189 fn from(data: Ptr<Vec<KValue>>) -> Self {
190 Self(Inner::Full(data))
191 }
192}
193
194impl From<Vec<KValue>> for KTuple {
195 fn from(data: Vec<KValue>) -> Self {
196 Self(Inner::Full(data.into()))
197 }
198}
199
200impl From<&[KValue]> for KTuple {
201 fn from(data: &[KValue]) -> Self {
202 Self(Inner::Full(data.to_vec().into()))
203 }
204}
205
206impl<const N: usize> From<&[KValue; N]> for KTuple {
207 fn from(data: &[KValue; N]) -> Self {
208 Self::from(data.as_slice())
209 }
210}
211
212impl From<TupleSlice> for KTuple {
213 fn from(slice: TupleSlice) -> Self {
214 match TupleSlice16::try_from(slice) {
215 Ok(slice16) => Self::from(slice16),
216 Err(slice) => Self(Inner::SliceLarge(slice.into())),
217 }
218 }
219}
220
221impl From<TupleSlice16> for KTuple {
222 fn from(slice: TupleSlice16) -> Self {
223 Self(Inner::Slice(slice))
224 }
225}
226
227#[derive(Clone)]
228struct TupleSlice {
229 data: Ptr<Vec<KValue>>,
230 bounds: Range<usize>,
231}
232
233impl Deref for TupleSlice {
234 type Target = [KValue];
235
236 fn deref(&self) -> &[KValue] {
237 unsafe { self.data.get_unchecked(self.bounds.clone()) }
239 }
240}
241
242impl From<Ptr<Vec<KValue>>> for TupleSlice {
243 fn from(data: Ptr<Vec<KValue>>) -> Self {
244 let bounds = 0..data.len();
245 Self { data, bounds }
246 }
247}
248
249impl From<TupleSlice16> for TupleSlice {
250 fn from(slice: TupleSlice16) -> Self {
251 Self {
252 data: slice.data,
253 bounds: u16_to_usize_range(slice.bounds),
254 }
255 }
256}
257
258#[derive(Clone)]
261struct TupleSlice16 {
262 data: Ptr<Vec<KValue>>,
263 bounds: Range<u16>,
264 _niche_placeholder: ZeroU8,
273}
274
275impl Deref for TupleSlice16 {
276 type Target = [KValue];
277
278 fn deref(&self) -> &[KValue] {
279 unsafe {
281 self.data
282 .get_unchecked(u16_to_usize_range(self.bounds.clone()))
283 }
284 }
285}
286
287impl TryFrom<TupleSlice> for TupleSlice16 {
288 type Error = TupleSlice;
289
290 fn try_from(slice: TupleSlice) -> std::result::Result<Self, Self::Error> {
291 usize_to_u16_range(slice.bounds.clone())
292 .map(|bounds| Self {
293 data: slice.data.clone(),
294 bounds,
295 _niche_placeholder: ZeroU8::Zero,
296 })
297 .ok_or(slice)
298 }
299}
300
301#[repr(u8)]
302#[derive(Clone)]
303enum ZeroU8 {
304 Zero = 0,
305}
306
307fn u16_to_usize_range(r: Range<u16>) -> Range<usize> {
308 r.start as usize..r.end as usize
309}
310
311fn usize_to_u16_range(r: Range<usize>) -> Option<Range<u16>> {
312 match (u16::try_from(r.start), u16::try_from(r.end)) {
313 (Ok(start), Ok(end)) => Some(start..end),
314 _ => None,
315 }
316}
317
318#[cfg(test)]
319mod tests {
320 use super::*;
321
322 #[test]
323 fn test_tuple_mem_size() {
324 assert!(std::mem::size_of::<KTuple>() <= 16);
325 }
326}