use std.( int.(?), option.Option, panicking.assert, str.(?), ) fn char.from-digit*(num: u32, base: u32) Option[char] = { assert(base <= 36, "base is too high (maximum 36)") if num < base { let num = u8(num) Option.Some(char(if num < 10 { b'0' + num } else { b'a' + num - 10 })) } else { Option.None } } // The low-level UTF8 implementation was taken from rust's `core::char` module const TAG-CONT: u8 = 0b1000_0000 const TAG-TWO-B: u8 = 0b1100_0000 const TAG-THREE-B: u8 = 0b1110_0000 const TAG-FOUR-B: u8 = 0b1111_0000 const MAX-ONE-B: u32 = 0x80 const MAX-TWO-B: u32 = 0x800 const MAX-THREE-B: u32 = 0x10000 fn len-utf8*(ch: char) uint = len-utf8(u32(ch)) fn len-utf8(code: u32) uint = if code < MAX-ONE-B { 1 } else if code < MAX-TWO-B { 2 } else if code < MAX-THREE-B { 3 } else { 4 } fn encode-utf8*(ch: char, dst: &mut []u8) &mut []u8 = encode-utf8-raw(u32(ch), dst) fn encode-utf8-raw*(code: u32, dst: &mut []u8) &mut []u8 = { let len = code.len-utf8() assert(dst.len >= len) if len == 1 { dst.[0] = u8(code) } else if len == 2 { dst.[0] = u8(code >> 6 & 0x1f) | TAG-TWO-B dst.[1] = u8(code & 0x3f) | TAG-CONT } else if len == 3 { dst.[0] = u8(code >> 12 & 0x0f) | TAG-THREE-B dst.[1] = u8(code >> 6 & 0x3f) | TAG-CONT dst.[2] = u8(code & 0x3f) | TAG-CONT } else { // len == 4 dst.[0] = u8(code >> 18 & 0x07) | TAG-FOUR-B dst.[1] = u8(code >> 12 & 0x3f) | TAG-CONT dst.[2] = u8(code >> 6 & 0x3f) | TAG-CONT dst.[3] = u8(code & 0x3f) | TAG-CONT } &mut dst.[..len] }