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(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}