use super::check_arity;
use crate::codec;
use crate::error::{DogeError, DogeResult};
use crate::value::Value;
pub(super) const STR_METHODS: &[&str] = &["from_b64", "from_hex"];
pub(super) fn str_method(recv: &Value, name: &str, args: Vec<Value>) -> DogeResult {
let Value::Str(text) = recv else {
unreachable!("compiler bug: str_method called on a non-Str")
};
let argc = args.len();
match name {
"from_b64" => {
check_arity("Str", name, 0, argc)?;
codec::b64_decode(text).map(Value::bytes).map_err(|_| {
DogeError::value_error("cannot decode this Str as Bytes (not valid base64)")
})
}
"from_hex" => {
check_arity("Str", name, 0, argc)?;
codec::hex_decode(text).map(Value::bytes).map_err(|_| {
DogeError::value_error("cannot decode this Str as Bytes (not valid hex)")
})
}
_ => Err(DogeError::attr_error(format!("a Str has no method {name}"))),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::ErrorKind;
#[test]
fn from_b64_round_trips_and_rejects() {
let ok = str_method(&Value::str("aGk="), "from_b64", vec![]).unwrap();
assert!(matches!(ok, Value::Bytes(b) if &*b == b"hi"));
assert_eq!(
str_method(&Value::str("aGk"), "from_b64", vec![])
.unwrap_err()
.kind,
ErrorKind::ValueError
);
}
#[test]
fn from_hex_round_trips_and_rejects() {
let ok = str_method(&Value::str("6869"), "from_hex", vec![]).unwrap();
assert!(matches!(ok, Value::Bytes(b) if &*b == b"hi"));
assert_eq!(
str_method(&Value::str("zz"), "from_hex", vec![])
.unwrap_err()
.kind,
ErrorKind::ValueError
);
}
#[test]
fn unknown_method_is_an_attr_error() {
assert_eq!(
str_method(&Value::str("x"), "nope", vec![])
.unwrap_err()
.kind,
ErrorKind::AttrError
);
}
}