rune/
character.rs

1//! Character and string utilities.
2use crate::core::{
3    gc::Context,
4    object::{Gc, Object, OptionalFlag, int_to_char},
5};
6use anyhow::Result;
7use rune_macros::defun;
8
9#[defun]
10fn unibyte_string(bytes: &[Gc<i64>]) -> Result<Vec<u8>> {
11    let unibyte: Result<Vec<u8>, _> = bytes.iter().map(|x| u8::try_from(x.untag())).collect();
12    Ok(unibyte?)
13}
14
15#[defun]
16fn max_char(unicode: OptionalFlag) -> usize {
17    if unicode.is_some() { std::char::MAX as usize } else { 0x3F_FFFF }
18}
19
20#[defun]
21fn characterp(obj: Object) -> bool {
22    char::try_from(obj).is_ok()
23}
24
25#[defun]
26fn string(characters: &[Gc<i64>]) -> Result<String> {
27    let string: Result<_, _> = characters.iter().map(|x| int_to_char(x.untag())).collect();
28    Ok(string?)
29}
30
31#[defun]
32fn make_string<'ob>(
33    length: usize,
34    init: usize,
35    multibyte: OptionalFlag,
36    cx: &'ob Context,
37) -> Result<Object<'ob>> {
38    if multibyte.is_some() {
39        let chr = int_to_char(i64::try_from(init)?)?;
40        let size = chr.len_utf8();
41        let mut string = cx.string_with_capacity(length * size);
42        for _ in 0..length {
43            string.push(chr);
44        }
45        Ok(cx.add(string))
46    } else {
47        let chr = u8::try_from(init)?;
48        let string: Vec<_> = (0..length).map(|_| chr).collect();
49        Ok(cx.add(string))
50    }
51}