use super::funejson::Value; /// The GS1 mod-10 check digit for `data`, the digits of a GS1 key without its /// check digit. One rule serves every key length because the weights are /// counted from the right: 3, 1, 3, 1 ... starting with the digit that will sit /// next to the check digit. Counting from the left instead only works for /// EAN-13 and the other even-length data strings. /// /// # Panics /// Panics unless `data` is one or more ASCII digits. pub fn gs1_check_digit(data: &str) -> i64 { if data.is_empty() || !data.bytes().all(|b| b.is_ascii_digit()) { panic!("GS1 data must be one or more ASCII digits, received {:?}", data); } let mut total: u32 = 0; let mut weight: u32 = 3; for b in data.bytes().rev() { // Reducing as we go keeps the sum small for data of any length. total = (total + (b - b'0') as u32 * weight) % 10; weight = if weight == 3 { 1 } else { 3 }; } ((10 - total) % 10) as i64 } pub fn fune_vector(args: &[Value]) -> Value { // A non-string argument arrives as an empty string, which is refused with // the same message the other two languages give for a non-string. Value::Int(gs1_check_digit(args[0].as_str())) }