1use crate::Value;
2use anyhow::{bail, Result};
3use bytes::{Buf, BufMut};
4use netidx_core::pack::{
5 decode_varint, encode_varint, varint_len, Pack, PackError, MAX_VEC,
6};
7use poolshark::{arc::TArc as PArc, Poolable, RawPool, RawPoolable, WeakPool};
8use seq_macro::seq;
9use serde::{de::Visitor, ser::SerializeSeq, Deserialize, Serialize};
10use smallvec::{smallvec, SmallVec};
11use std::{
12 borrow::Borrow,
13 fmt::Debug,
14 hash::{Hash, Hasher},
15 mem::ManuallyDrop,
16 ops::{Bound, Deref, RangeBounds},
17 ptr,
18 slice::Iter,
19 sync::LazyLock,
20};
21use triomphe::{Arc, ThinArc};
22
23const MAX_LEN: usize = 128;
24
25const POOLS: [LazyLock<RawPool<ValArrayBase>>; 129] = seq!(N in 0..=128 {
26 [
27 #(LazyLock::new(|| RawPool::new(32 * (MAX_LEN + 1 - N), 1)),)*
28 ]
29});
30
31const SPOOL: LazyLock<RawPool<PArc<ValArraySlice>>> =
32 LazyLock::new(|| RawPool::new(1024, 64));
33
34fn get_by_size(len: usize) -> ValArrayBase {
35 if len <= MAX_LEN {
36 let pool = &POOLS[len];
37 match pool.try_take() {
38 Some(t) => t,
39 None => ValArrayBase::new_with_len(pool.downgrade(), len),
40 }
41 } else {
42 ValArrayBase::new_with_len(WeakPool::new(), len)
43 }
44}
45
46#[derive(Debug, Clone)]
47pub struct ValArrayBase(ManuallyDrop<ThinArc<WeakPool<Self>, Value>>);
48
49impl Drop for ValArrayBase {
50 fn drop(&mut self) {
51 if ThinArc::strong_count(&self.0) > 1 {
52 unsafe { ManuallyDrop::drop(&mut self.0) }
53 } else {
54 match self.0.header.header.upgrade() {
55 Some(pool) => pool.insert(unsafe { ptr::read(self) }),
56 None => unsafe { ManuallyDrop::drop(&mut self.0) },
57 }
58 }
59 }
60}
61
62impl Deref for ValArrayBase {
63 type Target = [Value];
64
65 fn deref(&self) -> &Self::Target {
66 &self.0.slice
67 }
68}
69
70unsafe impl RawPoolable for ValArrayBase {
71 fn capacity(&self) -> usize {
72 1
73 }
74
75 fn empty(pool: WeakPool<Self>) -> Self {
76 let t = ThinArc::from_header_and_iter(pool, [].into_iter());
77 ValArrayBase(ManuallyDrop::new(t))
78 }
79
80 fn reset(&mut self) {
81 self.0.with_arc_mut(|t| {
82 for v in Arc::get_mut(t).unwrap().slice.iter_mut() {
84 *v = Value::Bool(false);
86 }
87 })
88 }
89
90 fn really_drop(self) {
91 let mut t = ManuallyDrop::new(self);
92 unsafe { ManuallyDrop::drop(&mut t.0) }
93 }
94}
95
96impl ValArrayBase {
97 fn new_with_len(pool: WeakPool<Self>, len: usize) -> Self {
98 let iter = (0..len).map(|_| Value::Bool(false));
99 let t = ThinArc::from_header_and_iter(pool, iter);
100 Self(ManuallyDrop::new(t))
101 }
102}
103
104impl PartialEq for ValArrayBase {
105 fn eq(&self, other: &Self) -> bool {
106 self.0.slice == other.0.slice
107 }
108}
109
110impl Eq for ValArrayBase {}
111
112impl PartialOrd for ValArrayBase {
113 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
114 self.0.slice.partial_cmp(&other.0.slice)
115 }
116}
117
118impl Ord for ValArrayBase {
119 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
120 self.0.slice.cmp(&other.0.slice)
121 }
122}
123
124impl Hash for ValArrayBase {
125 fn hash<H: Hasher>(&self, state: &mut H) {
126 self.0.slice.hash(state)
127 }
128}
129
130#[derive(Debug, Clone)]
131pub struct ValArraySlice {
132 base: ValArrayBase,
133 start: Bound<usize>,
134 end: Bound<usize>,
135}
136
137impl Deref for ValArraySlice {
138 type Target = [Value];
139
140 fn deref(&self) -> &Self::Target {
141 &self.base[(self.start, self.end)]
142 }
143}
144
145impl Poolable for ValArraySlice {
146 fn empty() -> Self {
147 Self { base: get_by_size(0), start: Bound::Unbounded, end: Bound::Unbounded }
148 }
149
150 fn capacity(&self) -> usize {
151 1
152 }
153
154 fn reset(&mut self) {
155 self.base = get_by_size(0);
156 self.start = Bound::Unbounded;
157 self.end = Bound::Unbounded
158 }
159}
160
161#[derive(Debug, Clone)]
162pub enum ValArray {
163 Base(ValArrayBase),
164 Slice(PArc<ValArraySlice>),
165}
166
167impl Deref for ValArray {
168 type Target = [Value];
169
170 fn deref(&self) -> &Self::Target {
171 match self {
172 Self::Base(a) => &*a,
173 Self::Slice(s) => &**s,
174 }
175 }
176}
177
178impl PartialEq for ValArray {
179 fn eq(&self, other: &Self) -> bool {
180 &self[..] == &other[..]
181 }
182}
183
184impl Eq for ValArray {}
185
186impl PartialOrd for ValArray {
187 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
188 self[..].partial_cmp(&other[..])
189 }
190}
191
192impl Ord for ValArray {
193 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
194 self[..].cmp(&other[..])
195 }
196}
197
198impl Hash for ValArray {
199 fn hash<H: Hasher>(&self, state: &mut H) {
200 self[..].hash(state)
201 }
202}
203
204impl Borrow<[Value]> for ValArray {
205 fn borrow(&self) -> &[Value] {
206 &*self
207 }
208}
209
210impl From<Vec<Value>> for ValArray {
211 fn from(v: Vec<Value>) -> Self {
212 Self::from_iter_exact(v.into_iter())
213 }
214}
215
216impl<const S: usize> From<SmallVec<[Value; S]>> for ValArray {
217 fn from(v: SmallVec<[Value; S]>) -> Self {
218 Self::from_iter_exact(v.into_iter())
219 }
220}
221
222impl<const S: usize> From<[Value; S]> for ValArray {
223 fn from(v: [Value; S]) -> Self {
224 Self::from_iter_exact(v.into_iter())
225 }
226}
227
228impl From<&[Value]> for ValArray {
229 fn from(v: &[Value]) -> Self {
230 Self::from_iter_exact(v.into_iter().map(|v| v.clone()))
231 }
232}
233
234impl FromIterator<Value> for ValArray {
235 fn from_iter<T: IntoIterator<Item = Value>>(iter: T) -> Self {
236 let mut tmp: SmallVec<[Value; 64]> = smallvec![];
237 for v in iter {
238 tmp.push(v);
239 }
240 Self::from_iter_exact(tmp.into_iter())
241 }
242}
243
244impl Into<Vec<Value>> for ValArray {
245 fn into(self) -> Vec<Value> {
246 let mut tmp = Vec::with_capacity(self.len());
247 for v in self.iter() {
248 tmp.push(v.clone());
249 }
250 tmp
251 }
252}
253
254impl<const S: usize> Into<SmallVec<[Value; S]>> for ValArray {
255 fn into(self) -> SmallVec<[Value; S]> {
256 let mut tmp = smallvec![];
257 for v in self.iter() {
258 tmp.push(v.clone())
259 }
260 tmp
261 }
262}
263
264pub struct OwnedValArrayIter {
265 pos: usize,
266 a: ValArray,
267}
268
269impl Iterator for OwnedValArrayIter {
270 type Item = Value;
271
272 fn next(&mut self) -> Option<Self::Item> {
273 let res = self.a.get(self.pos).map(|v| v.clone());
274 self.pos += 1;
275 res
276 }
277}
278
279impl IntoIterator for ValArray {
280 type IntoIter = OwnedValArrayIter;
281 type Item = Value;
282
283 fn into_iter(self) -> Self::IntoIter {
284 OwnedValArrayIter { pos: 0, a: self }
285 }
286}
287
288impl<'a> IntoIterator for &'a ValArray {
289 type IntoIter = Iter<'a, Value>;
290 type Item = &'a Value;
291
292 fn into_iter(self) -> Self::IntoIter {
293 self.iter()
294 }
295}
296
297impl ValArray {
298 pub fn from_iter_exact<I: Iterator<Item = Value> + ExactSizeIterator>(
299 iter: I,
300 ) -> Self {
301 let mut res = get_by_size(iter.len());
302 res.0.with_arc_mut(|res| {
303 let res = Arc::get_mut(res).unwrap();
304 for (i, v) in iter.enumerate() {
305 res.slice[i] = v;
306 }
307 });
308 Self::Base(res)
309 }
310
311 pub fn subslice<R: RangeBounds<usize>>(&self, r: R) -> Result<Self> {
314 fn check_bounds(
315 a: &ValArrayBase,
316 start: Bound<usize>,
317 end: Bound<usize>,
318 ) -> Result<()> {
319 let len = a.len();
320 match start {
321 Bound::Unbounded => (),
322 Bound::Excluded(i) => {
323 if i > len - 1 {
324 bail!("start index {i} out of bounds {len}")
325 }
326 }
327 Bound::Included(i) => {
328 if i > len {
329 bail!("start index {i} out of bounds {len}")
330 }
331 }
332 }
333 match end {
334 Bound::Unbounded => (),
335 Bound::Excluded(i) => {
336 if i > len {
337 bail!("end index {i} out of bounds {len}")
338 }
339 }
340 Bound::Included(i) => {
341 if i >= len {
342 bail!("end index {i} out of bounds {len}")
343 }
344 }
345 }
346 match (start, end) {
347 (
348 Bound::Unbounded,
349 Bound::Unbounded | Bound::Included(_) | Bound::Excluded(_),
350 )
351 | (Bound::Included(_) | Bound::Excluded(_), Bound::Unbounded) => (),
352 (Bound::Included(i), Bound::Included(j))
353 | (Bound::Excluded(i), Bound::Included(j))
354 | (Bound::Included(i), Bound::Excluded(j)) => {
355 if j < i {
356 bail!("array index starts at {i} but ends at {j}")
357 }
358 }
359 (Bound::Excluded(i), Bound::Excluded(j)) => {
360 if j <= i {
361 bail!("array index starts at ex {i} but ends at ex {j}")
362 }
363 }
364 }
365 Ok(())
366 }
367 match self {
368 Self::Base(a) => {
369 let (start, end) =
370 (r.start_bound().map(|i| *i), r.end_bound().map(|i| *i));
371 let t = ValArraySlice { base: a.clone(), start, end };
372 check_bounds(&a, start, end)?;
373 Ok(Self::Slice(PArc::new(&SPOOL, t)))
374 }
375 Self::Slice(s) => {
376 let max_i = match s.end {
377 Bound::Unbounded => s.base.len(),
378 Bound::Excluded(i) => i,
379 Bound::Included(i) => i,
380 };
381 let (start, end) =
382 (r.start_bound().map(|i| *i), r.end_bound().map(|i| *i));
383 match (start, end) {
384 (Bound::Excluded(i), Bound::Excluded(j)) if j <= i => {
385 bail!("negative size slice ex {i}, ex {j}")
386 }
387 (Bound::Included(i), Bound::Included(j)) if j < i => {
388 bail!("negative size slice {i}, {j}")
389 }
390 (_, _) => (),
391 }
392 let (start_i, start_off, start) = match (s.start, start) {
393 (Bound::Unbounded, Bound::Unbounded) => (0, 0, Bound::Unbounded),
394 (Bound::Unbounded, Bound::Excluded(i)) => {
395 if i >= max_i {
396 bail!("slice start {i} is out of bounds {max_i}")
397 }
398 (i, i, Bound::Excluded(i))
399 }
400 (Bound::Unbounded, Bound::Included(i)) => {
401 if i > max_i {
402 bail!("slice start {i} is out of bounds {max_i}")
403 }
404 (i, i, Bound::Included(i))
405 }
406 (Bound::Excluded(i), Bound::Unbounded) => (i, 0, Bound::Excluded(i)),
407 (Bound::Excluded(i), Bound::Included(j)) => {
408 let si = i + j;
409 if si >= max_i {
410 bail!("slice start {si} is out of bounds {max_i}")
411 }
412 (si, j, Bound::Excluded(si))
413 }
414 (Bound::Excluded(i), Bound::Excluded(j)) => {
415 let si = i + j;
416 if si >= max_i {
417 bail!("slice start {si} is out of bounds {max_i}")
418 }
419 (si, j, Bound::Excluded(si))
420 }
421 (Bound::Included(i), Bound::Unbounded) => (i, 0, Bound::Included(i)),
422 (Bound::Included(i), Bound::Included(j)) => {
423 let si = i + j;
424 if si > max_i {
425 bail!("slice start {si} is out of bounds {max_i}")
426 }
427 (si, j, Bound::Included(si))
428 }
429 (Bound::Included(i), Bound::Excluded(j)) => {
430 let si = i + j;
431 if si >= max_i {
432 bail!("slice start {si} is out of bounds {max_i}")
433 }
434 (si, j, Bound::Excluded(si))
435 }
436 };
437 let end = match (s.end, end) {
438 (Bound::Unbounded, Bound::Unbounded) => Bound::Unbounded,
439 (Bound::Unbounded, Bound::Excluded(j)) => {
440 if j < start_off {
441 bail!("array index starts at {start_off} but ends at {j}")
442 }
443 let r = start_i + (j - start_off);
444 if r > max_i {
445 bail!("slice end {r} is out of bounds {max_i}")
446 }
447 Bound::Excluded(r)
448 }
449 (Bound::Unbounded, Bound::Included(j)) => {
450 if j < start_off {
451 bail!("array index starts at {start_off} but ends at {j}")
452 }
453 let r = start_i + (j - start_off);
454 if r > max_i {
455 bail!("slice end {r} is out of bounds {max_i}")
456 }
457 Bound::Included(r)
458 }
459 (Bound::Excluded(i), Bound::Unbounded) => Bound::Excluded(i),
460 (Bound::Excluded(i), Bound::Excluded(j)) => {
461 if j < start_off {
462 bail!("array index starts at {start_off} but ends at {j}")
463 }
464 let r = start_i + (j - start_off);
465 if r > i {
466 bail!("slice end {r} is out of bounds {i}")
467 }
468 Bound::Excluded(r)
469 }
470 (Bound::Excluded(i), Bound::Included(j)) => {
471 if j < start_off {
472 bail!("array index starts at {start_off} but ends at {j}")
473 }
474 let r = start_i + (j - start_off);
475 if r >= i {
476 bail!("slice end {r} is out of bounds {i}")
477 }
478 Bound::Included(r)
479 }
480 (Bound::Included(i), Bound::Unbounded) => Bound::Included(i),
481 (Bound::Included(i), Bound::Excluded(j)) => {
482 if j < start_off {
483 bail!("array index starts at {start_off} but ends at {j}")
484 }
485 let r = start_i + (j - start_off);
486 if r > i + 1 {
487 bail!("slice end {r} is out of bounds {i}")
488 }
489 Bound::Excluded(r)
490 }
491 (Bound::Included(i), Bound::Included(j)) => {
492 if j < start_off {
493 bail!("array index starts at {start_off} but ends at {j}")
494 }
495 let r = start_i + (j - start_off);
496 if r > i {
497 bail!("slice end {r} is out of bound {i}")
498 }
499 Bound::Included(r)
500 }
501 };
502 let t = ValArraySlice { base: s.base.clone(), start, end };
503 Ok(Self::Slice(PArc::new(&SPOOL, t)))
504 }
505 }
506 }
507}
508
509impl Serialize for ValArray {
510 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
511 where
512 S: serde::Serializer,
513 {
514 let mut seq = serializer.serialize_seq(Some(self.len()))?;
515 for v in &**self {
516 seq.serialize_element(v)?
517 }
518 seq.end()
519 }
520}
521
522struct ValArrayVisitor;
523
524impl<'de> Visitor<'de> for ValArrayVisitor {
525 type Value = ValArray;
526
527 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
528 write!(f, "expecting a sequence")
529 }
530
531 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
532 where
533 A: serde::de::SeqAccess<'de>,
534 {
535 let mut tmp: SmallVec<[Value; 64]> = smallvec![];
536 while let Some(v) = seq.next_element()? {
537 tmp.push(v);
538 }
539 Ok(ValArray::from(tmp))
540 }
541}
542
543impl<'de> Deserialize<'de> for ValArray {
544 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
545 where
546 D: serde::Deserializer<'de>,
547 {
548 deserializer.deserialize_seq(ValArrayVisitor)
549 }
550}
551
552impl Pack for ValArray {
553 fn encoded_len(&self) -> usize {
554 self.iter()
555 .fold(varint_len(self.len() as u64), |len, t| len + Pack::encoded_len(t))
556 }
557
558 fn encode(&self, buf: &mut impl BufMut) -> Result<(), PackError> {
559 encode_varint(self.len() as u64, buf);
560 for t in &**self {
561 Pack::encode(t, buf)?
562 }
563 Ok(())
564 }
565
566 fn decode(buf: &mut impl Buf) -> Result<Self, PackError> {
567 let elts = decode_varint(buf)? as usize;
568 if elts > MAX_VEC {
569 return Err(PackError::TooBig);
570 }
571 let mut data = get_by_size(elts);
572 data.0.with_arc_mut(|data| {
573 let data = Arc::get_mut(data).unwrap();
574 for i in 0..elts {
575 data.slice[i] = Pack::decode(buf)?;
576 }
577 Ok(())
578 })?;
579 Ok(Self::Base(data))
580 }
581}