style: cargo fmt + clippy fix 全项目格式化

This commit is contained in:
2026-06-16 23:58:15 +08:00
parent 9201cd820c
commit 30af4ff607
16 changed files with 1298 additions and 165 deletions
+10 -5
View File
@@ -61,8 +61,8 @@ fn main() -> anyhow::Result<()> {
margin: args.margin, margin: args.margin,
}; };
let qr = QrCode::encode(&args.content, config) let qr =
.map_err(|e| anyhow::anyhow!("编码失败: {}", e))?; QrCode::encode(&args.content, config).map_err(|e| anyhow::anyhow!("编码失败: {}", e))?;
match args.output { match args.output {
Some(path) => { Some(path) => {
@@ -76,14 +76,19 @@ fn main() -> anyhow::Result<()> {
"png" => { "png" => {
let bytes = qr.to_png_bytes(args.size); let bytes = qr.to_png_bytes(args.size);
std::fs::write(&path, bytes)?; std::fs::write(&path, bytes)?;
println!("已生成: {} (版本 {}, {}×{} 模块, {} 级纠错)", println!(
path, qr.version.0, qr.size(), qr.size(), "已生成: {} (版本 {}, {}×{} 模块, {} 级纠错)",
path,
qr.version.0,
qr.size(),
qr.size(),
match qr.level { match qr.level {
EcLevel::L => "L", EcLevel::L => "L",
EcLevel::M => "M", EcLevel::M => "M",
EcLevel::Q => "Q", EcLevel::Q => "Q",
EcLevel::H => "H", EcLevel::H => "H",
}); }
);
} }
"svg" => { "svg" => {
let svg = qr.to_svg(); let svg = qr.to_svg();
+18 -8
View File
@@ -111,8 +111,7 @@ mod tests {
fn test_mul_commutative() { fn test_mul_commutative() {
for a in 0..=255u8 { for a in 0..=255u8 {
for b in (a..=255u8).step_by(17) { for b in (a..=255u8).step_by(17) {
assert_eq!(mul(a, b), mul(b, a), assert_eq!(mul(a, b), mul(b, a), "交换律失败: {:02X} * {:02X}", a, b);
"交换律失败: {:02X} * {:02X}", a, b);
} }
} }
} }
@@ -121,8 +120,14 @@ mod tests {
fn test_mul_associative() { fn test_mul_associative() {
let cases = [(3, 5, 7), (0xFF, 2, 4), (1, 1, 1), (0x80, 0x40, 0x20)]; let cases = [(3, 5, 7), (0xFF, 2, 4), (1, 1, 1), (0x80, 0x40, 0x20)];
for (a, b, c) in cases { for (a, b, c) in cases {
assert_eq!(mul(mul(a, b), c), mul(a, mul(b, c)), assert_eq!(
"结合律失败: {:02X} * {:02X} * {:02X}", a, b, c); mul(mul(a, b), c),
mul(a, mul(b, c)),
"结合律失败: {:02X} * {:02X} * {:02X}",
a,
b,
c
);
} }
} }
@@ -130,8 +135,7 @@ mod tests {
fn test_div_inverse() { fn test_div_inverse() {
for a in 1..=255u8 { for a in 1..=255u8 {
let inv = div(1, a); let inv = div(1, a);
assert_eq!(mul(a, inv), 1, assert_eq!(mul(a, inv), 1, "逆元失败: {:02X} * {:02X} != 1", a, inv);
"逆元失败: {:02X} * {:02X} != 1", a, inv);
} }
} }
@@ -140,8 +144,14 @@ mod tests {
for a in 1..=255u8 { for a in 1..=255u8 {
for b in (1..=255u8).step_by(17) { for b in (1..=255u8).step_by(17) {
let q = div(a, b); let q = div(a, b);
assert_eq!(mul(q, b), a, assert_eq!(
"除乘一致性失败: {:02X} / {:02X} = {:02X}", a, q, b); mul(q, b),
a,
"除乘一致性失败: {:02X} / {:02X} = {:02X}",
a,
q,
b
);
} }
} }
} }
+1 -4
View File
@@ -64,10 +64,7 @@ pub fn interleave(blocks: &[Vec<u8>], ec_count: u8) -> Vec<u8> {
} }
// 对每个块计算 EC // 对每个块计算 EC
let ec_blocks: Vec<Vec<u8>> = blocks let ec_blocks: Vec<Vec<u8>> = blocks.iter().map(|b| compute_ec(b, ec_count)).collect();
.iter()
.map(|b| compute_ec(b, ec_count))
.collect();
// EC 码字交错 // EC 码字交错
for i in 0..ec_count as usize { for i in 0..ec_count as usize {
+1 -3
View File
@@ -1,6 +1,4 @@
use crate::encoder::mode::{ use crate::encoder::mode::{encode_alphanumeric, encode_byte, encode_kanji, encode_numeric, Mode};
encode_alphanumeric, encode_byte, encode_kanji, encode_numeric, Mode,
};
use crate::encoder::segment::segment_text; use crate::encoder::segment::segment_text;
use crate::version::{get_data_capacity, EcLevel, Version}; use crate::version::{get_data_capacity, EcLevel, Version};
+1 -1
View File
@@ -1,3 +1,3 @@
pub mod bitstream;
pub mod mode; pub mod mode;
pub mod segment; pub mod segment;
pub mod bitstream;
+32 -7
View File
@@ -22,16 +22,38 @@ impl Mode {
pub fn count_bits(self, version: u8) -> u8 { pub fn count_bits(self, version: u8) -> u8 {
match self { match self {
Mode::Numeric => { Mode::Numeric => {
if version <= 9 { 10 } else if version <= 26 { 12 } else { 14 } if version <= 9 {
10
} else if version <= 26 {
12
} else {
14
}
} }
Mode::Alphanumeric => { Mode::Alphanumeric => {
if version <= 9 { 9 } else if version <= 26 { 11 } else { 13 } if version <= 9 {
9
} else if version <= 26 {
11
} else {
13
}
} }
Mode::Byte => { Mode::Byte => {
if version <= 9 { 8 } else { 16 } if version <= 9 {
8
} else {
16
}
} }
Mode::Kanji => { Mode::Kanji => {
if version <= 9 { 8 } else if version <= 26 { 10 } else { 12 } if version <= 9 {
8
} else if version <= 26 {
10
} else {
12
}
} }
} }
} }
@@ -40,7 +62,8 @@ impl Mode {
/// 数字模式编码: 每 3 位数字 → 10 bit /// 数字模式编码: 每 3 位数字 → 10 bit
pub fn encode_numeric(input: &str) -> Vec<bool> { pub fn encode_numeric(input: &str) -> Vec<bool> {
let mut bits = Vec::new(); let mut bits = Vec::new();
let chars: Vec<u8> = input.chars() let chars: Vec<u8> = input
.chars()
.filter_map(|c| c.to_digit(10).map(|d| d as u8)) .filter_map(|c| c.to_digit(10).map(|d| d as u8))
.collect(); .collect();
@@ -65,9 +88,11 @@ const ALPHANUMERIC_CHARS: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./
/// 字母数字模式编码: 每 2 个字符 → 11 bit /// 字母数字模式编码: 每 2 个字符 → 11 bit
pub fn encode_alphanumeric(input: &str) -> Vec<bool> { pub fn encode_alphanumeric(input: &str) -> Vec<bool> {
let values: Vec<u8> = input.chars() let values: Vec<u8> = input
.chars()
.filter_map(|c| { .filter_map(|c| {
ALPHANUMERIC_CHARS.iter() ALPHANUMERIC_CHARS
.iter()
.position(|&x| x == c as u8) .position(|&x| x == c as u8)
.map(|i| i as u8) .map(|i| i as u8)
}) })
+1 -1
View File
@@ -1,6 +1,6 @@
pub mod ecc; pub mod ecc;
pub mod encoder; pub mod encoder;
pub mod matrix; pub mod matrix;
pub mod qr;
pub mod render; pub mod render;
pub mod version; pub mod version;
pub mod qr;
+7 -3
View File
@@ -2,15 +2,19 @@
#[derive(Clone)] #[derive(Clone)]
pub struct Matrix { pub struct Matrix {
pub size: u8, pub size: u8,
pub modules: Vec<Vec<bool>>, // true = 暗(黑), false = 亮(白) pub modules: Vec<Vec<bool>>, // true = 暗(黑), false = 亮(白)
pub reserved: Vec<Vec<bool>>, // true = 功能图案占用,不可放数据 pub reserved: Vec<Vec<bool>>, // true = 功能图案占用,不可放数据
} }
impl Matrix { impl Matrix {
pub fn new(size: u8) -> Self { pub fn new(size: u8) -> Self {
let modules = vec![vec![false; size as usize]; size as usize]; let modules = vec![vec![false; size as usize]; size as usize];
let reserved = vec![vec![false; size as usize]; size as usize]; let reserved = vec![vec![false; size as usize]; size as usize];
Matrix { size, modules, reserved } Matrix {
size,
modules,
reserved,
}
} }
pub fn get(&self, x: u8, y: u8) -> bool { pub fn get(&self, x: u8, y: u8) -> bool {
+1 -1
View File
@@ -209,7 +209,7 @@ mod tests {
let m = Matrix::new(21); let m = Matrix::new(21);
// 不设置 reserved,所有区域都是数据区 // 不设置 reserved,所有区域都是数据区
let masked = apply_mask(&m, 0); // (x+y) % 2 == 0 let masked = apply_mask(&m, 0); // (x+y) % 2 == 0
// 初始全白,掩码 0 会在 (x+y)%2==0 的位置翻转 // 初始全白,掩码 0 会在 (x+y)%2==0 的位置翻转
assert_eq!(masked.get(0, 0), true); // (0+0)%2=0 → 翻转 assert_eq!(masked.get(0, 0), true); // (0+0)%2=0 → 翻转
assert_eq!(masked.get(1, 0), false); // (1+0)%2=1 → 不变 assert_eq!(masked.get(1, 0), false); // (1+0)%2=1 → 不变
} }
+1 -1
View File
@@ -1,4 +1,4 @@
pub mod grid; pub mod grid;
pub mod mask;
pub mod patterns; pub mod patterns;
pub mod placement; pub mod placement;
pub mod mask;
+56 -18
View File
@@ -3,9 +3,9 @@ use crate::matrix::grid::Matrix;
/// 放置定位图案(3 个角上的大回字形,7×7) /// 放置定位图案(3 个角上的大回字形,7×7)
pub fn place_finder_patterns(matrix: &mut Matrix) { pub fn place_finder_patterns(matrix: &mut Matrix) {
let positions = [ let positions = [
(0u8, 0u8), // 左上 (0u8, 0u8), // 左上
(matrix.size - 7, 0), // 右上 (matrix.size - 7, 0), // 右上
(0, matrix.size - 7), // 左下 (0, matrix.size - 7), // 左下
]; ];
for &(fx, fy) in &positions { for &(fx, fy) in &positions {
@@ -78,11 +78,17 @@ fn is_near_finder(x: u8, y: u8, size: u8) -> bool {
let x = x as i16; let x = x as i16;
let y = y as i16; let y = y as i16;
// 左上角 // 左上角
if x - 2 < 7 && y - 2 < 7 { return true; } if x - 2 < 7 && y - 2 < 7 {
return true;
}
// 右上角 // 右上角
if x + 2 >= s - 7 && y - 2 < 7 { return true; } if x + 2 >= s - 7 && y - 2 < 7 {
return true;
}
// 左下角 // 左下角
if x - 2 < 7 && y + 2 >= s - 7 { return true; } if x - 2 < 7 && y + 2 >= s - 7 {
return true;
}
false false
} }
@@ -92,13 +98,21 @@ pub fn reserve_format_areas(matrix: &mut Matrix) {
// 定位图案旁的格式信息条 // 定位图案旁的格式信息条
for i in 0..9u8 { for i in 0..9u8 {
// 左上水平 // 左上水平
if i != 6 { matrix.reserve(i, 8); } if i != 6 {
matrix.reserve(i, 8);
}
// 左上垂直 // 左上垂直
if i != 6 { matrix.reserve(8, i); } if i != 6 {
matrix.reserve(8, i);
}
// 右上垂直 // 右上垂直
if i + size - 8 < size { matrix.reserve(size - 1 - i, 8); } if i + size - 8 < size {
matrix.reserve(size - 1 - i, 8);
}
// 左下水平 // 左下水平
if i + size - 8 < size { matrix.reserve(8, size - 1 - i); } if i + size - 8 < size {
matrix.reserve(8, size - 1 - i);
}
} }
// 暗模块位置 // 暗模块位置
if size > 8 { if size > 8 {
@@ -144,16 +158,40 @@ pub fn place_format_info(matrix: &mut Matrix, format: u16) {
// 第一组:左上角定位图案旁 // 第一组:左上角定位图案旁
let coords1: [(u8, u8); 15] = [ let coords1: [(u8, u8); 15] = [
(0, 8), (1, 8), (2, 8), (3, 8), (4, 8), (5, 8), (7, 8), (8, 8), (0, 8),
(8, 7), (8, 5), (8, 4), (8, 3), (8, 2), (8, 1), (8, 0), (1, 8),
(2, 8),
(3, 8),
(4, 8),
(5, 8),
(7, 8),
(8, 8),
(8, 7),
(8, 5),
(8, 4),
(8, 3),
(8, 2),
(8, 1),
(8, 0),
]; ];
// 第二组:右下角,拆分为右上角旁 + 左下角旁 // 第二组:右下角,拆分为右上角旁 + 左下角旁
let coords2: [(u8, u8); 15] = [ let coords2: [(u8, u8); 15] = [
(size - 1, 8), (size - 2, 8), (size - 3, 8), (size - 4, 8), (size - 1, 8),
(size - 5, 8), (size - 6, 8), (size - 7, 8), (size - 8, 8), (size - 2, 8),
(8, size - 7), (8, size - 6), (8, size - 5), (8, size - 4), (size - 3, 8),
(8, size - 3), (8, size - 2), (8, size - 1), (size - 4, 8),
(size - 5, 8),
(size - 6, 8),
(size - 7, 8),
(size - 8, 8),
(8, size - 7),
(8, size - 6),
(8, size - 5),
(8, size - 4),
(8, size - 3),
(8, size - 2),
(8, size - 1),
]; ];
for i in 0..15 { for i in 0..15 {
@@ -220,8 +258,8 @@ mod tests {
fn test_timing_patterns_alternate() { fn test_timing_patterns_alternate() {
let mut m = Matrix::new(21); let mut m = Matrix::new(21);
place_timing_patterns(&mut m); place_timing_patterns(&mut m);
assert!(m.get(8, 6)); // 偶数 = 暗 assert!(m.get(8, 6)); // 偶数 = 暗
assert!(!m.get(9, 6)); // 奇数 = 亮 assert!(!m.get(9, 6)); // 奇数 = 亮
} }
#[test] #[test]
+8 -11
View File
@@ -1,15 +1,15 @@
use crate::version::{Version, EcLevel, get_data_capacity};
use crate::encoder::bitstream::build_codewords;
use crate::encoder::segment::{segment_text, segment_bit_length};
use crate::ecc::reed_solomon; use crate::ecc::reed_solomon;
use crate::encoder::bitstream::build_codewords;
use crate::encoder::segment::{segment_bit_length, segment_text};
use crate::matrix::grid::Matrix; use crate::matrix::grid::Matrix;
use crate::matrix::mask::best_mask;
use crate::matrix::patterns::{ use crate::matrix::patterns::{
place_finder_patterns, place_timing_patterns, place_alignment_patterns, encode_format_info, encode_version_info, place_alignment_patterns, place_finder_patterns,
reserve_format_areas, reserve_version_areas, place_format_info, place_timing_patterns, place_version_info, reserve_format_areas,
encode_format_info, encode_version_info, place_format_info, place_version_info, reserve_version_areas,
}; };
use crate::matrix::placement::place_data; use crate::matrix::placement::place_data;
use crate::matrix::mask::best_mask; use crate::version::{get_data_capacity, EcLevel, Version};
/// 版本选择模式 /// 版本选择模式
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -61,10 +61,7 @@ impl QrCode {
let mut selected = None; let mut selected = None;
for v in 1..=40 { for v in 1..=40 {
let ver = Version(v); let ver = Version(v);
let total_bits: u16 = segments let total_bits: u16 = segments.iter().map(|s| segment_bit_length(s, v)).sum();
.iter()
.map(|s| segment_bit_length(s, v))
.sum();
let cap = get_data_capacity(ver, config.level) as u32 * 8; let cap = get_data_capacity(ver, config.level) as u32 * 8;
if cap >= total_bits as u32 { if cap >= total_bits as u32 {
selected = Some(ver); selected = Some(ver);
+1 -1
View File
@@ -1,3 +1,3 @@
pub mod ascii;
pub mod png; pub mod png;
pub mod svg; pub mod svg;
pub mod ascii;
+2 -5
View File
@@ -34,10 +34,7 @@ pub fn render_png(qr: &QrCode, module_size: u8) -> Vec<u8> {
} }
let mut buf = Vec::new(); let mut buf = Vec::new();
img.write_to( img.write_to(&mut std::io::Cursor::new(&mut buf), image::ImageFormat::Png)
&mut std::io::Cursor::new(&mut buf), .expect("PNG 编码失败");
image::ImageFormat::Png,
)
.expect("PNG 编码失败");
buf buf
} }
+1150 -94
View File
File diff suppressed because it is too large Load Diff
+8 -2
View File
@@ -12,7 +12,10 @@ fn test_encode_simple_text() {
#[test] #[test]
fn test_all_levels() { fn test_all_levels() {
for level in [EcLevel::L, EcLevel::M, EcLevel::Q, EcLevel::H] { for level in [EcLevel::L, EcLevel::M, EcLevel::Q, EcLevel::H] {
let config = QrConfig { level, ..Default::default() }; let config = QrConfig {
level,
..Default::default()
};
let qr = QrCode::encode("TEST", config).unwrap(); let qr = QrCode::encode("TEST", config).unwrap();
assert!(qr.size() >= 21); assert!(qr.size() >= 21);
assert!(qr.size() <= 177); assert!(qr.size() <= 177);
@@ -113,7 +116,10 @@ fn test_margin_is_included_in_dimensions() {
let ascii = qr.to_ascii(false); let ascii = qr.to_ascii(false);
let first_line = ascii.lines().next().unwrap(); let first_line = ascii.lines().next().unwrap();
let chars_per_module = 2; // ██ 是两个字符 let chars_per_module = 2; // ██ 是两个字符
assert_eq!(first_line.chars().count(), expected_total as usize * chars_per_module); assert_eq!(
first_line.chars().count(),
expected_total as usize * chars_per_module
);
} }
#[test] #[test]