rune/
character.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
//! Character and string utilities.
use crate::core::{
    gc::Context,
    object::{int_to_char, Gc, Object, OptionalFlag},
};
use anyhow::Result;
use rune_macros::defun;

#[defun]
fn unibyte_string(bytes: &[Gc<i64>]) -> Result<Vec<u8>> {
    let unibyte: Result<Vec<u8>, _> = bytes.iter().map(|x| u8::try_from(x.untag())).collect();
    Ok(unibyte?)
}

#[defun]
fn max_char(unicode: OptionalFlag) -> usize {
    if unicode.is_some() {
        std::char::MAX as usize
    } else {
        0x3F_FFFF
    }
}

#[defun]
fn characterp(obj: Object) -> bool {
    char::try_from(obj).is_ok()
}

#[defun]
fn string(characters: &[Gc<i64>]) -> Result<String> {
    let string: Result<_, _> = characters.iter().map(|x| int_to_char(x.untag())).collect();
    Ok(string?)
}

#[defun]
fn make_string<'ob>(
    length: usize,
    init: usize,
    multibyte: OptionalFlag,
    cx: &'ob Context,
) -> Result<Object<'ob>> {
    if multibyte.is_some() {
        let chr = int_to_char(i64::try_from(init)?)?;
        let size = chr.len_utf8();
        let mut string = cx.string_with_capacity(length * size);
        for _ in 0..length {
            string.push(chr);
        }
        Ok(cx.add(string))
    } else {
        let chr = u8::try_from(init)?;
        let string: Vec<_> = (0..length).map(|_| chr).collect();
        Ok(cx.add(string))
    }
}