use crate::{
args::ArgValues,
bytecode::VM,
defer_drop,
exception_private::{ExcType, RunResult, SimpleException},
types::str::allocate_char,
value::Value,
};
pub fn builtin_chr(vm: &mut VM<'_>, args: ArgValues) -> RunResult<Value> {
let value = args.get_one_arg("chr", vm.heap)?;
defer_drop!(value, vm);
match value {
Value::Int(n) => {
if *n < 0 || *n > 0x0010_FFFF {
Err(SimpleException::new_msg(ExcType::ValueError, "chr() arg not in range(0x110000)").into())
} else if let Some(c) = char::from_u32(
#[expect(
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
reason = "range of n already validated in the first if condition"
)]
{
*n as u32
},
) {
Ok(allocate_char(c, vm.heap))
} else {
Err(SimpleException::new_msg(ExcType::ValueError, "chr() arg not in range(0x110000)").into())
}
}
Value::Bool(b) => {
let c = if *b { '\x01' } else { '\x00' };
Ok(allocate_char(c, vm.heap))
}
_ => {
let type_name = value.py_type_name(vm);
Err(SimpleException::new_msg(
ExcType::TypeError,
format!("an integer is required (got type {type_name})"),
)
.into())
}
}
}