Hey Frank, i used your FIN example form my own learning session.
I guess you will love the result:
#[derive(Debug)] // damit println!("{:?}", fin); geht
#[allow(non_snake_case)] // meckert sonst ĂĽber GroĂźschreibung
struct FIN {
pub Firma: [u8; 3],
pub Baureihe: u16,
pub Motornummer: u8,
pub Linkslenker: bool, // (false = Rechtslenker)
pub Herstellungsplatz: char,
pub Folgenummer: u32,
}
#[allow(non_snake_case)]
#[allow(dead_code)]
impl FIN {
fn from_str(fin: &str) -> FIN {
fn sub_str<'a>(str: &'a str, offset: &mut u8, size: u8) -> &'a str {
let start = *offset;
*offset += size;
&str[start as usize .. *offset as usize]
}
use std::str::FromStr;
let mut offset = 0;
let firma: [u8; 3] = match fin.len() {
17 => {
// fin.bytes().take(3).into_array()
offset = 3;
let mut b = fin.bytes();
[b.next().unwrap(),
b.next().unwrap(),
b.next().unwrap()]
}
14 => {
[87, 66, 68] // "WBD"
}
_ => { panic!(format!("UngĂĽltiger FIN '{}'", fin))}
};
// collections::slice::SliceConcatExt => unstable
// let s = fin.chars().take(3).concat().parse::<u16>();
FIN {
Firma: firma,
Baureihe: FromStr::from_str(sub_str(fin, &mut offset, 3)).unwrap(),
Motornummer: FromStr::from_str(sub_str(fin, &mut offset, 3)).unwrap(),
Linkslenker: sub_str(fin, &mut offset, 1).chars().next().unwrap() == '1',
Herstellungsplatz: sub_str(fin, &mut offset, 1).chars().next().unwrap(),
Folgenummer: FromStr::from_str(sub_str(fin, &mut offset, 6)).unwrap(),
}
}
fn als_Rechtslenker(&self) -> FIN {
FIN {Linkslenker: false, .. *self}
}
fn to_string(&self) -> String {
use std::ascii::AsciiExt;
let mut buf = String::with_capacity(17);
let firma = String::from_utf8(self.Firma.to_ascii_uppercase()).unwrap();
buf.push_str(&format!("{}{:03}{:03}", firma, self.Baureihe, self.Motornummer));
buf.push(if self.Linkslenker {'1'} else {'2'});
buf.push_str(&format!("{}{:6}", self.Herstellungsplatz, self.Folgenummer));
buf
}
}
use std::fmt;
use std::collections::HashMap;
impl fmt::Display for FIN {
#[allow(unused_must_use)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let hp = { //HerstellungsPlätze
let mut p: HashMap<char, &'static str> = HashMap::new();
p.insert('A', "Sindelfingen");
p.insert('B', "Buxdehude");
p
};
f.write_str(if self.Linkslenker { "Lenker: links" } else { "Lenker: für Engländer ;)" });
f.write_str(&format!("\nHerstellungsplatz: {}",
hp.get(&(self.Herstellungsplatz)).unwrap_or(&"Unbekannt")));
fmt::Display::fmt("\n", f)
}
}
#[test]
fn test_it() {
let fin = FIN {
Firma: b"wbd".to_owned(),
Baureihe: 211,
Motornummer: 6,
Linkslenker: true,
Herstellungsplatz: 'A',
Folgenummer: 123456,
};
assert_eq!("WBD2110061A123456", fin.to_string());
assert_eq!("WBD2120061B123789", FIN::from_str("WBD2120061B123789").to_string());
}
fn main() {
let fin1 = FIN {
Firma: b"WBD".to_owned(),
Baureihe: 211,
Motornummer: 6,
Linkslenker: true,
Herstellungsplatz: 'A',
Folgenummer: 123456,
};
let fin2 = FIN {Herstellungsplatz: 'C', Folgenummer: fin1.Folgenummer + 1, .. fin1};
println!("{}:", fin1.to_string());
println!("{}", fin1);
println!("{}", fin1.als_Rechtslenker());
println!("\n{}:", fin2.to_string());
println!("{:?}", fin2);
println!("{}", fin2);
println!("\n{:?}", FIN::from_str("2220032B234567"));
}