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