checkdigit

    Check-digit algorithms and identifier validation for MoonBit: Luhn, Verhoeff, Damm, payment cards, IBAN, IMEI, resident IDs, Aadhaar, VIN, ISIN, LEI, USCC, CPF, CNPJ, BSN, codice fiscale, GS1 retail barcodes (EAN/UPC/GTIN) and bibliographic numbers (ISBN, ISSN)

    checkdigit
    luhn
    iban
    imei
    isin
    vin
    lei
    uscc
    cpf
    cnpj
    ean
    gtin
    isbn
    issn
    validation
    Download zip
    Author
    Version
    0.4.0
    License
    Apache-2.0
    Last updated
    28 days ago
    Downloads
    39

    No dependencies

    #checkdigit

    Check-digit algorithms and identifier validation for MoonBit.

    license mooncakes

    checkdigit implements the three check-digit algorithms used by most real-world numbering schemes, and builds the identifier formats on top of them: payment cards (ISO/IEC 7812), IBAN bank accounts (ISO 13616), IMEI device numbers (3GPP TS 23.003), Chinese resident identity cards (GB 11643), Aadhaar numbers, VINs (ISO 3779), ISINs (ISO 6166), LEIs (ISO 17442), unified social credit identifiers (GB 32100), CPF and CNPJ (Brazil), BSN (Netherlands), the Italian codice fiscale, the GS1 retail barcodes (EAN-8, UPC-A, EAN-13, GTIN-14, UPC-E), and the bibliographic numbers (ISBN-10, ISBN-13, ISSN).

    ///|
    fn main {
    // 7992739871 -> check digit 3
    println(luhn_check_digit("7992739871")) // Some(3)
    println(luhn_valid("79927398713")) // true

    // Brand detection and full card check
    println(detect_brand("378282246310005")) // amex
    println(card_valid("378282246310005")) // true

    // IBAN accepts spaces and lowercase
    println(iban_valid("gb82 west 1234 5698 7654 32")) // true
    println(iban_format("GB82WEST12345698765432")) // Some("GB82 WEST 1234 5698 7654 32")

    // Identifiers that carry a check character of their own
    println(cn_id_birthdate("11010519491231002X")) // Some("19491231")
    println(vin_valid("1M8GDM9AXKP042788")) // true
    println(isin_country("US0378331005")) // Some("US")
    println(lei_lou("529900T8BM49AURSDO55")) // Some("5299")

    // Formatting helpers for the identifiers that have a printed form
    println(cpf_format("11144477735")) // Some("111.444.777-35")
    println(cnpj_format("11222333000181")) // Some("11.222.333/0001-81")
    println(uscc_division("91350100M000100Y43")) // Some("350100")

    // Retail barcodes and bibliographic numbers
    println(ean13_valid("4006381333931")) // true
    println(upce_expand("07832309")) // Some("078000003239")
    println(isbn10_to_isbn13("0306406152")) // Some("9780306406157")
    }

    #What it covers

    AreaFunctions
    Luhn (mod 10)luhn_valid, luhn_check_digit
    Verhoeff (dihedral group D5)verhoeff_valid, verhoeff_check_digit
    Damm (anti-symmetric quasigroup)damm_valid, damm_check_digit
    Payment cardscard_valid, detect_brand, card_format, CardBrand
    IBAN (ISO 13616)iban_valid, iban_country, iban_bban, iban_format, iban_normalize, iban_expected_length, iban_check_digits, iban_assemble
    IMEI (3GPP TS 23.003)imei_valid, imei_check_digit, imei_tac, imei_serial
    Resident ID (GB 11643)cn_id_valid, cn_id_check_char, cn_id_region, cn_id_birthdate
    Aadhaaraadhaar_valid, aadhaar_check_digit
    VIN (ISO 3779)vin_valid, vin_check_char, vin_wmi, vin_vis
    ISIN (ISO 6166)isin_valid, isin_check_digit, isin_country
    LEI (ISO 17442)lei_valid, lei_check_digits, lei_lou
    Unified social credit id (GB 32100)uscc_valid, uscc_check_char, uscc_division
    CPF (Brazil)cpf_valid, cpf_check_digits, cpf_format
    CNPJ (Brazil)cnpj_valid, cnpj_check_digits, cnpj_format
    BSN (Netherlands)bsn_valid, bsn_check_digit
    Codice fiscale (Italy)cf_valid, cf_check_char
    GTIN / retail barcode (GS1)gtin_valid, gtin_check_digit, ean8_valid, ean13_valid, upca_valid, upce_valid, gtin14_valid, upce_expand, upce_check_digit
    ISBN / ISSN (bibliographic)isbn10_valid, isbn10_check_char, isbn13_valid, isbn13_check_digit, isbn10_to_isbn13, issn_valid, issn_check_char

    All validators are total: they take a String and return Bool, or return None when a value cannot be computed. No exceptions, no panics on bad input.

    #Algorithms

    • Luhn catches any single-digit error and most adjacent transpositions. Used by payment cards, IMEI, and many national identifiers.
    • Verhoeff catches all single-digit errors and all adjacent transpositions, using a multiplication table over the dihedral group D5.
    • Damm also catches all single-digit errors and all adjacent transpositions, but needs a single table lookup per digit instead of a position-dependent permutation.

    #Identifiers

    • Payment cards — brand detection by issuer identification number, then the length rules for that brand, then Luhn. Brands: Visa, Mastercard, American Express, Discover, JCB, Diners Club, UnionPay, Maestro. Overlapping issuer ranges are resolved by testing the most specific range first (Discover's 622126–622925 sits inside UnionPay's 62).
    • IBAN — country code, registered length for that country (75 countries), then the mod-97-10 check. Input is normalised, so spaces and lowercase are accepted. Bank account numbers can also be generated: iban_check_digits computes the two check digits for a country code plus BBAN, and iban_assemble returns the complete IBAN.
    • IMEI — 15 digits with a Luhn check digit, plus TAC (first 8 digits) and serial number (digits 9–14) extraction.
    • Chinese resident identity card — 18 characters: division code, birth date, sequence, then the ISO 7064 MOD 11-2 check character (a digit or X). The birth date is range-checked, so month 13 or day 00 is rejected; month lengths and leap years are deliberately not modelled, and the doc comment says so.
    • Aadhaar — 12 digits whose last is a Verhoeff check digit, reusing the Verhoeff module directly.
    • VIN — 17 characters excluding I, O and Q, with a modulo-11 check character at position nine that may be X. The positional weight table has a zero in the ninth slot so the check character does not disturb its own sum.
    • ISIN — 12 characters: a two-letter country code, nine alphanumeric characters of security identifier, and a Luhn digit computed after every letter has been expanded to its two-digit value.
    • LEI — 20 characters: a four-character local operating unit prefix, two reserved zeroes, twelve characters of entity reference, and two check digits at the end. Validation expands letters to 10..35 and requires the whole identifier to be 1 modulo 97, the same scheme IBAN uses.
    • Unified social credit identifier — 18 characters: registration authority, entity category, a six-digit division code, a nine-character organisation code, and a check character. The check character is chosen over a 31-character code set, the digits plus the letters minus I, O, S, V and Z — the five that read as another character in handwriting. Position i carries the weight 3^(i-1) mod 31, which spreads a single wrong character across the whole sum instead of shifting it by a constant.
    • CPF and CNPJ — the Brazilian individual and company registries. Both are two mod-11 check digits over a weighted prefix, with the second digit covering a prefix one character longer than the first; the two weight tables differ only in where the cycle of nine weights restarts. cpf_format and cnpj_format return the punctuated printed form. All-equal-digit input satisfies the arithmetic but is never issued, so it is rejected.
    • BSN — the Dutch citizen service number. This one has no separate check digit: the property holds over all nine digits at once, weighted from nine down to one with the last position negated, and the total must be a multiple of eleven. Negating that last position is what stops a Dutch bank account number, checked with the same weights all positive, from passing as a BSN. The eight-digit form with its leading zero omitted is accepted.
    • Codice fiscale — the Italian tax code. Sixteen characters, of which the last is the CIN, computed over the first fifteen with two different value tables: one for the odd positions and one for the even. Validation also checks the required layout, including the twelve month codes, which skip the letters that would spell words, and the omocodia letters that stand in for digits when two people would otherwise share a code.
    • Retail barcodes (GS1) — the GTIN family: EAN-8, UPC-A, EAN-13 and GTIN-14 all share one mod-10 check digit computed with the alternating 3-1 weighting read from the right, so gtin_valid accepts any of the four registered lengths. UPC-E is the zero-suppressed form of UPC-A; upce_expand restores the twelve-digit UPC-A, and that expansion is what the UPC-E check digit is verified against.
    • ISBN and ISSN — ISBN-10 carries a mod-11 check character that may be X (ten), under weights 10 down to 2. ISBN-13 is an EAN-13 restricted to the 978 and 979 bookland prefixes, so it reuses the GS1 check digit, and isbn10_to_isbn13 converts a ten-character ISBN to its thirteen-character form. ISSN is an eight-character serial number with its own mod-11 check character, verified with weights 8 down to 2.

    #Installation

    moon add sssssurf/checkdigit

    #Command line

    The repository also ships a small CLI for trying the validators out:

    moon run cmd/main -- card 378282246310005 moon run cmd/main -- iban "gb82 west 1234 5698 7654 32" moon run cmd/main -- imei 490154203237518 moon run cmd/main -- luhn 7992739871 moon run cmd/main -- verhoeff 236 moon run cmd/main -- damm 572 moon run cmd/main -- cnid 11010519491231002X moon run cmd/main -- aadhaar 234123412346 moon run cmd/main -- vin 1M8GDM9AXKP042788 moon run cmd/main -- isin US0378331005 moon run cmd/main -- lei 529900T8BM49AURSDO55 moon run cmd/main -- uscc 91350100M000100Y43 moon run cmd/main -- cpf 11144477735 moon run cmd/main -- cnpj 11222333000181 moon run cmd/main -- bsn 111222333 moon run cmd/main -- cf RSSMRA85T10A562S moon run cmd/main -- gtin 4006381333931 moon run cmd/main -- upce 07832309 moon run cmd/main -- isbn 9780306406157 moon run cmd/main -- issn 03785955

    $ moon run cmd/main -- imei 490154203237518 imei: 490154203237518 tac: 49015420 serial: 323751 check digit: 8 status: valid $ moon run cmd/main -- lei 529900T8BM49AURSDO55 lei: 529900T8BM49AURSDO55 lou: 5299 expected check digits: 55 status: valid $ moon run cmd/main -- gtin 4006381333931 gtin: 4006381333931 expected check digit: 1 status: valid $ moon run cmd/main -- upce 07832309 upce: 07832309 expands to: 078000003239 expected check digit: 9 status: valid $ moon run cmd/main -- isbn 9780306406157 isbn: 9780306406157 form: isbn-13 expected check digit: 7 status: valid

    #与现有库的关系(互补边界)

    生态里已经有一批通用校验 / schema 库,它们与本库处理的层次不同,因此是互补而非重叠:

    已有库它解决的问题与本库的边界
    Betterlol/moon_zod、cosgammmmma/moonschema、QuietlyChan/moonschema、mizchi/jsonschemaJSON / 数据结构的 schema 校验:字段类型、必填、email / uuid / url 等格式约束它们校验数据的形状与格式,不做任何算术校验位运算。本库只做数字标识符的校验位算法,不解析 JSON,也不定义 schema。
    ryota0624/moovalid、kosei28/maru通用校验组合子(Validated、错误累积、in_range 等)它们提供校验框架;本库提供具体领域算法。本库不提供错误累积或组合子 API。
    Han-Wentao/mooncontractOpenAPI 契约校验与 mock它校验接口契约(请求 / 响应结构),属于 API 层;本库处理的是单个标识符字符串内部的校验位。
    ZJH-666-ZJH/moonmrzICAO 9303 机读区(护照 / 签证 MRZ)的 7-3-1 校验位唯一的交集是"校验位"这个概念。它面向旅行证件 MRZ 文本,使用 ICAO 9303 的 7-3-1 加权方案;本库面向支付卡 / 银行账号 / 设备号 / 证券与法人标识,使用 Luhn、Verhoeff、Damm、ISO 7064 与 mod-97。两者的算法、输入格式、应用领域均不同。

    在 mooncakes.io 上以 luhn、iban、imei、aadhaar、vin、isin、lei、 uscc、cpf、cnpj、bsn、codice fiscale、ean、gtin、isbn、issn 检索,目前没有任何模块命中;本库填补的是这一块空白。

    #Testing

    moon test

    97 tests cover the three algorithms against published reference vectors, the issuer-range overlap boundaries, IBAN's published examples, the worked examples of each identifier standard, the internal lookup tables, and malformed input. The LEI vectors are identifiers registered with GLEIF, so the expected check digits come from the registry rather than from a restatement of the algorithm.

    robustness_test.mbt additionally drives every public entry point with hostile input — empty and whitespace-only strings, full-width and Arabic-Indic digits, over-long strings, inner spaces, a trailing NUL — to pin down the promise that every function is total: invalid input returns false or None, never a panic. With the boundary tests in checkdigit_test.mbt, the suite now stands at 97.

    The command output recorded in this file and in docs/reproducible-demo.md is itself checked, so it cannot silently go stale:

    node scripts/check-docs.mjs

    That script re-runs the documented commands and compares the results line by line, including the test count quoted above.

    #Development

    #Runnable example

    moon run cmd/demo

    cmd/demo is a tour of all twenty-one identifiers. Every line it prints is produced by the library at run time, and the last section shows five pieces of junk input being rejected without a panic.

    #References

    • ISO/IEC 7812 — Identification cards, issuer identification numbers
    • ISO 13616 — International Bank Account Number (IBAN), mod-97-10
    • 3GPP TS 23.003 — Numbering, addressing and identification (IMEI)
    • GB 11643 — 公民身份号码 (Chinese resident identity card number)
    • GB 32100 — 法人和其他组织统一社会信用代码编码规则 (unified social credit identifier)
    • ISO 3779 — Vehicle Identification Number (VIN), world manufacturer identifier
    • ISO 6166 — International Securities Identification Number (ISIN)
    • ISO 17442 — Legal Entity Identifier (LEI)
    • GS1 General Specifications — GTIN check digit and UPC-E zero suppression
    • ISO 2108 — International Standard Book Number (ISBN)
    • ISO 3297 — International Standard Serial Number (ISSN)
    • UIDAI — Aadhaar number specification (Verhoeff check digit)
    • Receita Federal — CPF and CNPJ check-digit specification
    • De Nederlandsche Bank — BSN eleven-test (11-proef)
    • DM 23/12/1976 — Codice fiscale, CIN computation
    • GLEIF — Global LEI registry, api.gleif.org
    • H. P. Damm, Totally anti-symmetric quasigroups for all orders n ≠ 2 mod 4
    • J. Verhoeff, Error detecting decimal codes

    #License

    Apache-2.0. See LICENSE.

    CardBrand

    pub enum CardBrand {
    Visa
    Mastercard
    Amex
    Discover
    Jcb
    DinersClub
    UnionPay
    Maestro
    Unknown
    }

    Recognised card networks. Unknown means no issuer range matched.
    impl Show for CardBrand

    CardBrand::output

    fn CardBrand::output(self : CardBrand, logger : &Logger) -> Unit

    Show has two methods, output and to_string, and #must_implement_one lets an impl supply either. The one it leaves to the default is still promoted onto CardBrand as a regular method, which the compiler warns about (E0079) because a later refactor could drop it without notice. Both are named here so the promotion is stated rather than implied.

    CardBrand::to_string

    fn CardBrand::to_string(self : CardBrand) -> String

    Show has two methods, output and to_string, and #must_implement_one lets an impl supply either. The one it leaves to the default is still promoted onto CardBrand as a regular method, which the compiler warns about (E0079) because a later refactor could drop it without notice. Both are named here so the promotion is stated rather than implied.

    aadhaar_check_digit

    fn aadhaar_check_digit(first11 : String) -> Int?

    Verhoeff check digit for the first eleven digits of an Aadhaar number.

    aadhaar_valid

    fn aadhaar_valid(s : String) -> Bool

    Validate a 12-digit Aadhaar number.

    bsn_check_digit

    fn bsn_check_digit(first8 : String) -> Int?

    The ninth digit implied by the first eight. Returns None when the first eight digits do not fix a digit, which happens when the required value would have to be ten.

    bsn_valid

    fn bsn_valid(s : String) -> Bool

    Validate a BSN. Both the nine-digit form and the eight-digit form with its leading zero omitted are accepted. An all-zero number satisfies the arithmetic but is never issued, so it is rejected.

    card_format

    fn card_format(s : String) -> String?

    Group the digits into blocks of four for display, e.g. "3782 8224 6310 005". Returns None unless every character is a digit.

    card_valid

    fn card_valid(s : String) -> Bool

    Full card check: a known brand, a valid length for that brand, and a correct Luhn check digit.

    cf_check_char

    fn cf_check_char(first15 : String) -> String?

    The check letter that belongs after the first 15 characters of a codice fiscale.

    cf_valid

    fn cf_valid(s : String) -> Bool

    Validate a 16-character codice fiscale, including the layout the code is required to follow: six letters, two numeric characters, a month letter, two numeric characters, a letter, three numeric characters and the check letter. Lowercase input is accepted.

    cn_id_birthdate

    fn cn_id_birthdate(s : String) -> String?

    The eight birth-date digits as YYYYMMDD, or None when the number is not valid.

    cn_id_check_char

    fn cn_id_check_char(first17 : String) -> String?

    The check character that should follow the first 17 digits of an identity card number, as a string ("0".."9" or "X").

    cn_id_region

    fn cn_id_region(s : String) -> String?

    The six-digit administrative division code, or None when the number is not valid.

    cn_id_valid

    fn cn_id_valid(s : String) -> Bool

    Validate an 18-character resident identity card number. Lowercase "x" is accepted for the check character.

    cnpj_check_digits

    fn cnpj_check_digits(first12 : String) -> String?

    The two check digits implied by the first twelve digits of a CNPJ. The digit rule itself is the shared one from the CPF module.

    cnpj_format

    fn cnpj_format(s : String) -> String?

    The usual display form, 00.000.000/0000-00, or None when the input is not fourteen digits.

    cnpj_valid

    fn cnpj_valid(s : String) -> Bool

    Validate a 14-digit CNPJ, including both check digits. Punctuation is not accepted; strip it first.

    cpf_check_digits

    fn cpf_check_digits(first9 : String) -> String?

    The two check digits implied by the first nine digits of a CPF.

    cpf_format

    fn cpf_format(s : String) -> String?

    The usual display form, 000.000.000-00, or None when the input is not eleven digits.

    cpf_valid

    fn cpf_valid(s : String) -> Bool

    Validate an 11-digit CPF, including both check digits. Punctuation is not accepted; strip it first.

    damm_check_digit

    fn damm_check_digit(payload : String) -> Int?

    Compute the Damm check digit that should be appended to payload.

    damm_valid

    fn damm_valid(s : String) -> Bool

    Validate a number that already carries its Damm check digit.

    detect_brand

    fn detect_brand(s : String) -> CardBrand

    Identify the card network from its issuer range. The most specific ranges are tested first (Discover's 622126-622925 range overlaps UnionPay's 62).

    ean13_valid

    fn ean13_valid(s : String) -> Bool

    Validate a thirteen-digit EAN-13, the standard international retail code. ISBN-13 and ISSN are both restrictions of this shape.

    ean8_valid

    fn ean8_valid(s : String) -> Bool

    Validate an eight-digit EAN-8, the short retail code used on small packages.

    gtin14_valid

    fn gtin14_valid(s : String) -> Bool

    Validate a fourteen-digit GTIN-14, the shipping-container level of the GTIN hierarchy.

    gtin_check_digit

    fn gtin_check_digit(payload : String) -> Int?

    The GTIN check digit for a payload of digits: the digit that, appended, makes the alternating-weight sum a multiple of ten. Weights are 3 and 1 starting with 3 at the rightmost payload digit, which is the weight the position to the left of the check digit always carries. Returns None unless every character is a digit.

    gtin_valid

    fn gtin_valid(s : String) -> Bool

    Validate any GTIN by its own length: eight, twelve, thirteen or fourteen digits. Any other length is invalid, since those are the four registered GTIN sizes.

    iban_assemble

    fn iban_assemble(country : String, bban : String) -> String?

    Assemble a complete IBAN from a country code and a BBAN. The result is always check-digit correct; it is not checked against any national BBAN format, only against the ISO 13616 length and check digits.

    iban_bban

    fn iban_bban(s : String) -> String?

    The country part of an IBAN: everything after the four-character header.

    iban_check_digits

    fn iban_check_digits(country : String, bban : String) -> String?

    Compute the two check digits that turn a country code and BBAN into a complete IBAN. For example iban_check_digits("GB", "WEST12345698765432") gives "82". The country must be registered and the total length must match the registered length for that country.

    iban_country

    fn iban_country(s : String) -> String?

    The two-letter country code of an IBAN, or None when it is malformed.

    iban_expected_length

    fn iban_expected_length(cc : String) -> Int?

    The registered IBAN length for a country code, or None if unrecognised.

    iban_format

    fn iban_format(s : String) -> String?

    Group a valid IBAN into blocks of four for display, e.g. "GB82 WEST 1234 5698 7654 32". Returns None when the input is not valid.

    iban_normalize

    fn iban_normalize(s : String) -> String

    Strip spaces and uppercase so a human-formatted IBAN can be checked. Only ASCII letters and digits survive.

    iban_valid

    fn iban_valid(s : String) -> Bool

    Validate an IBAN, ignoring spaces and case. Checks the country code, the registered length for that country, and the mod-97 check digits.

    imei_check_digit

    fn imei_check_digit(first14 : String) -> Int?

    Compute the check digit for the first 14 digits of an IMEI.

    imei_serial

    fn imei_serial(s : String) -> String?

    The 6-digit serial number: digits 9 through 14 of an IMEI.

    imei_tac

    fn imei_tac(s : String) -> String?

    The Type Allocation Code: the first 8 digits of an IMEI.

    imei_valid

    fn imei_valid(s : String) -> Bool

    Validate a complete 15-digit IMEI, including its Luhn check digit.

    isbn10_check_char

    fn isbn10_check_char(first9 : String) -> Char?

    The check character for the first nine digits of an ISBN-10. It is a digit, or 'X' for the value ten. Weights run 10 down to 2. Returns None unless all nine characters are digits.

    isbn10_to_isbn13

    fn isbn10_to_isbn13(s : String) -> String?

    Convert a ten-character ISBN-10 to its thirteen-digit ISBN-13 form: prepend 978 to the nine data digits and recompute the check digit. Returns None when the input is not a well-formed ISBN-10.

    isbn10_valid

    fn isbn10_valid(s : String) -> Bool

    Validate a ten-character ISBN-10. The last character may be 'X'; a lowercase 'x' is accepted.

    isbn13_check_digit

    fn isbn13_check_digit(first12 : String) -> Int?

    The check digit of the thirteen-digit ISBN form for a twelve-digit payload. The payload must begin with the 978 or 979 bookland prefix, so an arbitrary EAN-13 is not accepted here. Returns None otherwise.

    isbn13_valid

    fn isbn13_valid(s : String) -> Bool

    Validate a thirteen-character ISBN-13: an EAN-13 whose prefix is 978 or 979.

    isin_check_digit

    fn isin_check_digit(first11 : String) -> Int?

    The Luhn check digit implied by the first eleven characters of an ISIN.

    isin_country

    fn isin_country(s : String) -> String?

    The two-letter country code of an ISIN, or None when it is malformed.

    isin_valid

    fn isin_valid(s : String) -> Bool

    Validate a 12-character ISIN. Lowercase input is accepted.

    issn_check_char

    fn issn_check_char(first7 : String) -> Char?

    The check character for the first seven digits of an ISSN. It is a digit or 'X'. Weights run 8 down to 2. Returns None unless all seven are digits.

    issn_valid

    fn issn_valid(s : String) -> Bool

    Validate an eight-character ISSN. The last character may be 'X'; a lowercase 'x' is accepted.

    lei_check_digits

    fn lei_check_digits(first18 : String) -> String?

    The two check digits that belong at the end of an LEI. Given the first eighteen characters, this returns the digits that make the whole identifier valid.

    lei_lou

    fn lei_lou(s : String) -> String?

    The four-character local operating unit prefix of an LEI, or None when the identifier is not valid.

    lei_valid

    fn lei_valid(s : String) -> Bool

    Validate a 20-character LEI. Lowercase input is accepted.

    luhn_check_digit

    fn luhn_check_digit(payload : String) -> Int?

    Compute the Luhn check digit that should be appended to payload.

    luhn_valid

    fn luhn_valid(s : String) -> Bool

    Validate a number that already carries its Luhn check digit.

    upca_valid

    fn upca_valid(s : String) -> Bool

    Validate a twelve-digit UPC-A, the North American retail code.

    upce_check_digit

    fn upce_check_digit(first7 : String) -> Int?

    The UPC-A check digit implied by the first seven characters of a UPC-E.

    upce_expand

    fn upce_expand(s : String) -> String?

    Expand an eight-character UPC-E to the twelve-digit UPC-A it stands for. The check digit is recomputed from the expanded payload, so a UPC-E whose own check digit is wrong still expands to a well-formed UPC-A. Returns None unless the input is eight digits with a number system of 0 or 1.

    upce_valid

    fn upce_valid(s : String) -> Bool

    Validate an eight-character UPC-E. Its check digit must equal the one the expanded UPC-A would carry.

    uscc_check_char

    fn uscc_check_char(first17 : String) -> String?

    The check character that should follow the first 17 characters of a unified social credit identifier.

    uscc_division

    fn uscc_division(s : String) -> String?

    The six-character administrative division code, characters three to eight, or None when the identifier is not valid.

    uscc_valid

    fn uscc_valid(s : String) -> Bool

    Validate an 18-character unified social credit identifier. Lowercase input is accepted.

    verhoeff_check_digit

    fn verhoeff_check_digit(payload : String) -> Int?

    Compute the Verhoeff check digit that should be appended to payload.

    verhoeff_valid

    fn verhoeff_valid(s : String) -> Bool

    Validate a number that already carries its Verhoeff check digit.

    vin_check_char

    fn vin_check_char(first17 : String) -> String?

    The check character that belongs in position nine, as a string ("0".."9" or "X").

    vin_valid

    fn vin_valid(s : String) -> Bool

    Validate a 17-character VIN, including its check character. Lowercase input is accepted.

    vin_vis

    fn vin_vis(s : String) -> String?

    The Vehicle Identifier Section: the last eight characters, or None when the VIN is not valid.

    vin_wmi

    fn vin_wmi(s : String) -> String?

    The World Manufacturer Identifier: the first three characters, or None when the VIN is not valid.