use crate::error::Result;
use crate::hdu::Hdu;
use crate::image_data::ImageData;
use std::fs::File;
use std::io::{BufReader, BufWriter, Cursor, Read, Seek, Write};
use std::path::Path;
#[derive(Debug, Clone)]
pub struct FitsFile {
pub hdus: Vec<Hdu>,
}
impl FitsFile {
pub fn new() -> Self {
FitsFile { hdus: Vec::new() }
}
pub fn from_reader<R: Read + Seek>(reader: &mut R) -> Result<Self> {
let mut hdus = Vec::new();
hdus.push(Hdu::read_from(reader)?);
loop {
match Hdu::read_from(reader) {
Ok(hdu) => hdus.push(hdu),
Err(crate::error::Error::Io(ref e))
if e.kind() == std::io::ErrorKind::UnexpectedEof =>
{
break;
}
Err(e) => return Err(e),
}
}
Ok(FitsFile { hdus })
}
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
let file = File::open(path)?;
let mut reader = BufReader::new(file);
Self::from_reader(&mut reader)
}
pub fn from_bytes(data: &[u8]) -> Result<Self> {
let mut cursor = Cursor::new(data);
Self::from_reader(&mut cursor)
}
pub fn to_writer<W: Write>(&self, writer: &mut W) -> Result<()> {
for hdu in &self.hdus {
hdu.write_to(writer)?;
}
Ok(())
}
pub fn to_writer_with_checksum<W: Write>(&self, writer: &mut W) -> Result<()> {
for hdu in &self.hdus {
hdu.write_with_checksum(writer)?;
}
Ok(())
}
pub fn to_bytes_with_checksum(&self) -> Result<Vec<u8>> {
let mut buf = Vec::new();
self.to_writer_with_checksum(&mut buf)?;
Ok(buf)
}
pub fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
let file = File::create(path)?;
let mut writer = BufWriter::new(file);
self.to_writer(&mut writer)
}
pub fn to_bytes(&self) -> Result<Vec<u8>> {
let mut buf = Vec::new();
self.to_writer(&mut buf)?;
Ok(buf)
}
pub fn primary(&self) -> &Hdu {
&self.hdus[0]
}
pub fn primary_mut(&mut self) -> &mut Hdu {
&mut self.hdus[0]
}
pub fn extensions(&self) -> &[Hdu] {
if self.hdus.len() > 1 {
&self.hdus[1..]
} else {
&[]
}
}
pub fn len(&self) -> usize {
self.hdus.len()
}
pub fn is_empty(&self) -> bool {
self.hdus.is_empty()
}
pub fn with_primary_image(image: ImageData) -> Self {
FitsFile {
hdus: vec![Hdu::primary_image(image)],
}
}
pub fn with_empty_primary() -> Self {
FitsFile {
hdus: vec![Hdu::primary_empty()],
}
}
pub fn push_extension(&mut self, hdu: Hdu) {
self.hdus.push(hdu);
}
pub fn find_extension(&self, extname: &str) -> Option<&Hdu> {
self.extensions()
.iter()
.find(|hdu| hdu.header.get_string("EXTNAME") == Some(extname))
}
pub fn iter(&self) -> std::slice::Iter<'_, Hdu> {
self.hdus.iter()
}
}
impl Default for FitsFile {
fn default() -> Self {
Self::new()
}
}
impl<'a> IntoIterator for &'a FitsFile {
type Item = &'a Hdu;
type IntoIter = std::slice::Iter<'a, Hdu>;
fn into_iter(self) -> Self::IntoIter {
self.hdus.iter()
}
}