use crate::{
common::{ascii_alphanum_to_u8, is_ascii_alphanumeric_upper_no_vowels, is_length_eq},
error::CheckDigitError,
Calculator,
};
#[derive(Clone, Copy, Debug, Default)]
pub struct CheckDigitAlgorithm {}
const SHARED_INSTANCE: CheckDigitAlgorithm = CheckDigitAlgorithm {};
pub const fn get_algorithm_instance() -> &'static CheckDigitAlgorithm {
&SHARED_INSTANCE
}
const WEIGHTS: [u16; 6] = [1, 3, 1, 7, 3, 9];
impl Calculator<u8> for CheckDigitAlgorithm {
fn name(&self) -> &'static str {
"Stock Exchange Daily Official List (SEDOL)"
}
fn calculate(&self, s: &str) -> Result<u8, CheckDigitError> {
is_length_eq(s, 6)?;
is_ascii_alphanumeric_upper_no_vowels(s)?;
let sum: u16 = s
.chars()
.enumerate()
.map(|(i, c)| (ascii_alphanum_to_u8(c) as u16) * WEIGHTS[i])
.sum();
Ok(((10 - (sum % 10)) % 10) as u8)
}
}
#[cfg(test)]
mod tests {
use crate::sedol::CheckDigitAlgorithm;
use crate::Calculator;
#[test]
fn test_validate_hsbc() {
let sedol = CheckDigitAlgorithm::default();
assert!(sedol.is_valid("0540528"));
assert_eq!(sedol.calculate("054052"), Ok(8));
}
}