Skip to main content

aver_rt/
lib.rs

1#![doc = include_str!("../README.md")]
2
3mod display;
4#[cfg(feature = "http")]
5pub mod http;
6pub mod http_server;
7#[cfg(feature = "random")]
8pub mod random;
9mod runtime;
10mod service_types;
11pub mod tcp;
12#[cfg(feature = "terminal")]
13pub mod terminal;
14
15pub use display::{AverDisplay, aver_display};
16pub use runtime::{
17    append_text, cli_args, console_error, console_print, console_warn, delete_dir, delete_file,
18    env_get, env_set, list_dir, make_dir, path_exists, read_line, read_text, string_slice,
19    time_now, time_sleep, time_unix_ms, write_text,
20};
21pub use service_types::{Header, HttpRequest, HttpResponse, TcpConnection};
22
23#[cfg(feature = "terminal")]
24pub use terminal::{
25    TerminalGuard, clear as terminal_clear, disable_raw_mode as terminal_disable_raw_mode,
26    enable_raw_mode as terminal_enable_raw_mode, flush as terminal_flush,
27    hide_cursor as terminal_hide_cursor, move_to as terminal_move_to,
28    print_at_cursor as terminal_print, read_key as terminal_read_key,
29    reset_color as terminal_reset_color, restore_terminal, set_color as terminal_set_color,
30    show_cursor as terminal_show_cursor, size as terminal_size,
31};
32
33use std::fmt;
34use std::hash::{Hash, Hasher};
35use std::iter::FusedIterator;
36use std::rc::Rc;
37
38const LIST_APPEND_CHUNK_LIMIT: usize = 128;
39
40pub struct AverList<T> {
41    inner: Rc<AverListInner<T>>,
42}
43
44enum AverListInner<T> {
45    Flat {
46        items: Rc<Vec<T>>,
47        start: usize,
48    },
49    Prepend {
50        head: T,
51        tail: AverList<T>,
52        len: usize,
53    },
54    Concat {
55        left: AverList<T>,
56        right: AverList<T>,
57        len: usize,
58    },
59    Segments {
60        current: AverList<T>,
61        rest: Rc<Vec<AverList<T>>>,
62        start: usize,
63        len: usize,
64    },
65}
66
67fn empty_list_inner<T>() -> Rc<AverListInner<T>> {
68    Rc::new(AverListInner::Flat {
69        items: Rc::new(Vec::new()),
70        start: 0,
71    })
72}
73
74fn empty_list<T>(inner: &Rc<AverListInner<T>>) -> AverList<T> {
75    AverList {
76        inner: Rc::clone(inner),
77    }
78}
79
80fn take_list_inner<T>(
81    list: &mut AverList<T>,
82    empty_inner: &Rc<AverListInner<T>>,
83) -> Rc<AverListInner<T>> {
84    let original = std::mem::replace(list, empty_list(empty_inner));
85    original.inner
86}
87
88fn detach_unique_children<T>(
89    inner: &mut AverListInner<T>,
90    empty_inner: &Rc<AverListInner<T>>,
91    pending: &mut Vec<Rc<AverListInner<T>>>,
92) {
93    match inner {
94        AverListInner::Flat { .. } => {}
95        AverListInner::Prepend { tail, .. } => {
96            pending.push(take_list_inner(tail, empty_inner));
97        }
98        AverListInner::Concat { left, right, .. } => {
99            pending.push(take_list_inner(left, empty_inner));
100            pending.push(take_list_inner(right, empty_inner));
101        }
102        AverListInner::Segments { current, rest, .. } => {
103            pending.push(take_list_inner(current, empty_inner));
104            let rest_rc = std::mem::replace(rest, Rc::new(Vec::new()));
105            if let Ok(mut rest_vec) = Rc::try_unwrap(rest_rc) {
106                for part in &mut rest_vec {
107                    pending.push(take_list_inner(part, empty_inner));
108                }
109            }
110        }
111    }
112}
113
114impl<T> Drop for AverListInner<T> {
115    fn drop(&mut self) {
116        if matches!(self, AverListInner::Flat { .. }) {
117            return;
118        }
119
120        let empty_inner = empty_list_inner();
121        let mut pending = Vec::new();
122
123        // Detach unique children eagerly so deep list teardown does not recurse
124        // through nested `Rc<AverListInner<_>>` chains on the Rust call stack.
125        detach_unique_children(self, &empty_inner, &mut pending);
126
127        while let Some(child) = pending.pop() {
128            if let Ok(mut child_inner) = Rc::try_unwrap(child) {
129                detach_unique_children(&mut child_inner, &empty_inner, &mut pending);
130            }
131        }
132    }
133}
134
135#[derive(Clone)]
136enum ListCursor<'a, T> {
137    Node(&'a AverList<T>),
138    Slice(&'a [T], usize),
139    SegmentSlice(&'a [AverList<T>], usize),
140}
141
142pub struct AverListIter<'a, T> {
143    stack: Vec<ListCursor<'a, T>>,
144    remaining: usize,
145}
146
147impl<T> Clone for AverList<T> {
148    fn clone(&self) -> Self {
149        Self {
150            inner: Rc::clone(&self.inner),
151        }
152    }
153}
154
155impl<T> AverList<T> {
156    fn concat_node(left: &Self, right: &Self) -> Self {
157        Self {
158            inner: Rc::new(AverListInner::Concat {
159                left: left.clone(),
160                right: right.clone(),
161                len: left.len() + right.len(),
162            }),
163        }
164    }
165
166    fn segments_rc(mut current: Self, rest: Rc<Vec<Self>>, mut start: usize) -> Self {
167        while current.is_empty() {
168            if let Some(next) = rest.get(start).cloned() {
169                current = next;
170                start += 1;
171            } else {
172                return Self::empty();
173            }
174        }
175
176        if start >= rest.len() {
177            return current;
178        }
179
180        let len = current.len() + rest[start..].iter().map(AverList::len).sum::<usize>();
181        Self {
182            inner: Rc::new(AverListInner::Segments {
183                current,
184                rest,
185                start,
186                len,
187            }),
188        }
189    }
190
191    fn rebuild_from_rights(mut base: Self, mut rights: Vec<Self>) -> Self {
192        while let Some(right) = rights.pop() {
193            base = Self::concat(&base, &right);
194        }
195        base
196    }
197
198    fn flat_tail(items: &Rc<Vec<T>>, start: usize) -> Option<Self> {
199        if start >= items.len() {
200            return None;
201        }
202        if start + 1 >= items.len() {
203            return Some(Self::empty());
204        }
205        Some(Self {
206            inner: Rc::new(AverListInner::Flat {
207                items: Rc::clone(items),
208                start: start + 1,
209            }),
210        })
211    }
212
213    fn uncons(&self) -> Option<(&T, Self)> {
214        let mut rights = Vec::new();
215        let mut current = self;
216
217        loop {
218            match current.inner.as_ref() {
219                AverListInner::Flat { items, start } => {
220                    let head = items.get(*start)?;
221                    let tail = Self::flat_tail(items, *start)?;
222                    return Some((head, Self::rebuild_from_rights(tail, rights)));
223                }
224                AverListInner::Prepend { head, tail, .. } => {
225                    return Some((head, Self::rebuild_from_rights(tail.clone(), rights)));
226                }
227                AverListInner::Concat { left, right, .. } => {
228                    if left.is_empty() {
229                        current = right;
230                        continue;
231                    }
232                    rights.push(right.clone());
233                    current = left;
234                }
235                AverListInner::Segments {
236                    current: head_segment,
237                    rest,
238                    start,
239                    ..
240                } => {
241                    let (head, tail) = head_segment.uncons()?;
242                    return Some((head, Self::segments_rc(tail, Rc::clone(rest), *start)));
243                }
244            }
245        }
246    }
247
248    pub fn uncons_cloned(&self) -> Option<(T, Self)>
249    where
250        T: Clone,
251    {
252        self.uncons().map(|(head, tail)| (head.clone(), tail))
253    }
254
255    pub fn empty() -> Self {
256        Self::from_vec(vec![])
257    }
258
259    pub fn from_vec(items: Vec<T>) -> Self {
260        Self {
261            inner: Rc::new(AverListInner::Flat {
262                items: Rc::new(items),
263                start: 0,
264            }),
265        }
266    }
267
268    pub fn len(&self) -> usize {
269        match self.inner.as_ref() {
270            AverListInner::Flat { items, start } => items.len().saturating_sub(*start),
271            AverListInner::Prepend { len, .. }
272            | AverListInner::Concat { len, .. }
273            | AverListInner::Segments { len, .. } => *len,
274        }
275    }
276
277    pub fn is_empty(&self) -> bool {
278        self.len() == 0
279    }
280
281    pub fn get(&self, index: usize) -> Option<&T> {
282        let mut current = self;
283        let mut remaining = index;
284
285        loop {
286            match current.inner.as_ref() {
287                AverListInner::Flat { items, start } => {
288                    return items.get(start.saturating_add(remaining));
289                }
290                AverListInner::Prepend { head, tail, .. } => {
291                    if remaining == 0 {
292                        return Some(head);
293                    }
294                    remaining -= 1;
295                    current = tail;
296                }
297                AverListInner::Concat { left, right, .. } => {
298                    let left_len = left.len();
299                    if remaining < left_len {
300                        current = left;
301                    } else {
302                        remaining -= left_len;
303                        current = right;
304                    }
305                }
306                AverListInner::Segments {
307                    current: head_segment,
308                    rest,
309                    start,
310                    ..
311                } => {
312                    let head_len = head_segment.len();
313                    if remaining < head_len {
314                        current = head_segment;
315                    } else {
316                        remaining -= head_len;
317                        let mut found = None;
318                        for part in &rest[*start..] {
319                            let part_len = part.len();
320                            if remaining < part_len {
321                                found = Some(part);
322                                break;
323                            }
324                            remaining -= part_len;
325                        }
326                        current = found?;
327                    }
328                }
329            }
330        }
331    }
332
333    pub fn first(&self) -> Option<&T> {
334        self.get(0)
335    }
336
337    pub fn as_slice(&self) -> Option<&[T]> {
338        match self.inner.as_ref() {
339            AverListInner::Flat { items, start } => Some(items.get(*start..).unwrap_or(&[])),
340            AverListInner::Prepend { .. }
341            | AverListInner::Concat { .. }
342            | AverListInner::Segments { .. } => None,
343        }
344    }
345
346    pub fn iter(&self) -> AverListIter<'_, T> {
347        AverListIter {
348            stack: vec![ListCursor::Node(self)],
349            remaining: self.len(),
350        }
351    }
352
353    pub fn tail(&self) -> Option<Self> {
354        match self.inner.as_ref() {
355            AverListInner::Flat { items, start } => Self::flat_tail(items, *start),
356            AverListInner::Prepend { tail, .. } => Some(tail.clone()),
357            AverListInner::Concat { .. } | AverListInner::Segments { .. } => {
358                self.uncons().map(|(_, tail)| tail)
359            }
360        }
361    }
362
363    pub fn prepend(item: T, list: &Self) -> Self {
364        if list.is_empty() {
365            return Self::from_vec(vec![item]);
366        }
367        Self {
368            inner: Rc::new(AverListInner::Prepend {
369                head: item,
370                tail: list.clone(),
371                len: list.len() + 1,
372            }),
373        }
374    }
375
376    pub fn concat(left: &Self, right: &Self) -> Self {
377        if left.is_empty() {
378            return right.clone();
379        }
380        if right.is_empty() {
381            return left.clone();
382        }
383        Self::concat_node(left, right)
384    }
385
386    pub fn append(list: &Self, item: T) -> Self {
387        let singleton = Self::from_vec(vec![item]);
388        if list.is_empty() {
389            return singleton;
390        }
391
392        match list.inner.as_ref() {
393            AverListInner::Segments {
394                current,
395                rest,
396                start,
397                ..
398            } => {
399                let mut parts = rest[*start..].to_vec();
400                if let Some(last) = parts.last_mut() {
401                    if last.len() < LIST_APPEND_CHUNK_LIMIT {
402                        *last = Self::concat(last, &singleton);
403                    } else {
404                        parts.push(singleton);
405                    }
406                } else {
407                    parts.push(singleton);
408                }
409                Self::segments_rc(current.clone(), Rc::new(parts), 0)
410            }
411            _ if list.len() < LIST_APPEND_CHUNK_LIMIT => Self::concat(list, &singleton),
412            _ => Self::segments_rc(list.clone(), Rc::new(vec![singleton]), 0),
413        }
414    }
415
416    pub fn to_vec(&self) -> Vec<T>
417    where
418        T: Clone,
419    {
420        let mut out = Vec::with_capacity(self.len());
421        out.extend(self.iter().cloned());
422        out
423    }
424
425    pub fn reverse(&self) -> Self
426    where
427        T: Clone,
428    {
429        let mut out = self.to_vec();
430        out.reverse();
431        Self::from_vec(out)
432    }
433
434    pub fn contains(&self, item: &T) -> bool
435    where
436        T: PartialEq,
437    {
438        self.iter().any(|x| x == item)
439    }
440}
441
442impl<'a, T> Iterator for AverListIter<'a, T> {
443    type Item = &'a T;
444
445    fn next(&mut self) -> Option<Self::Item> {
446        while let Some(cursor) = self.stack.pop() {
447            match cursor {
448                ListCursor::Slice(items, index) => {
449                    if let Some(item) = items.get(index) {
450                        self.stack.push(ListCursor::Slice(items, index + 1));
451                        self.remaining = self.remaining.saturating_sub(1);
452                        return Some(item);
453                    }
454                }
455                ListCursor::Node(list) => match list.inner.as_ref() {
456                    AverListInner::Flat { items, start } => {
457                        let slice = items.get(*start..).unwrap_or(&[]);
458                        if !slice.is_empty() {
459                            self.stack.push(ListCursor::Slice(slice, 0));
460                        }
461                    }
462                    AverListInner::Prepend { head, tail, .. } => {
463                        self.stack.push(ListCursor::Node(tail));
464                        self.remaining = self.remaining.saturating_sub(1);
465                        return Some(head);
466                    }
467                    AverListInner::Concat { left, right, .. } => {
468                        self.stack.push(ListCursor::Node(right));
469                        self.stack.push(ListCursor::Node(left));
470                    }
471                    AverListInner::Segments {
472                        current,
473                        rest,
474                        start,
475                        ..
476                    } => {
477                        let slice = rest.get(*start..).unwrap_or(&[]);
478                        if !slice.is_empty() {
479                            self.stack.push(ListCursor::SegmentSlice(slice, 0));
480                        }
481                        self.stack.push(ListCursor::Node(current));
482                    }
483                },
484                ListCursor::SegmentSlice(items, index) => {
485                    if let Some(item) = items.get(index) {
486                        self.stack.push(ListCursor::SegmentSlice(items, index + 1));
487                        self.stack.push(ListCursor::Node(item));
488                    }
489                }
490            }
491        }
492        None
493    }
494
495    fn size_hint(&self) -> (usize, Option<usize>) {
496        (self.remaining, Some(self.remaining))
497    }
498}
499
500impl<T> ExactSizeIterator for AverListIter<'_, T> {
501    fn len(&self) -> usize {
502        self.remaining
503    }
504}
505
506impl<T> FusedIterator for AverListIter<'_, T> {}
507
508impl<'a, T> IntoIterator for &'a AverList<T> {
509    type Item = &'a T;
510    type IntoIter = AverListIter<'a, T>;
511
512    fn into_iter(self) -> Self::IntoIter {
513        self.iter()
514    }
515}
516
517impl<T: Clone> IntoIterator for AverList<T> {
518    type Item = T;
519    type IntoIter = std::vec::IntoIter<T>;
520
521    fn into_iter(self) -> Self::IntoIter {
522        self.to_vec().into_iter()
523    }
524}
525
526impl<T: fmt::Debug> fmt::Debug for AverList<T> {
527    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
528        f.debug_list().entries(self.iter()).finish()
529    }
530}
531
532impl<T: PartialEq> PartialEq for AverList<T> {
533    fn eq(&self, other: &Self) -> bool {
534        self.len() == other.len() && self.iter().zip(other.iter()).all(|(a, b)| a == b)
535    }
536}
537
538impl<T: Eq> Eq for AverList<T> {}
539
540impl<T: Hash> Hash for AverList<T> {
541    fn hash<H: Hasher>(&self, state: &mut H) {
542        8u8.hash(state);
543        self.len().hash(state);
544        for item in self.iter() {
545            item.hash(state);
546        }
547    }
548}
549
550pub fn list_uncons<T>(list: &AverList<T>) -> Option<(&T, AverList<T>)> {
551    list.uncons()
552}
553
554pub fn list_uncons_cloned<T: Clone>(list: &AverList<T>) -> Option<(T, AverList<T>)> {
555    list.uncons_cloned()
556}
557
558pub fn string_join<S: AsRef<str>>(parts: &AverList<S>, sep: &str) -> String {
559    let mut iter = parts.iter();
560    let Some(first) = iter.next() else {
561        return String::new();
562    };
563    let mut out = first.as_ref().to_string();
564    for part in iter {
565        out.push_str(sep);
566        out.push_str(part.as_ref());
567    }
568    out
569}
570
571#[cfg(test)]
572mod tests {
573    use super::{
574        AverList, AverListInner, LIST_APPEND_CHUNK_LIMIT, aver_display, env_set, string_slice,
575    };
576
577    #[test]
578    fn prepend_and_tail_share_structure() {
579        let base = AverList::from_vec(vec![2, 3]);
580        let full = AverList::prepend(1, &base);
581        assert_eq!(full.first(), Some(&1));
582        assert_eq!(full.tail().unwrap(), base);
583    }
584
585    #[test]
586    fn concat_and_iter_preserve_order() {
587        let left = AverList::from_vec(vec![1, 2]);
588        let right = AverList::from_vec(vec![3, 4]);
589        let joined = AverList::concat(&left, &right);
590        assert_eq!(joined.to_vec(), vec![1, 2, 3, 4]);
591    }
592
593    #[test]
594    fn dropping_deep_prepend_chain_does_not_overflow() {
595        let mut list = AverList::empty();
596        for value in 0..200_000 {
597            list = AverList::prepend(value, &list);
598        }
599
600        assert_eq!(list.len(), 200_000);
601        drop(list);
602    }
603
604    #[test]
605    fn tail_of_deep_append_chain_does_not_overflow() {
606        let mut list = AverList::empty();
607        for value in 0..200_000 {
608            list = AverList::append(&list, value);
609        }
610
611        let tail = list.tail().expect("non-empty list must have a tail");
612        assert_eq!(tail.len(), 199_999);
613        assert_eq!(tail.first(), Some(&1));
614    }
615
616    #[test]
617    fn list_uncons_of_deep_append_chain_does_not_overflow() {
618        let mut list = AverList::empty();
619        for value in 0..200_000 {
620            list = AverList::append(&list, value);
621        }
622
623        let (head, tail) = super::list_uncons(&list).expect("non-empty list must uncons");
624        assert_eq!(*head, 0);
625        assert_eq!(tail.len(), 199_999);
626        assert_eq!(tail.first(), Some(&1));
627    }
628
629    #[test]
630    fn cloned_uncons_preserves_append_chain_tail_contents() {
631        let mut list = AverList::empty();
632        for value in 0..5 {
633            list = AverList::append(&list, value);
634        }
635
636        let (head, tail) = super::list_uncons_cloned(&list).expect("non-empty list must uncons");
637        assert_eq!(head, 0);
638        assert_eq!(tail.to_vec(), vec![1, 2, 3, 4]);
639    }
640
641    #[test]
642    fn get_reads_flat_list_in_place() {
643        let list = AverList::from_vec(vec![10, 20, 30]);
644
645        assert_eq!(list.get(0), Some(&10));
646        assert_eq!(list.get(2), Some(&30));
647        assert_eq!(list.get(3), None);
648    }
649
650    #[test]
651    fn get_walks_concat_and_prepend_without_flattening() {
652        let base = AverList::from_vec(vec![2, 3]);
653        let prepended = AverList::prepend(1, &base);
654        let joined = AverList::concat(&prepended, &AverList::from_vec(vec![4, 5]));
655
656        assert_eq!(joined.get(0), Some(&1));
657        assert_eq!(joined.get(2), Some(&3));
658        assert_eq!(joined.get(4), Some(&5));
659        assert_eq!(joined.get(5), None);
660    }
661
662    #[test]
663    fn repeated_tail_over_append_chain_preserves_all_items() {
664        let mut list = AverList::empty();
665        for value in 0..6 {
666            list = AverList::append(&list, value);
667        }
668
669        let mut rest = list;
670        let mut seen = Vec::new();
671        while let Some((head, tail)) = super::list_uncons(&rest) {
672            seen.push(*head);
673            rest = tail;
674        }
675
676        assert_eq!(seen, vec![0, 1, 2, 3, 4, 5]);
677    }
678
679    #[test]
680    fn append_promotes_long_right_spines_into_segments() {
681        let mut list = AverList::empty();
682        for value in 0..200 {
683            list = AverList::append(&list, value);
684        }
685
686        match list.inner.as_ref() {
687            AverListInner::Segments {
688                current,
689                rest,
690                start,
691                ..
692            } => {
693                assert_eq!(current.len(), LIST_APPEND_CHUNK_LIMIT);
694                assert_eq!(rest[*start].len(), 72);
695            }
696            other => panic!(
697                "expected segmented append shape, got {}",
698                aver_display_shape(other)
699            ),
700        }
701    }
702
703    #[test]
704    fn get_walks_segmented_append_chain_without_losing_order() {
705        let mut list = AverList::empty();
706        for value in 0..300 {
707            list = AverList::append(&list, value);
708        }
709
710        assert_eq!(list.get(0), Some(&0));
711        assert_eq!(list.get(127), Some(&127));
712        assert_eq!(list.get(128), Some(&128));
713        assert_eq!(list.get(255), Some(&255));
714        assert_eq!(list.get(299), Some(&299));
715        assert_eq!(list.get(300), None);
716    }
717
718    #[test]
719    fn aver_display_quotes_strings_inside_lists() {
720        let parts = AverList::from_vec(vec!["a".to_string(), "b".to_string()]);
721        assert_eq!(aver_display(&parts), "[\"a\", \"b\"]");
722    }
723
724    #[test]
725    fn string_slice_uses_code_point_indices() {
726        assert_eq!(string_slice("zażółć", 1, 4), "ażó");
727    }
728
729    #[test]
730    fn string_slice_clamps_negative_indices() {
731        assert_eq!(string_slice("hello", -2, 2), "he");
732        assert_eq!(string_slice("hello", 1, -1), "");
733    }
734
735    #[test]
736    fn env_set_rejects_invalid_keys() {
737        assert_eq!(
738            env_set("", "x"),
739            Err("Env.set: key must not be empty".to_string())
740        );
741        assert_eq!(
742            env_set("A=B", "x"),
743            Err("Env.set: key must not contain '='".to_string())
744        );
745    }
746
747    fn aver_display_shape<T>(inner: &AverListInner<T>) -> &'static str {
748        match inner {
749            AverListInner::Flat { .. } => "Flat",
750            AverListInner::Prepend { .. } => "Prepend",
751            AverListInner::Concat { .. } => "Concat",
752            AverListInner::Segments { .. } => "Segments",
753        }
754    }
755}