Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions builtin/builtin.mbti
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ impl Int {
#deprecated
shr(Int, Int) -> Int
to_byte(Int) -> Byte
to_char(Int) -> Char?
to_double(Int) -> Double
to_float(Int) -> Float
to_int16(Int) -> Int16
Expand All @@ -421,6 +422,7 @@ impl Int {
to_uint(Int) -> UInt
to_uint16(Int) -> UInt16
to_uint64(Int) -> UInt64
unsafe_to_char(Int) -> Char
until(Int, Int, step~ : Int = .., inclusive~ : Bool = ..) -> Iter[Int]
#deprecated
upto(Int, Int, inclusive~ : Bool = ..) -> Iter[Int]
Expand Down
12 changes: 12 additions & 0 deletions builtin/intrinsics.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -1471,6 +1471,18 @@ pub fn Bytes::new(len : Int) -> Bytes {
/// ```
pub fn Int::to_byte(self : Int) -> Byte = "%i32_to_byte"

///|
pub fn Int::unsafe_to_char(self : Int) -> Char = "%char_from_int"

///|
pub fn Int::to_char(self : Int) -> Char? {
if self is (0..=0xD7FF) || self is (0xE000..=0x10FFFF) {
Some(self.unsafe_to_char())
} else {
None
}
}

///|
/// Converts an unsigned 64-bit integer to a byte by truncating it to fit within
/// the byte range (0 to 255).
Expand Down
47 changes: 47 additions & 0 deletions builtin/intrinsics_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -465,3 +465,50 @@ test "convert byte to int64" {
let result = b.to_int64()
inspect!(result, content="255")
}

///|
test "Int::to_char" {
inspect!(Int::to_char(97), content="Some('a')")
inspect!(Int::to_char(65), content="Some('A')")
inspect!(Int::to_char(49), content="Some('1')")
inspect!(Int::to_char(33), content="Some('!')")
}

///|
test "Int::to_char - Invalid values" {
inspect!(Int::to_char(-1), content="None")
inspect!(Int::to_char(1114112), content="None")
inspect!(Int::to_char(1114113), content="None")
}

///|
test "Int::to_char - Valid values" {
inspect!(Int::to_char(0), content="Some('\\x00')")
inspect!(Int::to_char(127), content="Some('')")
inspect!(Int::to_char(128), content="Some('€')")
inspect!(Int::to_char(0x7F), content="Some('')")
inspect!(Int::to_char(0x80), content="Some('€')")
inspect!(Int::to_char(0xFF), content="Some('ÿ')")
inspect!(Int::to_char(0x100), content="Some('Ā')")
inspect!(Int::to_char(0xFFFF), content="Some('￿')")
inspect!(Int::to_char(0x10000), content="Some('𐀀')")
inspect!(Int::to_char(0x10FFFF), content="Some('􏿿')")
}

///|
test "Int::to_char - Invalid values" {
inspect!(Int::to_char(-1), content="None")
inspect!(Int::to_char(0x10FFFF + 1), content="None")
inspect!(Int::to_char(0xD800), content="None")
inspect!(Int::to_char(0xDFFF), content="None")
inspect!(Int::to_char(0xD900), content="None")
inspect!(Int::to_char(0xDF00), content="None")
}

///|
test "Int::to_char - Boundary cases" {
inspect!(Int::to_char(0xD7FF), content="Some('퟿')")
inspect!(Int::to_char(0xE000), content="Some('')")
inspect!(Int::to_char(0x10FFFF), content="Some('􏿿')")
inspect!(Int::to_char(0x10FFFF + 1), content="None")
}
2 changes: 1 addition & 1 deletion builtin/iter_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ test "map" {
let iter = test_from_array(['1', '2', '3', '4', '5'])
let exb = StringBuilder::new(size_hint=0)
iter
.map(fn { x => Char::from_int(x.to_int() + 1) })
.map(fn { x => (x.to_int() + 1).to_char().unwrap() })
.each(fn { x => exb.write_char(x) })
inspect!(exb, content="23456")
}
Expand Down