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}