rustronomy_fits/raw/
header_block.rs

1/*
2    Copyright (C) 2022 Raúl Wolters
3
4    This file is part of rustronomy-fits.
5
6    rustronomy is free software: you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation, either version 3 of the License, or
9    (at your option) any later version.
10
11    rustronomy is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with rustronomy.  If not, see <http://www.gnu.org/licenses/>.
18*/
19
20use std::error::Error;
21
22use crate::header_err::{self, HeaderBlockBufferErr as HBBErr};
23
24use super::keyword_record::KeywordRecord;
25
26#[derive(Debug)]
27pub(crate) struct HeaderBlock {
28  /*  NOT PART OF USER-FACING API
29      This struct and its implementations are used in decoding/encoding
30      headers and should not be used directly by the user
31  */
32  pub(crate) records: Vec<KeywordRecord>,
33}
34
35impl HeaderBlock {
36  pub(crate) fn decode_from_bytes(bytes: &[u8]) -> Result<(Self, bool), HBBErr> {
37    /*  If we're in the last headerblock of the header (denoted by the END
38        keyword, then we have to set the return value of is_final to true
39    */
40
41    let mut is_final = false;
42
43    //First, require that the Header block is 2880 blocks long
44    if bytes.len() != 2880 {
45      return Err(HBBErr::new(header_err::BUFFER_LEN));
46    }
47
48    //Create vector of keywordrecords and return it
49    let mut records: Vec<KeywordRecord> = Vec::new();
50    for i in 0..36 {
51      //36 keywords in a HeaderBlock
52      //Decode
53      let record = KeywordRecord::decode_from_bytes(&bytes[(i * 80)..(i * 80 + 80)])?;
54      //And parse
55      if *record.keyword == String::from("END") {
56        //This is the END keyword, which we DON'T append!
57        // -> but we should set is_final to true
58        is_final = true;
59        break;
60      }
61
62      //Append the parsed keyword
63      records.push(record);
64    }
65
66    return Ok((HeaderBlock { records: records }, is_final));
67  }
68
69  pub(crate) fn encode_fill_buff(self, buf: &mut Vec<u8>) -> Result<(), Box<dyn Error>> {
70    for record in self.records {
71      record.encode_fill_buff(buf)?;
72    }
73    Ok(())
74  }
75
76  pub(crate) fn encode_to_bytes(self) -> Result<Vec<u8>, Box<dyn Error>> {
77    //Fill buf with data
78    let mut buf: Vec<u8> = Vec::new();
79    self.encode_fill_buff(&mut buf)?;
80
81    //FITS files must always come in 2880 byte chunks. We fill the remaining
82    //bytes with zeros to satisfy this condition
83    if buf.len() < 2880 {
84      buf.append(&mut vec![0u8; 2880 - buf.len()]);
85      return Ok(buf);
86    } else if buf.len() > 2880 {
87      return Err(Box::new(HBBErr::new(header_err::BUFFER_LEN)));
88    } else {
89      return Ok(buf);
90    }
91  }
92}