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