pretty code

2019年6月26日 星期三

Rust 探索之旅 - 撞牆期開始

到目前為止,我最喜歡 Rust 的一個地方是它可以使用 "_" 來分隔數字,可以當千分位號使用,也可以分隔 16 進位數字,後者應該是我們程式設計師最常使用的。

最近在整理上禮拜看的一個演算法,其中有一些魔術數字,由於位數太多,實在很容易在 porting code 時出錯,剛好我已經完成 C 語言的版本,故想使用目前為止會的 Rust 來實作看看,殊不知開始進入了瘋狂 google 的地獄輪迴。

細節就不多說了,總之就是花了一個早上,才寫出這個 100 行的程式,開始有點懷念 Go 了,雖然我也很久沒寫了,距離上一次使用 Go 寫測試程式也有一年多了吧?

2019/06/27 更新
使用 rustfmt 重新排版 code。

重點提示
01. 函數只能有一個回傳值,參數要寫型別。
02. Data Type 真的有一種型別叫 "usize"。
03. 型別不符時,可以使用 "as" 轉型。
04. "print!" 不會換行,故可能會存在 Buffer 無法印出,使用 flush 清空 Buffer。

use std::io;
use std::io::Write;
use std::u64;

const BIT_TABLE: [u8; 16] = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4];

fn get_parity_bit(data: u64) -> u8 {
    let mut odd_bit_count: u8 = 0;
    let mut step: u8 = 0;

    let mut n: u64 = data;
    let mut index: u64;

    for _i in 0..16 {
        n = n >> step;

        index = n & 0x00000000_0000000F;
        odd_bit_count += BIT_TABLE[index as usize];

        step = 4;
    }

    if odd_bit_count % 2 == 0 {
        return 0;
    }

    return 1;
}

fn get_parity(data: u64) -> u8 {
    let p1 = get_parity_bit(data & 0xDAB5556A_AAAAAAD5);
    let p2 = get_parity_bit(data & 0xB66CCCD9_999999B3);
    let p3 = get_parity_bit(data & 0x71E3C3C7_8787878F);
    let p4 = get_parity_bit(data & 0x0FE03FC0_7F807F80);
    let p5 = get_parity_bit(data & 0x001FFFC0_007FFF80);
    let p6 = get_parity_bit(data & 0x0000003F_FFFFFF80);
    let p7 = get_parity_bit(data & 0x00000000_0000007F);
    let p8 = get_parity_bit(data & 0xFFFFFFFF_FFFFFFFF);

    println!("p1 = {}", p1);
    println!("p2 = {}", p2);
    println!("p3 = {}", p3);
    println!("p4 = {}", p4);
    println!("p5 = {}", p5);
    println!("p6 = {}", p6);
    println!("p7 = {}", p7);
    println!("p8 = {}", p8);

    // The MSB is p8
    let parity_bit = p8 << 7 | p7 << 6 | p6 << 5 | p5 << 4 | p4 << 3 | p3 << 2 | p2 << 1 | p1;

    return parity_bit;
}

fn main() {
    let mut num: String;

    let mut data: u64;
    let mut p: u8;

    loop {
        print!("Please input hex integer(8 byte - 8F7F6F5F4F3F2F1F): ");
        io::stdout().flush().expect("Can't flush buffer");

        num = String::new();
        io::stdin()
            .read_line(&mut num)
            .expect("Failed to read line");

        num = num.trim().to_string();

        if num == "q" {
            println!("Bye Bye");
            break;
        }

        if num.len() != 16 {
            println!("Please input hex integer with 16 {} {}", num.len(), num);
            continue;
        }

        println!("");

        data = u64::from_str_radix(&num, 16).expect("Failed to convert to integer");
        p = get_parity(data);

        println!("--------------------------------------");
        println!("data   = 0x{:016X}", data);
        println!("parity = 0x{:02X}", p);
        println!("-------------------------------------- \n");
    }
}

沒有留言: