use core::panic;
use std::fmt::{self, Debug, Formatter};
use std::io::{self, Seek, SeekFrom};
use std::fs::File;
use crate::io::header::Header;
use crate::io::hdus::primaryhdu::PrimaryHDU;
use crate::io::hdus::image::imagehdu::ImageHDU;
use crate::io::hdus::bintable::bintablehdu::BinTableHDU;
use crate::io::hdus::table::tablehdu::TableHDU;
use crate::io::hdus::utils::buffer_has_more_data;
pub struct HDUList {
pub hdus: Vec<HDU>,
}
impl Debug for HDUList{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.hdus.iter().for_each(|hdu| {
write!(f, "{:?}", hdu).unwrap();
});
Ok(())
}
}
impl Default for HDUList {
fn default() -> Self {
Self::new()
}
}
impl HDUList {
pub fn new() -> Self {
HDUList {
hdus: Vec::new(),
}
}
pub fn fromfile(filename : &str) -> Result<Self, std::io::Error> {
let mut f = File::open(filename)?;
let mut hdulist = HDUList::new();
let mut primary_hdu = true;
loop {
let hdu = HDU::read_from_file(&mut f, Some(primary_hdu));
let hdu = match hdu {
Ok(hdu) => hdu,
Err(e) => {
println!("Error reading HDU: {}", e);
continue;
}
};
primary_hdu = false;
hdulist.add_hdu(hdu);
if !buffer_has_more_data(&mut f)? {
break;
}
}
Ok(hdulist)
}
pub fn write_to(&mut self, filename: &str) -> Result<(), std::io::Error> {
let mut f = File::create(filename)?;
for hdu in &mut self.hdus {
match hdu {
HDU::Primary(hdu) => hdu.write_to_file(&mut f)?,
HDU::Image(hdu) => hdu.write_to_file(&mut f)?,
HDU::Table(hdu) => hdu.write_to_file(&mut f)?,
HDU::BinTable(hdu) => hdu.write_to_file(&mut f)?,
}
}
Ok(())
}
pub fn add_hdu(&mut self, hdu: HDU) {
self.hdus.push(hdu);
}
}
pub enum HDU {
Primary(PrimaryHDU),
Image(ImageHDU),
Table(TableHDU),
BinTable(BinTableHDU),
}
impl fmt::Debug for HDU {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
HDU::Primary(hdu) => write!(f, "<Primary HDU object at memory location {:p}>", hdu),
HDU::Image(hdu) => write!(f, "<Image HDU object at memory location {:p}>", hdu),
HDU::Table(hdu) => write!(f, "<Table HDU object at memory location {:p}>", hdu),
HDU::BinTable(hdu) => write!(f, "<BinTable HDU object at memory location {:p}>", hdu),
}
}
}
impl HDU {
pub fn read_from_file(f: &mut File, primary_hdu: Option<bool>) -> Result<Self, std::io::Error> {
let current_pos = f.stream_position()?;
let mut header = Header::new();
header.read_from_file(f)?;
if primary_hdu.unwrap_or(false) {
f.seek(SeekFrom::Start(current_pos))?;
let primaryhdu = PrimaryHDU::read_from_file(f)?;
Ok(HDU::Primary(primaryhdu))
} else if header.contains_key("XTENSION") {
let mut hdu_type = header["XTENSION"].value.to_string();
hdu_type.retain(|c| !c.is_whitespace());
match hdu_type.as_str() {
"IMAGE" => {
f.seek(SeekFrom::Start(current_pos))?;
let imagehdu = ImageHDU::read_from_file(f)?;
return Ok(HDU::Image(imagehdu))
},
"TABLE" => {
f.seek(SeekFrom::Start(current_pos))?;
let tablehdu = TableHDU::read_from_file(f)?;
return Ok(HDU::Table(tablehdu))
},
"BINTABLE" => {
f.seek(SeekFrom::Start(current_pos))?;
let bintablehdu = BinTableHDU::read_from_file(f)?;
return Ok(HDU::BinTable(bintablehdu))
},
_ => {
Err(io::Error::new(io::ErrorKind::Other, "Not implemented HDU type"))
}
}
} else {
panic!("Not implemented");
}
}
}