use super::IcrcError;
pub fn normalize_subaccount_hex(value: &str) -> Result<String, IcrcError> {
Ok(validated_subaccount_hex(value)?.to_ascii_lowercase())
}
#[cfg(feature = "icrc-host")]
pub(in crate::icrc) fn normalize_optional_subaccount_hex(
value: Option<&str>,
) -> Result<Option<String>, IcrcError> {
value.map(normalize_subaccount_hex).transpose()
}
#[cfg(any(test, feature = "icrc-host"))]
pub(in crate::icrc) fn subaccount_bytes_from_hex(value: &str) -> Result<[u8; 32], IcrcError> {
Ok(crate::hex::decode_hex(validated_subaccount_hex(value)?)
.expect("validated ASCII hexadecimal byte pairs")
.try_into()
.expect("validated 32-byte subaccount"))
}
fn validated_subaccount_hex(value: &str) -> Result<&str, IcrcError> {
let value = value.trim();
if !value.len().is_multiple_of(2) {
return Err(IcrcError::InvalidSubaccountHex {
reason: "hex string must contain an even number of characters".to_string(),
});
}
if !value.bytes().all(|byte| byte.is_ascii_hexdigit()) {
return Err(IcrcError::InvalidSubaccountHex {
reason: "hex string must contain only ASCII hexadecimal digits".to_string(),
});
}
let bytes = value.len() / 2;
if bytes != 32 {
return Err(IcrcError::InvalidSubaccountLength { bytes });
}
Ok(value)
}
#[cfg(test)]
mod tests;