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;
7mod runtime;
8mod service_types;
9pub mod tcp;
10
11pub use display::{AverDisplay, aver_display};
12pub use runtime::{
13    append_text, cli_args, console_error, console_print, console_warn, delete_dir, delete_file,
14    env_get, env_set, list_dir, make_dir, path_exists, read_line, read_text, string_slice,
15    time_now, time_sleep, time_unix_ms, write_text,
16};
17pub use service_types::{Header, HttpRequest, HttpResponse, TcpConnection};
18
19use std::fmt;
20use std::hash::{Hash, Hasher};
21use std::iter::FusedIterator;
22use std::rc::Rc;
23
24pub struct AverList<T> {
25    inner: Rc<AverListInner<T>>,
26}
27
28enum AverListInner<T> {
29    Flat {
30        items: Rc<Vec<T>>,
31        start: usize,
32    },
33    Prepend {
34        head: T,
35        tail: AverList<T>,
36        len: usize,
37    },
38    Concat {
39        left: AverList<T>,
40        right: AverList<T>,
41        len: usize,
42    },
43}
44
45fn empty_list_inner<T>() -> Rc<AverListInner<T>> {
46    Rc::new(AverListInner::Flat {
47        items: Rc::new(Vec::new()),
48        start: 0,
49    })
50}
51
52fn empty_list<T>(inner: &Rc<AverListInner<T>>) -> AverList<T> {
53    AverList {
54        inner: Rc::clone(inner),
55    }
56}
57
58fn take_list_inner<T>(
59    list: &mut AverList<T>,
60    empty_inner: &Rc<AverListInner<T>>,
61) -> Rc<AverListInner<T>> {
62    let original = std::mem::replace(list, empty_list(empty_inner));
63    original.inner
64}
65
66fn detach_unique_children<T>(
67    inner: &mut AverListInner<T>,
68    empty_inner: &Rc<AverListInner<T>>,
69    pending: &mut Vec<Rc<AverListInner<T>>>,
70) {
71    match inner {
72        AverListInner::Flat { .. } => {}
73        AverListInner::Prepend { tail, .. } => {
74            pending.push(take_list_inner(tail, empty_inner));
75        }
76        AverListInner::Concat { left, right, .. } => {
77            pending.push(take_list_inner(left, empty_inner));
78            pending.push(take_list_inner(right, empty_inner));
79        }
80    }
81}
82
83impl<T> Drop for AverListInner<T> {
84    fn drop(&mut self) {
85        if matches!(self, AverListInner::Flat { .. }) {
86            return;
87        }
88
89        let empty_inner = empty_list_inner();
90        let mut pending = Vec::new();
91
92        // Detach unique children eagerly so deep list teardown does not recurse
93        // through nested `Rc<AverListInner<_>>` chains on the Rust call stack.
94        detach_unique_children(self, &empty_inner, &mut pending);
95
96        while let Some(child) = pending.pop() {
97            if let Ok(mut child_inner) = Rc::try_unwrap(child) {
98                detach_unique_children(&mut child_inner, &empty_inner, &mut pending);
99            }
100        }
101    }
102}
103
104#[derive(Clone)]
105enum ListCursor<'a, T> {
106    Node(&'a AverList<T>),
107    Slice(&'a [T], usize),
108}
109
110pub struct AverListIter<'a, T> {
111    stack: Vec<ListCursor<'a, T>>,
112    remaining: usize,
113}
114
115impl<T> Clone for AverList<T> {
116    fn clone(&self) -> Self {
117        Self {
118            inner: Rc::clone(&self.inner),
119        }
120    }
121}
122
123impl<T> AverList<T> {
124    fn concat_node(left: &Self, right: &Self) -> Self {
125        Self {
126            inner: Rc::new(AverListInner::Concat {
127                left: left.clone(),
128                right: right.clone(),
129                len: left.len() + right.len(),
130            }),
131        }
132    }
133
134    fn rebuild_from_rights(mut base: Self, mut rights: Vec<Self>) -> Self {
135        while let Some(right) = rights.pop() {
136            base = Self::concat(&base, &right);
137        }
138        base
139    }
140
141    fn flat_tail(items: &Rc<Vec<T>>, start: usize) -> Option<Self> {
142        if start >= items.len() {
143            return None;
144        }
145        if start + 1 >= items.len() {
146            return Some(Self::empty());
147        }
148        Some(Self {
149            inner: Rc::new(AverListInner::Flat {
150                items: Rc::clone(items),
151                start: start + 1,
152            }),
153        })
154    }
155
156    fn uncons(&self) -> Option<(&T, Self)> {
157        let mut rights = Vec::new();
158        let mut current = self;
159
160        loop {
161            match current.inner.as_ref() {
162                AverListInner::Flat { items, start } => {
163                    let head = items.get(*start)?;
164                    let tail = Self::flat_tail(items, *start)?;
165                    return Some((head, Self::rebuild_from_rights(tail, rights)));
166                }
167                AverListInner::Prepend { head, tail, .. } => {
168                    return Some((head, Self::rebuild_from_rights(tail.clone(), rights)));
169                }
170                AverListInner::Concat { left, right, .. } => {
171                    if left.is_empty() {
172                        current = right;
173                        continue;
174                    }
175                    rights.push(right.clone());
176                    current = left;
177                }
178            }
179        }
180    }
181
182    pub fn uncons_cloned(&self) -> Option<(T, Self)>
183    where
184        T: Clone,
185    {
186        match self.inner.as_ref() {
187            AverListInner::Flat { items, start } => {
188                let head = items.get(*start)?.clone();
189                let tail = Self::flat_tail(items, *start).unwrap_or_else(Self::empty);
190                Some((head, tail))
191            }
192            AverListInner::Prepend { head, tail, .. } => Some((head.clone(), tail.clone())),
193            AverListInner::Concat { .. } => {
194                let mut iter = self.iter();
195                let head = iter.next()?.clone();
196                let mut tail = Vec::with_capacity(self.len().saturating_sub(1));
197                tail.extend(iter.cloned());
198                Some((head, Self::from_vec(tail)))
199            }
200        }
201    }
202
203    pub fn empty() -> Self {
204        Self::from_vec(vec![])
205    }
206
207    pub fn from_vec(items: Vec<T>) -> Self {
208        Self {
209            inner: Rc::new(AverListInner::Flat {
210                items: Rc::new(items),
211                start: 0,
212            }),
213        }
214    }
215
216    pub fn len(&self) -> usize {
217        match self.inner.as_ref() {
218            AverListInner::Flat { items, start } => items.len().saturating_sub(*start),
219            AverListInner::Prepend { len, .. } | AverListInner::Concat { len, .. } => *len,
220        }
221    }
222
223    pub fn is_empty(&self) -> bool {
224        self.len() == 0
225    }
226
227    pub fn get(&self, index: usize) -> Option<&T> {
228        let mut current = self;
229        let mut remaining = index;
230
231        loop {
232            match current.inner.as_ref() {
233                AverListInner::Flat { items, start } => {
234                    return items.get(start.saturating_add(remaining));
235                }
236                AverListInner::Prepend { head, tail, .. } => {
237                    if remaining == 0 {
238                        return Some(head);
239                    }
240                    remaining -= 1;
241                    current = tail;
242                }
243                AverListInner::Concat { left, right, .. } => {
244                    let left_len = left.len();
245                    if remaining < left_len {
246                        current = left;
247                    } else {
248                        remaining -= left_len;
249                        current = right;
250                    }
251                }
252            }
253        }
254    }
255
256    pub fn first(&self) -> Option<&T> {
257        self.get(0)
258    }
259
260    pub fn as_slice(&self) -> Option<&[T]> {
261        match self.inner.as_ref() {
262            AverListInner::Flat { items, start } => Some(items.get(*start..).unwrap_or(&[])),
263            AverListInner::Prepend { .. } | AverListInner::Concat { .. } => None,
264        }
265    }
266
267    pub fn iter(&self) -> AverListIter<'_, T> {
268        AverListIter {
269            stack: vec![ListCursor::Node(self)],
270            remaining: self.len(),
271        }
272    }
273
274    pub fn tail(&self) -> Option<Self> {
275        match self.inner.as_ref() {
276            AverListInner::Flat { items, start } => Self::flat_tail(items, *start),
277            AverListInner::Prepend { tail, .. } => Some(tail.clone()),
278            AverListInner::Concat { .. } => self.uncons().map(|(_, tail)| tail),
279        }
280    }
281
282    pub fn prepend(item: T, list: &Self) -> Self {
283        if list.is_empty() {
284            return Self::from_vec(vec![item]);
285        }
286        Self {
287            inner: Rc::new(AverListInner::Prepend {
288                head: item,
289                tail: list.clone(),
290                len: list.len() + 1,
291            }),
292        }
293    }
294
295    pub fn concat(left: &Self, right: &Self) -> Self {
296        if left.is_empty() {
297            return right.clone();
298        }
299        if right.is_empty() {
300            return left.clone();
301        }
302        Self::concat_node(left, right)
303    }
304
305    pub fn append(list: &Self, item: T) -> Self {
306        Self::concat(list, &Self::from_vec(vec![item]))
307    }
308
309    pub fn to_vec(&self) -> Vec<T>
310    where
311        T: Clone,
312    {
313        let mut out = Vec::with_capacity(self.len());
314        out.extend(self.iter().cloned());
315        out
316    }
317
318    pub fn reverse(&self) -> Self
319    where
320        T: Clone,
321    {
322        let mut out = self.to_vec();
323        out.reverse();
324        Self::from_vec(out)
325    }
326
327    pub fn contains(&self, item: &T) -> bool
328    where
329        T: PartialEq,
330    {
331        self.iter().any(|x| x == item)
332    }
333}
334
335impl<'a, T> Iterator for AverListIter<'a, T> {
336    type Item = &'a T;
337
338    fn next(&mut self) -> Option<Self::Item> {
339        while let Some(cursor) = self.stack.pop() {
340            match cursor {
341                ListCursor::Slice(items, index) => {
342                    if let Some(item) = items.get(index) {
343                        self.stack.push(ListCursor::Slice(items, index + 1));
344                        self.remaining = self.remaining.saturating_sub(1);
345                        return Some(item);
346                    }
347                }
348                ListCursor::Node(list) => match list.inner.as_ref() {
349                    AverListInner::Flat { items, start } => {
350                        let slice = items.get(*start..).unwrap_or(&[]);
351                        if !slice.is_empty() {
352                            self.stack.push(ListCursor::Slice(slice, 0));
353                        }
354                    }
355                    AverListInner::Prepend { head, tail, .. } => {
356                        self.stack.push(ListCursor::Node(tail));
357                        self.remaining = self.remaining.saturating_sub(1);
358                        return Some(head);
359                    }
360                    AverListInner::Concat { left, right, .. } => {
361                        self.stack.push(ListCursor::Node(right));
362                        self.stack.push(ListCursor::Node(left));
363                    }
364                },
365            }
366        }
367        None
368    }
369
370    fn size_hint(&self) -> (usize, Option<usize>) {
371        (self.remaining, Some(self.remaining))
372    }
373}
374
375impl<T> ExactSizeIterator for AverListIter<'_, T> {
376    fn len(&self) -> usize {
377        self.remaining
378    }
379}
380
381impl<T> FusedIterator for AverListIter<'_, T> {}
382
383impl<'a, T> IntoIterator for &'a AverList<T> {
384    type Item = &'a T;
385    type IntoIter = AverListIter<'a, T>;
386
387    fn into_iter(self) -> Self::IntoIter {
388        self.iter()
389    }
390}
391
392impl<T: Clone> IntoIterator for AverList<T> {
393    type Item = T;
394    type IntoIter = std::vec::IntoIter<T>;
395
396    fn into_iter(self) -> Self::IntoIter {
397        self.to_vec().into_iter()
398    }
399}
400
401impl<T: fmt::Debug> fmt::Debug for AverList<T> {
402    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403        f.debug_list().entries(self.iter()).finish()
404    }
405}
406
407impl<T: PartialEq> PartialEq for AverList<T> {
408    fn eq(&self, other: &Self) -> bool {
409        self.len() == other.len() && self.iter().zip(other.iter()).all(|(a, b)| a == b)
410    }
411}
412
413impl<T: Eq> Eq for AverList<T> {}
414
415impl<T: Hash> Hash for AverList<T> {
416    fn hash<H: Hasher>(&self, state: &mut H) {
417        8u8.hash(state);
418        self.len().hash(state);
419        for item in self.iter() {
420            item.hash(state);
421        }
422    }
423}
424
425pub fn list_uncons<T>(list: &AverList<T>) -> Option<(&T, AverList<T>)> {
426    list.uncons()
427}
428
429pub fn list_uncons_cloned<T: Clone>(list: &AverList<T>) -> Option<(T, AverList<T>)> {
430    list.uncons_cloned()
431}
432
433pub fn string_join<S: AsRef<str>>(parts: &AverList<S>, sep: &str) -> String {
434    let mut iter = parts.iter();
435    let Some(first) = iter.next() else {
436        return String::new();
437    };
438    let mut out = first.as_ref().to_string();
439    for part in iter {
440        out.push_str(sep);
441        out.push_str(part.as_ref());
442    }
443    out
444}
445
446#[cfg(test)]
447mod tests {
448    use super::{AverList, aver_display, env_set, string_slice};
449
450    #[test]
451    fn prepend_and_tail_share_structure() {
452        let base = AverList::from_vec(vec![2, 3]);
453        let full = AverList::prepend(1, &base);
454        assert_eq!(full.first(), Some(&1));
455        assert_eq!(full.tail().unwrap(), base);
456    }
457
458    #[test]
459    fn concat_and_iter_preserve_order() {
460        let left = AverList::from_vec(vec![1, 2]);
461        let right = AverList::from_vec(vec![3, 4]);
462        let joined = AverList::concat(&left, &right);
463        assert_eq!(joined.to_vec(), vec![1, 2, 3, 4]);
464    }
465
466    #[test]
467    fn dropping_deep_prepend_chain_does_not_overflow() {
468        let mut list = AverList::empty();
469        for value in 0..200_000 {
470            list = AverList::prepend(value, &list);
471        }
472
473        assert_eq!(list.len(), 200_000);
474        drop(list);
475    }
476
477    #[test]
478    fn tail_of_deep_append_chain_does_not_overflow() {
479        let mut list = AverList::empty();
480        for value in 0..200_000 {
481            list = AverList::append(&list, value);
482        }
483
484        let tail = list.tail().expect("non-empty list must have a tail");
485        assert_eq!(tail.len(), 199_999);
486        assert_eq!(tail.first(), Some(&1));
487    }
488
489    #[test]
490    fn list_uncons_of_deep_append_chain_does_not_overflow() {
491        let mut list = AverList::empty();
492        for value in 0..200_000 {
493            list = AverList::append(&list, value);
494        }
495
496        let (head, tail) = super::list_uncons(&list).expect("non-empty list must uncons");
497        assert_eq!(*head, 0);
498        assert_eq!(tail.len(), 199_999);
499        assert_eq!(tail.first(), Some(&1));
500    }
501
502    #[test]
503    fn cloned_uncons_flattens_append_chain_tail() {
504        let mut list = AverList::empty();
505        for value in 0..5 {
506            list = AverList::append(&list, value);
507        }
508
509        let (head, tail) = super::list_uncons_cloned(&list).expect("non-empty list must uncons");
510        assert_eq!(head, 0);
511        assert_eq!(tail.as_slice(), Some(&[1, 2, 3, 4][..]));
512    }
513
514    #[test]
515    fn get_reads_flat_list_in_place() {
516        let list = AverList::from_vec(vec![10, 20, 30]);
517
518        assert_eq!(list.get(0), Some(&10));
519        assert_eq!(list.get(2), Some(&30));
520        assert_eq!(list.get(3), None);
521    }
522
523    #[test]
524    fn get_walks_concat_and_prepend_without_flattening() {
525        let base = AverList::from_vec(vec![2, 3]);
526        let prepended = AverList::prepend(1, &base);
527        let joined = AverList::concat(&prepended, &AverList::from_vec(vec![4, 5]));
528
529        assert_eq!(joined.get(0), Some(&1));
530        assert_eq!(joined.get(2), Some(&3));
531        assert_eq!(joined.get(4), Some(&5));
532        assert_eq!(joined.get(5), None);
533    }
534
535    #[test]
536    fn repeated_tail_over_append_chain_preserves_all_items() {
537        let mut list = AverList::empty();
538        for value in 0..6 {
539            list = AverList::append(&list, value);
540        }
541
542        let mut rest = list;
543        let mut seen = Vec::new();
544        while let Some((head, tail)) = super::list_uncons(&rest) {
545            seen.push(*head);
546            rest = tail;
547        }
548
549        assert_eq!(seen, vec![0, 1, 2, 3, 4, 5]);
550    }
551
552    #[test]
553    fn aver_display_quotes_strings_inside_lists() {
554        let parts = AverList::from_vec(vec!["a".to_string(), "b".to_string()]);
555        assert_eq!(aver_display(&parts), "[\"a\", \"b\"]");
556    }
557
558    #[test]
559    fn string_slice_uses_code_point_indices() {
560        assert_eq!(string_slice("zażółć", 1, 4), "ażó");
561    }
562
563    #[test]
564    fn string_slice_clamps_negative_indices() {
565        assert_eq!(string_slice("hello", -2, 2), "he");
566        assert_eq!(string_slice("hello", 1, -1), "");
567    }
568
569    #[test]
570    fn env_set_rejects_invalid_keys() {
571        assert_eq!(
572            env_set("", "x"),
573            Err("Env.set: key must not be empty".to_string())
574        );
575        assert_eq!(
576            env_set("A=B", "x"),
577            Err("Env.set: key must not contain '='".to_string())
578        );
579    }
580}