~ajk/bsr

9c8efc11f5304c0167e9d883fece8a12354ca96d — Andrew Kay 2 years ago fa3a3ce
Run cargo fmt
3 files changed, 86 insertions(+), 49 deletions(-)

M src/bitstream.rs
M src/lib.rs
M src/main.rs
M src/bitstream.rs => src/bitstream.rs +53 -30
@@ 8,7 8,7 @@ pub struct Header {
    pub part_name: String,
    pub design_date: String,
    pub design_time: String,
    pub bitstream_length: u32
    pub bitstream_length: u32,
}

// See http://www.fpga-faq.com/FAQ_Pages/0026_Tell_me_about_bit_files.htm.


@@ 18,7 18,7 @@ enum Tag {
    PartName = 0x62,
    DesignDate = 0x63,
    DesignTime = 0x64,
    Bitstream = 0x65
    Bitstream = 0x65,
}

pub fn read_header<R: Read>(reader: &mut R) -> io::Result<Header> {


@@ 78,13 78,20 @@ pub fn read_header<R: Read>(reader: &mut R) -> io::Result<Header> {
        return invalid_data("expected bitstream tag");
    }

    let bitstream_length = read_u32(reader).or_else(|_| invalid_data("error reading bitstream length"))?;
    let bitstream_length =
        read_u32(reader).or_else(|_| invalid_data("error reading bitstream length"))?;

    if bitstream_length % 4 != 0 {
        return invalid_data("bitstream length must be multiple of 4");
    }

    Ok(Header { design_name, part_name, design_date, design_time, bitstream_length })
    Ok(Header {
        design_name,
        part_name,
        design_date,
        design_time,
        bitstream_length,
    })
}

#[cfg(test)]


@@ 94,20 101,25 @@ mod read_header_tests {
    #[test]
    fn test_valid_header() {
        let buffer: [u8; 144] = [
            0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61, 0x00, 0x32,
            0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x31, 0x5f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72,
            0x3b, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x3d, 0x30, 0x58, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46,
            0x46, 0x46, 0x3b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x32, 0x30, 0x32, 0x30, 0x2e,
            0x31, 0x00, 0x62, 0x00, 0x0c, 0x37, 0x7a, 0x30, 0x32, 0x30, 0x63, 0x6c, 0x67, 0x34, 0x30, 0x30,
            0x00, 0x63, 0x00, 0x0b, 0x32, 0x30, 0x32, 0x30, 0x2f, 0x31, 0x32, 0x2f, 0x32, 0x33, 0x00, 0x64,
            0x00, 0x09, 0x30, 0x33, 0x3a, 0x30, 0x33, 0x3a, 0x35, 0x30, 0x00, 0x65, 0x00, 0x3d, 0xba, 0xfc,
            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
            0x00, 0x00, 0x00, 0xbb, 0x11, 0x22, 0x00, 0x44, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
            0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61,
            0x00, 0x32, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x31, 0x5f, 0x77, 0x72, 0x61,
            0x70, 0x70, 0x65, 0x72, 0x3b, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x3d, 0x30, 0x58,
            0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x3b, 0x56, 0x65, 0x72, 0x73, 0x69,
            0x6f, 0x6e, 0x3d, 0x32, 0x30, 0x32, 0x30, 0x2e, 0x31, 0x00, 0x62, 0x00, 0x0c, 0x37,
            0x7a, 0x30, 0x32, 0x30, 0x63, 0x6c, 0x67, 0x34, 0x30, 0x30, 0x00, 0x63, 0x00, 0x0b,
            0x32, 0x30, 0x32, 0x30, 0x2f, 0x31, 0x32, 0x2f, 0x32, 0x33, 0x00, 0x64, 0x00, 0x09,
            0x30, 0x33, 0x3a, 0x30, 0x33, 0x3a, 0x35, 0x30, 0x00, 0x65, 0x00, 0x3d, 0xba, 0xfc,
            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
            0xff, 0xff, 0x00, 0x00, 0x00, 0xbb, 0x11, 0x22, 0x00, 0x44, 0xff, 0xff, 0xff, 0xff,
            0xff, 0xff, 0xff, 0xff,
        ];

        let header = read_header(&mut buffer.as_ref()).unwrap();

        assert_eq!(header.design_name, "design_1_wrapper;UserID=0XFFFFFFFF;Version=2020.1");
        assert_eq!(
            header.design_name,
            "design_1_wrapper;UserID=0XFFFFFFFF;Version=2020.1"
        );
        assert_eq!(header.part_name, "7z020clg400");
        assert_eq!(header.design_date, "2020/12/23");
        assert_eq!(header.design_time, "03:03:50");


@@ 124,11 136,12 @@ mod read_header_tests {
    #[test]
    fn test_invalid_header() {
        let buffer: [u8; 74] = [
            0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61, 0x00, 0x32,
            0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x31, 0x5f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72,
            0x3b, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x3d, 0x30, 0x58, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46,
            0x46, 0x46, 0x3b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x32, 0x30, 0x32, 0x30, 0x2e,
            0x31, 0x00, 0x62, 0x00, 0x0c, 0x37, 0x7a, 0x30, 0x32, 0x30
            0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0x61,
            0x00, 0x32, 0x64, 0x65, 0x73, 0x69, 0x67, 0x6e, 0x5f, 0x31, 0x5f, 0x77, 0x72, 0x61,
            0x70, 0x70, 0x65, 0x72, 0x3b, 0x55, 0x73, 0x65, 0x72, 0x49, 0x44, 0x3d, 0x30, 0x58,
            0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x3b, 0x56, 0x65, 0x72, 0x73, 0x69,
            0x6f, 0x6e, 0x3d, 0x32, 0x30, 0x32, 0x30, 0x2e, 0x31, 0x00, 0x62, 0x00, 0x0c, 0x37,
            0x7a, 0x30, 0x32, 0x30,
        ];

        assert!(read_header(&mut buffer.as_ref()).is_err());


@@ 138,14 151,18 @@ mod read_header_tests {
pub struct Bitstream<R> {
    reader: R,
    length: usize,
    counter: usize
    counter: usize,
}

impl<R> Bitstream<R> {
    pub fn new(reader: R, header: &Header) -> Bitstream<R> {
        let length = (header.bitstream_length / 4) as usize;

        Bitstream { reader, length, counter: 0 }
        Bitstream {
            reader,
            length,
            counter: 0,
        }
    }
}



@@ 186,7 203,8 @@ mod bitstream_tests {
    #[test]
    fn test_valid() {
        let buffer: [u8; 16] = [
            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04
            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
            0x00, 0x04,
        ];

        let header = Header {


@@ 194,18 212,21 @@ mod bitstream_tests {
            part_name: "part".to_string(),
            design_date: "date".to_string(),
            design_time: "time".to_string(),
            bitstream_length: 16
            bitstream_length: 16,
        };

        let bitstream = Bitstream::new(buffer.as_ref(), &header);

        assert_eq!(bitstream.collect::<Result<Vec<_>, _>>().unwrap(), [1, 2, 3, 4]);
        assert_eq!(
            bitstream.collect::<Result<Vec<_>, _>>().unwrap(),
            [1, 2, 3, 4]
        );
    }

    #[test]
    fn test_invalid() {
        let buffer: [u8; 12] = [
            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03
            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03,
        ];

        let header = Header {


@@ 213,7 234,7 @@ mod bitstream_tests {
            part_name: "part".to_string(),
            design_date: "date".to_string(),
            design_time: "time".to_string(),
            bitstream_length: 16
            bitstream_length: 16,
        };

        let bitstream = Bitstream::new(buffer.as_ref(), &header);


@@ 224,7 245,8 @@ mod bitstream_tests {
    #[test]
    fn test_len() {
        let buffer: [u8; 16] = [
            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04
            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
            0x00, 0x04,
        ];

        let header = Header {


@@ 232,7 254,7 @@ mod bitstream_tests {
            part_name: "part".to_string(),
            design_date: "date".to_string(),
            design_time: "time".to_string(),
            bitstream_length: 16
            bitstream_length: 16,
        };

        let mut bitstream = Bitstream::new(buffer.as_ref(), &header);


@@ 282,11 304,12 @@ fn read_string<R: Read>(reader: &mut R) -> io::Result<String> {

    reader.read_exact(&mut buffer)?;

    if buffer[length-1] != 0x00 {
    if buffer[length - 1] != 0x00 {
        return invalid_data("expected NULL terminated string");
    }

    String::from_utf8(buffer[..length-1].to_vec()).or_else(|_| invalid_data("expected valid string"))
    String::from_utf8(buffer[..length - 1].to_vec())
        .or_else(|_| invalid_data("expected valid string"))
}

fn invalid_data<T>(message: &str) -> io::Result<T> {

M src/lib.rs => src/lib.rs +18 -6
@@ 3,9 3,13 @@ use std::io::prelude::*;

pub mod bitstream;

use bitstream::{read_header, Header, Bitstream};
use bitstream::{read_header, Bitstream, Header};

pub fn run<R: BufRead>(input: &mut R, should_show_info: bool, should_convert: bool) -> io::Result<()> {
pub fn run<R: BufRead>(
    input: &mut R,
    should_show_info: bool,
    should_convert: bool,
) -> io::Result<()> {
    let header = read_header(input)?;

    if should_show_info {


@@ 30,11 34,19 @@ pub fn run<R: BufRead>(input: &mut R, should_show_info: bool, should_convert: bo
}

fn format_header(header: &Header) -> String {
    format!("design = {}\npart = {}\ndate = {}\ntime = {}\nbitstream length = {}",
            header.design_name, header.part_name, header.design_date,
            header.design_time, header.bitstream_length)
    format!(
        "design = {}\npart = {}\ndate = {}\ntime = {}\nbitstream length = {}",
        header.design_name,
        header.part_name,
        header.design_date,
        header.design_time,
        header.bitstream_length
    )
}

fn convert_bitstream<R: Read, W: Write>(writer: &mut W, bitstream: &mut Bitstream<R>) -> io::Result<()> {
fn convert_bitstream<R: Read, W: Write>(
    writer: &mut W,
    bitstream: &mut Bitstream<R>,
) -> io::Result<()> {
    bitstream.try_for_each(|w1| w1.and_then(|w2| writer.write_all(&w2.to_le_bytes())))
}

M src/main.rs => src/main.rs +15 -13
@@ 1,7 1,7 @@
use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;
use std::process;

use clap::{App, Arg};


@@ 11,7 11,7 @@ fn main() {

    let input: Box<dyn Read> = match path.as_str() {
        "-" => Box::new(io::stdin()),
        _ => Box::new(File::open(path).expect("error opening bitstream"))
        _ => Box::new(File::open(path).expect("error opening bitstream")),
    };

    let mut input = BufReader::new(input);


@@ 26,17 26,19 @@ fn main() {

fn parse_args() -> (String, bool, bool) {
    let matches = App::new("bsr")
        .arg(Arg::with_name("show_info")
             .short("i")
             .conflicts_with("only_show_info")
             .help("Show bitstream info"))
        .arg(Arg::with_name("only_show_info")
             .short("I")
             .conflicts_with("show_info")
             .help("Only show bitstream info, do not convert"))
        .arg(Arg::with_name("path")
             .required(false)
             .index(1))
        .arg(
            Arg::with_name("show_info")
                .short("i")
                .conflicts_with("only_show_info")
                .help("Show bitstream info"),
        )
        .arg(
            Arg::with_name("only_show_info")
                .short("I")
                .conflicts_with("show_info")
                .help("Only show bitstream info, do not convert"),
        )
        .arg(Arg::with_name("path").required(false).index(1))
        .get_matches();

    let path = matches.value_of("path").unwrap_or("-");