Skip to main content

hara_native/core/
operation.rs

1fn string_value<'a>(value: &'a Value, operation: &str) -> Result<&'a str, String> {
2    match value {
3        Value::String(value) => Ok(value),
4        _ => Err(format!("{operation} expects a string")),
5    }
6}
7
8fn code_point_length(text: &str) -> usize {
9    text.chars().count()
10}
11
12fn code_point_slice(text: &str, start: usize, end: usize) -> Result<String, String> {
13    let length = text.chars().count();
14    if start > end || end > length {
15        return Err("str/slice range is out of bounds".into());
16    }
17    Ok(text.chars().skip(start).take(end - start).collect())
18}
19
20fn code_point_char_at(text: &str, index: usize) -> Result<char, String> {
21    text.chars()
22        .nth(index)
23        .ok_or_else(|| "str/char-at index out of bounds".into())
24}
25
26fn code_point_byte_index(text: &str, code_point_offset: usize) -> usize {
27    text.char_indices()
28        .nth(code_point_offset)
29        .map(|(byte_index, _)| byte_index)
30        .unwrap_or(text.len())
31}
32
33fn code_point_index(text: &str, byte_index: usize) -> usize {
34    text[..byte_index.min(text.len())].chars().count()
35}
36
37fn code_point_index_of(text: &str, part: &str, offset: usize) -> i64 {
38    let byte_offset = code_point_byte_index(text, offset);
39    text[byte_offset..]
40        .find(part)
41        .map(|index| (code_point_index(text, byte_offset + index)) as i64)
42        .unwrap_or(-1)
43}
44
45fn code_point_last_index_of(text: &str, part: &str, offset: usize) -> i64 {
46    let len = code_point_length(text);
47    if part.is_empty() {
48        return (offset.min(len)) as i64;
49    }
50    let mut code_point_index = 0;
51    let mut last: Option<usize> = None;
52    for (byte_index, _) in text.char_indices() {
53        if code_point_index > offset && offset < len {
54            break;
55        }
56        if text[byte_index..].starts_with(part) {
57            last = Some(code_point_index);
58        }
59        code_point_index += 1;
60    }
61    last.map(|index| index as i64).unwrap_or(-1)
62}
63
64fn string_operation(operation: &str, values: Vec<Value>) -> Result<Value, String> {
65    let pair = |values: &[Value]| -> Result<(String, String), String> {
66        if values.len() != 2 {
67            return Err(format!("{operation} expects two strings"));
68        }
69        Ok((
70            string_value(&values[0], operation)?.to_owned(),
71            string_value(&values[1], operation)?.to_owned(),
72        ))
73    };
74    match operation {
75        "str/starts-with?" | "str/ends-with?" => {
76            let (text, part) = pair(&values)?;
77            Ok(Value::Bool(if operation == "str/starts-with?" {
78                text.starts_with(&part)
79            } else {
80                text.ends_with(&part)
81            }))
82        }
83        "str/includes?" => {
84            let (text, part) = pair(&values)?;
85            Ok(Value::Bool(text.contains(&part)))
86        }
87        "str/pad-left" | "str/pad-right" => {
88            if values.len() != 3 {
89                return Err(format!(
90                    "{operation} expects a string, length, and padding string"
91                ));
92            }
93            let text = string_value(&values[0], operation)?;
94            let length = value_index(&values[1])?;
95            let padding = string_value(&values[2], operation)?;
96            let text_length = code_point_length(text);
97            if padding.is_empty() || text_length >= length {
98                return Ok(Value::String(text.into()));
99            }
100            let needed = length - text_length;
101            let padding_chars: Vec<char> = padding.chars().collect();
102            let fill: String = padding_chars.iter().cycle().take(needed).copied().collect();
103            Ok(Value::String(if operation == "str/pad-left" {
104                format!("{fill}{text}")
105            } else {
106                format!("{text}{fill}")
107            }))
108        }
109        "str/char-at" => {
110            if values.len() != 2 {
111                return Err("str/char-at expects a string and index".into());
112            }
113            let text = string_value(&values[0], operation)?;
114            let index = value_index(&values[1])?;
115            code_point_char_at(text, index).map(Value::Character)
116        }
117        "str/split" => {
118            if values.len() != 2 {
119                return Err("str/split expects a string and string or regexp separator".into());
120            }
121            let text = string_value(&values[0], operation)?;
122            if text.is_empty() {
123                return Ok(Value::Nil);
124            }
125            let parts = match &values[1] {
126                Value::String(separator) => text
127                    .split(separator)
128                    .map(|part| Value::String(part.into()))
129                    .collect(),
130                Value::Regex(pattern) => {
131                    if pattern.is_empty() {
132                        return Ok(Value::Vector(PVector::from_iter(
133                            text.chars()
134                                .map(|character| Value::String(character.to_string())),
135                        )));
136                    }
137                    let mut parts: Vec<Value> = regex::Regex::new(pattern)
138                        .map_err(|error| format!("invalid regexp: {error}"))?
139                        .split(text)
140                        .map(|part| Value::String(part.into()))
141                        .collect();
142                    while matches!(parts.last(), Some(Value::String(value)) if value.is_empty()) {
143                        parts.pop();
144                    }
145                    parts
146                }
147                _ => return Err("str/split expects a string and string or regexp separator".into()),
148            };
149            Ok(Value::Vector(parts.into()))
150        }
151        "str/split-lines" => {
152            if values.len() != 1 {
153                return Err("str/split-lines expects one string".into());
154            }
155            let text = string_value(&values[0], operation)?;
156            let parts: Vec<Value> = text
157                .split('\n')
158                .map(|part| Value::String(part.into()))
159                .collect();
160            Ok(Value::Vector(parts.into()))
161        }
162        "str/join" => {
163            if values.len() != 2 {
164                return Err("str/join expects a separator and collection".into());
165            }
166            let separator = string_value(&values[0], operation)?;
167            let parts = iterator_values(values[1].clone())?
168                .into_iter()
169                .map(|value| match value {
170                    Value::String(value) => Ok(value),
171                    Value::Character(value) => Ok(value.to_string()),
172                    _ => Err("str/join expects a collection of strings or characters".into()),
173                })
174                .collect::<Result<Vec<String>, String>>()?;
175            Ok(Value::String(parts.join(separator)))
176        }
177        "str/index-of" => {
178            if values.len() != 2 && values.len() != 3 {
179                return Err("str/index-of expects a string, substring, and optional offset".into());
180            }
181            let text = string_value(&values[0], operation)?;
182            let part = string_value(&values[1], operation)?;
183            let offset = if values.len() == 3 {
184                value_index(&values[2])?
185            } else {
186                0
187            };
188            Ok(Value::Number(code_point_index_of(text, part, offset)))
189        }
190        "str/last-index-of" => {
191            if values.len() != 2 && values.len() != 3 {
192                return Err(
193                    "str/last-index-of expects a string, substring, and optional offset".into(),
194                );
195            }
196            let text = string_value(&values[0], operation)?;
197            let part = string_value(&values[1], operation)?;
198            let offset = if values.len() == 3 {
199                value_index(&values[2])?
200            } else {
201                code_point_length(text)
202            };
203            Ok(Value::Number(code_point_last_index_of(text, part, offset)))
204        }
205        "str/slice" => {
206            if values.len() != 2 && values.len() != 3 {
207                return Err("str/slice expects a string, start, and optional end".into());
208            }
209            let text = string_value(&values[0], operation)?;
210            let start = value_index(&values[1])?;
211            let end = if values.len() == 3 {
212                value_index(&values[2])?
213            } else {
214                code_point_length(text)
215            };
216            code_point_slice(text, start, end).map(Value::String)
217        }
218        "str/to-fixed" => {
219            if values.len() != 2 {
220                return Err("str/to-fixed expects a number and precision".into());
221            }
222            let number = numeric::to_f64_explicit(&values[0])
223                .map_err(|_| "str/to-fixed expects a number and precision".to_string())?;
224            let precision = value_index(&values[1])?;
225            if precision > 100 {
226                return Err("str/to-fixed precision must be in the range 0..100".into());
227            }
228            Ok(Value::String(format!("{number:.precision$}")))
229        }
230        "str/replace" => {
231            if values.len() != 3 {
232                return Err("str/replace expects a string, match, and replacement".into());
233            }
234            Ok(Value::String(string_value(&values[0], operation)?.replace(
235                string_value(&values[1], operation)?,
236                string_value(&values[2], operation)?,
237            )))
238        }
239        "str/replace-first" => {
240            if values.len() != 3 {
241                return Err("str/replace-first expects a string, match, and replacement".into());
242            }
243            let text = string_value(&values[0], operation)?;
244            let part = string_value(&values[1], operation)?;
245            let replacement = string_value(&values[2], operation)?;
246            Ok(Value::String(text.replacen(part, replacement, 1)))
247        }
248        "str/trim" | "str/trim-left" | "str/trim-right" => {
249            if values.len() != 1 {
250                return Err(format!("{operation} expects one string"));
251            }
252            let text = string_value(&values[0], operation)?;
253            Ok(Value::String(match operation {
254                "str/trim" => text.trim().into(),
255                "str/trim-left" => text.trim_start().into(),
256                _ => text.trim_end().into(),
257            }))
258        }
259        "str/length" => {
260            if values.len() != 1 {
261                return Err(format!("{operation} expects one string"));
262            }
263            let text = string_value(&values[0], operation)?;
264            Ok(Value::Number(code_point_length(text) as i64))
265        }
266        "str/blank?" => {
267            if values.len() != 1 {
268                return Err("str/blank? expects one string".into());
269            }
270            let text = string_value(&values[0], operation)?;
271            Ok(Value::Bool(text.trim().is_empty()))
272        }
273        "str/repeat" => {
274            if values.len() != 2 {
275                return Err("str/repeat expects a string and count".into());
276            }
277            let text = string_value(&values[0], operation)?;
278            let count = value_index(&values[1])?;
279            Ok(Value::String(text.repeat(count)))
280        }
281        "str/capitalize" => {
282            if values.len() != 1 {
283                return Err("str/capitalize expects one string".into());
284            }
285            let text = string_value(&values[0], operation)?;
286            let mut chars = text.chars();
287            match chars.next() {
288                Some(first) => Ok(Value::String(
289                    first.to_uppercase().collect::<String>() + chars.as_str(),
290                )),
291                None => Ok(Value::String(text.into())),
292            }
293        }
294        "str/decapitalize" => {
295            if values.len() != 1 {
296                return Err("str/decapitalize expects one string".into());
297            }
298            let text = string_value(&values[0], operation)?;
299            let mut chars = text.chars();
300            match chars.next() {
301                Some(first) => Ok(Value::String(
302                    first.to_lowercase().collect::<String>() + chars.as_str(),
303                )),
304                None => Ok(Value::String(text.into())),
305            }
306        }
307        "str/upper" => {
308            if values.len() != 1 {
309                return Err(format!("{operation} expects one string"));
310            }
311            let text = string_value(&values[0], operation)?;
312            Ok(Value::String(text.to_uppercase()))
313        }
314        "str/lower" => {
315            if values.len() != 1 {
316                return Err(format!("{operation} expects one string"));
317            }
318            let text = string_value(&values[0], operation)?;
319            Ok(Value::String(text.to_lowercase()))
320        }
321        "str/reverse" => {
322            if values.len() != 1 {
323                return Err("str/reverse expects one string".into());
324            }
325            let text = string_value(&values[0], operation)?;
326            Ok(Value::String(text.chars().rev().collect()))
327        }
328        "str/encode-utf8" => {
329            if values.len() != 1 {
330                return Err(format!("{operation} expects one string"));
331            }
332            match &values[0] {
333                Value::String(text) => Ok(Value::ByteBuffer(Rc::new(RefCell::new(
334                    text.as_bytes().to_vec(),
335                )))),
336                _ => Err(format!("{operation} expects a string")),
337            }
338        }
339        "str/decode-utf8" => {
340            if values.len() != 1 {
341                return Err(format!("{operation} expects bytes"));
342            }
343            let raw = byte_values(&values[0], operation)?;
344            String::from_utf8(raw)
345                .map(Value::String)
346                .map_err(|_| format!("{operation} invalid UTF-8"))
347        }
348        _ => Err(format!("unknown string operation: {operation}")),
349    }
350}
351fn marker_key(value: &Value, operation: &str) -> Result<String, String> {
352    match value {
353        Value::String(key) => Ok(key.clone()),
354        Value::Keyword(key) => Ok(key.as_str().to_owned()),
355        _ => Err(format!("{operation} expects a string key")),
356    }
357}
358
359fn native_mutable_values(operation: &str, values: Vec<Value>) -> Result<Value, String> {
360    let (type_name, method) = operation
361        .strip_prefix("std.native.")
362        .and_then(|name| name.split_once('/'))
363        .ok_or_else(|| format!("invalid native mutable operation: {operation}"))?;
364    if method == "new" {
365        return if type_name == "Arr" {
366            Ok(Value::Array(Rc::new(RefCell::new(values))))
367        } else {
368            if values.len() % 2 != 0 {
369                return Err("object expects key/value pairs".into());
370            }
371            let pairs = values
372                .chunks(2)
373                .map(|pair| Ok((marker_key(&pair[0], "object")?, pair[1].clone())))
374                .collect::<Result<Vec<_>, String>>()?;
375            Ok(Value::Object(Rc::new(RefCell::new(pairs))))
376        };
377    }
378    if values.is_empty() {
379        return Err(format!(
380            "std.native.{type_name}/{method} expects a receiver"
381        ));
382    }
383    let supported = native_declarations()
384        .iter()
385        .find(|declaration| declaration.name == type_name)
386        .is_some_and(|declaration| declaration.method(method));
387    if !supported {
388        return Err(format!("unknown std.native.{type_name} method: {method}"));
389    }
390    let receiver = values[0].clone();
391    let args = values[1..].to_vec();
392    marker_call_values(receiver, method, args)
393}
394
395fn dot_call(
396    receiver: Value,
397    method: &Form,
398    env: &mut HashMap<String, Value>,
399) -> Result<Value, String> {
400    let parts = match method {
401        Form::List(parts) if !parts.is_empty() => parts,
402        _ => return Err("dot call expects a method list".into()),
403    };
404    let name = match &parts[0] {
405        Form::Symbol(name) => name.as_str(),
406        _ => return Err("dot method must be a symbol".into()),
407    };
408    let args = parts[1..]
409        .iter()
410        .map(|form| eval(form, env))
411        .collect::<Result<Vec<_>, _>>()?;
412    dot_call_values(receiver, name, args)
413}
414
415pub(crate) fn dot_call_values(
416    receiver: Value,
417    name: &str,
418    args: Vec<Value>,
419) -> Result<Value, String> {
420    if matches!(receiver, Value::Array(_) | Value::Object(_)) {
421        return Err(
422            "dot calls do not support arrays or objects; use Arr/ or Obj/ functions".into(),
423        );
424    }
425    marker_call_values(receiver, name, args)
426}
427
428fn marker_call_values(receiver: Value, name: &str, args: Vec<Value>) -> Result<Value, String> {
429    match receiver {
430        Value::Array(array) => match name {
431            "get" => {
432                if args.len() < 1 || args.len() > 2 {
433                    return Err("array/get expects an index and optional default".into());
434                }
435                let index = value_index(&args[0])?;
436                Ok(array
437                    .borrow()
438                    .get(index)
439                    .cloned()
440                    .or_else(|| args.get(1).cloned())
441                    .unwrap_or(Value::Nil))
442            }
443            "set" => {
444                if args.len() != 2 {
445                    return Err("array/set expects an index and value".into());
446                }
447                let index = value_index(&args[0])?;
448                let mut values = array.borrow_mut();
449                if index >= values.len() {
450                    return Err("array/set index out of bounds".into());
451                }
452                values[index] = args[1].clone();
453                drop(values);
454                Ok(Value::Array(array))
455            }
456            "push-first" => {
457                if args.len() != 1 {
458                    return Err("array/push-first expects one value".into());
459                }
460                array.borrow_mut().insert(0, args[0].clone());
461                Ok(Value::Array(array))
462            }
463            "push-last" => {
464                if args.len() != 1 {
465                    return Err("array/push-last expects one value".into());
466                }
467                array.borrow_mut().push(args[0].clone());
468                Ok(Value::Array(array))
469            }
470            "pop-first" => {
471                if !args.is_empty() {
472                    return Err("array/pop-first expects no arguments".into());
473                }
474                let mut values = array.borrow_mut();
475                Ok(if values.is_empty() {
476                    Value::Nil
477                } else {
478                    values.remove(0)
479                })
480            }
481            "pop-last" => {
482                if !args.is_empty() {
483                    return Err("array/pop-last expects no arguments".into());
484                }
485                Ok(array.borrow_mut().pop().unwrap_or(Value::Nil))
486            }
487            "insert" => {
488                if args.len() != 2 {
489                    return Err("array/insert expects an index and value".into());
490                }
491                let index = value_index(&args[0])?;
492                let mut values = array.borrow_mut();
493                if index > values.len() {
494                    return Err("array/insert index out of bounds".into());
495                }
496                values.insert(index, args[1].clone());
497                drop(values);
498                Ok(Value::Array(array))
499            }
500            "remove" => {
501                if args.len() != 1 {
502                    return Err("array/remove expects an index".into());
503                }
504                let index = value_index(&args[0])?;
505                let mut values = array.borrow_mut();
506                if index >= values.len() {
507                    return Err("array/remove index out of bounds".into());
508                }
509                Ok(values.remove(index))
510            }
511            "clone" => {
512                if !args.is_empty() {
513                    return Err("array/clone expects no arguments".into());
514                }
515                Ok(Value::Array(Rc::new(RefCell::new(array.borrow().clone()))))
516            }
517            "slice" => {
518                if args.is_empty() || args.len() > 2 {
519                    return Err("array/slice expects start and optional end".into());
520                }
521                let start = value_index(&args[0])?;
522                let end = if args.len() == 2 {
523                    value_index(&args[1])?
524                } else {
525                    array.borrow().len()
526                };
527                let values = array.borrow();
528                if start > end || end > values.len() {
529                    return Err("array/slice range is out of bounds".into());
530                }
531                Ok(Value::Array(Rc::new(RefCell::new(
532                    values[start..end].to_vec(),
533                ))))
534            }
535            "map" | "filter" => {
536                if args.len() != 1 {
537                    return Err(format!("array/{name} expects one function"));
538                }
539                let function = match &args[0] {
540                    Value::Function(function) => function,
541                    _ => return Err(format!("array/{name} expects a function")),
542                };
543                let mut output = Vec::new();
544                for value in array.borrow().iter().cloned() {
545                    let mapped = call_function(function, vec![value.clone()])?;
546                    if name == "map" {
547                        output.push(mapped);
548                    } else if mapped.truthy() {
549                        output.push(value);
550                    }
551                }
552                Ok(Value::Array(Rc::new(RefCell::new(output))))
553            }
554            "fold-left" | "fold-right" => {
555                if args.len() != 2 {
556                    return Err(format!("array/{name} expects a function and initial value"));
557                }
558                let function = match &args[0] {
559                    Value::Function(function) => function,
560                    _ => return Err(format!("array/{name} expects a function")),
561                };
562                let values = array.borrow();
563                let mut output = args[1].clone();
564                if name == "fold-left" {
565                    for value in values.iter().cloned() {
566                        output = call_function(function, vec![output, value])?;
567                    }
568                } else {
569                    for value in values.iter().rev().cloned() {
570                        output = call_function(function, vec![value, output])?;
571                    }
572                }
573                Ok(output)
574            }
575            _ => Err(format!("unsupported array method: {name}")),
576        },
577        Value::Object(object) => match name {
578            "has?" => {
579                if args.len() != 1 {
580                    return Err("object/has? expects a key".into());
581                }
582                let key = marker_key(&args[0], "object/has?")?;
583                Ok(Value::Bool(
584                    object
585                        .borrow()
586                        .iter()
587                        .any(|(candidate, _)| candidate == &key),
588                ))
589            }
590            "get" => {
591                if args.len() < 1 || args.len() > 2 {
592                    return Err("object/get expects a key and optional default".into());
593                }
594                let key = marker_key(&args[0], "object/get")?;
595                Ok(object
596                    .borrow()
597                    .iter()
598                    .find(|(candidate, _)| candidate == &key)
599                    .map(|(_, value)| value.clone())
600                    .or_else(|| args.get(1).cloned())
601                    .unwrap_or(Value::Nil))
602            }
603            "set" => {
604                if args.len() != 2 {
605                    return Err("object/set expects a key and value".into());
606                }
607                let key = marker_key(&args[0], "object/set")?;
608                let mut values = object.borrow_mut();
609                if let Some((_, value)) = values.iter_mut().find(|(candidate, _)| candidate == &key)
610                {
611                    *value = args[1].clone();
612                } else {
613                    values.push((key, args[1].clone()));
614                }
615                drop(values);
616                Ok(Value::Object(object))
617            }
618            "delete" => {
619                if args.len() != 1 {
620                    return Err("object/delete expects a key".into());
621                }
622                let key = marker_key(&args[0], "object/delete")?;
623                let mut values = object.borrow_mut();
624                if let Some(index) = values.iter().position(|(candidate, _)| candidate == &key) {
625                    Ok(values.remove(index).1)
626                } else {
627                    Ok(Value::Nil)
628                }
629            }
630            "keys" | "vals" | "pairs" => {
631                if !args.is_empty() {
632                    return Err(format!("object/{name} expects no arguments"));
633                }
634                let output = object
635                    .borrow()
636                    .iter()
637                    .map(|(key, value)| match name {
638                        "keys" => Value::String(key.clone()),
639                        "vals" => value.clone(),
640                        _ => Value::Array(Rc::new(RefCell::new(vec![
641                            Value::String(key.clone()),
642                            value.clone(),
643                        ]))),
644                    })
645                    .collect();
646                Ok(Value::Array(Rc::new(RefCell::new(output))))
647            }
648            "assign" => {
649                if args.len() != 1 {
650                    return Err("object/assign expects an object".into());
651                }
652                let other = match &args[0] {
653                    Value::Object(other) => other.clone(),
654                    _ => return Err("object/assign expects an object".into()),
655                };
656                let mut values = object.borrow_mut();
657                for (key, value) in other.borrow().iter() {
658                    if let Some((_, existing)) =
659                        values.iter_mut().find(|(candidate, _)| candidate == key)
660                    {
661                        *existing = value.clone();
662                    } else {
663                        values.push((key.clone(), value.clone()));
664                    }
665                }
666                drop(values);
667                Ok(Value::Object(object))
668            }
669            "clone" => {
670                if !args.is_empty() {
671                    return Err("object/clone expects no arguments".into());
672                }
673                Ok(Value::Object(Rc::new(RefCell::new(
674                    object.borrow().clone(),
675                ))))
676            }
677            _ => Err(format!("unsupported object method: {name}")),
678        },
679        _ => Err("dot calls require an array or object marker".into()),
680    }
681}
682
683fn byte_input(value: &Value, operation: &str) -> Result<u8, String> {
684    match value {
685        Value::Number(number) if (-128..=255).contains(number) => Ok((*number as i8) as u8),
686        _ => Err(format!(
687            "{operation} expects a value in the range -128..255"
688        )),
689    }
690}
691
692fn byte_buffer(value: &Value, operation: &str) -> Result<Rc<RefCell<Vec<u8>>>, String> {
693    match value {
694        Value::ByteBuffer(bytes) => Ok(bytes.clone()),
695        _ => Err(format!("{operation} expects bytes")),
696    }
697}
698
699fn byte_values(value: &Value, operation: &str) -> Result<Vec<u8>, String> {
700    match value {
701        Value::Bytes(bytes) => Ok(bytes.clone()),
702        Value::ByteBuffer(bytes) => Ok(bytes.borrow().clone()),
703        _ => Err(format!("{operation} expects bytes")),
704    }
705}
706
707fn byte_count(value: &Value) -> Result<Value, String> {
708    match value {
709        Value::Bytes(bytes) => Ok(Value::Number(bytes.len() as i64)),
710        Value::ByteBuffer(bytes) => Ok(Value::Number(bytes.borrow().len() as i64)),
711        _ => Err("bytes/count expects bytes".into()),
712    }
713}
714
715fn byte_get(value: &Value, index: &Value, default: Option<Value>) -> Result<Value, String> {
716    let index = value_index(index)?;
717    let found = match value {
718        Value::Bytes(bytes) => bytes.get(index).copied(),
719        Value::ByteBuffer(bytes) => bytes.borrow().get(index).copied(),
720        _ => return Err("bytes/get expects bytes".into()),
721    };
722    match found {
723        Some(byte) => Ok(Value::Number(byte as i64)),
724        None => default.ok_or_else(|| "bytes/get index out of bounds".into()),
725    }
726}
727
728fn byte_copy(value: &Value) -> Result<Value, String> {
729    let bytes = byte_buffer(value, "bytes/copy")?;
730    let copied = bytes.borrow().clone();
731    Ok(Value::ByteBuffer(Rc::new(RefCell::new(copied))))
732}
733
734fn byte_slice(value: &Value, start: &Value, end: &Value) -> Result<Value, String> {
735    let start = value_index(start)?;
736    let end = value_index(end)?;
737    let bytes = byte_buffer(value, "bytes/slice")?;
738    let bytes = bytes.borrow();
739    if start > end || end > bytes.len() {
740        return Err(format!(
741            "bytes/slice range is out of bounds: {start}..{end}"
742        ));
743    }
744    Ok(Value::ByteBuffer(Rc::new(RefCell::new(
745        bytes[start..end].to_vec(),
746    ))))
747}
748
749fn byte_set(value: &Value, index: &Value, item: &Value) -> Result<Value, String> {
750    let index = value_index(index)?;
751    let item = byte_input(item, "bytes/set")?;
752    let bytes = byte_buffer(value, "bytes/set")?;
753    let mut bytes = bytes.borrow_mut();
754    if index >= bytes.len() {
755        return Err("bytes/set index out of bounds".into());
756    }
757    bytes[index] = item;
758    Ok(value.clone())
759}
760
761pub(crate) fn iterator_values(value: Value) -> Result<Vec<Value>, String> {
762    match value {
763        Value::Seq(values) => values.iter().collect::<Result<Vec<_>, _>>(),
764        Value::Extension(receiver) => {
765            let value = Value::Extension(receiver.clone());
766            let iterator = extension_protocol_call(
767                &receiver,
768                "std.protocol.iiter.IIter",
769                "iter",
770                std::slice::from_ref(&value),
771            )?;
772            iterator_values(iterator)
773        }
774        Value::Nil => Ok(Vec::new()),
775        Value::Tuple(values) => Ok(values.iter().cloned().collect()),
776        Value::Vector(values) => Ok(values.iter().cloned().collect()),
777        Value::MapEntry(entry) => Ok(entry.iter().cloned().collect()),
778        Value::List(values) => Ok(values.iter().cloned().collect()),
779        Value::Cons(values) => Ok(values.iter().collect()),
780        Value::Deque(values) => Ok(values.iter().cloned().collect()),
781        Value::Queue(values) => Ok(values.iter().cloned().collect()),
782        Value::PriorityMap(values) => Ok(values
783            .iter()
784            .map(|(key, value)| pair_value(key, value))
785            .collect()),
786        Value::String(text) => Ok(text.chars().map(Value::Character).collect()),
787        Value::Bytes(bytes) => Ok(bytes
788            .into_iter()
789            .map(|byte| Value::Number(byte as i8 as i64))
790            .collect()),
791        Value::ByteBuffer(bytes) => Ok(bytes
792            .borrow()
793            .iter()
794            .map(|byte| Value::Number(*byte as i8 as i64))
795            .collect()),
796        Value::Array(values) => Ok(values.borrow().clone()),
797        Value::Object(values) => Ok(values
798            .borrow()
799            .iter()
800            .map(|(key, value)| pair_value(Value::String(key.clone()), value.clone()))
801            .collect()),
802        Value::Struct(value) => Ok(value
803            .ordered_entries()
804            .into_iter()
805            .map(|(key, value)| pair_value(key, value))
806            .collect()),
807        Value::Mutable(value) => Ok(value
808            .ordered_entries()
809            .into_iter()
810            .map(|(key, value)| pair_value(key, value))
811            .collect()),
812        Value::MutableCollection(collection) => {
813            let borrowed = collection.borrow();
814            let collection = borrowed
815                .as_ref()
816                .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
817            match collection {
818                MutableCollection::Map(values) => Ok(values
819                    .iter()
820                    .map(|(key, value)| pair_value(key.clone(), value.clone()))
821                    .collect()),
822                MutableCollection::OrderedMap(values) => Ok(values
823                    .iter()
824                    .map(|(key, value)| pair_value(key.clone(), value.clone()))
825                    .collect()),
826                MutableCollection::SortedMap(values) => Ok(values
827                    .iter()
828                    .map(|(key, value)| pair_value(key.clone(), value.clone()))
829                    .collect()),
830                MutableCollection::Trie(values) => Ok(values
831                    .entries()
832                    .into_iter()
833                    .map(|(key, value)| pair_value(Value::String(key.clone()), value.clone()))
834                    .collect()),
835                MutableCollection::Set(values) => Ok(values.iter().cloned().collect()),
836                MutableCollection::OrderedSet(values) => Ok(values.iter().cloned().collect()),
837                MutableCollection::SortedSet(values) => Ok(values.iter().cloned().collect()),
838                MutableCollection::List(values) => Ok(values.iter().cloned().collect()),
839                MutableCollection::Queue(values) => Ok(values.iter().cloned().collect()),
840                MutableCollection::Vector(values) => Ok(values.iter().cloned().collect()),
841            }
842        }
843        Value::Pointer(pointer) => Ok(pointer
844            .fields()
845            .iter()
846            .map(|(key, value)| pair_value(key.clone(), value.clone()))
847            .collect()),
848        value @ (Value::Map(_) | Value::OrderedMap(_) | Value::SortedMap(_) | Value::Trie(_)) => {
849            Ok(map_entries(&value)
850                .unwrap()
851                .into_iter()
852                .map(|(key, value)| pair_value(key, value))
853                .collect())
854        }
855        value @ (Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_)) => {
856            Ok(set_items(&value).unwrap().into_iter().cloned().collect())
857        }
858        Value::Iterator(_) => {
859            let mut values = Vec::new();
860            while let Some(item) = iterator_try_next(&value)? {
861                values.push(item);
862            }
863            Ok(values)
864        }
865        value => Err(format!(
866            "iter expects a collection, got {}",
867            value.display()
868        )),
869    }
870}
871
872fn iterator_to_vec(value: Value) -> Result<Vec<Value>, String> {
873    iterator_values(value)
874}
875
876fn make_iterator(value: Value) -> Result<Value, String> {
877    match &value {
878        Value::Iterator(_) => Ok(value),
879        Value::Seq(sequence) => Ok(Value::Iterator(Rc::new(RefCell::new(
880            IteratorState::generated(IteratorGenerator::Seq((**sequence).clone())),
881        )))),
882        Value::Nil
883        | Value::String(_)
884        | Value::Bytes(_)
885        | Value::ByteBuffer(_)
886        | Value::Array(_)
887        | Value::Object(_)
888        | Value::Struct(_)
889        | Value::Mutable(_)
890        | Value::MutableCollection(_)
891        | Value::Map(_)
892        | Value::OrderedMap(_)
893        | Value::SortedMap(_)
894        | Value::Trie(_)
895        | Value::PriorityMap(_)
896        | Value::Pointer(_)
897        | Value::Set(_)
898        | Value::OrderedSet(_)
899        | Value::SortedSet(_)
900        | Value::List(_)
901        | Value::Cons(_)
902        | Value::Queue(_)
903        | Value::Deque(_)
904        | Value::Tuple(_)
905        | Value::MapEntry(_)
906        | Value::Vector(_) => Ok(Value::Iterator(Rc::new(RefCell::new(IteratorState::new(
907            iterator_values(value)?,
908        ))))),
909        _ => match protocol_call("std.protocol.iiter.IIter", "iter", &[value])? {
910            Value::Iterator(iterator) => Ok(Value::Iterator(iterator)),
911            _ => Err("IIter/iter must return an iterator".into()),
912        },
913    }
914}
915
916pub fn iterator_from_values(values: Vec<Value>) -> Value {
917    Value::Iterator(Rc::new(RefCell::new(IteratorState::new(values))))
918}
919
920fn iterator_seq(value: Value) -> Result<Value, String> {
921    if matches!(value, Value::Seq(_)) {
922        return Ok(value);
923    }
924    let source = make_iterator(value)?;
925    let sequence = PSeq::new(RuntimeSeqSource {
926        source,
927        finished: false,
928    });
929    match sequence.peek_first() {
930        None => Ok(Value::Nil),
931        Some(Ok(_)) => Ok(Value::Seq(Box::new(sequence))),
932        Some(Err(error)) => Err(error),
933    }
934}
935
936struct RuntimeSeqSource {
937    source: Value,
938    finished: bool,
939}
940
941impl Iterator for RuntimeSeqSource {
942    type Item = Result<Value, String>;
943
944    fn next(&mut self) -> Option<Self::Item> {
945        if self.finished {
946            return None;
947        }
948        match iterator_try_next(&self.source) {
949            Ok(Some(value)) => Some(Ok(value)),
950            Ok(None) => {
951                self.finished = true;
952                None
953            }
954            Err(error) => {
955                self.finished = true;
956                Some(Err(error))
957            }
958        }
959    }
960}
961
962fn iterator_constant(value: Value) -> Value {
963    Value::Iterator(Rc::new(RefCell::new(IteratorState::generated(
964        IteratorGenerator::Constant(value),
965    ))))
966}
967fn iterator_prepend(head: Value, source: Value) -> Result<Value, String> {
968    let source = match source {
969        Value::Iterator(iterator) => Value::Iterator(iterator),
970        value => make_iterator(value)?,
971    };
972    let state = IteratorState::generated(IteratorGenerator::Prepend(Some(head), source));
973    Ok(Value::Iterator(Rc::new(RefCell::new(state))))
974}
975fn iterator_repeated(function: Value) -> Value {
976    Value::Iterator(Rc::new(RefCell::new(IteratorState::generated(
977        IteratorGenerator::Repeated(function),
978    ))))
979}
980fn iterator_iterate(function: Value, seed: Value) -> Value {
981    Value::Iterator(Rc::new(RefCell::new(IteratorState::generated(
982        IteratorGenerator::Iterate(function, seed),
983    ))))
984}
985fn iterator_take_while(function: Value, value: Value) -> Result<Value, String> {
986    let source = match value {
987        Value::Iterator(iterator) => Value::Iterator(iterator),
988        value => make_iterator(value)?,
989    };
990    Ok(Value::Iterator(Rc::new(RefCell::new(
991        IteratorState::generated(IteratorGenerator::TakeWhile(function, source)),
992    ))))
993}
994fn iterator_map(function: Value, value: Value) -> Result<Value, String> {
995    iterator_map_with(function, value, false)
996}
997fn iterator_map_with(function: Value, value: Value, spread: bool) -> Result<Value, String> {
998    let source = match value {
999        Value::Iterator(iterator) => Value::Iterator(iterator),
1000        value => make_iterator(value)?,
1001    };
1002    Ok(Value::Iterator(Rc::new(RefCell::new(
1003        IteratorState::generated(IteratorGenerator::Map(function, source, spread)),
1004    ))))
1005}
1006fn iterator_partition(value: Value, amount: usize, all: bool) -> Result<Value, String> {
1007    if amount == 0 {
1008        return Err("partition amount must be positive".into());
1009    }
1010    let source = match value {
1011        Value::Iterator(iterator) => Value::Iterator(iterator),
1012        value => make_iterator(value)?,
1013    };
1014    Ok(Value::Iterator(Rc::new(RefCell::new(
1015        IteratorState::generated(IteratorGenerator::Partition(source, amount, all)),
1016    ))))
1017}
1018
1019fn iterator_interleave(values: Vec<Value>) -> Result<Value, String> {
1020    let sources = values
1021        .into_iter()
1022        .map(|value| match value {
1023            Value::Iterator(iterator) => Ok(Value::Iterator(iterator)),
1024            value => make_iterator(value),
1025        })
1026        .collect::<Result<Vec<_>, _>>()?;
1027    Ok(Value::Iterator(Rc::new(RefCell::new(
1028        IteratorState::generated(IteratorGenerator::Interleave(sources, 0)),
1029    ))))
1030}
1031
1032fn iterator_interpose(separator: Value, value: Value) -> Result<Value, String> {
1033    let source = match value {
1034        Value::Iterator(iterator) => Value::Iterator(iterator),
1035        value => make_iterator(value)?,
1036    };
1037    Ok(Value::Iterator(Rc::new(RefCell::new(
1038        IteratorState::generated(IteratorGenerator::Interpose(source, separator, true, None)),
1039    ))))
1040}
1041
1042fn iterator_concat(values: Vec<Value>) -> Result<Value, String> {
1043    let sources = values
1044        .into_iter()
1045        .map(|value| match value {
1046            Value::Iterator(iterator) => Ok(Value::Iterator(iterator)),
1047            value => make_iterator(value),
1048        })
1049        .collect::<Result<Vec<_>, _>>()?;
1050    Ok(Value::Iterator(Rc::new(RefCell::new(
1051        IteratorState::generated(IteratorGenerator::Concat(sources, 0)),
1052    ))))
1053}
1054
1055fn iterator_zip(values: Vec<Value>) -> Result<Value, String> {
1056    let sources = values
1057        .into_iter()
1058        .map(|value| match value {
1059            Value::Iterator(iterator) => Ok(Value::Iterator(iterator)),
1060            value => make_iterator(value),
1061        })
1062        .collect::<Result<Vec<_>, _>>()?;
1063    Ok(Value::Iterator(Rc::new(RefCell::new(
1064        IteratorState::generated(IteratorGenerator::Zip(sources)),
1065    ))))
1066}
1067
1068fn iterator_mapcat(function: Value, value: Value) -> Result<Value, String> {
1069    let source = match value {
1070        Value::Iterator(iterator) => Value::Iterator(iterator),
1071        value => make_iterator(value)?,
1072    };
1073    Ok(Value::Iterator(Rc::new(RefCell::new(
1074        IteratorState::generated(IteratorGenerator::Mapcat(function, source, None)),
1075    ))))
1076}
1077fn iterator_keep(function: Value, value: Value) -> Result<Value, String> {
1078    let source = match value {
1079        Value::Iterator(iterator) => Value::Iterator(iterator),
1080        value => make_iterator(value)?,
1081    };
1082    Ok(Value::Iterator(Rc::new(RefCell::new(
1083        IteratorState::generated(IteratorGenerator::Keep(function, source)),
1084    ))))
1085}
1086
1087fn iterator_filter(function: Value, value: Value) -> Result<Value, String> {
1088    let source = match value {
1089        Value::Iterator(iterator) => Value::Iterator(iterator),
1090        value => make_iterator(value)?,
1091    };
1092    Ok(Value::Iterator(Rc::new(RefCell::new(
1093        IteratorState::generated(IteratorGenerator::Filter(function, source)),
1094    ))))
1095}
1096
1097fn iterator_drop_while(function: Value, value: Value) -> Result<Value, String> {
1098    let source = match value {
1099        Value::Iterator(iterator) => Value::Iterator(iterator),
1100        value => make_iterator(value)?,
1101    };
1102    Ok(Value::Iterator(Rc::new(RefCell::new(
1103        IteratorState::generated(IteratorGenerator::DropWhile(function, source, false)),
1104    ))))
1105}
1106fn iterator_take(value: Value, amount: usize) -> Result<Value, String> {
1107    let source = match value {
1108        Value::Iterator(iterator) => Value::Iterator(iterator),
1109        value => make_iterator(value)?,
1110    };
1111    Ok(Value::Iterator(Rc::new(RefCell::new(
1112        IteratorState::generated(IteratorGenerator::Take(source, amount)),
1113    ))))
1114}
1115fn iterator_drop(value: Value, amount: usize) -> Result<Value, String> {
1116    let source = match value {
1117        Value::Iterator(iterator) => Value::Iterator(iterator),
1118        value => make_iterator(value)?,
1119    };
1120    Ok(Value::Iterator(Rc::new(RefCell::new(
1121        IteratorState::generated(IteratorGenerator::Drop(source, amount)),
1122    ))))
1123}
1124
1125fn iterator_cycle(value: Value) -> Result<Value, String> {
1126    let source = match value {
1127        Value::Iterator(iterator) => Value::Iterator(iterator),
1128        value => make_iterator(value)?,
1129    };
1130    if !matches!(iterator_has_next(&source)?, Value::Bool(true)) {
1131        return Err("cycle expects a non-empty source".into());
1132    }
1133    Ok(Value::Iterator(Rc::new(RefCell::new(
1134        IteratorState::generated(IteratorGenerator::Cycle(source, Vec::new(), 0, false)),
1135    ))))
1136}
1137
1138fn iterator_has_next(value: &Value) -> Result<Value, String> {
1139    match value {
1140        Value::Iterator(iterator) => Ok(Value::Bool(iterator.borrow_mut().has_next()?)),
1141        _ => Err("iter-next? expects an iterator".into()),
1142    }
1143}
1144
1145fn iterator_try_next(value: &Value) -> Result<Option<Value>, String> {
1146    match value {
1147        Value::Iterator(iterator) => iterator.borrow_mut().try_next(),
1148        _ => Err("iter-next expects an iterator".into()),
1149    }
1150}
1151
1152fn iterator_next(value: &Value) -> Result<Value, String> {
1153    iterator_try_next(value)?.ok_or_else(|| "iter-next reached the end of the iterator".into())
1154}
1155
1156fn iterator_close(value: &Value) -> Result<Value, String> {
1157    match value {
1158        Value::Iterator(iterator) => {
1159            iterator.borrow_mut().close();
1160            Ok(Value::Nil)
1161        }
1162        _ => Err("iter-close expects an iterator".into()),
1163    }
1164}
1165
1166fn collection_first(value: Value) -> Result<Value, String> {
1167    match value {
1168        Value::Seq(sequence) => sequence
1169            .peek_first()
1170            .transpose()?
1171            .ok_or_else(|| "invalid empty Seq value".to_string()),
1172        Value::Iterator(iterator) => Ok(iterator.borrow_mut().try_next()?.unwrap_or(Value::Nil)),
1173        value => Ok(iterator_values(value)?
1174            .into_iter()
1175            .next()
1176            .unwrap_or(Value::Nil)),
1177    }
1178}
1179
1180fn collection_rest(value: Value) -> Result<Value, String> {
1181    if let Value::Seq(sequence) = value {
1182        let tail = sequence.pop_first();
1183        return match tail.peek_first() {
1184            None => Ok(Value::Nil),
1185            Some(Ok(_)) => Ok(Value::Seq(Box::new(tail))),
1186            Some(Err(error)) => Err(error),
1187        };
1188    }
1189    let source = match value {
1190        Value::Iterator(iterator) => Value::Iterator(iterator),
1191        value => make_iterator(value)?,
1192    };
1193    if iterator_try_next(&source)?.is_none() {
1194        return Ok(Value::Nil);
1195    }
1196    iterator_seq(source)
1197}
1198
1199fn collection_last(value: Value) -> Result<Value, String> {
1200    Ok(iterator_to_vec(value)?
1201        .into_iter()
1202        .last()
1203        .unwrap_or(Value::Nil))
1204}
1205
1206fn collection_empty_value(value: Value) -> Result<Value, String> {
1207    match value {
1208        Value::Extension(receiver) => extension_protocol_call(
1209            &receiver,
1210            "std.protocol.iempty.IEmpty",
1211            "empty",
1212            &[Value::Extension(receiver.clone())],
1213        ),
1214        Value::Nil => Ok(Value::Nil),
1215        Value::Array(_) => Ok(Value::Array(Rc::new(RefCell::new(Vec::new())))),
1216        Value::Object(_) => Ok(Value::Object(Rc::new(RefCell::new(Vec::new())))),
1217        Value::List(values) => Ok(Value::List(values.empty())),
1218        Value::Cons(values) => Ok(Value::List(PList::new().with_meta(values.meta().cloned()))),
1219        Value::Queue(values) => Ok(Value::Queue(Box::new(values.empty()))),
1220        Value::Deque(values) => Ok(Value::Deque(Box::new(values.empty()))),
1221        Value::Vector(values) => Ok(Value::Vector(values.empty())),
1222        Value::Tuple(values) => Ok(Value::Tuple(Box::new(values.empty()))),
1223        Value::Seq(values) => Ok(Value::Tuple(Box::new(
1224            PTuple::Tup0.with_meta(values.meta().cloned()),
1225        ))),
1226        Value::Map(values) => Ok(Value::Map(values.empty())),
1227        Value::OrderedMap(values) => Ok(Value::OrderedMap(Box::new(values.empty()))),
1228        Value::SortedMap(values) => Ok(Value::SortedMap(Box::new(values.empty()))),
1229        Value::Trie(values) => Ok(Value::Trie(Box::new(values.empty()))),
1230        Value::PriorityMap(values) => Ok(Value::PriorityMap(Box::new(values.empty()))),
1231        Value::Set(values) => Ok(Value::Set(values.empty())),
1232        Value::OrderedSet(values) => Ok(Value::OrderedSet(Box::new(values.empty()))),
1233        Value::SortedSet(values) => Ok(Value::SortedSet(Box::new(values.empty()))),
1234        Value::Struct(value) => Ok(Value::Struct(Rc::new(StructValue::from_values(
1235            value.ty.clone(),
1236            vec![Value::Nil; value.ty.fields.len()],
1237            value.metadata.clone(),
1238        )?))),
1239        Value::Mutable(_) => Err("empty does not support mutable values".into()),
1240        value => Err(format!(
1241            "empty expects a collection, got {}",
1242            portable_type_name(&value)
1243        )),
1244    }
1245}
1246
1247fn collection_count(value: &Value) -> Result<Value, String> {
1248    if let Value::Extension(receiver) = value {
1249        return extension_protocol_call(
1250            receiver,
1251            "std.protocol.icount.ICount",
1252            "count",
1253            std::slice::from_ref(value),
1254        );
1255    }
1256    let count = match value {
1257        Value::Nil => 0,
1258        Value::String(v) => v.chars().count(),
1259        Value::Tuple(v) => v.len(),
1260        Value::Vector(v) => v.len(),
1261        Value::MapEntry(_) => 2,
1262        Value::List(v) => v.len(),
1263        Value::Cons(v) => v.iter().count(),
1264        Value::Queue(v) => v.len(),
1265        Value::Deque(v) => v.len(),
1266        value @ (Value::Map(_)
1267        | Value::OrderedMap(_)
1268        | Value::SortedMap(_)
1269        | Value::Trie(_)
1270        | Value::PriorityMap(_)) => map_entries(value).unwrap().len(),
1271        value @ (Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_)) => {
1272            set_items(value).unwrap().len()
1273        }
1274        Value::Bytes(v) => v.len(),
1275        Value::ByteBuffer(v) => v.borrow().len(),
1276        Value::Array(v) => v.borrow().len(),
1277        Value::Object(v) => v.borrow().len(),
1278        Value::Struct(v) => v.ty.fields.len(),
1279        Value::Mutable(v) => v.ty.fields.len(),
1280        Value::Pointer(v) => v.fields().len(),
1281        Value::MutableCollection(collection) => {
1282            let borrowed = collection.borrow();
1283            let mutable = borrowed
1284                .as_ref()
1285                .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
1286            match mutable {
1287                MutableCollection::Map(values) => values.len(),
1288                MutableCollection::OrderedMap(values) => values.len(),
1289                MutableCollection::SortedMap(values) => values.len(),
1290                MutableCollection::Trie(values) => values.len(),
1291                MutableCollection::Set(values) => values.len(),
1292                MutableCollection::OrderedSet(values) => values.len(),
1293                MutableCollection::SortedSet(values) => values.len(),
1294                MutableCollection::List(values) => values.len(),
1295                MutableCollection::Queue(values) => values.len(),
1296                MutableCollection::Vector(values) => values.len(),
1297            }
1298        }
1299        Value::Seq(sequence) => {
1300            let mut count = 0;
1301            for value in sequence.iter() {
1302                value?;
1303                count += 1;
1304            }
1305            count
1306        }
1307        Value::Iterator(_) => {
1308            let mut count = 0;
1309            while iterator_try_next(value)?.is_some() {
1310                count += 1;
1311            }
1312            count
1313        }
1314        _ => return Err("count expects a collection".into()),
1315    };
1316    Ok(Value::Number(count as i64))
1317}
1318
1319fn iterator_is_finite(value: &Value) -> bool {
1320    match value {
1321        Value::Iterator(iterator) => iterator.borrow().is_finite(),
1322        Value::Seq(_) => false,
1323        _ => true,
1324    }
1325}
1326
1327fn collection_get(value: &Value, key: &Value, default: Value) -> Result<Value, String> {
1328    match value {
1329        Value::Extension(receiver) => extension_protocol_call(
1330            receiver,
1331            "std.protocol.ilookup.ILookup",
1332            "lookup",
1333            &[value.clone(), key.clone(), default],
1334        ),
1335        Value::Nil | Value::Seq(_) => Ok(default),
1336        Value::Tuple(values) => {
1337            let index = value_index(key)?;
1338            Ok(values.get(index).cloned().unwrap_or(default))
1339        }
1340        Value::Vector(values) => {
1341            let index = value_index(key)?;
1342            Ok(values.get(index).cloned().unwrap_or(default))
1343        }
1344        Value::MapEntry(entry) => {
1345            let index = value_index(key)?;
1346            Ok(entry.nth(index).cloned().unwrap_or(default))
1347        }
1348        Value::Array(values) => {
1349            let index = value_index(key)?;
1350            Ok(values.borrow().get(index).cloned().unwrap_or(default))
1351        }
1352        Value::Cons(values) => {
1353            let index = value_index(key)?;
1354            Ok(values.iter().nth(index).unwrap_or(default))
1355        }
1356        Value::List(values) => {
1357            let index = value_index(key)?;
1358            Ok(values.get(index).cloned().unwrap_or(default))
1359        }
1360        Value::Queue(values) => {
1361            let index = value_index(key)?;
1362            Ok(values.get(index).cloned().unwrap_or(default))
1363        }
1364        Value::Deque(values) => {
1365            let index = value_index(key)?;
1366            Ok(values.get(index).cloned().unwrap_or(default))
1367        }
1368        Value::MutableCollection(collection) => {
1369            let borrowed = collection.borrow();
1370            let mutable = borrowed
1371                .as_ref()
1372                .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
1373            let found = match mutable {
1374                MutableCollection::Map(values) => values.get(key).cloned(),
1375                MutableCollection::OrderedMap(values) => values.get(key).cloned(),
1376                MutableCollection::SortedMap(values) => values.get(key).cloned(),
1377                MutableCollection::Trie(values) => values.get(&marker_key(key, "trie")?).cloned(),
1378                MutableCollection::Set(values) => values.get(key).cloned(),
1379                MutableCollection::OrderedSet(values) => values.get(key).cloned(),
1380                MutableCollection::SortedSet(values) => values.get(key).cloned(),
1381                MutableCollection::List(values) => values.get(value_index(key)?).cloned(),
1382                MutableCollection::Queue(values) => values.get(value_index(key)?).cloned(),
1383                MutableCollection::Vector(values) => values.get(value_index(key)?).cloned(),
1384            };
1385            Ok(found.unwrap_or(default))
1386        }
1387        Value::Bytes(_) | Value::ByteBuffer(_) => byte_get(value, key, Some(default)),
1388        Value::String(text) => {
1389            let index = value_index(key)?;
1390            Ok(text
1391                .chars()
1392                .nth(index)
1393                .map(Value::Character)
1394                .unwrap_or(default))
1395        }
1396        value @ (Value::Map(_)
1397        | Value::OrderedMap(_)
1398        | Value::SortedMap(_)
1399        | Value::Trie(_)
1400        | Value::PriorityMap(_)) => Ok(map_value(value, key).cloned().unwrap_or(default)),
1401        value @ (Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_)) => {
1402            Ok(set_find(value, key).unwrap_or(default))
1403        }
1404        Value::Object(entries) => {
1405            let name = match key {
1406                Value::String(name) => name.as_str(),
1407                Value::Keyword(name) => name.as_str(),
1408                _ => return Ok(default),
1409            };
1410            Ok(entries
1411                .borrow()
1412                .iter()
1413                .find(|(candidate, _)| candidate == name)
1414                .map(|(_, value)| value.clone())
1415                .unwrap_or(default))
1416        }
1417        Value::Struct(value) => Ok(named_field_name(key)
1418            .and_then(|name| value.get(name))
1419            .cloned()
1420            .unwrap_or(default)),
1421        Value::Mutable(value) => Ok(named_field_name(key)
1422            .and_then(|name| value.get(name))
1423            .unwrap_or(default)),
1424        Value::Pointer(pointer) => Ok(pointer.get(key).cloned().unwrap_or(default)),
1425        Value::Result(result) => {
1426            let Value::Keyword(key) = key else {
1427                return Ok(default);
1428            };
1429            Ok(match key.as_str() {
1430                "status" => result.status_value(),
1431                "data" => result.data.clone(),
1432                "error" => result.error_value(),
1433                "context" => {
1434                    if map_entries(&result.context).is_some_and(|entries| entries.is_empty()) {
1435                        Value::Nil
1436                    } else {
1437                        result.context.clone()
1438                    }
1439                }
1440                _ => default,
1441            })
1442        }
1443        value => Err(format!(
1444            "get expects a collection, received {}",
1445            portable_type_name(value)
1446        )),
1447    }
1448}
1449
1450fn collection_nth(value: &Value, key: &Value) -> Result<Value, String> {
1451    let index = value_index(key)?;
1452    if let Value::Iterator(iterator) = value {
1453        let mut state = iterator.borrow_mut();
1454        for _ in 0..index {
1455            if state.try_next()?.is_none() {
1456                return Err("nth index out of bounds".into());
1457            }
1458        }
1459        return state
1460            .try_next()?
1461            .ok_or_else(|| "nth index out of bounds".into());
1462    }
1463    let result = match value {
1464        Value::Tuple(values) => values.get(index).cloned(),
1465        Value::Vector(values) => values.get(index).cloned(),
1466        Value::MapEntry(entry) => entry.nth(index).cloned(),
1467        Value::Array(values) => values.borrow().get(index).cloned(),
1468        Value::Cons(values) => values.iter().nth(index),
1469        Value::List(values) => values.get(index).cloned(),
1470        Value::Queue(values) => values.get(index).cloned(),
1471        Value::Deque(values) => values.get(index).cloned(),
1472        Value::MutableCollection(collection) => {
1473            let borrowed = collection.borrow();
1474            let mutable = borrowed
1475                .as_ref()
1476                .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
1477            match mutable {
1478                MutableCollection::List(values) => values.get(index).cloned(),
1479                MutableCollection::Queue(values) => values.get(index).cloned(),
1480                MutableCollection::Vector(values) => values.get(index).cloned(),
1481                _ => return Err("nth expects an indexed collection".into()),
1482            }
1483        }
1484        Value::String(text) => text
1485            .chars()
1486            .nth(index)
1487            .map(Value::Character),
1488        _ => return Err("nth expects an indexed collection".into()),
1489    };
1490    result.ok_or_else(|| "nth index out of bounds".into())
1491}
1492
1493fn collection_assoc(value: &Value, key: &Value, replacement: Value) -> Result<Value, String> {
1494    match value {
1495        Value::Extension(receiver) => extension_protocol_call(
1496            receiver,
1497            "std.protocol.iassoc.IAssoc",
1498            "assoc",
1499            &[value.clone(), key.clone(), replacement],
1500        ),
1501        Value::MutableCollection(collection) => {
1502            let mut borrowed = collection.borrow_mut();
1503            let mutable = borrowed
1504                .as_mut()
1505                .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
1506            match mutable {
1507                MutableCollection::Map(values) => {
1508                    values.assoc(key.clone(), replacement);
1509                }
1510                MutableCollection::OrderedMap(values) => {
1511                    values.assoc(key.clone(), replacement);
1512                }
1513                MutableCollection::SortedMap(values) => {
1514                    values.assoc(key.clone(), replacement);
1515                }
1516                MutableCollection::Trie(values) => {
1517                    values.assoc(marker_key(key, "trie")?, replacement);
1518                }
1519                MutableCollection::Vector(values) => {
1520                    values.assoc(value_index(key)?, replacement);
1521                }
1522                MutableCollection::List(values) => {
1523                    values
1524                        .assoc(value_index(key)?, replacement)
1525                        .ok_or_else(|| "assoc index out of bounds".to_string())?;
1526                }
1527                _ => return Err("assoc expects a mutable map, vector, or list".into()),
1528            }
1529            Ok(Value::MutableCollection(collection.clone()))
1530        }
1531        Value::Tuple(values) => {
1532            let index = value_index(key)?;
1533            if index == values.len() {
1534                return tuple_push_last(values, replacement);
1535            }
1536            if index > values.len() {
1537                return Err("assoc index out of bounds".into());
1538            }
1539            let mut items: Vec<Value> = values.iter().cloned().collect();
1540            items[index] = replacement;
1541            Ok(Value::Tuple(Box::new(
1542                PTuple::from_values(items)?.with_meta(values.meta().cloned()),
1543            )))
1544        }
1545        Value::Vector(values) => {
1546            let index = value_index(key)?;
1547            values
1548                .assoc_value(index, replacement)
1549                .map(Value::Vector)
1550                .ok_or_else(|| "assoc index out of bounds".into())
1551        }
1552        Value::Deque(values) => values
1553            .assoc_value(value_index(key)?, replacement)
1554            .map(|values| Value::Deque(Box::new(values)))
1555            .ok_or_else(|| "assoc index out of bounds".to_string()),
1556        value @ (Value::Map(_)
1557        | Value::OrderedMap(_)
1558        | Value::SortedMap(_)
1559        | Value::Trie(_)
1560        | Value::PriorityMap(_)) => map_assoc_value(value, key.clone(), replacement),
1561        Value::Object(entries) => {
1562            let name = marker_key(key, "object")?;
1563            let mut output = entries.borrow().clone();
1564            if let Some((_, item)) = output.iter_mut().find(|(candidate, _)| candidate == &name) {
1565                *item = replacement;
1566            } else {
1567                output.push((name, replacement));
1568            }
1569            Ok(Value::Object(Rc::new(RefCell::new(output))))
1570        }
1571        Value::Struct(value) => {
1572            let name = named_field_name(key).ok_or_else(|| {
1573                "assoc struct field must be an unqualified string, keyword, or symbol".to_string()
1574            })?;
1575            if !value.ty.fields.iter().any(|candidate| candidate == name) {
1576                return Err(format!("unknown struct field: {name}"));
1577            }
1578            Ok(Value::Struct(Rc::new(StructValue {
1579                ty: value.ty.clone(),
1580                values: value.values.assoc_value(named_field_key(name), replacement),
1581                metadata: value.metadata.clone(),
1582            })))
1583        }
1584        Value::Mutable(_) => Err("assoc does not support mutable values".into()),
1585        Value::Nil => Ok(Value::Map(
1586            PMap::new().assoc_value(key.clone(), replacement),
1587        )),
1588        _ => Err("assoc expects a vector, map, object, or struct".into()),
1589    }
1590}
1591
1592fn collection_dissoc(value: &Value, keys: &[Value]) -> Result<Value, String> {
1593    match value {
1594        Value::Extension(_) => keys.iter().try_fold(value.clone(), |current, key| {
1595            let Value::Extension(receiver) = &current else {
1596                return collection_dissoc(&current, std::slice::from_ref(key));
1597            };
1598            extension_protocol_call(
1599                receiver,
1600                "std.protocol.idissoc.IDissoc",
1601                "dissoc",
1602                &[current.clone(), key.clone()],
1603            )
1604        }),
1605        Value::Mutable(_) => Err("dissoc does not support mutable values".into()),
1606        Value::Struct(value) => {
1607            let declared = keys
1608                .iter()
1609                .filter_map(named_field_name)
1610                .any(|name| value.ty.fields.iter().any(|candidate| candidate == name));
1611            if !declared {
1612                return Ok(Value::Struct(value.clone()));
1613            }
1614            let mut values = value.values.with_meta(value.metadata.clone());
1615            for key in keys {
1616                if let Some(name) = named_field_name(key) {
1617                    values = values.dissoc_value(&named_field_key(name));
1618                }
1619            }
1620            Ok(Value::OrderedMap(Box::new(values)))
1621        }
1622        Value::MutableCollection(collection) => {
1623            let mut collection_value = collection.borrow_mut();
1624            let mutable = collection_value
1625                .as_mut()
1626                .ok_or_else(|| "mutable collection used after to-persistent".to_string())?;
1627            for key in keys {
1628                match &mut *mutable {
1629                    MutableCollection::Map(values) => {
1630                        values.dissoc(key);
1631                    }
1632                    MutableCollection::OrderedMap(values) => {
1633                        values.dissoc(key);
1634                    }
1635                    MutableCollection::SortedMap(values) => {
1636                        values.dissoc(key);
1637                    }
1638                    MutableCollection::Trie(values) => {
1639                        values.dissoc(&marker_key(key, "trie")?);
1640                    }
1641                    MutableCollection::Set(values) => {
1642                        values.dissoc(key);
1643                    }
1644                    MutableCollection::OrderedSet(values) => {
1645                        values.dissoc(key);
1646                    }
1647                    MutableCollection::SortedSet(values) => {
1648                        values.dissoc(key);
1649                    }
1650                    _ => return Err("dissoc expects a mutable map or set".into()),
1651                }
1652            }
1653            drop(collection_value);
1654            Ok(Value::MutableCollection(collection.clone()))
1655        }
1656        value @ (Value::Map(_)
1657        | Value::OrderedMap(_)
1658        | Value::SortedMap(_)
1659        | Value::Trie(_)
1660        | Value::PriorityMap(_)) => keys
1661            .iter()
1662            .try_fold(value.clone(), |map, key| map_dissoc_value(&map, key)),
1663        value @ (Value::Set(_) | Value::OrderedSet(_) | Value::SortedSet(_)) => keys
1664            .iter()
1665            .try_fold(value.clone(), |set, key| set_dissoc_value(&set, key)),
1666        Value::Nil => Ok(Value::Map(PMap::new())),
1667        _ => Err("dissoc expects a map".into()),
1668    }
1669}
1670
1671fn unique_values(values: Vec<Value>) -> Vec<Value> {
1672    let mut unique = Vec::new();
1673    for value in values {
1674        if !unique.contains(&value) {
1675            unique.push(value);
1676        }
1677    }
1678    unique
1679}