Suggestions on approach

Emptying out text, as I'd like to wipe these, please.

To represent the various types of records, you probably want an enum.

enum Record {
    FooRecord { fields... },
    BarRecord { fields... },
}

As for parsing each kind of record, you might want to try out the byteorder crate instead of using from_be_bytes directly, although both are good ways of doing it. Regarding doing different things depending on record type, I'd first read the identification header, and then I'd have a big match on the kind of record and have a function per record you call from the match.

Regarding the hash map, that depends on the details. You should use a hash map if you have a variable number of keys you don't know ahead of time, and a struct if you know all the fields when writing the code.

Here's an example using the byteorder crate. I guessed that it was big endian.

use std::io::{BufRead, Result};
use byteorder::{BigEndian, ReadBytesExt};

struct Table1Record {
    len: u16,
    seg: u16,
    flg: u8,
    rty: u8,
    tme: u32,
    dte: u32,
    sid: u32,
}

impl Table1Record {
    /// Read from the provided buffered input stream.
    pub fn read_from<R: BufRead>(reader: &mut R) -> Result<Table1Record> {
        let len = reader.read_u16::<BigEndian>()?;
        let seg = reader.read_u16::<BigEndian>()?;
        let flg = reader.read_u8()?;
        let rty = reader.read_u8()?;
        let tme = reader.read_u32::<BigEndian>()?;
        let dte = reader.read_u32::<BigEndian>()?;
        let sid = reader.read_u32::<BigEndian>()?;
        
        Ok(Table1Record {
            len, seg, flg, rty, tme, dte, sid,
        })
    }
}

Note that it often makes sense to make a struct like the above for each table, and you enum can then look like this:

enum Record {
    FooRecord(FooRecordStruct),
    BarRecord(BarRecordStruct),
}
1 Like

If you have variable length data, a Vec or HashMap can indeed make sense depending on the shape of your data. I'm imagining something like this:

struct Record {
    header: Header,
    body: RecordBody,
}
enum RecordBody {
    FooRecord(FooRecordStruct),
    BarRecord(BarRecordStruct),
}

impl Record {
    pub fn read_from<R: BufRead>(reader: &mut R) -> Result<Record> {
        let header = Header::read_from(reader)?;
        let body = match header.kind {
            0 => RecordBody::FooRecord(FooRecordStruct::read_from(reader)?),
            1 => RecordBody::BarRecord(BarRecordStruct::read_from(reader)?),
            kind => return Err(Error::new(ErrorKind::InvalidData, format!("Invalid kind: {}", kind)))
        };
        Ok(Record {
            header,
            body,
        })
    }
}

see full example

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.