geam-stdlib 0.2.1

Official Gleam standard-library providers for Geam
Documentation
use crate::HostFailure;
use ecow::EcoString;
use num_bigint::BigInt;
use num_traits::ToPrimitive;
use unicode_segmentation::UnicodeSegmentation;

pub(in crate::string) fn pop_grapheme(string: EcoString) -> Result<(EcoString, EcoString), ()> {
    let Some(grapheme) = string.graphemes(true).next() else {
        return Err(());
    };
    let rest = EcoString::from(&string[grapheme.len()..]);
    Ok((grapheme.into(), rest))
}

pub(in crate::string) fn unsafe_int_to_utf_codepoint(value: BigInt) -> Result<char, HostFailure> {
    value
        .to_u32()
        .and_then(char::from_u32)
        .ok_or_else(|| HostFailure::new("integer is not a valid Unicode codepoint"))
}

pub(in crate::string) fn utf_codepoint_to_int(value: char) -> BigInt {
    BigInt::from(u32::from(value))
}

#[cfg(test)]
mod tests {
    use super::{unsafe_int_to_utf_codepoint, utf_codepoint_to_int};
    use num_bigint::BigInt;

    #[test]
    fn converts_exact_unicode_scalar_values() {
        assert_eq!(unsafe_int_to_utf_codepoint(65.into()), Ok('A'));
        assert_eq!(
            utf_codepoint_to_int('\u{10ffff}'),
            BigInt::from(0x10ffff_u32)
        );
        assert_eq!(
            unsafe_int_to_utf_codepoint((-1).into())
                .expect_err("negative codepoint should fail")
                .message(),
            "integer is not a valid Unicode codepoint",
        );
        assert_eq!(
            unsafe_int_to_utf_codepoint(0xd800_u32.into())
                .expect_err("surrogate should fail")
                .message(),
            "integer is not a valid Unicode codepoint",
        );
        assert_eq!(
            unsafe_int_to_utf_codepoint(BigInt::from(u64::MAX))
                .expect_err("unrepresentable codepoint should fail")
                .message(),
            "integer is not a valid Unicode codepoint",
        );
    }
}