这是一个小程序,用于计算STM32程序映像的CRC,与STM32硬件上的CRC兼容。它是一个逐字的CRC,bin文件被编码成一系列32位的小endian字。
这是我第一次认真地尝试Rust,我想征求一些一般性意见,以及几个问题:
buff[3] as u32)的方法?T: Read特征界限应该去哪里?他们也应该上WordIterator吗?use std::fs::File;
use std::io::Read;
struct WordIterator<T> {
rd: T
}
impl<T: Read> WordIterator<T> {
fn new(f: T) -> WordIterator<T> {
WordIterator {rd: f}
}
}
impl<T: Read> Iterator for WordIterator<T> {
type Item = u32;
fn next(&mut self) -> Option<u32> {
let mut buf = [0 as u8; 4];
match self.rd.read(&mut buf) {
Ok(4) => {
let v: u32 = (buf[3] as u32) << 24 |
(buf[2] as u32) << 16 |
(buf[1] as u32) << 8 |
(buf[0] as u32) << 0;
Some( v )
},
_ => {
None
}
}
}
}
struct CrcCalculator {
lookup_table: [u32; 256]
}
impl CrcCalculator {
fn new() -> CrcCalculator {
let mut calc = CrcCalculator {lookup_table: [0; 256]};
// Calculate the table:
for v in 0..256 {
let mut v2: u32 = v << 24;
for _ in 0..8 {
if 0 != v2 & 0x80000000 {
v2 = (v2 << 1) ^ 0x04C11DB7;
}
else {
v2 = v2 << 1;
}
}
calc.lookup_table[v as usize] = v2;
}
calc
}
fn calculate<T: Read>(&self, f: T) -> (u32, u32) {
let mut crc: u32 = 0xFFFFFFFF;
let mut count = 0;
for word in WordIterator::new(f) {
crc = crc ^ word;
crc = (crc << 8) ^ self.lookup_table[((crc >> 24) & 0xFF) as usize];
crc = (crc << 8) ^ self.lookup_table[((crc >> 24) & 0xFF) as usize];
crc = (crc << 8) ^ self.lookup_table[((crc >> 24) & 0xFF) as usize];
crc = (crc << 8) ^ self.lookup_table[((crc >> 24) & 0xFF) as usize];
count += 1;
}
(count, crc)
}
}
fn main() {
let lt = CrcCalculator::new();
let f = File::open("Image.bin").unwrap();
let (count, crc) = lt.calculate(f);
println!("count=0x{:X} crc=0x{:08X}", count, crc);
}发布于 2016-05-22 16:41:13
总的来说,这看起来很合理!在struct声明中有一些类似于小样式nits的空格。更重要的一点是:
usize和u32之间来回切换,所以仍然需要一些地方。expect而不是展开,以帮助您和您的用户理解失败。T是很棒的,但在本例中,我建议R来反映Read绑定。rd具有更大的范围,因为它在多个位置之间共享,应该有一个更简单的名称。where子句来指定特征界限。我觉得更容易读懂。extern crate byteorder;
use byteorder::{LittleEndian, ReadBytesExt};
use std::fs::File;
use std::io::{Read, BufReader};
struct WordIterator<R> {
inner: R,
}
impl<R> WordIterator<R> {
fn new(r: R) -> WordIterator<R> {
WordIterator { inner: r }
}
}
impl<R> Iterator for WordIterator<R>
where R: Read,
{
type Item = u32;
fn next(&mut self) -> Option<u32> {
self.inner.read_u32::<LittleEndian>().ok()
}
}
struct CrcCalculator {
lookup_table: [u32; 256],
}
impl CrcCalculator {
fn new() -> CrcCalculator {
let mut calc = CrcCalculator { lookup_table: [0; 256] };
// Calculate the table:
for v in 0..256 {
let mut v2 = v << 24;
for _ in 0..8 {
if 0 != v2 & 0x80000000 {
v2 = (v2 << 1) ^ 0x04C11DB7;
} else {
v2 = v2 << 1;
}
}
calc.lookup_table[v as usize] = v2;
}
calc
}
fn calculate<R>(&self, r: R) -> (u32, u32)
where R: Read,
{
let mut crc = 0xFFFFFFFF;
let mut count = 0;
for word in WordIterator::new(r) {
crc = crc ^ word;
for _ in 0..4 {
crc = (crc << 8) ^ self.next_component(crc);
}
count += 1;
}
(count, crc)
}
fn next_component(&self, crc: u32) -> u32 {
self.lookup_table[((crc >> 24) & 0xFF) as usize]
}
}
fn main() {
let calculator = CrcCalculator::new();
let f = BufReader::new(File::open("Image.bin").expect("Couldn't open input file"));
let (count, crc) = calculator.calculate(f);
println!("count=0x{:X} crc=0x{:08X}", count, crc);
}为了好玩,我想看看编译时构建解决方案会是什么样子。
use std::env;
use std::io::{self, Write, BufWriter};
use std::fs::File;
use std::path::Path;
fn write_table<W>(mut w: W) -> io::Result<()>
where W: Write,
{
try!(writeln!(w, "static CRC_LOOKUP_TABLE: [u32; 256] = ["));
for v in 0..256u32 {
let mut v2 = v << 24;
for _ in 0..8 {
if 0 != v2 & 0x80000000 {
v2 = (v2 << 1) ^ 0x04C11DB7;
} else {
v2 = v2 << 1;
}
}
if v % 8 == 0 { try!(write!(w, " ")) }
try!(write!(w, "0x{:08X}, ", v2));
if (v + 1) % 8 == 0 { try!(writeln!(w, "")) }
}
writeln!(w, "];")
}
fn main() {
let out_dir = env::var("OUT_DIR").expect("Could not determine where to place output");
let dest_path = Path::new(&out_dir).join("lookup_table.rs");
let f = File::create(&dest_path).expect("Could not create lookup table file");
let f = BufWriter::new(f);
write_table(f).expect("Could not write lookup table")
}这意味着CRC函数不再需要是实例方法,而且可以是空闲函数:
include!(concat!(env!("OUT_DIR"), "/lookup_table.rs"));
fn crc_next_component(crc: u32) -> u32 {
CRC_LOOKUP_TABLE[((crc >> 24) & 0xFF) as usize]
}
fn crc<R>(r: R) -> (u32, u32)
where R: Read,
{
let mut crc = 0xFFFFFFFF;
let mut count = 0;
for word in WordIterator::new(r) {
crc = crc ^ word;
for _ in 0..4 {
crc = (crc << 8) ^ crc_next_component(crc);
}
count += 1;
}
(count, crc)
}https://codereview.stackexchange.com/questions/129027
复制相似问题