use alloc::string::String;
type Annotation = (String, Option<String>);
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
struct Codecs {
scale: bool,
ethabi: bool,
}
impl Codecs {
const BOTH: Self = Self {
scale: true,
ethabi: true,
};
const NONE: Self = Self {
scale: false,
ethabi: false,
};
}
fn codecs(annotations: &[Annotation]) -> Codecs {
let mut result = Codecs::NONE;
let mut saw_codec_annotation = false;
for (name, value) in annotations {
if name != "codec" {
continue;
}
saw_codec_annotation = true;
match value {
None => {
result = Codecs::BOTH;
}
Some(value) => {
for token in value
.split(',')
.map(str::trim)
.filter(|token| !token.is_empty())
{
match token {
"scale" => result.scale = true,
"ethabi" => result.ethabi = true,
_ => {}
}
}
}
}
}
if !saw_codec_annotation {
result = Codecs::BOTH;
}
result
}
pub fn has_scale_codec(annotations: &[Annotation]) -> bool {
codecs(annotations).scale
}
pub fn has_ethabi_codec(annotations: &[Annotation]) -> bool {
codecs(annotations).ethabi
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::string::ToString as _;
use alloc::vec;
use alloc::vec::Vec;
fn ann(name: &str, value: Option<&str>) -> Annotation {
(name.to_string(), value.map(|s| s.to_string()))
}
#[test]
fn no_annotations_means_both() {
let anns: Vec<Annotation> = vec![];
assert!(has_scale_codec(&anns));
assert!(has_ethabi_codec(&anns));
}
#[test]
fn codec_scale_only() {
let anns = vec![ann("codec", Some("scale"))];
assert!(has_scale_codec(&anns));
assert!(!has_ethabi_codec(&anns));
}
#[test]
fn codec_ethabi_only() {
let anns = vec![ann("codec", Some("ethabi"))];
assert!(!has_scale_codec(&anns));
assert!(has_ethabi_codec(&anns));
}
#[test]
fn codec_both_explicit() {
let anns = vec![ann("codec", Some("scale,ethabi"))];
assert!(has_scale_codec(&anns));
assert!(has_ethabi_codec(&anns));
}
#[test]
fn codec_both_with_spaces() {
let anns = vec![ann("codec", Some("scale, ethabi"))];
assert!(has_scale_codec(&anns));
assert!(has_ethabi_codec(&anns));
}
#[test]
fn codec_no_value_means_both() {
let anns = vec![ann("codec", None)];
assert!(has_scale_codec(&anns));
assert!(has_ethabi_codec(&anns));
}
#[test]
fn repeated_codec_annotations_are_merged() {
let anns = vec![ann("codec", Some("scale")), ann("codec", Some("ethabi"))];
assert!(has_scale_codec(&anns));
assert!(has_ethabi_codec(&anns));
}
#[test]
fn unknown_and_empty_tokens_are_ignored() {
let anns = vec![ann("codec", Some("scale, ,unknown"))];
assert!(has_scale_codec(&anns));
assert!(!has_ethabi_codec(&anns));
}
#[test]
fn other_annotations_are_ignored_when_codec_missing() {
let anns = vec![ann("query", None), ann("payable", None)];
assert!(has_scale_codec(&anns));
assert!(has_ethabi_codec(&anns));
}
}