feat: 版本参数表 — 40 版本容量 + 自动选择
This commit is contained in:
+295
-1
@@ -1 +1,295 @@
|
|||||||
// FIXME: 版本参数表 — Task 3
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
/// 纠错级别
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum EcLevel {
|
||||||
|
L, // 约 7%
|
||||||
|
M, // 约 15%
|
||||||
|
Q, // 约 25%
|
||||||
|
H, // 约 30%
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EcLevel {
|
||||||
|
/// 格式信息中使用的指示位
|
||||||
|
pub fn indicator_bits(self) -> u8 {
|
||||||
|
match self {
|
||||||
|
EcLevel::L => 0b01,
|
||||||
|
EcLevel::M => 0b00,
|
||||||
|
EcLevel::Q => 0b11,
|
||||||
|
EcLevel::H => 0b10,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 版本号 1~40
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct Version(pub u8);
|
||||||
|
|
||||||
|
impl Version {
|
||||||
|
pub fn new(v: u8) -> Option<Self> {
|
||||||
|
if (1..=40).contains(&v) { Some(Version(v)) } else { None }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// QR 码边长(模块数)
|
||||||
|
pub fn size(self) -> u8 {
|
||||||
|
17 + self.0 * 4
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 对齐图案位置列表
|
||||||
|
pub fn alignment_positions(self) -> &'static [u8] {
|
||||||
|
&ALIGNMENT_POSITIONS[self.0 as usize - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取该版本+级别的纠错信息
|
||||||
|
pub fn ec_info(self, level: EcLevel) -> EcInfo {
|
||||||
|
let row = &VERSION_TABLE[self.0 as usize - 1];
|
||||||
|
let (total, ec_per_block, g1_blocks, g1_data, g2_blocks, g2_data) = match level {
|
||||||
|
EcLevel::L => (row.l_total, row.l_ec, row.l_g1, row.l_g1_data, row.l_g2, row.l_g2_data),
|
||||||
|
EcLevel::M => (row.m_total, row.m_ec, row.m_g1, row.m_g1_data, row.m_g2, row.m_g2_data),
|
||||||
|
EcLevel::Q => (row.q_total, row.q_ec, row.q_g1, row.q_g1_data, row.q_g2, row.q_g2_data),
|
||||||
|
EcLevel::H => (row.h_total, row.h_ec, row.h_g1, row.h_g1_data, row.h_g2, row.h_g2_data),
|
||||||
|
};
|
||||||
|
EcInfo {
|
||||||
|
total_codewords: total,
|
||||||
|
ec_per_block,
|
||||||
|
blocks: vec![
|
||||||
|
BlockInfo { count: g1_blocks, data_codewords: g1_data },
|
||||||
|
BlockInfo { count: g2_blocks, data_codewords: g2_data },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EcInfo {
|
||||||
|
pub total_codewords: u16,
|
||||||
|
pub ec_per_block: u8,
|
||||||
|
pub blocks: Vec<BlockInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BlockInfo {
|
||||||
|
pub count: u16,
|
||||||
|
pub data_codewords: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 单行版本数据
|
||||||
|
struct VersionRow {
|
||||||
|
l_total: u16, l_ec: u8, l_g1: u16, l_g1_data: u16, l_g2: u16, l_g2_data: u16,
|
||||||
|
m_total: u16, m_ec: u8, m_g1: u16, m_g1_data: u16, m_g2: u16, m_g2_data: u16,
|
||||||
|
q_total: u16, q_ec: u8, q_g1: u16, q_g1_data: u16, q_g2: u16, q_g2_data: u16,
|
||||||
|
h_total: u16, h_ec: u8, h_g1: u16, h_g1_data: u16, h_g2: u16, h_g2_data: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ISO 18004 附录 I — 40 版本 × 4 纠错级别的容量表
|
||||||
|
/// 格式: (总码字数, EC码字/块, 组1块数, 组1数据码字数, 组2块数, 组2数据码字数)
|
||||||
|
/// 当 g2_data == 0 时,表示仅有一组
|
||||||
|
static VERSION_TABLE: [VersionRow; 40] = [
|
||||||
|
// 版本 1
|
||||||
|
VersionRow { l_total:26, l_ec:7, l_g1:1, l_g1_data:19, l_g2:0, l_g2_data:0, m_total:26, m_ec:10, m_g1:1, m_g1_data:16, m_g2:0, m_g2_data:0, q_total:26, q_ec:13, q_g1:1, q_g1_data:13, q_g2:0, q_g2_data:0, h_total:26, h_ec:17, h_g1:1, h_g1_data:9, h_g2:0, h_g2_data:0 },
|
||||||
|
// 版本 2
|
||||||
|
VersionRow { l_total:44, l_ec:10, l_g1:1, l_g1_data:34, l_g2:0, l_g2_data:0, m_total:44, m_ec:16, m_g1:1, m_g1_data:28, m_g2:0, m_g2_data:0, q_total:44, q_ec:22, q_g1:1, q_g1_data:22, q_g2:0, q_g2_data:0, h_total:44, h_ec:28, h_g1:1, h_g1_data:16, h_g2:0, h_g2_data:0 },
|
||||||
|
// 版本 3
|
||||||
|
VersionRow { l_total:70, l_ec:15, l_g1:1, l_g1_data:55, l_g2:0, l_g2_data:0, m_total:70, m_ec:26, m_g1:1, m_g1_data:44, m_g2:0, m_g2_data:0, q_total:70, q_ec:18, q_g1:2, q_g1_data:17, q_g2:0, q_g2_data:0, h_total:70, h_ec:22, h_g1:2, h_g1_data:13, h_g2:0, h_g2_data:0 },
|
||||||
|
// 版本 4
|
||||||
|
VersionRow { l_total:100, l_ec:20, l_g1:1, l_g1_data:80, l_g2:0, l_g2_data:0, m_total:100, m_ec:18, m_g1:2, m_g1_data:32, m_g2:0, m_g2_data:0, q_total:100, q_ec:26, q_g1:2, q_g1_data:24, q_g2:0, q_g2_data:0, h_total:100, h_ec:16, h_g1:4, h_g1_data:9, h_g2:0, h_g2_data:0 },
|
||||||
|
// 版本 5
|
||||||
|
VersionRow { l_total:134, l_ec:26, l_g1:1, l_g1_data:108, l_g2:0, l_g2_data:0, m_total:134, m_ec:24, m_g1:2, m_g1_data:43, m_g2:0, m_g2_data:0, q_total:134, q_ec:18, q_g1:2, q_g1_data:15, q_g2:2, q_g2_data:16, h_total:134, h_ec:22, h_g1:4, h_g1_data:11, h_g2:2, h_g2_data:12 },
|
||||||
|
// 版本 6
|
||||||
|
VersionRow { l_total:172, l_ec:18, l_g1:2, l_g1_data:68, l_g2:0, l_g2_data:0, m_total:172, m_ec:16, m_g1:4, m_g1_data:27, m_g2:0, m_g2_data:0, q_total:172, q_ec:24, q_g1:4, q_g1_data:19, q_g2:0, q_g2_data:0, h_total:172, h_ec:28, h_g1:4, h_g1_data:15, h_g2:0, h_g2_data:0 },
|
||||||
|
// 版本 7
|
||||||
|
VersionRow { l_total:196, l_ec:20, l_g1:2, l_g1_data:78, l_g2:0, l_g2_data:0, m_total:196, m_ec:18, m_g1:4, m_g1_data:31, m_g2:0, m_g2_data:0, q_total:196, q_ec:18, q_g1:2, q_g1_data:14, q_g2:4, q_g2_data:15, h_total:196, h_ec:26, h_g1:4, h_g1_data:13, h_g2:1, h_g2_data:14 },
|
||||||
|
// 版本 8
|
||||||
|
VersionRow { l_total:242, l_ec:24, l_g1:2, l_g1_data:97, l_g2:0, l_g2_data:0, m_total:242, m_ec:22, m_g1:2, m_g1_data:38, m_g2:2, m_g2_data:39, q_total:242, q_ec:22, q_g1:4, q_g1_data:18, q_g2:2, q_g2_data:19, h_total:242, h_ec:26, h_g1:4, h_g1_data:14, h_g2:2, h_g2_data:15 },
|
||||||
|
// 版本 9
|
||||||
|
VersionRow { l_total:292, l_ec:30, l_g1:2, l_g1_data:116, l_g2:0, l_g2_data:0, m_total:292, m_ec:22, m_g1:3, m_g1_data:36, m_g2:2, m_g2_data:37, q_total:292, q_ec:20, q_g1:4, q_g1_data:16, q_g2:4, q_g2_data:17, h_total:292, h_ec:24, h_g1:4, h_g1_data:12, h_g2:4, h_g2_data:13 },
|
||||||
|
// 版本 10
|
||||||
|
VersionRow { l_total:346, l_ec:18, l_g1:2, l_g1_data:68, l_g2:2, l_g2_data:69, m_total:346, m_ec:26, m_g1:4, m_g1_data:43, m_g2:1, m_g2_data:44, q_total:346, q_ec:24, q_g1:6, q_g1_data:19, q_g2:2, q_g2_data:20, h_total:346, h_ec:28, h_g1:6, h_g1_data:15, h_g2:2, h_g2_data:16 },
|
||||||
|
// 版本 11
|
||||||
|
VersionRow { l_total:404, l_ec:20, l_g1:4, l_g1_data:81, l_g2:0, l_g2_data:0, m_total:404, m_ec:30, m_g1:1, m_g1_data:50, m_g2:4, m_g2_data:51, q_total:404, q_ec:28, q_g1:4, q_g1_data:22, q_g2:4, q_g2_data:23, h_total:404, h_ec:24, h_g1:3, h_g1_data:12, h_g2:8, h_g2_data:13 },
|
||||||
|
// 版本 12
|
||||||
|
VersionRow { l_total:466, l_ec:24, l_g1:2, l_g1_data:92, l_g2:2, l_g2_data:93, m_total:466, m_ec:22, m_g1:6, m_g1_data:36, m_g2:2, m_g2_data:37, q_total:466, q_ec:26, q_g1:4, q_g1_data:20, q_g2:6, q_g2_data:21, h_total:466, h_ec:28, h_g1:7, h_g1_data:14, h_g2:4, h_g2_data:15 },
|
||||||
|
// 版本 13
|
||||||
|
VersionRow { l_total:532, l_ec:26, l_g1:4, l_g1_data:107, l_g2:0, l_g2_data:0, m_total:532, m_ec:22, m_g1:8, m_g1_data:37, m_g2:1, m_g2_data:38, q_total:532, q_ec:24, q_g1:8, q_g1_data:20, q_g2:4, q_g2_data:21, h_total:532, h_ec:22, h_g1:12, h_g1_data:11, h_g2:4, h_g2_data:12 },
|
||||||
|
// 版本 14
|
||||||
|
VersionRow { l_total:581, l_ec:30, l_g1:3, l_g1_data:115, l_g2:1, l_g2_data:116, m_total:581, m_ec:24, m_g1:4, m_g1_data:40, m_g2:5, m_g2_data:41, q_total:581, q_ec:20, q_g1:11, q_g1_data:16, q_g2:5, q_g2_data:17, h_total:581, h_ec:24, h_g1:11, h_g1_data:12, h_g2:5, h_g2_data:13 },
|
||||||
|
// 版本 15
|
||||||
|
VersionRow { l_total:655, l_ec:22, l_g1:5, l_g1_data:87, l_g2:1, l_g2_data:88, m_total:655, m_ec:24, m_g1:5, m_g1_data:41, m_g2:5, m_g2_data:42, q_total:655, q_ec:30, q_g1:5, q_g1_data:24, q_g2:7, q_g2_data:25, h_total:655, h_ec:24, h_g1:11, h_g1_data:12, h_g2:7, h_g2_data:13 },
|
||||||
|
// 版本 16
|
||||||
|
VersionRow { l_total:733, l_ec:24, l_g1:5, l_g1_data:98, l_g2:1, l_g2_data:99, m_total:733, m_ec:28, m_g1:7, m_g1_data:45, m_g2:3, m_g2_data:46, q_total:733, q_ec:24, q_g1:15, q_g1_data:19, q_g2:2, q_g2_data:20, h_total:733, h_ec:30, h_g1:3, h_g1_data:15, h_g2:13, h_g2_data:16 },
|
||||||
|
// 版本 17
|
||||||
|
VersionRow { l_total:815, l_ec:28, l_g1:1, l_g1_data:107, l_g2:5, l_g2_data:108, m_total:815, m_ec:28, m_g1:10, m_g1_data:46, m_g2:1, m_g2_data:47, q_total:815, q_ec:28, q_g1:1, q_g1_data:22, q_g2:15, q_g2_data:23, h_total:815, h_ec:28, h_g1:2, h_g1_data:14, h_g2:17, h_g2_data:15 },
|
||||||
|
// 版本 18
|
||||||
|
VersionRow { l_total:901, l_ec:30, l_g1:5, l_g1_data:120, l_g2:1, l_g2_data:121, m_total:901, m_ec:26, m_g1:9, m_g1_data:43, m_g2:4, m_g2_data:44, q_total:901, q_ec:28, q_g1:17, q_g1_data:22, q_g2:1, q_g2_data:23, h_total:901, h_ec:28, h_g1:2, h_g1_data:14, h_g2:19, h_g2_data:15 },
|
||||||
|
// 版本 19
|
||||||
|
VersionRow { l_total:991, l_ec:28, l_g1:3, l_g1_data:113, l_g2:4, l_g2_data:114, m_total:991, m_ec:26, m_g1:3, m_g1_data:44, m_g2:11, m_g2_data:45, q_total:991, q_ec:26, q_g1:17, q_g1_data:21, q_g2:4, q_g2_data:22, h_total:991, h_ec:26, h_g1:9, h_g1_data:13, h_g2:16, h_g2_data:14 },
|
||||||
|
// 版本 20
|
||||||
|
VersionRow { l_total:1085, l_ec:28, l_g1:3, l_g1_data:107, l_g2:5, l_g2_data:108, m_total:1085, m_ec:26, m_g1:3, m_g1_data:41, m_g2:13, m_g2_data:42, q_total:1085, q_ec:30, q_g1:15, q_g1_data:24, q_g2:5, q_g2_data:25, h_total:1085, h_ec:28, h_g1:15, h_g1_data:15, h_g2:10, h_g2_data:16 },
|
||||||
|
// 版本 21
|
||||||
|
VersionRow { l_total:1156, l_ec:28, l_g1:4, l_g1_data:116, l_g2:4, l_g2_data:117, m_total:1156, m_ec:26, m_g1:17, m_g1_data:42, m_g2:0, m_g2_data:0, q_total:1156, q_ec:28, q_g1:17, q_g1_data:22, q_g2:6, q_g2_data:23, h_total:1156, h_ec:30, h_g1:19, h_g1_data:16, h_g2:6, h_g2_data:17 },
|
||||||
|
// 版本 22
|
||||||
|
VersionRow { l_total:1258, l_ec:28, l_g1:2, l_g1_data:111, l_g2:7, l_g2_data:112, m_total:1258, m_ec:28, m_g1:17, m_g1_data:46, m_g2:0, m_g2_data:0, q_total:1258, q_ec:30, q_g1:7, q_g1_data:24, q_g2:16, q_g2_data:25, h_total:1258, h_ec:24, h_g1:34, h_g1_data:13, h_g2:0, h_g2_data:0 },
|
||||||
|
// 版本 23
|
||||||
|
VersionRow { l_total:1364, l_ec:30, l_g1:4, l_g1_data:121, l_g2:5, l_g2_data:122, m_total:1364, m_ec:28, m_g1:4, m_g1_data:47, m_g2:14, m_g2_data:48, q_total:1364, q_ec:30, q_g1:11, q_g1_data:24, q_g2:14, q_g2_data:25, h_total:1364, h_ec:30, h_g1:16, h_g1_data:15, h_g2:14, h_g2_data:16 },
|
||||||
|
// 版本 24
|
||||||
|
VersionRow { l_total:1474, l_ec:30, l_g1:6, l_g1_data:117, l_g2:4, l_g2_data:118, m_total:1474, m_ec:28, m_g1:6, m_g1_data:45, m_g2:14, m_g2_data:46, q_total:1474, q_ec:30, q_g1:11, q_g1_data:24, q_g2:16, q_g2_data:25, h_total:1474, h_ec:30, h_g1:30, h_g1_data:16, h_g2:2, h_g2_data:17 },
|
||||||
|
// 版本 25
|
||||||
|
VersionRow { l_total:1588, l_ec:26, l_g1:8, l_g1_data:106, l_g2:4, l_g2_data:107, m_total:1588, m_ec:28, m_g1:8, m_g1_data:47, m_g2:13, m_g2_data:48, q_total:1588, q_ec:30, q_g1:7, q_g1_data:24, q_g2:22, q_g2_data:25, h_total:1588, h_ec:30, h_g1:22, h_g1_data:15, h_g2:13, h_g2_data:16 },
|
||||||
|
// 版本 26
|
||||||
|
VersionRow { l_total:1706, l_ec:28, l_g1:10, l_g1_data:114, l_g2:2, l_g2_data:115, m_total:1706, m_ec:28, m_g1:19, m_g1_data:46, m_g2:4, m_g2_data:47, q_total:1706, q_ec:28, q_g1:28, q_g1_data:22, q_g2:6, q_g2_data:23, h_total:1706, h_ec:30, h_g1:33, h_g1_data:16, h_g2:4, h_g2_data:17 },
|
||||||
|
// 版本 27
|
||||||
|
VersionRow { l_total:1828, l_ec:30, l_g1:8, l_g1_data:122, l_g2:4, l_g2_data:123, m_total:1828, m_ec:28, m_g1:22, m_g1_data:45, m_g2:3, m_g2_data:46, q_total:1828, q_ec:30, q_g1:8, q_g1_data:23, q_g2:26, q_g2_data:24, h_total:1828, h_ec:30, h_g1:12, h_g1_data:15, h_g2:28, h_g2_data:16 },
|
||||||
|
// 版本 28
|
||||||
|
VersionRow { l_total:1921, l_ec:30, l_g1:3, l_g1_data:117, l_g2:10, l_g2_data:118, m_total:1921, m_ec:28, m_g1:3, m_g1_data:45, m_g2:23, m_g2_data:46, q_total:1921, q_ec:30, q_g1:4, q_g1_data:24, q_g2:31, q_g2_data:25, h_total:1921, h_ec:30, h_g1:11, h_g1_data:15, h_g2:31, h_g2_data:16 },
|
||||||
|
// 版本 29
|
||||||
|
VersionRow { l_total:2051, l_ec:30, l_g1:7, l_g1_data:116, l_g2:7, l_g2_data:117, m_total:2051, m_ec:28, m_g1:21, m_g1_data:45, m_g2:7, m_g2_data:46, q_total:2051, q_ec:30, q_g1:1, q_g1_data:23, q_g2:37, q_g2_data:24, h_total:2051, h_ec:30, h_g1:19, h_g1_data:15, h_g2:26, h_g2_data:16 },
|
||||||
|
// 版本 30
|
||||||
|
VersionRow { l_total:2185, l_ec:30, l_g1:5, l_g1_data:115, l_g2:10, l_g2_data:116, m_total:2185, m_ec:28, m_g1:19, m_g1_data:47, m_g2:10, m_g2_data:48, q_total:2185, q_ec:30, q_g1:15, q_g1_data:24, q_g2:25, q_g2_data:25, h_total:2185, h_ec:30, h_g1:23, h_g1_data:15, h_g2:25, h_g2_data:16 },
|
||||||
|
// 版本 31
|
||||||
|
VersionRow { l_total:2323, l_ec:30, l_g1:13, l_g1_data:115, l_g2:3, l_g2_data:116, m_total:2323, m_ec:28, m_g1:2, m_g1_data:46, m_g2:29, m_g2_data:47, q_total:2323, q_ec:30, q_g1:42, q_g1_data:24, q_g2:1, q_g2_data:25, h_total:2323, h_ec:30, h_g1:23, h_g1_data:15, h_g2:28, h_g2_data:16 },
|
||||||
|
// 版本 32
|
||||||
|
VersionRow { l_total:2465, l_ec:30, l_g1:17, l_g1_data:115, l_g2:0, l_g2_data:0, m_total:2465, m_ec:28, m_g1:10, m_g1_data:46, m_g2:23, m_g2_data:47, q_total:2465, q_ec:30, q_g1:10, q_g1_data:24, q_g2:35, q_g2_data:25, h_total:2465, h_ec:30, h_g1:19, h_g1_data:15, h_g2:35, h_g2_data:16 },
|
||||||
|
// 版本 33
|
||||||
|
VersionRow { l_total:2611, l_ec:30, l_g1:17, l_g1_data:115, l_g2:1, l_g2_data:116, m_total:2611, m_ec:28, m_g1:14, m_g1_data:46, m_g2:21, m_g2_data:47, q_total:2611, q_ec:30, q_g1:29, q_g1_data:24, q_g2:19, q_g2_data:25, h_total:2611, h_ec:30, h_g1:11, h_g1_data:15, h_g2:46, h_g2_data:16 },
|
||||||
|
// 版本 34
|
||||||
|
VersionRow { l_total:2761, l_ec:30, l_g1:13, l_g1_data:115, l_g2:6, l_g2_data:116, m_total:2761, m_ec:28, m_g1:14, m_g1_data:46, m_g2:23, m_g2_data:47, q_total:2761, q_ec:30, q_g1:44, q_g1_data:24, q_g2:7, q_g2_data:25, h_total:2761, h_ec:30, h_g1:59, h_g1_data:16, h_g2:1, h_g2_data:17 },
|
||||||
|
// 版本 35
|
||||||
|
VersionRow { l_total:2876, l_ec:30, l_g1:12, l_g1_data:121, l_g2:7, l_g2_data:122, m_total:2876, m_ec:28, m_g1:12, m_g1_data:47, m_g2:26, m_g2_data:48, q_total:2876, q_ec:30, q_g1:39, q_g1_data:24, q_g2:14, q_g2_data:25, h_total:2876, h_ec:30, h_g1:22, h_g1_data:15, h_g2:41, h_g2_data:16 },
|
||||||
|
// 版本 36
|
||||||
|
VersionRow { l_total:3034, l_ec:30, l_g1:6, l_g1_data:121, l_g2:14, l_g2_data:122, m_total:3034, m_ec:28, m_g1:6, m_g1_data:47, m_g2:34, m_g2_data:48, q_total:3034, q_ec:30, q_g1:46, q_g1_data:24, q_g2:10, q_g2_data:25, h_total:3034, h_ec:30, h_g1:2, h_g1_data:15, h_g2:64, h_g2_data:16 },
|
||||||
|
// 版本 37
|
||||||
|
VersionRow { l_total:3196, l_ec:30, l_g1:17, l_g1_data:122, l_g2:4, l_g2_data:123, m_total:3196, m_ec:28, m_g1:29, m_g1_data:46, m_g2:14, m_g2_data:47, q_total:3196, q_ec:30, q_g1:49, q_g1_data:24, q_g2:10, q_g2_data:25, h_total:3196, h_ec:30, h_g1:24, h_g1_data:15, h_g2:46, h_g2_data:16 },
|
||||||
|
// 版本 38
|
||||||
|
VersionRow { l_total:3362, l_ec:30, l_g1:4, l_g1_data:122, l_g2:18, l_g2_data:123, m_total:3362, m_ec:28, m_g1:13, m_g1_data:46, m_g2:32, m_g2_data:47, q_total:3362, q_ec:30, q_g1:48, q_g1_data:24, q_g2:14, q_g2_data:25, h_total:3362, h_ec:30, h_g1:42, h_g1_data:15, h_g2:32, h_g2_data:16 },
|
||||||
|
// 版本 39
|
||||||
|
VersionRow { l_total:3532, l_ec:30, l_g1:20, l_g1_data:117, l_g2:4, l_g2_data:118, m_total:3532, m_ec:28, m_g1:40, m_g1_data:47, m_g2:7, m_g2_data:48, q_total:3532, q_ec:30, q_g1:43, q_g1_data:24, q_g2:22, q_g2_data:25, h_total:3532, h_ec:30, h_g1:10, h_g1_data:15, h_g2:67, h_g2_data:16 },
|
||||||
|
// 版本 40
|
||||||
|
VersionRow { l_total:3706, l_ec:30, l_g1:19, l_g1_data:118, l_g2:6, l_g2_data:119, m_total:3706, m_ec:28, m_g1:18, m_g1_data:47, m_g2:31, m_g2_data:48, q_total:3706, q_ec:30, q_g1:34, q_g1_data:24, q_g2:34, q_g2_data:25, h_total:3706, h_ec:30, h_g1:20, h_g1_data:15, h_g2:61, h_g2_data:16 },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 对齐图案中心位置表(每个版本的坐标数组)
|
||||||
|
static ALIGNMENT_POSITIONS: [&[u8]; 40] = [
|
||||||
|
&[], // v1 (无对齐图案)
|
||||||
|
&[6, 18], // v2
|
||||||
|
&[6, 22], // v3
|
||||||
|
&[6, 26], // v4
|
||||||
|
&[6, 30], // v5
|
||||||
|
&[6, 34], // v6
|
||||||
|
&[6, 22, 38], // v7
|
||||||
|
&[6, 24, 42], // v8
|
||||||
|
&[6, 26, 46], // v9
|
||||||
|
&[6, 28, 50], // v10
|
||||||
|
&[6, 30, 54], // v11
|
||||||
|
&[6, 32, 58], // v12
|
||||||
|
&[6, 34, 62], // v13
|
||||||
|
&[6, 26, 46, 66], // v14
|
||||||
|
&[6, 26, 48, 70], // v15
|
||||||
|
&[6, 26, 50, 74], // v16
|
||||||
|
&[6, 30, 54, 78], // v17
|
||||||
|
&[6, 30, 56, 82], // v18
|
||||||
|
&[6, 30, 58, 86], // v19
|
||||||
|
&[6, 34, 62, 90], // v20
|
||||||
|
&[6, 28, 50, 72, 94], // v21
|
||||||
|
&[6, 26, 50, 74, 98], // v22
|
||||||
|
&[6, 30, 54, 78, 102], // v23
|
||||||
|
&[6, 28, 54, 80, 106], // v24
|
||||||
|
&[6, 32, 58, 84, 110], // v25
|
||||||
|
&[6, 30, 58, 86, 114], // v26
|
||||||
|
&[6, 34, 62, 90, 118], // v27
|
||||||
|
&[6, 26, 50, 74, 98, 122], // v28
|
||||||
|
&[6, 30, 54, 78, 102, 126], // v29
|
||||||
|
&[6, 26, 52, 78, 104, 130], // v30
|
||||||
|
&[6, 30, 56, 82, 108, 134], // v31
|
||||||
|
&[6, 34, 60, 86, 112, 138], // v32
|
||||||
|
&[6, 30, 58, 86, 114, 142], // v33
|
||||||
|
&[6, 34, 62, 90, 118, 146], // v34
|
||||||
|
&[6, 30, 54, 78, 102, 126, 150], // v35
|
||||||
|
&[6, 24, 50, 76, 102, 128, 154], // v36
|
||||||
|
&[6, 28, 54, 80, 106, 132, 158], // v37
|
||||||
|
&[6, 32, 58, 84, 110, 136, 162], // v38
|
||||||
|
&[6, 26, 54, 82, 110, 138, 166], // v39
|
||||||
|
&[6, 30, 58, 86, 114, 142, 170], // v40
|
||||||
|
];
|
||||||
|
|
||||||
|
/// 获取某版本+级别的数据码字容量
|
||||||
|
fn init_capacity_table() -> [[u16; 4]; 40] {
|
||||||
|
let mut table = [[0u16; 4]; 40];
|
||||||
|
for v in 1..=40u8 {
|
||||||
|
let ver = Version(v);
|
||||||
|
let li: [EcLevel; 4] = [EcLevel::L, EcLevel::M, EcLevel::Q, EcLevel::H];
|
||||||
|
for (idx, &level) in li.iter().enumerate() {
|
||||||
|
let info = ver.ec_info(level);
|
||||||
|
let total_data: u16 = info.blocks.iter()
|
||||||
|
.map(|b| b.count * b.data_codewords)
|
||||||
|
.sum();
|
||||||
|
table[v as usize - 1][idx] = total_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_data_capacity(version: Version, level: EcLevel) -> u16 {
|
||||||
|
static CAPACITY: OnceLock<[[u16; 4]; 40]> = OnceLock::new();
|
||||||
|
let cap = CAPACITY.get_or_init(init_capacity_table);
|
||||||
|
cap[version.0 as usize - 1][level as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 自动选择最小版本:返回能容纳 data_bits 比特的最小版本
|
||||||
|
pub fn pick_version(data_bits: u16, level: EcLevel) -> Option<Version> {
|
||||||
|
for v in 1..=40 {
|
||||||
|
let cap_bits = get_data_capacity(Version(v), level) * 8;
|
||||||
|
if cap_bits >= data_bits {
|
||||||
|
return Some(Version(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_version_size() {
|
||||||
|
assert_eq!(Version(1).size(), 21);
|
||||||
|
assert_eq!(Version(40).size(), 177);
|
||||||
|
assert_eq!(Version(2).size(), 25);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_version_new_out_of_range() {
|
||||||
|
assert!(Version::new(0).is_none());
|
||||||
|
assert!(Version::new(41).is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pick_version_l() {
|
||||||
|
// Version 1 L 级: 19 数据码字 = 152 bits
|
||||||
|
let v = pick_version(152, EcLevel::L);
|
||||||
|
assert_eq!(v, Some(Version(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pick_version_none() {
|
||||||
|
// 超过 version 40 容量
|
||||||
|
let v = pick_version(30000, EcLevel::H);
|
||||||
|
assert!(v.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ec_info_blocks() {
|
||||||
|
let info = Version(1).ec_info(EcLevel::M);
|
||||||
|
// Version 1 M: 1 block × 16 data codewords, 10 ec per block
|
||||||
|
assert_eq!(info.total_codewords, 26);
|
||||||
|
assert_eq!(info.ec_per_block, 10);
|
||||||
|
assert_eq!(info.blocks.len(), 2);
|
||||||
|
assert_eq!(info.blocks[0].count, 1);
|
||||||
|
assert_eq!(info.blocks[0].data_codewords, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_indicator_bits() {
|
||||||
|
assert_eq!(EcLevel::L.indicator_bits(), 0b01);
|
||||||
|
assert_eq!(EcLevel::M.indicator_bits(), 0b00);
|
||||||
|
assert_eq!(EcLevel::Q.indicator_bits(), 0b11);
|
||||||
|
assert_eq!(EcLevel::H.indicator_bits(), 0b10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user