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