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 empty() -> Self {
183        Self::from_vec(vec![])
184    }
185
186    pub fn from_vec(items: Vec<T>) -> Self {
187        Self {
188            inner: Rc::new(AverListInner::Flat {
189                items: Rc::new(items),
190                start: 0,
191            }),
192        }
193    }
194
195    pub fn len(&self) -> usize {
196        match self.inner.as_ref() {
197            AverListInner::Flat { items, start } => items.len().saturating_sub(*start),
198            AverListInner::Prepend { len, .. } | AverListInner::Concat { len, .. } => *len,
199        }
200    }
201
202    pub fn is_empty(&self) -> bool {
203        self.len() == 0
204    }
205
206    pub fn get(&self, index: usize) -> Option<&T> {
207        self.iter().nth(index)
208    }
209
210    pub fn first(&self) -> Option<&T> {
211        self.iter().next()
212    }
213
214    pub fn as_slice(&self) -> Option<&[T]> {
215        match self.inner.as_ref() {
216            AverListInner::Flat { items, start } => Some(items.get(*start..).unwrap_or(&[])),
217            AverListInner::Prepend { .. } | AverListInner::Concat { .. } => None,
218        }
219    }
220
221    pub fn iter(&self) -> AverListIter<'_, T> {
222        AverListIter {
223            stack: vec![ListCursor::Node(self)],
224            remaining: self.len(),
225        }
226    }
227
228    pub fn tail(&self) -> Option<Self> {
229        match self.inner.as_ref() {
230            AverListInner::Flat { items, start } => Self::flat_tail(items, *start),
231            AverListInner::Prepend { tail, .. } => Some(tail.clone()),
232            AverListInner::Concat { .. } => self.uncons().map(|(_, tail)| tail),
233        }
234    }
235
236    pub fn prepend(item: T, list: &Self) -> Self {
237        if list.is_empty() {
238            return Self::from_vec(vec![item]);
239        }
240        Self {
241            inner: Rc::new(AverListInner::Prepend {
242                head: item,
243                tail: list.clone(),
244                len: list.len() + 1,
245            }),
246        }
247    }
248
249    pub fn concat(left: &Self, right: &Self) -> Self {
250        if left.is_empty() {
251            return right.clone();
252        }
253        if right.is_empty() {
254            return left.clone();
255        }
256        Self::concat_node(left, right)
257    }
258
259    pub fn append(list: &Self, item: T) -> Self {
260        Self::concat(list, &Self::from_vec(vec![item]))
261    }
262
263    pub fn to_vec(&self) -> Vec<T>
264    where
265        T: Clone,
266    {
267        let mut out = Vec::with_capacity(self.len());
268        out.extend(self.iter().cloned());
269        out
270    }
271
272    pub fn reverse(&self) -> Self
273    where
274        T: Clone,
275    {
276        let mut out = self.to_vec();
277        out.reverse();
278        Self::from_vec(out)
279    }
280
281    pub fn contains(&self, item: &T) -> bool
282    where
283        T: PartialEq,
284    {
285        self.iter().any(|x| x == item)
286    }
287}
288
289impl<'a, T> Iterator for AverListIter<'a, T> {
290    type Item = &'a T;
291
292    fn next(&mut self) -> Option<Self::Item> {
293        while let Some(cursor) = self.stack.pop() {
294            match cursor {
295                ListCursor::Slice(items, index) => {
296                    if let Some(item) = items.get(index) {
297                        self.stack.push(ListCursor::Slice(items, index + 1));
298                        self.remaining = self.remaining.saturating_sub(1);
299                        return Some(item);
300                    }
301                }
302                ListCursor::Node(list) => match list.inner.as_ref() {
303                    AverListInner::Flat { items, start } => {
304                        let slice = items.get(*start..).unwrap_or(&[]);
305                        if !slice.is_empty() {
306                            self.stack.push(ListCursor::Slice(slice, 0));
307                        }
308                    }
309                    AverListInner::Prepend { head, tail, .. } => {
310                        self.stack.push(ListCursor::Node(tail));
311                        self.remaining = self.remaining.saturating_sub(1);
312                        return Some(head);
313                    }
314                    AverListInner::Concat { left, right, .. } => {
315                        self.stack.push(ListCursor::Node(right));
316                        self.stack.push(ListCursor::Node(left));
317                    }
318                },
319            }
320        }
321        None
322    }
323
324    fn size_hint(&self) -> (usize, Option<usize>) {
325        (self.remaining, Some(self.remaining))
326    }
327}
328
329impl<T> ExactSizeIterator for AverListIter<'_, T> {
330    fn len(&self) -> usize {
331        self.remaining
332    }
333}
334
335impl<T> FusedIterator for AverListIter<'_, T> {}
336
337impl<'a, T> IntoIterator for &'a AverList<T> {
338    type Item = &'a T;
339    type IntoIter = AverListIter<'a, T>;
340
341    fn into_iter(self) -> Self::IntoIter {
342        self.iter()
343    }
344}
345
346impl<T: Clone> IntoIterator for AverList<T> {
347    type Item = T;
348    type IntoIter = std::vec::IntoIter<T>;
349
350    fn into_iter(self) -> Self::IntoIter {
351        self.to_vec().into_iter()
352    }
353}
354
355impl<T: fmt::Debug> fmt::Debug for AverList<T> {
356    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
357        f.debug_list().entries(self.iter()).finish()
358    }
359}
360
361impl<T: PartialEq> PartialEq for AverList<T> {
362    fn eq(&self, other: &Self) -> bool {
363        self.len() == other.len() && self.iter().zip(other.iter()).all(|(a, b)| a == b)
364    }
365}
366
367impl<T: Eq> Eq for AverList<T> {}
368
369impl<T: Hash> Hash for AverList<T> {
370    fn hash<H: Hasher>(&self, state: &mut H) {
371        8u8.hash(state);
372        self.len().hash(state);
373        for item in self.iter() {
374            item.hash(state);
375        }
376    }
377}
378
379pub fn list_uncons<T>(list: &AverList<T>) -> Option<(&T, AverList<T>)> {
380    list.uncons()
381}
382
383pub fn string_join<S: AsRef<str>>(parts: &AverList<S>, sep: &str) -> String {
384    let mut iter = parts.iter();
385    let Some(first) = iter.next() else {
386        return String::new();
387    };
388    let mut out = first.as_ref().to_string();
389    for part in iter {
390        out.push_str(sep);
391        out.push_str(part.as_ref());
392    }
393    out
394}
395
396#[cfg(test)]
397mod tests {
398    use super::{AverList, aver_display, env_set, string_slice};
399
400    #[test]
401    fn prepend_and_tail_share_structure() {
402        let base = AverList::from_vec(vec![2, 3]);
403        let full = AverList::prepend(1, &base);
404        assert_eq!(full.first(), Some(&1));
405        assert_eq!(full.tail().unwrap(), base);
406    }
407
408    #[test]
409    fn concat_and_iter_preserve_order() {
410        let left = AverList::from_vec(vec![1, 2]);
411        let right = AverList::from_vec(vec![3, 4]);
412        let joined = AverList::concat(&left, &right);
413        assert_eq!(joined.to_vec(), vec![1, 2, 3, 4]);
414    }
415
416    #[test]
417    fn dropping_deep_prepend_chain_does_not_overflow() {
418        let mut list = AverList::empty();
419        for value in 0..200_000 {
420            list = AverList::prepend(value, &list);
421        }
422
423        assert_eq!(list.len(), 200_000);
424        drop(list);
425    }
426
427    #[test]
428    fn tail_of_deep_append_chain_does_not_overflow() {
429        let mut list = AverList::empty();
430        for value in 0..200_000 {
431            list = AverList::append(&list, value);
432        }
433
434        let tail = list.tail().expect("non-empty list must have a tail");
435        assert_eq!(tail.len(), 199_999);
436        assert_eq!(tail.first(), Some(&1));
437    }
438
439    #[test]
440    fn list_uncons_of_deep_append_chain_does_not_overflow() {
441        let mut list = AverList::empty();
442        for value in 0..200_000 {
443            list = AverList::append(&list, value);
444        }
445
446        let (head, tail) = super::list_uncons(&list).expect("non-empty list must uncons");
447        assert_eq!(*head, 0);
448        assert_eq!(tail.len(), 199_999);
449        assert_eq!(tail.first(), Some(&1));
450    }
451
452    #[test]
453    fn repeated_tail_over_append_chain_preserves_all_items() {
454        let mut list = AverList::empty();
455        for value in 0..6 {
456            list = AverList::append(&list, value);
457        }
458
459        let mut rest = list;
460        let mut seen = Vec::new();
461        while let Some((head, tail)) = super::list_uncons(&rest) {
462            seen.push(*head);
463            rest = tail;
464        }
465
466        assert_eq!(seen, vec![0, 1, 2, 3, 4, 5]);
467    }
468
469    #[test]
470    fn aver_display_quotes_strings_inside_lists() {
471        let parts = AverList::from_vec(vec!["a".to_string(), "b".to_string()]);
472        assert_eq!(aver_display(&parts), "[\"a\", \"b\"]");
473    }
474
475    #[test]
476    fn string_slice_uses_code_point_indices() {
477        assert_eq!(string_slice("zażółć", 1, 4), "ażó");
478    }
479
480    #[test]
481    fn string_slice_clamps_negative_indices() {
482        assert_eq!(string_slice("hello", -2, 2), "he");
483        assert_eq!(string_slice("hello", 1, -1), "");
484    }
485
486    #[test]
487    fn env_set_rejects_invalid_keys() {
488        assert_eq!(
489            env_set("", "x"),
490            Err("Env.set: key must not be empty".to_string())
491        );
492        assert_eq!(
493            env_set("A=B", "x"),
494            Err("Env.set: key must not contain '='".to_string())
495        );
496    }
497}