///|
/// EAN-13 L-code(奇校验,左手区)。
let l_code : Array[String] = [
"0001101", "0011001", "0010011", "0111101", "0100011", "0110001", "0101111", "0111011",
"0110111", "0001011",
]
///|
/// EAN-13 G-code(偶校验,左手区,由首数字的奇偶模式选择)。
let g_code : Array[String] = [
"0100111", "0110011", "0011011", "0100001", "0011101", "0111001", "0000101", "0010001",
"0001001", "0010111",
]
///|
/// EAN-13 R-code(右手区,与 L-code 逐位取反)。
let r_code : Array[String] = [
"1110010", "1100110", "1101100", "1000010", "1011100", "1001110", "1010000", "1000100",
"1001000", "1110100",
]
///|
/// 首数字对应的左手 6 位奇偶模式(0=L,1=G)。
let ean13_parity : Array[String] = [
"000000", "001011", "001101", "001110", "010011", "011001", "011100", "010101",
"010110", "011010",
]
///|
/// 将一个 "01" 模式的字符串追加到模块数组。
fn append_pattern(modules : Array[Bool], pattern : String) -> Unit {
let p = @utf8.encode(pattern)
for i = 0; i < p.length(); i = i + 1 {
modules.push(p[i] == b'1')
}
}
///|
/// 编码 EAN-13。
///
/// 输入为 12 位(自动追加校验位)或 13 位(校验校验位是否匹配)。
/// 输出 95 个模块。
pub fn encode_ean13(data : String) -> Result[Barcode, EncodeError] {
if !only_digits_and_separators(data) {
return Err(
InvalidData("EAN-13 data must contain only digits and separators"),
)
}
let d = strip_separators(data)
if d.length() == 12 {
match mod10_check(d, 1, 3) {
Err(msg) => return Err(InvalidData(msg))
Ok(check) => return encode_ean13_fixed(d + check.to_string())
}
}
if d.length() != 13 {
return Err(
InvalidData(
"EAN-13 requires 12 digits (check digit is appended) or 13 digits",
),
)
}
if !mod10_verify(d, 1, 3) {
return Err(InvalidData("EAN-13 check digit mismatch"))
}
encode_ean13_fixed(d)
}
///|
/// 按 13 位完整数字(含校验位)生成模块序列。
fn encode_ean13_fixed(digits : String) -> Result[Barcode, EncodeError] {
if digits.length() != 13 || !is_all_digits(digits) {
return Err(InvalidData("EAN-13 requires 13 decimal digits"))
}
let b = @utf8.encode(digits)
let first = (b[0] - b'0').to_int()
let parity = ean13_parity[first]
let pb = @utf8.encode(parity)
let modules : Array[Bool] = []
append_pattern(modules, "101")
for i = 1; i <= 6; i = i + 1 {
let v = (b[i] - b'0').to_int()
let pattern = if pb[i - 1] == b'1' { g_code[v] } else { l_code[v] }
append_pattern(modules, pattern)
}
append_pattern(modules, "01010")
for i = 7; i < 13; i = i + 1 {
let v = (b[i] - b'0').to_int()
append_pattern(modules, r_code[v])
}
append_pattern(modules, "101")
Ok({ symbology: EAN13, data: digits, modules })
}
///|
/// 编码 EAN-8。
///
/// 输入为 7 位(自动追加校验位)或 8 位(校验校验位)。输出 67 个模块。
pub fn encode_ean8(data : String) -> Result[Barcode, EncodeError] {
if !only_digits_and_separators(data) {
return Err(
InvalidData("EAN-8 data must contain only digits and separators"),
)
}
let d = strip_separators(data)
if d.length() == 7 {
match mod10_check(d, 3, 1) {
Err(msg) => return Err(InvalidData(msg))
Ok(check) => return encode_ean8_fixed(d + check.to_string())
}
}
if d.length() != 8 {
return Err(
InvalidData(
"EAN-8 requires 7 digits (check digit is appended) or 8 digits",
),
)
}
if !mod10_verify(d, 3, 1) {
return Err(InvalidData("EAN-8 check digit mismatch"))
}
encode_ean8_fixed(d)
}
///|
/// 按 8 位完整数字(含校验位)生成模块序列。
fn encode_ean8_fixed(digits : String) -> Result[Barcode, EncodeError] {
if digits.length() != 8 || !is_all_digits(digits) {
return Err(InvalidData("EAN-8 requires 8 decimal digits"))
}
let b = @utf8.encode(digits)
let modules : Array[Bool] = []
append_pattern(modules, "101")
for i = 0; i < 4; i = i + 1 {
let v = (b[i] - b'0').to_int()
append_pattern(modules, l_code[v])
}
append_pattern(modules, "01010")
for i = 4; i < 8; i = i + 1 {
let v = (b[i] - b'0').to_int()
append_pattern(modules, r_code[v])
}
append_pattern(modules, "101")
Ok({ symbology: EAN8, data: digits, modules })
}
///|
/// 编码 UPC-A。
///
/// 输入为 11 位(自动追加校验位)或 12 位(校验校验位)。
/// UPC-A 等价于首位为 0 的 EAN-13,输出 95 个模块。
pub fn encode_upca(data : String) -> Result[Barcode, EncodeError] {
if !only_digits_and_separators(data) {
return Err(
InvalidData("UPC-A data must contain only digits and separators"),
)
}
let d = strip_separators(data)
if d.length() == 11 {
match mod10_check(d, 3, 1) {
Err(msg) => return Err(InvalidData(msg))
Ok(check) => return encode_upca_fixed(d + check.to_string())
}
}
if d.length() != 12 {
return Err(
InvalidData(
"UPC-A requires 11 digits (check digit is appended) or 12 digits",
),
)
}
if !mod10_verify(d, 3, 1) {
return Err(InvalidData("UPC-A check digit mismatch"))
}
encode_upca_fixed(d)
}
///|
/// 按 12 位完整 UPC-A 数字(含校验位)生成模块序列。
fn encode_upca_fixed(digits : String) -> Result[Barcode, EncodeError] {
if digits.length() != 12 || !is_all_digits(digits) {
return Err(InvalidData("UPC-A requires 12 decimal digits"))
}
match encode_ean13_fixed("0" + digits) {
Err(e) => Err(e)
Ok(b) => Ok({ symbology: UPCA, data: digits, modules: b.modules })
}
}