OXYGENHUB
# aded4110f0bd oxygen / vendor / crc-fast / src / bin / get-custom-params.rs
6.9 KiB · Rust · last changed Strata: the cloud stores send through ureq, so every release target links 1 month ago source blame history raw
1
// Copyright 2025 Don MacAskill. Licensed under MIT or Apache-2.0.
2
3
//! This is a simple program to get custom CRC parameters from the command line.
4
5
use std::env;
6
use std::process::ExitCode;
7
8
#[derive(Debug)]
9
struct Config {
10
    width: Option<u32>,
11
    polynomial: Option<u64>,
12
    init: Option<u64>,
13
    reflected: Option<bool>,
14
    xorout: Option<u64>,
15
    check: Option<u64>,
16
    name: Option<String>,
17
}
18
19
impl Config {
20
    fn new() -> Self {
21
        Config {
22
            width: None,
23
            polynomial: None,
24
            init: None,
25
            reflected: None,
26
            xorout: None,
27
            check: None,
28
            name: None,
29
        }
30
    }
31
32
    fn is_complete(&self) -> bool {
33
        self.width.is_some()
34
            && self.polynomial.is_some()
35
            && self.init.is_some()
36
            && self.reflected.is_some()
37
            && self.xorout.is_some()
38
            && self.check.is_some()
39
            && self.name.is_some()
40
    }
41
}
42
43
fn parse_hex_or_decimal(s: &str) -> Result<u64, String> {
44
    if s.starts_with("0x") || s.starts_with("0X") {
45
        u64::from_str_radix(&s[2..], 16).map_err(|_| format!("Invalid hexadecimal value: {s}",))
46
    } else {
47
        s.parse::<u64>()
48
            .map_err(|_| format!("Invalid decimal value: {s}",))
49
    }
50
}
51
52
fn parse_bool(s: &str) -> Result<bool, String> {
53
    match s.to_lowercase().as_str() {
54
        "true" | "1" | "yes" | "on" => Ok(true),
55
        "false" | "0" | "no" | "off" => Ok(false),
56
        _ => Err(format!("Invalid boolean value: {s} (use true/false)",)),
57
    }
58
}
59
60
fn parse_args(args: &[String]) -> Result<Config, String> {
61
    let mut config = Config::new();
62
    let mut i = 1; // Skip program name
63
64
    while i < args.len() {
65
        match args[i].as_str() {
66
            "-n" => {
67
                if i + 1 >= args.len() {
68
                    return Err("Missing value for -n (name)".to_string());
69
                }
70
                config.name = Some(args[i + 1].clone());
71
                i += 2;
72
            }
73
            "-w" => {
74
                if i + 1 >= args.len() {
75
                    return Err("Missing value for -w (width)".to_string());
76
                }
77
                config.width = Some(
78
                    args[i + 1]
79
                        .parse::<u32>()
80
                        .map_err(|_| format!("Invalid width value: {}", args[i + 1]))?,
81
                );
82
                i += 2;
83
            }
84
            "-p" => {
85
                if i + 1 >= args.len() {
86
                    return Err("Missing value for -p (polynomial)".to_string());
87
                }
88
                config.polynomial = Some(parse_hex_or_decimal(&args[i + 1])?);
89
                i += 2;
90
            }
91
            "-i" => {
92
                if i + 1 >= args.len() {
93
                    return Err("Missing value for -i (init)".to_string());
94
                }
95
                config.init = Some(parse_hex_or_decimal(&args[i + 1])?);
96
                i += 2;
97
            }
98
            "-r" => {
99
                if i + 1 >= args.len() {
100
                    return Err("Missing value for -r (reflected)".to_string());
101
                }
102
                config.reflected = Some(parse_bool(&args[i + 1])?);
103
                i += 2;
104
            }
105
            "-x" => {
106
                if i + 1 >= args.len() {
107
                    return Err("Missing value for -x (xorout)".to_string());
108
                }
109
                config.xorout = Some(parse_hex_or_decimal(&args[i + 1])?);
110
                i += 2;
111
            }
112
            "-c" => {
113
                if i + 1 >= args.len() {
114
                    return Err("Missing value for -c (check)".to_string());
115
                }
116
                config.check = Some(parse_hex_or_decimal(&args[i + 1])?);
117
                i += 2;
118
            }
119
            arg => {
120
                return Err(format!("Unknown argument: {arg}",));
121
            }
122
        }
123
    }
124
125
    Ok(config)
126
}
127
128
fn print_usage() {
129
    println!("Usage: get-custom-params -n <name> -w <width> -p <polynomial> -i <init> -r <reflected> -x <xorout> -c <check>");
130
    println!();
131
    println!("Example: get-custom-params -n CRC-32/ISCSI -w 32 -p 0x1edc6f41 -i 0xFFFFFFFF -r true -x 0xFFFFFFFF -c 0xe3069283");
132
    println!("Example: get-custom-params -n CRC-64/NVME -w 64 -p 0xad93d23594c93659 -i 0xffffffffffffffff -r true -x 0xffffffffffffffff -c 0xae8b14860a799888");
133
    println!();
134
    println!("Arguments:");
135
    println!("  -n <name>       Name of the CRC algorithm (e.g., CRC-32/ISCSI)");
136
    println!("  -w <width>      CRC width (number of bits)");
137
    println!("  -p <polynomial> CRC polynomial (hex or decimal)");
138
    println!("  -i <init>       Initial value (hex or decimal)");
139
    println!("  -r <reflected>  Reflected input/output (true/false)");
140
    println!("  -x <xorout>     XOR output value (hex or decimal)");
141
    println!("  -c <check>      Check value (hex or decimal)");
142
}
143
144
fn main() -> ExitCode {
145
    let args: Vec<String> = env::args().collect();
146
147
    if args.len() == 1 {
148
        print_usage();
149
        return ExitCode::from(1);
150
    }
151
152
    let config = match parse_args(&args) {
153
        Ok(config) => config,
154
        Err(error) => {
155
            eprintln!("Error: {error}",);
156
            println!();
157
            print_usage();
158
            return ExitCode::from(1);
159
        }
160
    };
161
162
    // Check if all required arguments are provided
163
    if !config.is_complete() {
164
        eprintln!("Error: All arguments are required");
165
        println!();
166
        print_usage();
167
        return ExitCode::from(1);
168
    }
169
170
    let static_name: &'static str = Box::leak(config.name.unwrap().into_boxed_str());
171
172
    let params = crc_fast::CrcParams::new(
173
        static_name,
174
        config.width.unwrap() as u8,
175
        config.polynomial.unwrap(),
176
        config.init.unwrap(),
177
        config.reflected.unwrap(),
178
        config.xorout.unwrap(),
179
        config.check.unwrap(),
180
    );
181
182
    println!();
183
    println!("// Generated CRC parameters for {static_name}",);
184
    println!(
185
        "pub const {}: CrcParams = CrcParams {{",
186
        static_name
187
            .to_uppercase()
188
            .replace("-", "_")
189
            .replace("/", "_")
190
    );
191
    println!(
192
        "    algorithm: CrcAlgorithm::{}Custom,",
193
        if config.width.unwrap() == 32 {
194
            "Crc32"
195
        } else {
196
            "Crc64"
197
        }
198
    );
199
    println!("    name: \"{static_name}\",",);
200
    println!("    width: {},", config.width.unwrap());
201
    println!("    poly: 0x{:x},", config.polynomial.unwrap());
202
    println!("    init: 0x{:x},", config.init.unwrap());
203
    println!("    refin: {},", config.reflected.unwrap());
204
    println!("    refout: {},", config.reflected.unwrap());
205
    println!("    xorout: 0x{:x},", config.xorout.unwrap());
206
    println!("    check: 0x{:x},", config.check.unwrap());
207
    println!("    keys: CrcKeysStorage::from_keys_fold_256([");
208
209
    // Print the keys array
210
    for i in 0..23 {
211
        let key = params.get_key(i);
212
        println!("        0x{key:016x},",);
213
    }
214
215
    println!("    ]),");
216
    println!("}};");
217
    println!();
218
219
    ExitCode::from(0)
220
}