use serde::{Deserialize, Serialize};
use std::fmt;
pub mod from_str;
pub mod parse_error;
pub mod testable;
pub use testable::*;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Serialize, Deserialize)]
pub struct NHSNumber {
pub digits: [i8; 10],
}
impl NHSNumber {
#[allow(dead_code)]
pub fn new(digits: [i8; 10]) -> Self {
NHSNumber { digits }
}
#[allow(dead_code)]
pub fn check_digit(&self) -> i8 {
crate::check_digit(self.digits)
}
#[allow(dead_code)]
pub fn calculate_check_digit(&self) -> i8 {
crate::calculate_check_digit(self.digits)
}
#[allow(dead_code)]
pub fn validate_check_digit(&self) -> bool {
crate::validate_check_digit(self.digits)
}
#[allow(dead_code)]
pub fn testable_random_sample() -> NHSNumber {
crate::testable_random_sample()
}
}
impl fmt::Display for NHSNumber {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}{}{} {}{}{} {}{}{}{}",
self.digits[0],
self.digits[1],
self.digits[2],
self.digits[3],
self.digits[4],
self.digits[5],
self.digits[6],
self.digits[7],
self.digits[8],
self.digits[9],
)
}
}
impl Into<String> for NHSNumber {
fn into(self) -> String {
self.to_string()
}
}
#[allow(dead_code)]
pub fn format(digits: [i8; 10]) -> String {
format!(
"{}{}{} {}{}{} {}{}{}{}",
digits[0],
digits[1],
digits[2],
digits[3],
digits[4],
digits[5],
digits[6],
digits[7],
digits[8],
digits[9],
)
}
#[allow(dead_code)]
pub fn check_digit(digits: [i8; 10]) -> i8 {
digits[9]
}
#[allow(dead_code)]
pub fn calculate_check_digit(digits: [i8; 10]) -> i8 {
let sum: usize = digits
.iter()
.take(9)
.enumerate()
.map(|(i, &d)| d as usize * (10 - i as usize))
.sum();
((11 - (sum % 11)) % 10) as i8
}
#[allow(dead_code)]
pub fn validate_check_digit(digits: [i8; 10]) -> bool {
crate::check_digit(digits) == crate::calculate_check_digit(digits)
}
#[cfg(test)]
mod tests {
mod structure {
use super::super::*;
#[test]
fn test_new() {
let a: NHSNumber = NHSNumber::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
let actual = a.to_string();
let expect = "012 345 6789";
assert_eq!(actual, expect);
}
#[test]
fn test_display() {
let a: NHSNumber = NHSNumber::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
let actual = a.to_string();
let expect = "012 345 6789";
assert_eq!(actual, expect);
}
#[test]
fn test_into_string() {
let a: NHSNumber = NHSNumber::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
let actual: String = a.into();
let expect = "012 345 6789";
assert_eq!(actual, expect);
}
#[test]
fn test_partial_eq() {
{
let a: NHSNumber = NHSNumber::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
let b: NHSNumber = NHSNumber::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
assert_eq!(a, b);
}
{
let a: NHSNumber = NHSNumber::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
let b: NHSNumber = NHSNumber::new([9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
assert_ne!(a, b);
}
}
#[test]
fn test_check_digit() {
let a = NHSNumber::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
let actual: i8 = a.check_digit();
let expect: i8 = 9;
assert_eq!(actual, expect);
}
#[test]
fn test_calculate_check_digit() {
let a: NHSNumber = NHSNumber::new([9, 9, 9, 1, 2, 3, 4, 5, 6, 0]);
let actual: i8 = a.calculate_check_digit();
let expect: i8 = 0;
assert_eq!(actual, expect);
}
#[test]
fn test_validate_check_digit() {
{
let a: NHSNumber = NHSNumber::new([9, 9, 9, 1, 2, 3, 4, 5, 6, 0]);
assert_eq!(a.validate_check_digit(), true);
}
{
let a: NHSNumber = NHSNumber::new([9, 9, 9, 1, 2, 3, 4, 5, 6, 1]);
assert_eq!(a.validate_check_digit(), false);
}
}
#[test]
fn test_testable_random_sample() {
let a: NHSNumber = NHSNumber::testable_random_sample();
assert!(a >= *crate::testable::TESTABLE_MIN);
assert!(a <= *crate::testable::TESTABLE_MAX);
}
}
mod utilities {
#[test]
fn test_format() {
let digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let actual = crate::format(digits);
let expect = "012 345 6789";
assert_eq!(actual, expect);
}
#[test]
fn test_check_digit() {
let digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let actual: i8 = crate::check_digit(digits);
let expect: i8 = 9;
assert_eq!(actual, expect);
}
#[test]
fn test_calculate_check_digit() {
let digits = [9, 9, 9, 1, 2, 3, 4, 5, 6, 0];
let actual: i8 = crate::calculate_check_digit(digits);
let expect: i8 = 0;
assert_eq!(actual, expect);
}
}
}