avra_lib/
writer.rs

1//! Contains hex writer of AVRA-rs
2
3use crate::builder::BuildResult;
4use failure::Error;
5use ihex::Record;
6use std::{fs::File, io::Write, path::PathBuf};
7
8pub struct GenerateResult {
9    code: String,
10    eeprom: String,
11}
12
13fn generate_hex_from_segment(segment: &[u8]) -> Result<String, Error> {
14    let mut records = vec![];
15    if segment.len() > 0 {
16        records.push(Record::ExtendedSegmentAddress(0x0));
17
18        for (i, chunk) in segment.chunks(16).enumerate() {
19            records.push(Record::Data {
20                offset: i as u16 * 16,
21                value: chunk.to_vec(),
22            });
23        }
24    }
25    records.push(Record::EndOfFile);
26
27    let hex = ihex::create_object_file_representation(&records)?;
28
29    Ok(hex)
30}
31
32fn generate_hex(br: &BuildResult) -> Result<GenerateResult, Error> {
33    let code = generate_hex_from_segment(&br.code)?;
34
35    let eeprom = generate_hex_from_segment(&br.eeprom)?;
36
37    Ok(GenerateResult { code, eeprom })
38}
39
40pub fn write_code_hex(path: PathBuf, br: &BuildResult) -> Result<(), Error> {
41    let output = generate_hex(br)?;
42    let mut file_output = File::create(path)?;
43    file_output.write_all(output.code.replace("\n", "\r\n").as_bytes())?;
44    file_output.write(b"\r\n")?;
45
46    Ok(())
47}
48
49pub fn write_eeprom_hex(path: PathBuf, br: &BuildResult) -> Result<(), Error> {
50    let output = generate_hex(br)?;
51    let mut file_output = File::create(path)?;
52    file_output.write_all(output.eeprom.replace("\n", "\r\n").as_bytes())?;
53    file_output.write(b"\r\n")?;
54
55    Ok(())
56}
57
58#[cfg(test)]
59mod writer_tests {
60    use super::*;
61
62    #[test]
63    fn check_empty() {
64        let result = generate_hex(&BuildResult {
65            code: vec![],
66            eeprom: vec![],
67            flash_size: 4194304,
68            eeprom_size: 65536,
69            ram_size: 0,
70            ram_filling: 0,
71            messages: vec![],
72        })
73        .unwrap();
74
75        assert_eq!(result.code, ":00000001FF\n".to_string());
76    }
77
78    #[test]
79    fn check_code() {
80        let build_result = BuildResult {
81            code: vec![
82                0xf, 0x92, 0x10, 0x2d, 0x1f, 0x5f, 0xa, 0xf4, 0xfc, 0xcf, 0x1f, 0x90, 0xea, 0xe0,
83                0xf0, 0xe0, 0x5, 0x91, 0xb, 0xc0, 0xf, 0x1a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c,
84                0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x42, 0x0, 0x44, 0xff, 0x42, 0x0, 0x4e, 0xda,
85                0x22, 0xe1,
86            ],
87            eeprom: vec![],
88            flash_size: 0,
89            eeprom_size: 0,
90            ram_size: 0,
91            ram_filling: 0,
92            messages: vec![],
93        };
94
95        let result = generate_hex(&build_result).unwrap();
96
97        assert_eq!(
98            result.code,
99            ":020000020000FC
100:100000000F92102D1F5F0AF4FCCF1F90EAE0F0E082
101:1000100005910BC00F1A48656C6C6F2C20576F72DE
102:0C0020006C64420044FF42004EDA22E112
103:00000001FF\n"
104                .to_string()
105        );
106    }
107}