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