1use std::collections::HashMap;
12
13use crate::value::{RuntimeError, Value};
14
15pub fn register(global: &mut HashMap<String, Value>) {
16 let mut members = HashMap::new();
17 for method in &["toHex", "fromHex"] {
18 members.insert(
19 method.to_string(),
20 Value::Builtin(format!("Byte.{}", method)),
21 );
22 }
23 global.insert(
24 "Byte".to_string(),
25 Value::Namespace {
26 name: "Byte".to_string(),
27 members,
28 },
29 );
30}
31
32pub fn effects(_name: &str) -> &'static [&'static str] {
33 &[]
34}
35
36pub fn call(name: &str, args: &[Value]) -> Option<Result<Value, RuntimeError>> {
37 match name {
38 "Byte.toHex" => Some(to_hex(args)),
39 "Byte.fromHex" => Some(from_hex(args)),
40 _ => None,
41 }
42}
43
44fn to_hex(args: &[Value]) -> Result<Value, RuntimeError> {
47 if args.len() != 1 {
48 return Err(RuntimeError::Error(format!(
49 "Byte.toHex() takes 1 argument, got {}",
50 args.len()
51 )));
52 }
53 let Value::Int(n) = &args[0] else {
54 return Err(RuntimeError::Error(
55 "Byte.toHex: argument must be an Int".to_string(),
56 ));
57 };
58 let n = *n;
59 if n < 0 || n > 255 {
60 return Ok(Value::Err(Box::new(Value::Str(format!(
61 "Byte.toHex: {} is out of range 0–255",
62 n
63 )))));
64 }
65 Ok(Value::Ok(Box::new(Value::Str(format!("{:02x}", n)))))
66}
67
68fn from_hex(args: &[Value]) -> Result<Value, RuntimeError> {
69 if args.len() != 1 {
70 return Err(RuntimeError::Error(format!(
71 "Byte.fromHex() takes 1 argument, got {}",
72 args.len()
73 )));
74 }
75 let Value::Str(s) = &args[0] else {
76 return Err(RuntimeError::Error(
77 "Byte.fromHex: argument must be a String".to_string(),
78 ));
79 };
80 if s.len() != 2 {
81 return Ok(Value::Err(Box::new(Value::Str(format!(
82 "Byte.fromHex: expected exactly 2 hex chars, got '{}'",
83 s
84 )))));
85 }
86 match u8::from_str_radix(s, 16) {
87 Ok(n) => Ok(Value::Ok(Box::new(Value::Int(n as i64)))),
88 Err(_) => Ok(Value::Err(Box::new(Value::Str(format!(
89 "Byte.fromHex: invalid hex '{}'",
90 s
91 ))))),
92 }
93}