use crate::v2_4::aom2::definitions::adl_code_definitions::AdlCodeDefinitionsData;
impl AdlCodeDefinitionsData {
#[must_use]
pub fn is_at_code(a_code: &str) -> bool {
a_code.starts_with(Self::AT_CODE_LEADER)
}
#[must_use]
pub fn is_value_code(a_code: &str) -> bool {
a_code.starts_with(Self::VALUE_CODE_LEADER)
}
#[must_use]
pub fn is_id_code(a_code: &str) -> bool {
a_code.starts_with(Self::ID_CODE_LEADER)
}
#[must_use]
pub fn is_value_set_code(a_code: &str) -> bool {
a_code.starts_with(Self::VALUE_SET_CODE_LEADER)
}
#[must_use]
pub fn is_adl_code(a_code: &str) -> bool {
Self::is_at_code(a_code)
|| Self::is_id_code(a_code)
|| Self::is_value_code(a_code)
|| Self::is_value_set_code(a_code)
}
#[must_use]
pub fn codes_conformant(a_child_code: &str, a_parent_code: &str) -> bool {
Self::is_valid_code(a_child_code)
&& a_child_code.starts_with(a_parent_code)
&& (a_child_code.len() == a_parent_code.len()
|| a_child_code
.get(a_parent_code.len()..)
.and_then(|rest| rest.chars().next())
== Some(Self::SPECIALISATION_SEPARATOR))
}
#[must_use]
pub fn is_redefined_code(a_code: &str) -> bool {
let Some(numeric) = Self::numeric_part(a_code) else {
return false;
};
let mut segments: Vec<&str> = numeric.split(Self::SPECIALISATION_SEPARATOR).collect();
if segments.pop().is_none() || segments.is_empty() {
return false;
}
segments
.iter()
.any(|segment| segment.bytes().any(|byte| byte != b'0'))
}
#[must_use]
pub fn is_valid_code(a_code: &str) -> bool {
let Some(numeric) = Self::numeric_part(a_code) else {
return false;
};
numeric
.split(Self::SPECIALISATION_SEPARATOR)
.all(|segment| !segment.is_empty() && segment.bytes().all(|byte| byte.is_ascii_digit()))
}
fn numeric_part(a_code: &str) -> Option<&str> {
let leader = if Self::is_id_code(a_code) {
Self::ID_CODE_LEADER
} else if Self::is_value_set_code(a_code) {
Self::VALUE_SET_CODE_LEADER
} else if Self::is_at_code(a_code) {
Self::AT_CODE_LEADER
} else {
return None;
};
a_code.strip_prefix(leader).filter(|rest| !rest.is_empty())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn each_leader_selects_its_own_code_kind() {
assert!(AdlCodeDefinitionsData::is_at_code("at0004"));
assert!(AdlCodeDefinitionsData::is_value_code("at0004"));
assert!(AdlCodeDefinitionsData::is_id_code("id1"));
assert!(AdlCodeDefinitionsData::is_value_set_code("ac1"));
assert!(!AdlCodeDefinitionsData::is_at_code("id1"));
assert!(!AdlCodeDefinitionsData::is_id_code("ac1"));
assert!(AdlCodeDefinitionsData::is_adl_code("ac1"));
assert!(!AdlCodeDefinitionsData::is_adl_code("XYZ"));
}
#[test]
fn a_valid_code_is_a_leader_over_dotted_numeric_segments() {
assert!(AdlCodeDefinitionsData::is_valid_code("at0000"));
assert!(AdlCodeDefinitionsData::is_valid_code("at0004.0.1"));
assert!(AdlCodeDefinitionsData::is_valid_code("id1.1.1"));
assert!(AdlCodeDefinitionsData::is_valid_code("ac1"));
assert!(!AdlCodeDefinitionsData::is_valid_code("at"));
assert!(!AdlCodeDefinitionsData::is_valid_code("at.1"));
assert!(!AdlCodeDefinitionsData::is_valid_code("at0004."));
assert!(!AdlCodeDefinitionsData::is_valid_code("foo"));
}
#[test]
fn conformance_requires_a_separator_boundary() {
assert!(AdlCodeDefinitionsData::codes_conformant("at0004", "at0004"));
assert!(AdlCodeDefinitionsData::codes_conformant(
"at0004.1", "at0004"
));
assert!(AdlCodeDefinitionsData::codes_conformant(
"at0004.1.2",
"at0004.1"
));
assert!(!AdlCodeDefinitionsData::codes_conformant(
"at00040", "at0004"
));
assert!(!AdlCodeDefinitionsData::codes_conformant(
"at0005", "at0004"
));
assert!(!AdlCodeDefinitionsData::codes_conformant("nope", "nope"));
}
#[test]
fn redefinition_is_a_non_zero_index_above_the_last() {
assert!(!AdlCodeDefinitionsData::is_redefined_code("at0.0.1"));
assert!(AdlCodeDefinitionsData::is_redefined_code("at1.0.1"));
assert!(AdlCodeDefinitionsData::is_redefined_code("at0004.1"));
assert!(!AdlCodeDefinitionsData::is_redefined_code("at0004"));
assert!(!AdlCodeDefinitionsData::is_redefined_code("nope"));
}
}