From 0f8d363b26d93b86966535d867331307599b23ab Mon Sep 17 00:00:00 2001 From: Matthieu Baumann Date: Wed, 8 Jan 2025 20:26:01 +0100 Subject: [PATCH 1/3] first commit --- src/error.rs | 3 + src/fits.rs | 187 ++++++++++++++++++++----- src/hdu/data/asciitable.rs | 17 ++- src/hdu/data/bintable.rs | 25 ++-- src/hdu/data/image.rs | 135 +++++++++--------- src/hdu/data/iter.rs | 106 +++++++------- src/hdu/data/layout.rs | 28 ++++ src/hdu/data/mod.rs | 69 ++++----- src/hdu/data/stream.rs | 31 ++-- src/hdu/extension.rs | 83 ++++++----- src/hdu/header/extension/asciitable.rs | 8 +- src/hdu/header/extension/bintable.rs | 8 +- src/hdu/header/extension/image.rs | 4 +- src/hdu/header/extension/mod.rs | 4 +- src/hdu/header/mod.rs | 13 +- src/hdu/mod.rs | 116 +++++---------- src/hdu/primary.rs | 62 ++++---- src/lib.rs | 74 +++++----- 18 files changed, 535 insertions(+), 438 deletions(-) create mode 100644 src/hdu/data/layout.rs diff --git a/src/error.rs b/src/error.rs index 7424cd3..a215c97 100644 --- a/src/error.rs +++ b/src/error.rs @@ -29,5 +29,8 @@ quick_error! { from(std::str::Utf8Error) display("Fail to parse a keyword as a utf8 string") } + Io { + from(std::io::Error) + } } } diff --git a/src/fits.rs b/src/fits.rs index 4fce8df..3bfdcd3 100644 --- a/src/fits.rs +++ b/src/fits.rs @@ -1,65 +1,180 @@ -use crate::hdu::extension::{AsyncXtensionHDU, XtensionHDU}; -use crate::hdu::primary::{AsyncPrimaryHDU, PrimaryHDU}; +use std::io::BufRead; +use serde::Serialize; + +use crate::hdu::data::DataBufRead; +use crate::hdu::extension::XtensionHDU; use crate::hdu::header::extension::asciitable::AsciiTable; use crate::hdu::header::extension::bintable::BinTable; use crate::hdu::header::extension::image::Image; +use crate::hdu::header::extension::Xtension; +use crate::hdu::header::Header; -use crate::hdu::data::{DataAsyncBufRead, DataBufRead}; +//use crate::hdu::data::{DataAsyncBufRead, DataBufRead}; -#[derive(Debug)] -pub struct Fits<'a, R> -where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable>, -{ - pub hdu: PrimaryHDU<'a, R>, +#[derive(Debug, Serialize)] +pub struct Fits { + start: bool, + num_bytes_read: usize, + error_parsing_encountered: bool, + reader: R, } use crate::error::Error; -impl<'a, R> Fits<'a, R> -where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable>, -{ +use crate::hdu::primary::PrimaryHDU; +impl<'a, R> Fits { /// Parse a FITS file /// # Params /// * `reader` - a reader created i.e. from the opening of a file - pub fn from_reader(reader: &'a mut R) -> Result { - let hdu = PrimaryHDU::new(reader)?; - - Ok(Self { hdu }) + pub fn from_reader(reader: R) -> Result { + //let hdu = PrimaryHDU::new(reader)?; + + Ok(Self { + reader, + num_bytes_read: 0, + error_parsing_encountered: false, + start: true, + }) } +} - pub fn get_primary_hdu(self) -> PrimaryHDU<'a, R> { - self.hdu +impl Fits +where + R: BufRead, +{ + /// Returns a boolean to know if we are at EOF + fn consume_until_next_hdu(&mut self) -> Result { + let is_remaining_bytes = (self.num_bytes_read % 2880) > 0; + // Skip the remaining bytes to set the reader where a new HDU begins + if is_remaining_bytes { + let mut block_mem_buf: [u8; 2880] = [0; 2880]; + + let num_off_bytes = (2880 - (self.num_bytes_read % 2880)) as usize; + match self.reader.read_exact(&mut block_mem_buf[..num_off_bytes]) { + // An error like unexpected EOF is not permitted by the standard but we make it pass + // interpreting it as the last HDU in the file + Err(ref e) if e.kind() == std::io::ErrorKind::UnexpectedEof => return Ok(true), + Err(e) => return Err(e.into()), + Ok(()) => {} + } + + self.num_bytes_read += dbg!(num_off_bytes); + } + + let eof = self.reader.fill_buf()?.is_empty(); + Ok(eof) } +} - pub fn get_xtension_hdu(self, mut idx: usize) -> Result, Error> { - let mut hdu_ext = self.hdu.next()?; - if idx == 0 { - if let Some(hdu) = hdu_ext { - Ok(hdu) +impl<'a, R> Iterator for Fits +where + //R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, + R: DataBufRead<'a, Image> + 'a, +{ + type Item = Result; + + fn next(&mut self) -> Option { + if self.error_parsing_encountered { + None + } else if self.start { + self.start = false; + + if let Ok(prim_hdu) = PrimaryHDU::new(&mut self.reader, &mut self.num_bytes_read) { + Some(Ok(XtensionHDU::Image(prim_hdu.0))) } else { - Err(Error::StaticError("No more ext HDU found")) + None } } else { - while let Some(hdu) = hdu_ext { - hdu_ext = hdu.next()?; - idx -= 1; + // We must consume the bytes until the next header is found + // if eof then the iterator finishes + match self.consume_until_next_hdu() { + Ok(eof) => { + if dbg!(eof) { + None + } else { + Some(XtensionHDU::new(&mut self.reader, &mut self.num_bytes_read)) + } + } + // an error has been found we return it and ends the iterator for future next calls + Err(e) => { + self.error_parsing_encountered = true; - if idx == 0 { - break; + Some(Err(e)) } } + } + } +} - if let Some(hdu) = hdu_ext { - Ok(hdu) - } else { - Err(Error::StaticError("No more ext HDU found")) - } +#[derive(Debug)] +pub struct HDU +where + X: Xtension, +{ + /// The header part that stores all the cards + header: Header, + // We do not store the the data part. it will be given when the data are asked by the user + //data: >::Data, +} + +impl HDU +where + X: Xtension + std::fmt::Debug, +{ + pub fn new<'a, R>( + reader: &mut R, + num_bytes_read: &mut usize, + card_80_bytes_buf: &mut [u8; 80], + ) -> Result + where + R: DataBufRead<'a, X> + 'a, + { + /* 1. Parse the header first */ + let header = Header::parse(reader, num_bytes_read, card_80_bytes_buf)?; + /* 2. Skip the next bytes to a new 2880 multiple of bytes + This is where the data block should start */ + let is_remaining_bytes = ((*num_bytes_read) % 2880) > 0; + + // Skip the remaining bytes to set the reader where a new HDU begins + if is_remaining_bytes { + let mut block_mem_buf: [u8; 2880] = [0; 2880]; + + let num_off_bytes = (2880 - ((*num_bytes_read) % 2880)) as usize; + reader + .read_exact(&mut block_mem_buf[..num_off_bytes]) + .map_err(|_| Error::StaticError("EOF reached"))?; + + *num_bytes_read += num_off_bytes; } + + // Data block + + Ok(Self { header }) + } + + pub fn get_header(&self) -> &Header { + &self.header + } + + // Retrieve the iterator or in memory data from the reader + // This has the effect of consuming the HDU + pub fn get_data<'a, R>(self, hdu_list: &'a mut Fits) -> >::Data + where + R: DataBufRead<'a, X> + DataBufRead<'a, Image>, //+ DataBufRead<'a, BinTable> + //+ DataBufRead<'a, AsciiTable>, + { + // Unroll the internal fits parsing parameters to give it to the data reader + let Fits { + num_bytes_read, + reader, + .. + } = hdu_list; + let xtension = self.header.get_xtension(); + >::prepare_data_reading(xtension, num_bytes_read, reader) } } +/* #[derive(Debug)] pub struct AsyncFits<'a, R> where @@ -114,4 +229,4 @@ where } } } -} +}*/ diff --git a/src/hdu/data/asciitable.rs b/src/hdu/data/asciitable.rs index 69b4e39..1a449de 100644 --- a/src/hdu/data/asciitable.rs +++ b/src/hdu/data/asciitable.rs @@ -8,20 +8,19 @@ use crate::error::Error; use super::iter; use super::stream; -use super::{Data, InMemData}; use crate::hdu::header::extension::asciitable::AsciiTable; use crate::hdu::DataBufRead; use crate::hdu::header::extension::Xtension; -use super::DataAsyncBufRead; - +//use super::DataAsyncBufRead; +/* impl<'a, R> DataBufRead<'a, AsciiTable> for Cursor where R: AsRef<[u8]> + Debug + Read + 'a, { - type Data = Data<'a, Self>; + type Data = Data<'a>; fn new_data_block(&'a mut self, ctx: &AsciiTable) -> Self::Data where @@ -55,9 +54,10 @@ where } fn consume_data_block( + &mut self, data: Self::Data, num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> { + ) -> Result<&mut Self, Error> { let Data { reader, num_bytes_read: num_bytes, @@ -83,9 +83,10 @@ where } fn consume_data_block( + &mut self, data: Self::Data, num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> { + ) -> Result<&mut Self, Error> { let iter::Iter { reader, num_bytes_read: num_bytes_already_read, @@ -102,7 +103,8 @@ where Ok(reader) } } - +*/ +/* #[async_trait(?Send)] impl<'a, R> DataAsyncBufRead<'a, AsciiTable> for futures::io::BufReader where @@ -142,3 +144,4 @@ where Ok(reader) } } +*/ diff --git a/src/hdu/data/bintable.rs b/src/hdu/data/bintable.rs index 0cd7dd4..2abfe9b 100644 --- a/src/hdu/data/bintable.rs +++ b/src/hdu/data/bintable.rs @@ -7,7 +7,6 @@ use futures::AsyncRead; use super::iter; use super::stream; -use super::{Data, InMemData}; use crate::error::Error; use crate::hdu::header::extension::bintable::BinTable; @@ -15,13 +14,13 @@ use crate::hdu::DataBufRead; use crate::hdu::header::extension::Xtension; -use super::DataAsyncBufRead; - +//use super::DataAsyncBufRead; +/* impl<'a, R> DataBufRead<'a, BinTable> for Cursor where R: AsRef<[u8]> + Debug + Read + 'a, { - type Data = Data<'a, Self>; + type Data = Data<'a>; fn new_data_block(&'a mut self, ctx: &BinTable) -> Self::Data where @@ -48,26 +47,26 @@ where Data { data: InMemData::U8(data), - reader: self, + //reader: self, num_bytes_read, } } } fn consume_data_block( + &mut self, data: Self::Data, num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> { + ) -> Result<&mut Self, Error> { let Data { - reader, num_bytes_read: num_bytes, .. } = data; *num_bytes_read = num_bytes as u64; - reader.set_position(reader.position() + num_bytes as u64); + self.set_position(self.position() + num_bytes as u64); - Ok(reader) + Ok(self) } } @@ -83,9 +82,10 @@ where } fn consume_data_block( + &mut self, data: Self::Data, num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> { + ) -> Result<&mut Self, Error> { let iter::Iter { reader, num_bytes_read: num_bytes_already_read, @@ -102,7 +102,8 @@ where Ok(reader) } } - +*/ +/* #[async_trait(?Send)] impl<'a, R> DataAsyncBufRead<'a, BinTable> for futures::io::BufReader where @@ -141,4 +142,4 @@ where Ok(reader) } -} +}*/ diff --git a/src/hdu/data/image.rs b/src/hdu/data/image.rs index 7043bf0..7b3927c 100644 --- a/src/hdu/data/image.rs +++ b/src/hdu/data/image.rs @@ -1,6 +1,9 @@ -pub use super::Access; -use super::DataAsyncBufRead; +//pub use super::Access; +//use super::DataAsyncBufRead; use crate::error::Error; +use crate::fits::Fits; +use crate::hdu::header::extension::asciitable::AsciiTable; +use crate::hdu::header::extension::bintable::BinTable; use crate::hdu::header::BitpixValue; use async_trait::async_trait; use byteorder::{BigEndian, ByteOrder}; @@ -10,8 +13,7 @@ use std::io::{BufReader, Cursor, Read}; use std::fmt::Debug; -use super::iter; -use super::{Data, InMemData}; +use super::{iter, InMemoryData, Slice}; use crate::hdu::header::extension::image::Image; use crate::hdu::header::extension::Xtension; use crate::hdu::DataBufRead; @@ -20,23 +22,26 @@ impl<'a, R> DataBufRead<'a, Image> for Cursor where R: AsRef<[u8]> + Debug + Read + 'a, { - type Data = Data<'a, Self>; + type Data = Slice<'a>; - fn new_data_block(&'a mut self, ctx: &Image) -> Self::Data - where - Self: Sized, - { - let num_bytes_read = ctx.get_num_bytes_data_block() as usize; + fn prepare_data_reading( + ctx: &Image, + num_bytes_read: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data { + let num_bytes_of_data = ctx.get_num_bytes_data_block() as usize; + // propagate the number of bytes read to the hdu_list iterator so that it knows where the reader is. + *num_bytes_read += num_bytes_of_data; let bitpix = ctx.get_bitpix(); - let bytes = self.get_ref(); + let bytes = reader.get_ref(); let bytes = bytes.as_ref(); - let pos = self.position() as usize; + let pos = reader.position() as usize; let start_byte_pos = pos; - let end_byte_pos = pos + num_bytes_read; + let end_byte_pos = pos + num_bytes_of_data; let bytes = &bytes[start_byte_pos..end_byte_pos]; @@ -48,16 +53,12 @@ where match bitpix { BitpixValue::U8 => { let (_, data, _) = x_mut_ref.align_to_mut::(); - let num_pixels = num_bytes_read as usize; + let num_pixels = num_bytes_of_data as usize; debug_assert!(data.len() >= num_pixels); let data = &data[..num_pixels]; - Data { - data: InMemData::U8(data), - reader: self, - num_bytes_read, - } + Slice::U8(data) } BitpixValue::I16 => { // 1. Verify the alignement @@ -66,15 +67,11 @@ where BigEndian::from_slice_i16(data); // 3. Keep only the pixels - let num_pixels = (num_bytes_read as usize) / std::mem::size_of::(); + let num_pixels = (num_bytes_of_data as usize) / std::mem::size_of::(); debug_assert!(data.len() >= num_pixels); let data = &data[..num_pixels]; - Data { - data: InMemData::I16(data), - reader: self, - num_bytes_read, - } + Slice::I16(data) } BitpixValue::I32 => { // 1. Verify the alignement @@ -83,15 +80,11 @@ where BigEndian::from_slice_i32(data); // 3. Keep only the pixels - let num_pixels = (num_bytes_read as usize) / std::mem::size_of::(); + let num_pixels = (num_bytes_of_data as usize) / std::mem::size_of::(); debug_assert!(data.len() >= num_pixels); let data = &data[..num_pixels]; - Data { - data: InMemData::I32(data), - reader: self, - num_bytes_read, - } + Slice::I32(data) } BitpixValue::I64 => { // 1. Verify the alignement @@ -99,15 +92,11 @@ where // 2. Convert to big endianness. This is O(N) over the size of the data BigEndian::from_slice_i64(data); // 3. Keep only the pixels - let num_pixels = num_bytes_read / std::mem::size_of::(); + let num_pixels = num_bytes_of_data / std::mem::size_of::(); debug_assert!(data.len() >= num_pixels); let data = &data[..num_pixels]; - Data { - data: InMemData::I64(data), - reader: self, - num_bytes_read, - } + Slice::I64(data) } BitpixValue::F32 => { // 1. Verify the alignement @@ -115,15 +104,11 @@ where // 2. Convert to big endianness. This is O(N) over the size of the data BigEndian::from_slice_f32(data); // 3. Keep only the pixels - let num_pixels = num_bytes_read / std::mem::size_of::(); + let num_pixels = num_bytes_of_data / std::mem::size_of::(); debug_assert!(data.len() >= num_pixels); let data = &data[..num_pixels]; - Data { - data: InMemData::F32(data), - reader: self, - num_bytes_read, - } + Slice::F32(data) } BitpixValue::F64 => { // 1. Verify the alignement @@ -131,60 +116,70 @@ where // 2. Convert to big endianness. This is O(N) over the size of the data BigEndian::from_slice_f64(data); // 3. Keep only the pixels - let num_pixels = num_bytes_read / std::mem::size_of::(); + let num_pixels = num_bytes_of_data / std::mem::size_of::(); debug_assert!(data.len() >= num_pixels); let data = &data[..num_pixels]; - Data { - data: InMemData::F64(data), - reader: self, - num_bytes_read, - } + Slice::F64(data) } } } } - fn consume_data_block( - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> { + /*fn consume_data_block(self, data: Self::Data, num_bytes_read: &mut u64) -> Result { let Data { - reader, num_bytes_read: num_bytes, .. } = data; *num_bytes_read = num_bytes as u64; - reader.set_position(reader.position() + num_bytes as u64); + self.set_position(self.position() + num_bytes as u64); - Ok(reader) - } + Ok(self) + }*/ } impl<'a, R> DataBufRead<'a, Image> for BufReader where R: Read + Debug + 'a, { - type Data = iter::Data<'a, Self>; - - fn new_data_block(&'a mut self, ctx: &Image) -> Self::Data { - let num_bytes_to_read = ctx.get_num_bytes_data_block(); + type Data = iter::Iter<'a, Self>; + + fn prepare_data_reading( + ctx: &Image, + num_bytes_read: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data { + let num_bytes_to_read = ctx.get_num_bytes_data_block() as usize; let bitpix = ctx.get_bitpix(); match bitpix { - BitpixValue::U8 => iter::Data::U8(iter::Iter::new(self, num_bytes_to_read)), - BitpixValue::I16 => iter::Data::I16(iter::Iter::new(self, num_bytes_to_read)), - BitpixValue::I32 => iter::Data::I32(iter::Iter::new(self, num_bytes_to_read)), - BitpixValue::I64 => iter::Data::I64(iter::Iter::new(self, num_bytes_to_read)), - BitpixValue::F32 => iter::Data::F32(iter::Iter::new(self, num_bytes_to_read)), - BitpixValue::F64 => iter::Data::F64(iter::Iter::new(self, num_bytes_to_read)), + BitpixValue::U8 => { + iter::Iter::U8(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + } + BitpixValue::I16 => { + iter::Iter::I16(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + } + BitpixValue::I32 => { + iter::Iter::I32(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + } + BitpixValue::I64 => { + iter::Iter::I64(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + } + BitpixValue::F32 => { + iter::Iter::F32(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + } + BitpixValue::F64 => { + iter::Iter::F64(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + } } } + /* fn consume_data_block( + &mut self, data: Self::Data, num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> { + ) -> Result<&mut Self, Error> { let (reader, num_bytes_already_read, num_bytes_to_read) = match data { iter::Data::U8(iter::Iter { reader, @@ -231,9 +226,10 @@ where *num_bytes_read = num_bytes_to_read; Ok(reader) - } + }*/ } +/* use super::stream; #[async_trait(?Send)] impl<'a, R> DataAsyncBufRead<'a, Image> for futures::io::BufReader @@ -311,3 +307,4 @@ where Ok(reader) } } +*/ diff --git a/src/hdu/data/iter.rs b/src/hdu/data/iter.rs index fc64ff2..6bf3a8d 100644 --- a/src/hdu/data/iter.rs +++ b/src/hdu/data/iter.rs @@ -5,7 +5,7 @@ use serde::Serialize; use crate::byteorder::ReadBytesExt; -use super::Access; +//use super::Access; /// An iterator on the data array /// This is an enum whose content depends on the @@ -15,177 +15,171 @@ use super::Access; /// for non in-memory readers (typically BufReader) that ensures /// a file may not fit in memory #[derive(Serialize, Debug)] -pub enum Data<'a, R> +pub enum Iter<'a, R> where R: BufRead, { - U8(Iter<'a, R, u8>), - I16(Iter<'a, R, i16>), - I32(Iter<'a, R, i32>), - I64(Iter<'a, R, i64>), - F32(Iter<'a, R, f32>), - F64(Iter<'a, R, f64>), -} - -impl<'a, R> Access for Data<'a, R> -where - R: BufRead, -{ - type Type = Self; - - fn get_data(&self) -> &Self::Type { - self - } - - fn get_data_mut(&mut self) -> &mut Self::Type { - self - } + U8(It<'a, R, u8>), + I16(It<'a, R, i16>), + I32(It<'a, R, i32>), + I64(It<'a, R, i64>), + F32(It<'a, R, f32>), + F64(It<'a, R, f64>), } #[derive(Serialize, Debug)] -pub struct Iter<'a, R, T> +pub struct It<'a, R, T> where R: BufRead, { pub reader: &'a mut R, - pub num_bytes_to_read: u64, - pub num_bytes_read: u64, + pub num_bytes_read: &'a mut usize, + pub num_bytes_to_read: usize, phantom: std::marker::PhantomData, } -impl<'a, R, T> Iter<'a, R, T> +impl<'a, R, T> It<'a, R, T> where R: BufRead, { - pub fn new(reader: &'a mut R, num_bytes_to_read: u64) -> Self { + pub fn new(reader: &'a mut R, num_bytes_read: &'a mut usize, num_bytes_to_read: usize) -> Self { Self { reader, - num_bytes_read: 0, - num_bytes_to_read, + num_bytes_to_read: *num_bytes_read + num_bytes_to_read, + num_bytes_read: num_bytes_read, phantom: std::marker::PhantomData, } } } -impl<'a, R> Iterator for Iter<'a, R, u8> +impl<'a, R> Iterator for It<'a, R, u8> where R: BufRead, { type Item = u8; fn next(&mut self) -> Option { - if self.num_bytes_to_read == self.num_bytes_read { + if self.num_bytes_to_read == *self.num_bytes_read { None } else { let item = self.reader.read_u8(); - self.num_bytes_read += std::mem::size_of::() as u64; + + let num_bytes_item = std::mem::size_of::(); + *self.num_bytes_read += num_bytes_item; item.ok() } } } -impl<'a, R> Iterator for Iter<'a, R, i16> +impl<'a, R> Iterator for It<'a, R, i16> where R: BufRead, { type Item = i16; fn next(&mut self) -> Option { - if self.num_bytes_to_read == self.num_bytes_read { + if self.num_bytes_to_read == *self.num_bytes_read { None } else { let item = self.reader.read_i16::(); - self.num_bytes_read += std::mem::size_of::() as u64; + + let num_bytes_item = std::mem::size_of::(); + *self.num_bytes_read += num_bytes_item; item.ok() } } } -impl<'a, R> Iterator for Iter<'a, R, i32> +impl<'a, R> Iterator for It<'a, R, i32> where R: BufRead, { type Item = i32; fn next(&mut self) -> Option { - if self.num_bytes_to_read == self.num_bytes_read { + if self.num_bytes_to_read == *self.num_bytes_read { None } else { let item = self.reader.read_i32::(); - self.num_bytes_read += std::mem::size_of::() as u64; + + let num_bytes_item = std::mem::size_of::(); + *self.num_bytes_read += num_bytes_item; item.ok() } } } -impl<'a, R> Iterator for Iter<'a, R, i64> +impl<'a, R> Iterator for It<'a, R, i64> where R: BufRead, { type Item = i64; fn next(&mut self) -> Option { - if self.num_bytes_to_read == self.num_bytes_read { + if self.num_bytes_to_read == *self.num_bytes_read { None } else { let item = self.reader.read_i64::(); - self.num_bytes_read += std::mem::size_of::() as u64; + + let num_bytes_item = std::mem::size_of::(); + *self.num_bytes_read += num_bytes_item; item.ok() } } } -impl<'a, R> Iterator for Iter<'a, R, f32> +impl<'a, R> Iterator for It<'a, R, f32> where R: BufRead, { type Item = f32; fn next(&mut self) -> Option { - if self.num_bytes_to_read == self.num_bytes_read { + if self.num_bytes_to_read == *self.num_bytes_read { None } else { let item = self.reader.read_f32::(); - self.num_bytes_read += std::mem::size_of::() as u64; + + let num_bytes_item = std::mem::size_of::(); + *self.num_bytes_read += num_bytes_item; item.ok() } } } -impl<'a, R> Iterator for Iter<'a, R, f64> +impl<'a, R> Iterator for It<'a, R, f64> where R: BufRead, { type Item = f64; fn next(&mut self) -> Option { - if self.num_bytes_to_read == self.num_bytes_read { + if self.num_bytes_to_read == *self.num_bytes_read { None } else { let item = self.reader.read_f64::(); - self.num_bytes_read += std::mem::size_of::() as u64; + + let num_bytes_item = std::mem::size_of::(); + *self.num_bytes_read += num_bytes_item; item.ok() } } } -impl<'a, R> Access for Iter<'a, R, u8> +/* +impl<'a, R> Access<'a> for Iter<'a, R, u8> where R: BufRead, { - type Type = Self; + type Type = &'a Self; - fn get_data(&self) -> &Self::Type { + fn get_data(&'a self) -> Self::Type { self } - - fn get_data_mut(&mut self) -> &mut Self::Type { - self - } -} +}*/ diff --git a/src/hdu/data/layout.rs b/src/hdu/data/layout.rs new file mode 100644 index 0000000..e569b06 --- /dev/null +++ b/src/hdu/data/layout.rs @@ -0,0 +1,28 @@ +use std::io::BufRead; + +use super::Slice; + +pub trait MemoryLayout<'a> { + type Type; + + fn get_data(&'a self) -> Self::Type; + //fn get_data_mut(&mut self) -> &mut Self::Type; +} +impl<'a> MemoryLayout<'a> for Slice<'a> { + type Type = &'a Self; + + fn get_data(&'a self) -> Self::Type { + self + } +} +use super::iter::Iter; +impl<'a, R> MemoryLayout<'a> for Iter<'a, R> +where + R: BufRead, +{ + type Type = &'a Self; + + fn get_data(&'a self) -> Self::Type { + self + } +} diff --git a/src/hdu/data/mod.rs b/src/hdu/data/mod.rs index 18f088f..9c233e4 100644 --- a/src/hdu/data/mod.rs +++ b/src/hdu/data/mod.rs @@ -2,6 +2,7 @@ pub mod asciitable; pub mod bintable; pub mod image; pub mod iter; +pub mod layout; pub mod stream; use serde::Serialize; @@ -12,15 +13,21 @@ use std::io::{BufRead, Read}; use std::marker::Unpin; use crate::error::Error; +use crate::fits::Fits; use crate::hdu::Xtension; +// reader must impl this pub trait DataBufRead<'a, X>: BufRead where X: Xtension, { - type Data: Access + Debug; + type Data: Debug + 'a; - fn new_data_block(&'a mut self, ctx: &X) -> Self::Data + fn prepare_data_reading( + ctx: &X, + num_bytes_read: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data where Self: Sized; @@ -32,10 +39,13 @@ where /// /// # Params /// * `data` - a reader created i.e. from the opening of a file - fn consume_data_block( + /*fn consume_data_block( + &'a mut self, data: Self::Data, num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error>; + ) -> Result<&'a mut Self, Error> + where + Self: Sized;*/ fn read_n_bytes_exact(&mut self, num_bytes_to_read: u64) -> Result<(), Error> { let mut num_bytes_read = 0; @@ -80,14 +90,19 @@ use async_trait::async_trait; use futures::io::AsyncBufRead; use futures::AsyncBufReadExt; +use super::header::extension::asciitable::AsciiTable; +use super::header::extension::bintable::BinTable; +use super::header::extension::image::Image; + +/* #[async_trait(?Send)] -pub trait DataAsyncBufRead<'a, X>: AsyncBufRead + Unpin +pub trait DataAsyncBufRead: AsyncBufRead + Unpin where X: Xtension, { - type Data: Access + Debug; + type Data: Debug; - fn new_data_block(&'a mut self, ctx: &X) -> Self::Data + fn new_data_block(&mut self, ctx: &X) -> Self::Data where Self: Sized; @@ -100,11 +115,12 @@ where /// # Params /// * `data` - a reader created i.e. from the opening of a file async fn consume_data_block( + &mut self, data: Self::Data, num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> + ) -> Result<&mut Self, Error> where - 'a: 'async_trait; + Self: Sized; async fn read_n_bytes_exact(&mut self, num_bytes_to_read: u64) -> Result<(), Error> { let mut num_bytes_read = 0; @@ -143,14 +159,7 @@ where Ok(()) } } -} - -pub trait Access { - type Type; - - fn get_data(&self) -> &Self::Type; - fn get_data_mut(&mut self) -> &mut Self::Type; -} +}*/ /// The full slice of data found in-memory /// This is an enum whose content depends on the @@ -161,32 +170,10 @@ pub trait Access { /// all the data fits in memory /// #[derive(Serialize, Debug)] -pub struct Data<'a, R> -where - R: Read + Debug + 'a, -{ - pub reader: &'a mut R, - pub num_bytes_read: usize, - pub data: InMemData<'a>, -} - -impl<'a, R> Access for Data<'a, R> -where - R: Read + Debug + 'a, -{ - type Type = InMemData<'a>; - - fn get_data(&self) -> &Self::Type { - &self.data - } - - fn get_data_mut(&mut self) -> &mut Self::Type { - &mut self.data - } -} +pub struct InMemoryData<'a>(Slice<'a>); #[derive(Serialize, Debug, Clone)] -pub enum InMemData<'a> { +pub enum Slice<'a> { U8(&'a [u8]), I16(&'a [i16]), I32(&'a [i32]), diff --git a/src/hdu/data/stream.rs b/src/hdu/data/stream.rs index 645fd9c..86fc20d 100644 --- a/src/hdu/data/stream.rs +++ b/src/hdu/data/stream.rs @@ -8,6 +8,7 @@ use futures::AsyncReadExt; /// The data part is expressed as a `DataOwned` structure /// for non in-memory readers (typically BufReader) that ensures /// a file may not fit in memory +/* #[derive(Serialize, Debug)] pub enum Data<'a, R> where @@ -19,23 +20,19 @@ where I64(St<'a, R, i64>), F32(St<'a, R, f32>), F64(St<'a, R, f64>), -} - -impl<'a, R> Access for Data<'a, R> +}*/ +/* +impl<'a, R> Access<'a> for Data<'a, R> where R: AsyncBufRead + Unpin, { - type Type = Self; - - fn get_data(&self) -> &Self::Type { - self - } + type Type = &'a mut Self; - fn get_data_mut(&mut self) -> &mut Self::Type { + fn get_data(&'a mut self) -> Self::Type { self } } - +*/ #[derive(Serialize, Debug)] pub struct St<'a, R, T> where @@ -71,7 +68,7 @@ use futures::Stream; use serde::Serialize; use std::pin::Pin; -use super::Access; +//use super::Access; impl<'a, R> Stream for St<'a, R, u8> where @@ -254,17 +251,15 @@ where } } -impl<'a, R> Access for St<'a, R, u8> +/* +impl<'a, R> Access<'a> for St<'a, R, u8> where R: AsyncBufRead + Unpin, { - type Type = Self; - - fn get_data(&self) -> &Self::Type { - self - } + type Type = &'a mut Self; - fn get_data_mut(&mut self) -> &mut Self::Type { + fn get_data(&'a mut self) -> Self::Type { self } } +*/ diff --git a/src/hdu/extension.rs b/src/hdu/extension.rs index 20c7c25..0571d14 100644 --- a/src/hdu/extension.rs +++ b/src/hdu/extension.rs @@ -2,79 +2,89 @@ use crate::hdu::header::extension::asciitable::AsciiTable; use crate::hdu::header::extension::bintable::BinTable; use crate::hdu::header::extension::image::Image; -use super::data::DataAsyncBufRead; +//use super::data::DataAsyncBufRead; use super::header::consume_next_card_async; use super::header::extension::XtensionType; -use super::AsyncHDU; +//use super::AsyncHDU; use crate::error::Error; +use crate::fits::HDU; use crate::hdu::header::extension::parse_xtension_card; use crate::hdu::primary::consume_next_card; -use crate::hdu::HDU; use crate::hdu::DataBufRead; #[derive(Debug)] -pub enum XtensionHDU<'a, R> -where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, -{ - Image(HDU<'a, R, Image>), - AsciiTable(HDU<'a, R, AsciiTable>), - BinTable(HDU<'a, R, BinTable>), +pub enum XtensionHDU { + Image(HDU), + AsciiTable(HDU), + BinTable(HDU), } -impl<'a, R> XtensionHDU<'a, R> -where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, -{ - pub fn new(reader: &'a mut R) -> Result { - let mut num_bytes_read = 0; +impl XtensionHDU { + pub fn new<'a, R>(reader: &mut R, num_bytes_read: &mut usize) -> Result + where + //R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, + R: DataBufRead<'a, Image> + 'a, + { let mut card_80_bytes_buf = [0; 80]; // XTENSION - consume_next_card(reader, &mut card_80_bytes_buf, &mut num_bytes_read)?; + consume_next_card(reader, &mut card_80_bytes_buf, num_bytes_read)?; let xtension_type = parse_xtension_card(&card_80_bytes_buf)?; let hdu = match xtension_type { - XtensionType::Image => XtensionHDU::Image(HDU::<'a, R, Image>::new( - reader, - &mut num_bytes_read, - &mut card_80_bytes_buf, - )?), - XtensionType::BinTable => XtensionHDU::BinTable(HDU::<'a, R, BinTable>::new( - reader, - &mut num_bytes_read, - &mut card_80_bytes_buf, - )?), - XtensionType::AsciiTable => XtensionHDU::AsciiTable(HDU::<'a, R, AsciiTable>::new( + XtensionType::Image => XtensionHDU::Image(HDU::::new( reader, - &mut num_bytes_read, + num_bytes_read, &mut card_80_bytes_buf, )?), + XtensionType::BinTable => { + todo!(); + /*XtensionHDU::BinTable(HDU::::new( + reader, + &mut num_bytes_read, + &mut card_80_bytes_buf, + )?)*/ + } + XtensionType::AsciiTable => { + todo!(); + /*XtensionHDU::AsciiTable(HDU::::new( + reader, + &mut num_bytes_read, + &mut card_80_bytes_buf, + )?),*/ + } }; Ok(hdu) } - fn consume(self) -> Result, Error> { + /*fn consume<'a, R>(self, reader: &'a mut R) -> Result, Error> + where + R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, + { match self { - XtensionHDU::Image(hdu) => hdu.consume(), - XtensionHDU::AsciiTable(hdu) => hdu.consume(), - XtensionHDU::BinTable(hdu) => hdu.consume(), + XtensionHDU::Image(hdu) => hdu.consume(reader), + XtensionHDU::AsciiTable(hdu) => hdu.consume(reader), + XtensionHDU::BinTable(hdu) => hdu.consume(reader), } } - pub fn next(self) -> Result, Error> { - if let Some(reader) = self.consume()? { + pub fn next<'a, R>(self, reader: &'a mut R) -> Result, Error> + where + R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, + { + if let Some(reader) = self.consume(reader)? { let hdu = Self::new(reader)?; Ok(Some(hdu)) } else { Ok(None) } - } + }*/ } +/* #[derive(Debug)] pub enum AsyncXtensionHDU<'a, R> where @@ -147,3 +157,4 @@ where } } } +*/ diff --git a/src/hdu/header/extension/asciitable.rs b/src/hdu/header/extension/asciitable.rs index e43f51c..657c2d4 100644 --- a/src/hdu/header/extension/asciitable.rs +++ b/src/hdu/header/extension/asciitable.rs @@ -233,7 +233,7 @@ impl Xtension for AsciiTable { fn parse( reader: &mut R, - num_bytes_read: &mut u64, + num_bytes_read: &mut usize, card_80_bytes_buf: &mut [u8; 80], _cards: &mut HashMap<[u8; 8], Value>, ) -> Result { @@ -294,7 +294,7 @@ impl Xtension for AsciiTable { async fn parse_async( reader: &mut R, - num_bytes_read: &mut u64, + num_bytes_read: &mut usize, card_80_bytes_buf: &mut [u8; 80], _cards: &mut HashMap<[u8; 8], Value>, ) -> Result @@ -383,7 +383,7 @@ mod tests { hdu::{extension::XtensionHDU, header::BitpixValue}, }; use std::{fs::File, io::BufReader}; - + /* fn compare_ascii_ext(filename: &str, ascii_table: AsciiTable) { let f = File::open(filename).unwrap(); @@ -588,5 +588,5 @@ mod tests { gcount: 1, }, ); - } + }*/ } diff --git a/src/hdu/header/extension/bintable.rs b/src/hdu/header/extension/bintable.rs index 337cc56..1c975d3 100644 --- a/src/hdu/header/extension/bintable.rs +++ b/src/hdu/header/extension/bintable.rs @@ -109,7 +109,7 @@ impl Xtension for BinTable { fn parse( reader: &mut R, - num_bytes_read: &mut u64, + num_bytes_read: &mut usize, card_80_bytes_buf: &mut [u8; 80], _cards: &mut HashMap<[u8; 8], Value>, ) -> Result { @@ -168,7 +168,7 @@ impl Xtension for BinTable { async fn parse_async( reader: &mut R, - num_bytes_read: &mut u64, + num_bytes_read: &mut usize, card_80_bytes_buf: &mut [u8; 80], _cards: &mut HashMap<[u8; 8], Value>, ) -> Result @@ -394,7 +394,7 @@ mod tests { hdu::{extension::XtensionHDU, header::BitpixValue}, }; use std::{fs::File, io::BufReader}; - + /* fn compare_bintable_ext(filename: &str, bin_table: BinTable) { let f = File::open(filename).unwrap(); @@ -445,5 +445,5 @@ mod tests { gcount: 1, }, ); - } + }*/ } diff --git a/src/hdu/header/extension/image.rs b/src/hdu/header/extension/image.rs index c3e4d0d..90c7e9d 100644 --- a/src/hdu/header/extension/image.rs +++ b/src/hdu/header/extension/image.rs @@ -67,7 +67,7 @@ impl Xtension for Image { fn parse( reader: &mut R, - num_bytes_read: &mut u64, + num_bytes_read: &mut usize, card_80_bytes_buf: &mut [u8; 80], cards: &mut HashMap, ) -> Result { @@ -102,7 +102,7 @@ impl Xtension for Image { async fn parse_async( reader: &mut R, - num_bytes_read: &mut u64, + num_bytes_read: &mut usize, card_80_bytes_buf: &mut [u8; 80], cards: &mut HashMap, ) -> Result diff --git a/src/hdu/header/extension/mod.rs b/src/hdu/header/extension/mod.rs index c4f7b30..610d9ad 100644 --- a/src/hdu/header/extension/mod.rs +++ b/src/hdu/header/extension/mod.rs @@ -40,7 +40,7 @@ pub trait Xtension { // During the parsing, some checks will be made fn parse( reader: &mut R, - num_bytes_read: &mut u64, + num_bytes_read: &mut usize, card_80_bytes_buf: &mut [u8; 80], cards: &mut HashMap, ) -> Result @@ -50,7 +50,7 @@ pub trait Xtension { // Async equivalent method async fn parse_async( reader: &mut R, - num_bytes_read: &mut u64, + num_bytes_read: &mut usize, card_80_bytes_buf: &mut [u8; 80], cards: &mut HashMap, ) -> Result diff --git a/src/hdu/header/mod.rs b/src/hdu/header/mod.rs index bad52b9..e69e85e 100644 --- a/src/hdu/header/mod.rs +++ b/src/hdu/header/mod.rs @@ -20,7 +20,7 @@ use crate::hdu::Xtension; pub fn consume_next_card( reader: &mut R, buf: &mut [u8; 80], - bytes_read: &mut u64, + bytes_read: &mut usize, ) -> Result<(), Error> { *bytes_read += 80; reader @@ -33,7 +33,7 @@ pub fn consume_next_card( pub async fn consume_next_card_async<'a, R: AsyncRead + std::marker::Unpin>( reader: &mut R, buf: &mut [u8; 80], - bytes_read: &mut u64, + bytes_read: &mut usize, ) -> Result<(), Error> { *bytes_read += 80; reader @@ -180,7 +180,7 @@ where { pub(crate) fn parse( reader: &mut R, - num_bytes_read: &mut u64, + num_bytes_read: &mut usize, card_80_bytes_buf: &mut [u8; 80], ) -> Result { let mut cards = HashMap::new(); @@ -204,7 +204,7 @@ where pub(crate) async fn parse_async<'a, R>( reader: &mut R, - num_bytes_read: &mut u64, + num_bytes_read: &mut usize, card_80_bytes_buf: &mut [u8; 80], ) -> Result where @@ -262,7 +262,7 @@ where self.cards.keys() } - pub fn cards(&self) -> impl Iterator + use<'_, X> { + pub fn cards(&self) -> impl Iterator + '_ { self.cards.iter().map(|(kw, v)| Card { kw: kw.to_owned(), v: v.to_owned(), @@ -311,6 +311,7 @@ mod tests { use std::fs::File; use std::io::Cursor; use std::io::Read; + /* #[test] fn test_keywords_iter() { let f = File::open("samples/misc/SN2923fxjA.fits").unwrap(); @@ -364,5 +365,5 @@ mod tests { "XPIXELSZ", "XPIXSZ", "Y1", "Y2", "YPIXELSZ", "YPIXSZ" ] ); - } + }*/ } diff --git a/src/hdu/mod.rs b/src/hdu/mod.rs index a8844a8..f80ee3e 100644 --- a/src/hdu/mod.rs +++ b/src/hdu/mod.rs @@ -4,38 +4,45 @@ pub mod data; pub mod extension; pub mod primary; -use crate::hdu::data::DataBufRead; use crate::hdu::header::extension::Xtension; +use crate::{fits::Fits, hdu::data::DataBufRead}; use futures::{AsyncBufReadExt, AsyncReadExt}; use header::Header; -use self::data::{Access, DataAsyncBufRead}; +//use self::data::DataAsyncBufRead; use crate::error::Error; +use self::data::layout::MemoryLayout; +use self::header::extension::asciitable::AsciiTable; +use self::header::extension::bintable::BinTable; +use self::header::extension::image::Image; + +/* +// Async variant #[derive(Debug)] -pub struct HDU<'a, R, X> +pub struct AsyncHDU<'a, R, X> where X: Xtension, - R: DataBufRead<'a, X>, + R: DataAsyncBufRead<'a, X>, { /// The header part that stores all the cards header: Header, /// The data part - data: >::Data, + data: >::Data, } -impl<'a, R, X> HDU<'a, R, X> +impl<'a, R, X> AsyncHDU<'a, R, X> where X: Xtension + std::fmt::Debug, - R: DataBufRead<'a, X> + 'a, + R: DataAsyncBufRead<'a, X> + 'a, { - pub fn new( + pub async fn new( reader: &'a mut R, num_bytes_read: &mut u64, card_80_bytes_buf: &mut [u8; 80], - ) -> Result { + ) -> Result, Error> { /* 1. Parse the header first */ - let header = Header::parse(reader, num_bytes_read, card_80_bytes_buf)?; + let header = Header::parse_async(reader, num_bytes_read, card_80_bytes_buf).await?; /* 2. Skip the next bytes to a new 2880 multiple of bytes This is where the data block should start */ let is_remaining_bytes = ((*num_bytes_read) % 2880) > 0; @@ -47,6 +54,7 @@ where let num_off_bytes = (2880 - ((*num_bytes_read) % 2880)) as usize; reader .read_exact(&mut block_mem_buf[..num_off_bytes]) + .await .map_err(|_| Error::StaticError("EOF reached"))?; } @@ -57,9 +65,11 @@ where Ok(Self { header, data }) } - fn consume(self) -> Result, Error> { + async fn consume(self) -> Result, Error> { let mut num_bytes_read = 0; - let reader = >::consume_data_block(self.data, &mut num_bytes_read)?; + let reader = + >::consume_data_block(self.data, &mut num_bytes_read) + .await?; let is_remaining_bytes = (num_bytes_read % 2880) > 0; // Skip the remaining bytes to set the reader where a new HDU begins @@ -69,6 +79,7 @@ where let num_off_bytes = (2880 - (num_bytes_read % 2880)) as usize; reader .read_exact(&mut block_mem_buf[..num_off_bytes]) + .await .ok() // An error like unexpected EOF is not standard frendly but we make it pass // interpreting it as the last HDU in the file .map(|_| reader) @@ -80,6 +91,7 @@ where if let Some(reader) = reader { let is_eof = reader .fill_buf() + .await .map_err(|_| { Error::StaticError("Unable to fill the buffer to check if data is remaining") })? @@ -98,67 +110,25 @@ where &self.header } - pub fn get_data(&self) -> &<>::Data as Access>::Type { + /*pub fn get_data(&'a mut self) -> <>::Data as Access<'a>>::Type { self.data.get_data() - } + }*/ - pub fn get_data_mut(&mut self) -> &mut <>::Data as Access>::Type { + /*pub fn get_data_mut(&mut self) -> &mut <>::Data as Access>::Type { self.data.get_data_mut() - } + }*/ } - -// Async variant -#[derive(Debug)] -pub struct AsyncHDU<'a, R, X> -where - X: Xtension, - R: DataAsyncBufRead<'a, X>, -{ - /// The header part that stores all the cards - header: Header, - /// The data part - data: >::Data, -} - -impl<'a, R, X> AsyncHDU<'a, R, X> +*/ +/* +impl Drop for HDU where X: Xtension + std::fmt::Debug, - R: DataAsyncBufRead<'a, X> + 'a, { - pub async fn new( - reader: &'a mut R, - num_bytes_read: &mut u64, - card_80_bytes_buf: &mut [u8; 80], - ) -> Result, Error> { - /* 1. Parse the header first */ - let header = Header::parse_async(reader, num_bytes_read, card_80_bytes_buf).await?; - /* 2. Skip the next bytes to a new 2880 multiple of bytes - This is where the data block should start */ - let is_remaining_bytes = ((*num_bytes_read) % 2880) > 0; - - // Skip the remaining bytes to set the reader where a new HDU begins - if is_remaining_bytes { - let mut block_mem_buf: [u8; 2880] = [0; 2880]; - - let num_off_bytes = (2880 - ((*num_bytes_read) % 2880)) as usize; - reader - .read_exact(&mut block_mem_buf[..num_off_bytes]) - .await - .map_err(|_| Error::StaticError("EOF reached"))?; - } - - // Data block - let xtension = header.get_xtension(); - let data = reader.new_data_block(xtension); - - Ok(Self { header, data }) - } - - async fn consume(self) -> Result, Error> { + fn drop(&mut self) { let mut num_bytes_read = 0; - let reader = - >::consume_data_block(self.data, &mut num_bytes_read) - .await?; + + let xtension = self.header.get_xtension(); + let num_bytes_read = self.num_bytes_read; let is_remaining_bytes = (num_bytes_read % 2880) > 0; // Skip the remaining bytes to set the reader where a new HDU begins @@ -168,7 +138,6 @@ where let num_off_bytes = (2880 - (num_bytes_read % 2880)) as usize; reader .read_exact(&mut block_mem_buf[..num_off_bytes]) - .await .ok() // An error like unexpected EOF is not standard frendly but we make it pass // interpreting it as the last HDU in the file .map(|_| reader) @@ -180,7 +149,6 @@ where if let Some(reader) = reader { let is_eof = reader .fill_buf() - .await .map_err(|_| { Error::StaticError("Unable to fill the buffer to check if data is remaining") })? @@ -194,16 +162,4 @@ where Ok(None) } } - - pub fn get_header(&self) -> &Header { - &self.header - } - - pub fn get_data(&self) -> &<>::Data as Access>::Type { - self.data.get_data() - } - - pub fn get_data_mut(&mut self) -> &mut <>::Data as Access>::Type { - self.data.get_data_mut() - } -} +}*/ diff --git a/src/hdu/primary.rs b/src/hdu/primary.rs index 6e2f43c..d519bab 100644 --- a/src/hdu/primary.rs +++ b/src/hdu/primary.rs @@ -1,9 +1,10 @@ use super::{ - data::DataAsyncBufRead, - extension::{AsyncXtensionHDU, XtensionHDU}, + //data::DataAsyncBufRead, + //extension::{AsyncXtensionHDU, XtensionHDU}, header::consume_next_card_async, - AsyncHDU, + //AsyncHDU, }; +use crate::hdu::extension::XtensionHDU; use std::fmt::Debug; use crate::hdu::header::extension::asciitable::AsciiTable; @@ -12,7 +13,7 @@ use crate::hdu::header::extension::image::Image; use crate::hdu::data::DataBufRead; -use crate::hdu::HDU; +use crate::fits::HDU; use crate::error::Error; pub use crate::hdu::header::{check_card_keyword, consume_next_card}; @@ -22,46 +23,47 @@ use std::ops::Deref; /// Structure storing the content of one HDU (i.e. Header Data Unit) /// of a fits file #[derive(Debug)] -pub struct PrimaryHDU<'a, R>(pub HDU<'a, R, Image>) -where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a; - -impl<'a, R> PrimaryHDU<'a, R> -where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, -{ - pub fn new(reader: &'a mut R) -> Result { - let mut num_bytes_read = 0; +pub struct PrimaryHDU(pub HDU); + +impl PrimaryHDU { + pub fn new<'a, R>(reader: &mut R, num_bytes_read: &mut usize) -> Result + where + //R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, + R: DataBufRead<'a, Image> + 'a, + { let mut card_80_bytes_buf = [0; 80]; // SIMPLE - consume_next_card(reader, &mut card_80_bytes_buf, &mut num_bytes_read)?; + consume_next_card(reader, &mut card_80_bytes_buf, num_bytes_read)?; let _ = check_card_keyword(&card_80_bytes_buf, b"SIMPLE ")?; - let hdu = HDU::<'a, R, Image>::new(reader, &mut num_bytes_read, &mut card_80_bytes_buf)?; + let hdu = HDU::::new(reader, num_bytes_read, &mut card_80_bytes_buf)?; Ok(PrimaryHDU(hdu)) } - fn consume(self) -> Result, Error> { - self.0.consume() + /*fn consume<'a, R>(self, reader: &mut R) -> Result, Error> + where + R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, + { + self.0.consume(reader) } - pub fn next(self) -> Result>, Error> { - if let Some(reader) = self.consume()? { + pub fn next<'a, R>(self, reader: &'a mut R) -> Result, Error> + where + R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, + { + if let Some(reader) = self.consume(reader)? { let hdu = XtensionHDU::new(reader)?; Ok(Some(hdu)) } else { Ok(None) } - } + }*/ } -impl<'a, R> Deref for PrimaryHDU<'a, R> -where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, -{ - type Target = HDU<'a, R, Image>; +impl Deref for PrimaryHDU { + type Target = HDU; fn deref(&self) -> &Self::Target { &self.0 @@ -69,15 +71,13 @@ where } use std::ops::DerefMut; -impl<'a, R> DerefMut for PrimaryHDU<'a, R> -where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, -{ +impl DerefMut for PrimaryHDU { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } +/* #[derive(Debug)] pub struct AsyncPrimaryHDU<'a, R>(pub AsyncHDU<'a, R, Image>) where @@ -146,7 +146,7 @@ where fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } -} +}*/ /* use std::pin::Pin; diff --git a/src/lib.rs b/src/lib.rs index 23e216c..dfd501d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,11 +38,11 @@ pub mod hdu; #[cfg(test)] mod tests { - use crate::fits::{AsyncFits, Fits}; - use crate::hdu::data::iter; + use crate::fits::Fits; use crate::hdu::data::stream; - use crate::hdu::data::InMemData; - use crate::hdu::extension::AsyncXtensionHDU; + //use crate::hdu::data::InMemData; + use crate::hdu::data::{iter, Slice}; + //use crate::hdu::extension::AsyncXtensionHDU; use crate::hdu::extension::XtensionHDU; use crate::hdu::header::extension::Xtension; use crate::hdu::header::BitpixValue; @@ -54,7 +54,7 @@ mod tests { use futures::{StreamExt, TryStreamExt}; use test_case::test_case; - #[test] + /*#[test] fn test_fits_image_mandatory_kw() { let f = File::open("samples/hipsgen/Npix208.fits").unwrap(); let bytes: Result, _> = f.bytes().collect(); @@ -253,7 +253,7 @@ mod tests { } _ => unreachable!(), } - } + }*/ #[test] fn test_fits_images_data_block() { @@ -262,54 +262,60 @@ mod tests { let mut f = File::open("samples/fits.gsfc.nasa.gov/EUVE.fits").unwrap(); let mut buf = Vec::new(); f.read_to_end(&mut buf).unwrap(); - let mut reader = Cursor::new(&buf[..]); + let reader = Cursor::new(&buf[..]); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); + let mut hdu_list = Fits::from_reader(reader).unwrap(); - let mut hdu_ext = hdu.next(); + //let mut hdu_ext = hdu.next(); - while let Ok(Some(xhdu)) = hdu_ext { - match &xhdu { + while let Some(hdu) = hdu_list.next() { + match hdu.unwrap() { XtensionHDU::Image(xhdu) => { - let xtension = xhdu.get_header().get_xtension(); - - let naxis1 = *xtension.get_naxisn(1).unwrap(); - let naxis2 = *xtension.get_naxisn(2).unwrap(); - - let num_pixels = (naxis2 * naxis1) as usize; - - match xhdu.get_data() { - InMemData::U8(mem) => assert_eq!(num_pixels, mem.len()), - InMemData::I16(mem) => assert_eq!(num_pixels, mem.len()), - InMemData::I32(mem) => assert_eq!(num_pixels, mem.len()), - InMemData::I64(mem) => assert_eq!(num_pixels, mem.len()), - InMemData::F32(mem) => assert_eq!(num_pixels, mem.len()), - InMemData::F64(mem) => assert_eq!(num_pixels, mem.len()), - } + let xtension = dbg!(xhdu.get_header().get_xtension()); + + let naxis1 = xtension.get_naxisn(1); + let naxis2 = xtension.get_naxisn(2); + + match (naxis1, naxis2) { + (Some(naxis1), Some(naxis2)) => { + let num_pixels = (naxis2 * naxis1) as usize; + + let data = xhdu.get_data(&mut hdu_list); + match data { + Slice::U8(mem) => assert_eq!(num_pixels, mem.len()), + Slice::I16(mem) => assert_eq!(num_pixels, mem.len()), + Slice::I32(mem) => assert_eq!(num_pixels, mem.len()), + Slice::I64(mem) => assert_eq!(num_pixels, mem.len()), + Slice::F32(mem) => assert_eq!(num_pixels, mem.len()), + Slice::F64(mem) => assert_eq!(num_pixels, mem.len()), + } + } + _ => (), + }; } XtensionHDU::BinTable(xhdu) => { let num_bytes = xhdu.get_header().get_xtension().get_num_bytes_data_block(); - - match xhdu.get_data() { + todo!(); + /*match xhdu.get_data(&mut hdu_list) { InMemData::U8(mem) => assert_eq!(num_bytes as usize, mem.len()), _ => unreachable!(), - } + }*/ } XtensionHDU::AsciiTable(xhdu) => { let num_bytes = xhdu.get_header().get_xtension().get_num_bytes_data_block(); + todo!(); + /*let num_bytes = xhdu.get_header().get_xtension().get_num_bytes_data_block(); match xhdu.get_data() { InMemData::U8(mem) => assert_eq!(num_bytes as usize, mem.len()), _ => unreachable!(), - } + }*/ } } - - hdu_ext = xhdu.next(); } } - #[test] + /*#[test] fn test_fits_images_data_block_bufreader() { use std::fs::File; @@ -509,5 +515,5 @@ mod tests { hdu_ext = xhdu.next().await; } - } + }*/ } From 21e20591c993bc273d5b0251444de0d7be8f6e6b Mon Sep 17 00:00:00 2001 From: Matthieu Baumann Date: Fri, 10 Jan 2025 16:27:37 +0100 Subject: [PATCH 2/3] API breaking: introduce a rust iterator over the HDU. Fix UB --- CHANGELOG | 11 + Cargo.toml | 4 +- README.md | 264 ++++++----- samples/fits.gsfc.nasa.gov/Astro_UIT.fits | 191 +++++++- src/async_fits.rs | 258 +++++++++++ src/fits.rs | 188 ++++---- src/hdu/data/asciitable.rs | 142 ++---- src/hdu/data/bintable.rs | 141 ++---- src/hdu/data/image.rs | 319 ++++--------- src/hdu/data/iter.rs | 34 +- src/hdu/data/layout.rs | 28 -- src/hdu/data/mod.rs | 74 +-- src/hdu/data/stream.rs | 71 ++- src/hdu/extension.rs | 159 ------- src/hdu/header/extension/asciitable.rs | 18 +- src/hdu/header/extension/bintable.rs | 19 +- src/hdu/header/extension/image.rs | 2 +- src/hdu/header/mod.rs | 114 ++--- src/hdu/mod.rs | 262 ++++++----- src/hdu/primary.rs | 49 -- src/lib.rs | 522 +++++++++++----------- 21 files changed, 1368 insertions(+), 1502 deletions(-) create mode 100644 CHANGELOG create mode 100644 src/async_fits.rs delete mode 100644 src/hdu/data/layout.rs diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..31b2d4b --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,11 @@ +# CHANGELOG.md + +## 0.3.0 (unreleased) + +Features: + +- BREAKING API change. Provide an iterator over the HDU list + +Bugfixes: + +- Be more safe about UB [https://github.com/cds-astro/fitsrs/issues/5]. BITPIX > 8 needs to be read from BigEndian scheme. It is thus necessary to create a new owned vector from the reading bytes. For BITPIX = 8, data can be directly read from the memory without allocating anything. diff --git a/Cargo.toml b/Cargo.toml index d00e54d..57a8fa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fitsrs" -version = "0.2.12" +version = "0.3.0" authors = ["Matthieu Baumann "] edition = "2018" description = "Implementation of the FITS image parser" @@ -21,7 +21,7 @@ exclude = [ byteorder = "1.4.2" serde = { version = "1.0.152", features = ["derive"] } serde_json = "1.0" -futures = "0.3.24" +futures = "0.3.31" async-trait = "0.1.66" quick-error = "2.0.1" diff --git a/README.md b/README.md index 6402951..03eea07 100644 --- a/README.md +++ b/README.md @@ -47,228 +47,222 @@ Example ---------- For files that can fit in memory -```rust -use fitsrs::{ - fits::Fits, - hdu::{ - data::InMemData, - extension::XtensionHDU - } -}; +```rust use std::fs::File; use std::io::Cursor; +use std::io::Read; +use fitsrs::{Fits, HDU}; +use fitsrs::{hdu::header::Xtension, hdu::data::Data}; let mut f = File::open("samples/fits.gsfc.nasa.gov/EUVE.fits").unwrap(); let mut buf = Vec::new(); f.read_to_end(&mut buf).unwrap(); -let mut reader = Cursor::new(&buf[..]); +let reader = Cursor::new(&buf[..]); -let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); +let mut hdu_list = Fits::from_reader(reader); // Access the HDU extensions -let mut hdu_ext = hdu.next(); - -while let Ok(Some(hdu)) = hdu_ext { - match &hdu { - XtensionHDU::Image(xhdu) => { - let xtension = xhdu.get_header().get_xtension(); +while let Some(Ok(hdu)) = hdu_list.next() { + match hdu { + HDU::Primary(_) => (), + HDU::XImage(hdu) => { + let xtension = hdu.get_header().get_xtension(); let naxis1 = *xtension.get_naxisn(1).unwrap() as usize; let naxis2 = *xtension.get_naxisn(2).unwrap() as usize; let num_pixels = naxis2 * naxis1; - match xhdu.get_data() { - InMemData::U8(mem) => assert_eq!(num_pixels, mem.len()), - InMemData::I16(mem) => assert_eq!(num_pixels, mem.len()), - InMemData::I32(mem) => assert_eq!(num_pixels, mem.len()), - InMemData::I64(mem) => assert_eq!(num_pixels, mem.len()), - InMemData::F32(mem) => assert_eq!(num_pixels, mem.len()), - InMemData::F64(mem) => assert_eq!(num_pixels, mem.len()), + match hdu.get_data(&mut hdu_list) { + Data::U8(mem) => assert_eq!(num_pixels, mem.len()), + Data::I16(mem) => assert_eq!(num_pixels, mem.len()), + Data::I32(mem) => assert_eq!(num_pixels, mem.len()), + Data::I64(mem) => assert_eq!(num_pixels, mem.len()), + Data::F32(mem) => assert_eq!(num_pixels, mem.len()), + Data::F64(mem) => assert_eq!(num_pixels, mem.len()), } }, - XtensionHDU::BinTable(xhdu) => { - let num_bytes = xhdu.get_header() + HDU::XBinaryTable(hdu) => { + let num_bytes = hdu.get_header() .get_xtension() .get_num_bytes_data_block(); - match xhdu.get_data() { - InMemData::U8(mem) => assert_eq!(num_bytes as usize, mem.len()), + match hdu.get_data(&mut hdu_list) { + Data::U8(mem) => assert_eq!(num_bytes as usize, mem.len()), _ => unreachable!() } }, - XtensionHDU::AsciiTable(xhdu) => { - let num_bytes = xhdu.get_header() + HDU::XASCIITable(hdu) => { + let num_bytes = hdu.get_header() .get_xtension() .get_num_bytes_data_block(); - match xhdu.get_data() { - InMemData::U8(mem) => assert_eq!(num_bytes as usize, mem.len()), + match hdu.get_data(&mut hdu_list) { + Data::U8(mem) => assert_eq!(num_bytes as usize, mem.len()), _ => unreachable!() } }, } - - hdu_ext = hdu.next(); } ``` -For files that may not be contained into the memory -```rust -use fitsrs::{ - fits::Fits, - hdu::{ - data::iter, - extension::XtensionHDU - } -}; +For BufReader +```rust use std::fs::File; +use std::io::Cursor; +use fitsrs::hdu::HDU; +use fitsrs::hdu::data::DataIter; +use fitsrs::fits::Fits; +use fitsrs::hdu::header::extension::Xtension; + use std::io::{BufReader, Read}; let f = File::open("samples/fits.gsfc.nasa.gov/EUVE.fits").unwrap(); -let mut reader = BufReader::new(f); - -let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); +let reader = BufReader::new(f); -let mut hdu_ext = hdu.next(); +let mut hdu_list = Fits::from_reader(reader); -while let Ok(Some(mut xhdu)) = hdu_ext { - match &mut xhdu { - XtensionHDU::Image(xhdu) => { - let xtension = xhdu.get_header().get_xtension(); +while let Some(Ok(hdu)) = hdu_list.next() { + match hdu { + // skip the primary HDU + HDU::Primary(_) => (), + HDU::XImage(hdu) => { + let xtension = hdu.get_header().get_xtension(); let naxis1 = *xtension.get_naxisn(1).unwrap(); let naxis2 = *xtension.get_naxisn(2).unwrap(); let num_pixels = (naxis2 * naxis1) as usize; - match xhdu.get_data_mut() { - iter::Data::U8(it) => { + match hdu.get_data(&mut hdu_list) { + DataIter::U8(it) => { let data = it.collect::>(); assert_eq!(num_pixels, data.len()) }, - iter::Data::I16(it) => { + DataIter::I16(it) => { let data = it.collect::>(); assert_eq!(num_pixels, data.len()) }, - iter::Data::I32(it) => { + DataIter::I32(it) => { let data = it.collect::>(); assert_eq!(num_pixels, data.len()) }, - iter::Data::I64(it) => { + DataIter::I64(it) => { let data = it.collect::>(); assert_eq!(num_pixels, data.len()) }, - iter::Data::F32(it) => { + DataIter::F32(it) => { let data = it.collect::>(); assert_eq!(num_pixels, data.len()) }, - iter::Data::F64(it) => { + DataIter::F64(it) => { let data = it.collect::>(); assert_eq!(num_pixels, data.len()) }, } }, - XtensionHDU::BinTable(xhdu) => { - let num_bytes = xhdu.get_header() + HDU::XBinaryTable(hdu) => { + let num_bytes = hdu.get_header() .get_xtension() .get_num_bytes_data_block(); - let it_bytes = xhdu.get_data_mut(); + let it_bytes = hdu.get_data(&mut hdu_list); let data = it_bytes.collect::>(); assert_eq!(num_bytes as usize, data.len()); }, - XtensionHDU::AsciiTable(xhdu) => { - let num_bytes = xhdu.get_header() + HDU::XASCIITable(hdu) => { + let num_bytes = hdu.get_header() .get_xtension() .get_num_bytes_data_block(); - let it_bytes = xhdu.get_data_mut(); + let it_bytes = hdu.get_data(&mut hdu_list); let data = it_bytes.collect::>(); assert_eq!(num_bytes as usize, data.len()); }, } - - hdu_ext = xhdu.next(); } ``` For async input readers: ```rust -use fitsrs::{ - fits::AsyncFits, - hdu::{ - data::stream, - extension::AsyncXtensionHDU +#[tokio::test] +async fn parse_fits_async() { + use std::fs::File; + use std::io::Cursor; + use fitsrs::hdu::AsyncHDU; + use fitsrs::hdu::data::stream::Stream; + use fitsrs::async_fits::AsyncFits; + use fitsrs::hdu::header::extension::Xtension; + + use std::io::{BufReader, Read}; + + // reader needs to implement futures::io::AsyncRead + let f = File::open("samples/fits.gsfc.nasa.gov/EUVE.fits").unwrap(); + let reader = BufReader::new(f); + + let mut hdu_list = AsyncFits::from_reader(reader); + + while let Some(Ok(mut hdu)) = hdu_list.next().await { + match hdu { + AsyncHDU::Primary(_) => (), + AsyncHDU::Image(hdu) => { + let xtension = hdu.get_header().get_xtension(); + + let naxis1 = *xtension.get_naxisn(1).unwrap() as usize; + let naxis2 = *xtension.get_naxisn(2).unwrap() as usize; + + let num_pixels = naxis2 * naxis1; + + match hdu.get_data(&mut hdu_list) { + Stream::U8(st) => { + let data = st.collect::>().await; + assert_eq!(num_pixels, data.len()) + }, + Stream::I16(st) => { + let data = st.collect::>().await; + assert_eq!(num_pixels, data.len()) + }, + Stream::I32(st) => { + let data = st.collect::>().await; + assert_eq!(num_pixels, data.len()) + }, + Stream::I64(st) => { + let data = st.collect::>().await; + assert_eq!(num_pixels, data.len()) + }, + Stream::F32(st) => { + let data = st.collect::>().await; + assert_eq!(num_pixels, data.len()) + }, + Stream::F64(st) => { + let data = st.collect::>().await; + assert_eq!(num_pixels, data.len()) + }, + } + }, + AsyncHDU::XBinaryTable(hdu) => { + let num_bytes = hdu.get_header() + .get_xtension() + .get_num_bytes_data_block(); + + let it_bytes = hdu.get_data(&mut hdu_list); + let data = it_bytes.collect::>().await; + assert_eq!(num_bytes as usize, data.len()); + }, + AsyncHDU::XASCIITable(hdu) => { + let num_bytes = xhdu.get_header() + .get_xtension() + .get_num_bytes_data_block(); + + let it_bytes = xhdu.get_data(&mut hdu_list); + let data = it_bytes.collect::>().await; + assert_eq!(num_bytes as usize, data.len()); + }, + } } -}; - -// reader needs to implement futures::io::AsyncRead -let AsyncFits { hdu } = AsyncFits::from_reader(&mut reader).await.unwrap(); - -let mut hdu_ext = hdu.next().await; - -while let Ok(Some(mut xhdu)) = hdu_ext { - match &mut xhdu { - AsyncXtensionHDU::Image(xhdu) => { - let xtension = xhdu.get_header().get_xtension(); - - let naxis1 = *xtension.get_naxisn(1).unwrap() as usize; - let naxis2 = *xtension.get_naxisn(2).unwrap() as usize; - - let num_pixels = naxis2 * naxis1; - - match xhdu.get_data_mut() { - stream::Data::U8(st) => { - let data = st.collect::>().await; - assert_eq!(num_pixels, data.len()) - }, - stream::Data::I16(st) => { - let data = st.collect::>().await; - assert_eq!(num_pixels, data.len()) - }, - stream::Data::I32(st) => { - let data = st.collect::>().await; - assert_eq!(num_pixels, data.len()) - }, - stream::Data::I64(st) => { - let data = st.collect::>().await; - assert_eq!(num_pixels, data.len()) - }, - stream::Data::F32(st) => { - let data = st.collect::>().await; - assert_eq!(num_pixels, data.len()) - }, - stream::Data::F64(st) => { - let data = st.collect::>().await; - assert_eq!(num_pixels, data.len()) - }, - } - }, - AsyncXtensionHDU::BinTable(xhdu) => { - let num_bytes = xhdu.get_header() - .get_xtension() - .get_num_bytes_data_block(); - - let it_bytes = xhdu.get_data_mut(); - let data = it_bytes.collect::>().await; - assert_eq!(num_bytes as usize, data.len()); - }, - AsyncXtensionHDU::AsciiTable(xhdu) => { - let num_bytes = xhdu.get_header() - .get_xtension() - .get_num_bytes_data_block(); - - let it_bytes = xhdu.get_data_mut(); - let data = it_bytes.collect::>().await; - assert_eq!(num_bytes as usize, data.len()); - }, - } - - hdu_ext = xhdu.next().await; } ``` \ No newline at end of file diff --git a/samples/fits.gsfc.nasa.gov/Astro_UIT.fits b/samples/fits.gsfc.nasa.gov/Astro_UIT.fits index 241ff56..c431d49 100644 --- a/samples/fits.gsfc.nasa.gov/Astro_UIT.fits +++ b/samples/fits.gsfc.nasa.gov/Astro_UIT.fits @@ -1,3 +1,188 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3110c73eebbdd479b9a51cb275f18650f17d22b818713562b6e27d873e128530 -size 864810 +SIMPLE = T / FLIGHT22 05Apr96 RSH BITPIX = 16 / SIGNED 16-BIT INTEGERS NAXIS = 2 / 2-DIMENSIONAL IMAGES NAXIS1 = 512 / SAMPLES PER LINE NAXIS2 = 512 / LINES PER IMAGE EXTEND = T / FILE MAY HAVE EXTENSIONS DATATYPE= 'INTEGER*2' / SAME INFORMATION AS BITPIX TELESCOP= 'UIT ' / TELECOPE USED INSTRUME= 'INTENSIFIED-FILM' / DETECTOR USED OBJECT = 'NGC4151 ' / TARGET NAME OBJECT2 = '_ ' / ALTERNATIVE TARGET NAME CATEGORY= 'FLIGHT ' / TARGET CATEGORY JOTFID = '8116-14 ' / ASTRO MISSION TARGET ID IMAGE = 'FUV2582 ' / IMAGE NUMBER ORIGIN = 'UIT/GSFC' / WHERE TAPE WRITTEN ASTRO = 2 / ASTRO MISSION NUMBER FRAMENO = 'b0582 ' / ANNOTATED FRAME NUMBER CATHODE = 'CSI ' / IMAGE TUBE PHOTOCATHODE FILTER = 'B1 ' / CAMERA/FILTER IDENTIFIER PDSDATIM= '06-JUL-1995 07:20' / MICRODENSITOMETRY DATE & TIME PDSID = 21 / MICRODENSITOMETER IDENT PDSAPERT= 20 / MICROD. APERTURE, MICRONS PDSSTEP = 10 / MICROD. STEP SIZE, MICRONS PIXELSIZ= 8.0000000E+01 / CURRENT PIXEL SIZE, MICRONS EQUINOX = 2.0000000E+03 / EQUINOX OF BEST COORDINATES NOMRA = 182.0044 / 1950 I.P.S. R.A., DEGREES NOMDEC = 39.6839 / 1950 I.P.S. DEC., DEGREES NOMROLL = 323.9500 / I.P.S. ROLL ANGLE NOMSCALE= 5.6832500E+01 / NOMINAL PLATE SCL (ARCSEC/MM) CALIBCON= 5.00000E-16 / PREFLIGHT LAB CALIB FOR CAMERA FEXPTIME= '8355 ' / EXPOSURE TIME, APPLICABLE FRM DATE-OBS= '13/03/95' / DATE OF OBSERVATION (GMT) TIME-OBS= 6.2728000E+00 / TIME OF OBS (HOURS GMT) BSCALE = 2.0587209E-16 / CALIBRATION CONST BUNIT = 'ERGS/CM**2/S/ANGSTRM' BZERO = 0.00000 / ADDITIVE CONST FOR CALIB. PATCHFIL= 'PATCH2 ' / FILE WITH PATCH INFORMATION FADJPROG= 'UITBAK ' / FOG ADJUSTMENT PROGRAM FADJVER = '2.1 ' / FOG ADJUSTMENT PROGRAM VERSION FADJDTIM= 'Jul 22,1996 12:53:24' FOGLL = 2.8988638E+02 / LOWER LEFT CORNER FOG FOGLLERR= 3.9720482E+01 / LOWER LEFT CORNER FOG ERROR FOGLR = 2.8807239E+02 / LOWER RIGHT CORNER FOG FOGLRERR= 3.9098114E+01 / LOWER RIGHT CORNER FOG ERROR FOGUL = 2.9494131E+02 / UPPER LEFT CORNER FOG FOGULERR= 4.0041096E+01 / UPPER LEFT CORNER FOG ERROR FOGUR = 2.8711835E+02 / UPPER RIGHT CORNER FOG FOGURERR= 3.8879002E+01 / UPPER RIGHT CORNER FOG ERROR EXPTIME = 8.3199997E+01 / EXPOSURE TIME, SECONDS FEXPNOTE= 'Fb40 ' / EXPOSURE TIME ANNOTATION EXPTMSRC= 'PREVFRAME' / SOURCE OF EXPTIME VALUE CRPIX1 = 2.5650000E+02 / REF. PIXEL, X, CENTER ORIGIN CRPIX2 = 2.5650000E+02 / REF. PIXEL, Y, CENTER ORIGIN CRVAL1 = 1.8265300E+02 / R. A., DEGREES, OF REF. PIXEL CRVAL2 = 3.9375320E+01 / DEC., DEGREES, OF REF. PIXEL CTYPE1 = 'RA---TAN' / COORDINATE TYPE CTYPE2 = 'DEC--TAN' / COORDINATE TYPE UNDISTRT= T / HAS THE IMAGE BEEN UNDISTORTED? CD1_1 = -1.2629445E-03 / SDAS-COMPATIBLE: DL/DX CD2_1 = 0.0000000E+00 / DM/DX CD1_2 = 0.0000000E+00 / DL/DY CD2_2 = 1.2629445E-03 / DM/DY BDRSTREM= 'FLIGHT22' / DATA REDUCTION STREAM IDENT PREDECES= 4275 / ENTRY OF PREVIOUS STEP LOGENTRY= 4281 / ENTRY IN BDR LOG HDCURVID= 'CALIB5 ' / CHARACTERISTIC CURVE IDENT FFID = 'FUV1V032' / FLAT FIELD IDENTIFIER FFSCALE = 253.769 / FLAT FIELD SCALE FACTOR CAMSCALE= 1.72E-16 / BASIC CAMERA CALIB. CONSTANT FILTFAC = 1.0 / AREA UNDER FILTER CURVE CALIBVER= '20-MAR-1996 LANDSMAN, USING ASTRO2 DATA' SHRINK = 2 / BOX-AVERAGE FACTOR ON INPUT BDRDATIM= 'Jul 22,1996 13:13:19' BDRIPRG = 'BDRON4 ' / CHAR. CURVE/FLAT-FIELD PROGRAM BDRIVER = '2.0 ' / CHAR. CURVE/FLAT-FIELD PROG VERS TIMEFAC = 1.5560098E+00 / T^0.1 PICSCAL0= 2.0673078E-18 / CAMSCALE*FILTFAC/EXPTIME PICSCALE= 3.2167511E-18 / CAMSCALE*FILTFAC*TIMEFAC/EXPTIME RADECSYS= 'FK5 ' / WORLD COORDINATE FRAME A_NMATCH= 4 / NUM OF ASTROM STDS MATCHED AX_RESID= 3.0000001E-01 / RMS ASTROM RESIDUALS (PIXELS): AY_RESID= 3.0000001E-01 / <0 MEANS DEFAULT SOLUTION HISTORY Jul 22,1996 13:13:21 ASTROM FROM BDR STREAM FLIGHT21 HISTORY Jul 22,1996 13:13:21 ASTROMETRY WAS THEN DONE BY UITCA2 HISTORY Jul 22,1996 13:13:21 VERSION 2.5 HISTORY Jul 22,1996 13:13:21 AT DATE AND TIME Jul 18,1995 17:41:19 VARCURVE= 'CALIB5 ' / VARIANCE FUNCTION IDENT PHT1PROG= 'UITPH1 ' / POINT SOURCE PHOTOMETRY PROGRAM PHT1VER = '4.4 ' / UITPH1 VERSION PHT1DTIM= 'Jul 22,1996 13:21:36' FWHM = 5.0000000E+00 / FWHM OF DETECTION FILTER IMIN = 30 / MINIMUM SIGNAL FOR DPFIND IMAX = 20000 / MAXIMUM SIGNAL FOR DPFIND APR = 3 / NUMBER OF PHOTOMETRY APERTURES APR1 = 3.0000000E+00 / RADIUS OF 1ST APERTURE APR2 = 2.0000000E+00 / RADIUS OF 2ND APERTURE APR3 = 7.0000000E+00 / RADIUS OF 3RD APERTURE SKYIN = 1.5000000E+01 / INNER RADIUS OF SKY ANNULUS SKYOUT = 2.5000000E+01 / OUTER RADIUS OF SKY ANNULUS BADLO = -1.0000000E+02 / LOWEST GOOD PIXEL VALUE BADHI = 2.0000000E+04 / HIGHEST GOOD PIXEL VALUE RCRIT = 9.9000000E+02 / RADIUS OF IMAGE CIRCLE USED SKWFAC = 2.0000000E-01 / PARAMETER FOR TRIMMING SKY LIMSKW = 15 / VALUE <= WHICH SKWFAC APPLIES MEALIM = -9.9990002E+02 / VALUE <= WHICH MEAN SKY USED SV_NAX1 = 2048 / X DIMENSION OF ORIGINAL IMAGE SV_NAX2 = 2048 / Y DIMENSION OF ORIGINAL IMAGE ASTRPROG= 'UITCA2 ' / ASTROMETRY PROGRAM NAME ASTRVER = '2.5 ' / ASTROMETRY PROGRAM VERSION ASTRDTIM= 'Jul 22,1996 14:16:55' HISTORY Jul 22,1996 14:16:55 ASTROMETRY. COPIED FROM IMAGE FUV2583 NHEDATIM= 'Jul 22,1996 16:05:36' NHEDPRG = 'NEWHED ' / HEADER ATTACHMENT PROGRAM NHEDVER = '3.1 ' / HEADER ATTACH. PROG. VERSION GEOMPROG= 'UITGE2 ' / ROTATION/RESAMPLING PROGRAM GEOMVER = '3.1 ' / GEOM PROGRAM VERSION GEOMDTIM= 'Jul 22,1996 16:11:19' SV001001= 6.9340203E-05 / ORIGINAL CD00M00N: DL/DX SV001002= -3.1189100E-04 / DL/DY SV002001= -3.0647300E-04 / DM/DX SV002002= -6.6140099E-05 / DM/DY SVPIX1 = 1.0245000E+03 / ORIGINAL REFERENCE PIXEL X SVPIX2 = 1.0245000E+03 / ORIGINAL REFERENCE PIXEL Y SVVAL1 = 1.8265289E+02 / ORIGINAL R.A. OF REF. PIXEL SVVAL2 = 3.9375599E+01 / ORIGINAL DEC. OF REF. PIXEL SVCTYPE1= 'RA--UIT2' / COORDINATE TYPE SVCTYPE2= 'DEC-UIT2' / COORDINATE TYPE BXAVDTIM= 'Jul 22,1996 16:19:19' BXAVPROG= 'UITBXA ' / ROTATION/RESAMPLING PROGRAM BXAVVER = '2.4 ' / RESAMPLING PROGRAM VERSION BXAVFAC = 4 / BOX-AVERAGE FACTOR FOR SMALL VER END ������������������������������������������������������ �������W�-#At� +\�����������=��^WPO[iecjkly���������������� "��4�� ������������������������������������������������������������ +!��_�����*wpy�������=��KCGEJRQJSea`epoq�}y��������������������`�� �������������������������������������������������������������������� ��+�� +SVeYc}|�J��fF9:==@HKEDSTR_f]eqnon}y����������������������u + ������������������������������������������������������������������������������ + +��� &/RgnC��F4035<78=DADGCBQST\cd\inghz}v���������s��w��kn�����o* + ��������������������������������������������������������������������������������������������������������������!��W��$3��X6'(*&.124<69:A?BKJJNQPSec^hmhfszs�����jo��p��m� ����f>�� + + +�������������������������������������������������������������� ��'���= %&#)*++.31967>?@CNKGKSVP\\bdmlmlo^{{dz�dS����.)1 #����~Y< +���� + ������������������������������������������������������������������������������������������������ ~��"�""$%()*25533;6=?BEHLLMYRSV]^cnnjq\Ol�`a����%7P=01����fI5�� +����������������������������������������������������������������������R�� +##&$)+--102176:=ACFMOJNUTQccdj_SliN]���FbfcnQF6�����p]@/���� +����������������������������������������������������������������������������������������������������������  ��+���3C!#%),)+/-..577>BDCKIHKTWQ_HP]ZId��=sr�|rd`DWH����{gF.  +���������������������������������������������������������������������������������������������� +v����#'',,/+0+/4648?BAEGCHEDGSI\~� N��alkys_eFC7.$���~V- +�������� +��������������������������������������������������������������������������������������������������M���� "&((-)).--/265:=;>77>EGr�ml{m|zzrWP`nPM;='*��v<�������� +���������������������������������������������������������������������������������������������������� +����&����C %(',.)+.-3302/304?]� X����}kl|}]wbRUD:<* +��H �������������������������������������������������������������������������������������������������������������������������� +����w��� +�!%&*%*))&+.*&2R��>q��x�|v�ofYoaYy^@@/��a( ������������������������������������������������������������������������������������������������������������������������������I����$!&%$%%#-I��,qx|go{�r�hqk]RJZlD_�u1 + + +  ���� + +�������������������������������������������������������������������������������������� ����������������������������������������  +%����<!*C��.JYe\hoi]�zocj]isrRX��; +���� +  +  + ����������������������������������������������������������������������������������������������������������������������������������������������e�����,V��G>ZLQ>VH]YYXXCXhiZP��; + + + + +  + + ����������������������������������������������������������������������������������������������������������������������������������;u�����*=07(8=EI5:EL?BZG'��; + + "*%$ " + + + ���������������������������������������������������������������������������������������������������������������������������������� +��Ys������,(+-$51/77�v9 + + + +   +&/7/363) + + + +�������������������������������������������������������������������������������������������������������������������������������������������������������������� +F[q��������* %��o. +  + +  +#,5@H><=0.1') + + ������������������������������������������������������������������������������������������������������������������������������������������������(ARg������� +���Y$ + + + + +  + !6DFF4EGJ/33.%% +������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ��0:O]s�����o> + + + +    ?TI?CB:5,43.'*#%" + ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� !0;KWF4 + +  + + *39AE<@<05.0/+(&(&  ������������������������������������������������������������������������������������������������������������������������������������������������������������������������  %3<>E@<;0..)-(%  ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������".8?@?:7.,-)&" ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.>B@?60)(&## "!!&! + +���������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������� + .6(*+)++% " !!! ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� +! #%'",(%#! + ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ + + # + ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ + + +������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������  + + + + ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ + + ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� +������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ + +��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������(-! �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� +./) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������-92)!����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������+/(#.;7/( +�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� + 9DA>62/'(& *C76/ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� (FQRMJICCHI[��;!BA;6#�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� 'MZ_STVXUTf~�47`' >B@;(���������������������������������������������������� +���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� -Qcfe_^\[bo��8����K�.":MDB1 +�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ,Wgdkgbdeer��N�������mC�<".LJD4 +����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������jlgkklno|��2�� +��������L W%)QIJ?)��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������intqv���4�� �������x?f'&GPLI,������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������pv|��D�1? 2 �������A�-'@WNK3 +������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0�9#$14!H + �����h�-$6VOP3 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������02K,LH�'   / +����h�8%/OSR;����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H16QN<6KBS!H(  �����C%'LUUC'��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������2LMQHH@"9/19L1/-������0P'(GVTD* +����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������LSKmLHP;`4&<<<8&( +���Bu.%<\ZS- ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������-b@ufQS2;V9.OD13����`�3$2TYT9$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������o:6eXC I]`zV8v/C:9: �����B++Q^Z?) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xWZ%o cI:aH>)VF.����#V,'K]TD. �������������������������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������lz_:����P_VPYCBA7C>�'����eq2'?YXM2#���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������:z}qDQN@=(.������:)8aX[:$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������6��F���LNcJ/Z_,@K5 +�����B*.X[_?%������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Kh���{ufDO;/+?���3M+-VZ]F(����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������!�{���sXFG\3 +���Eb,'H]aL,�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������po�N4����B��FfY�K/C# ���a&!9a[Q1���������������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������T����������^j{ml{T_6�����*1Z]X/ +������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ �����������������������������������������������������������������������������������_LNS89������8&U_V0 +����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������~��mXZye>,����� C#P^T8������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �����ur�D.`9������YY#";UT7�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������c[CIH3$�� ����#4TI7�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������0�*�8�m�i�KU5<!U8&z� ��|�/,LE0����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������r�Mn�hI�Pa4(/0$:(���:#C@. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������{W�OoL]7iPHw@02�����3O;20%������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������u\I����ViEjWGJGHk*�h����Zh/25*��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������QZP~jt\DQT�KEE(W����g����$$00( +��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������r0,MN?3 daXh)��4��;��������%/1* ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@;3`U*=K6(�B�-�A�0�����2),* +��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������?A&X.=R�0���;�A(�?B03"��� +<#-& ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'$ +;�?�P�t��-?0�JL</H##���5G* ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������S,d�N)0>�cq!�\D +�������-a' ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Io�R�Q +/�x�UT_c>8��������=��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������vl�X�fR�vwquC$�������������S�"����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������sT8 ������������������) + +������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������e�������j-��������������������u�9 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������a����u�����������������lrg  ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������~��]O[ele���e��������������{� " ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������dJ?GHIgse������������������U � " ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������+(5?>dvymtt����������[u���c +�) + +������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������/)1YtuOb�z�����zV�oqs��h��' + + +����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������!D9Cj_Gs����jbwh4�n;�s�eJ�y'  + ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� C2[PH�WSaz7C�O-�����uf5�h!  + +������������������������ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ +NNS.O�,�������\K!�`  ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� $0/�E�����������A8��L   +������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������"�8w��������} �y4 + ���������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������-^�� +/������������~0�� + +�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������C�3,<%,! +�������'�I3  + ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'��\=#E�������jB& +   +����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������*q�F:P0+%�����<�bA3) +  ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������b�7RYW4K9�3&�W�nL8*+"  + + ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;DEN!& +,��v��VF81'$     ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<2&#$(!3� �]G:60.'! + ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������IB<"J�n��bF=561,,$!-9.% + + ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������";*C�i �aN@974-*%"! "".GRJL?+  ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'�'�pPC;4/.*'&%!#+:Wy�`N:. �� +��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������6�pRM>;71,-%('$.@g����wcQ=+ +����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������YJ@=871,+(((.Gp������n^LA6# +����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������;932-,*-+.Gy������up[VPJ=!������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������2-+-)-4Is�������ja_^B'������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������+),7M���������qnibJ(���������������������������� ������ +��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������6R���������xul`D%������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������|xmW5 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������xkN7 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������}oO( ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������oO) + ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ +���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� + +��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������'&#��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������"=\=#���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� %n�- ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%T��( +�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� &62# ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� +���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ +������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������  ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� +����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������  + ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������!(!�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� #!#$%���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� $!#-$������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������   '+&2.������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ + %!��$." (/93���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ' -42635-��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%) + +  +&481'$$�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� +# 05(���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� *+"!%&# )2!����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������(+.--**# + +!)&!���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� + !+* "!#"$���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� +$/$  ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� + +'&  + + ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� + " ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ + ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ +������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������  ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ !& +��������������������������������������������������������������������������������������������������������������������������������������������������������������������������$)'''������������������������������������������������������������������������������������������������������������������������������������������������������������������������ + +!,( ���������������������������������������������������������������������������������������������������������������������������������������������������������� + +(-#��������������������������������������������������������������������������������������������������������������������������������������������������" %/. ����������������������������������������������������������������������������������������������������������������������������������������������������&,��!.54# ������������������������������������������������������������������������������������������������������������������������������������������������������������ �� +$0&  !-520, +����������������������������������������������������������������������������������������������������������������������������������  + ++/ !%!$($ ������������������������������������������������������������������������������������������������������������ \ No newline at end of file diff --git a/src/async_fits.rs b/src/async_fits.rs new file mode 100644 index 0000000..ab6b099 --- /dev/null +++ b/src/async_fits.rs @@ -0,0 +1,258 @@ +use std::pin::Pin; + +use futures::{Future, Stream}; +use serde::Serialize; + +use crate::hdu; +use crate::hdu::data::AsyncDataBufRead; +use crate::hdu::header::extension::asciitable::AsciiTable; +use crate::hdu::header::extension::bintable::BinTable; +use crate::hdu::header::extension::image::Image; +use crate::hdu::header::extension::Xtension; +use crate::hdu::header::Header; + +//use crate::hdu::data::{DataAsyncBufRead, DataBufRead}; + +#[derive(Debug, Serialize)] +pub struct AsyncFits { + start: bool, + // Store the number of bytes that remains to read so that the current HDU data finishes + // When getting the next HDU, we will first consume those bytes if there are some + num_remaining_bytes_in_cur_hdu: usize, + // Keep track of the number of total bytes for the current HDU as we might + // skip the trailing bytes to get to a multiple of 2880 bytes + num_bytes_in_cur_hdu: usize, + // If an error has been encountered, the HDU iterator ends + error_parsing_encountered: bool, + reader: R, +} + +use crate::error::Error; +impl<'a, R> AsyncFits { + /// Parse a FITS file + /// # Params + /// * `reader` - a reader created i.e. from the opening of a file + pub fn from_reader(reader: R) -> Self { + Self { + reader, + num_remaining_bytes_in_cur_hdu: 0, + num_bytes_in_cur_hdu: 0, + error_parsing_encountered: false, + start: true, + } + } +} + +use futures::AsyncBufReadExt; +impl<'a, R> AsyncFits +where + R: AsyncDataBufRead<'a, Image> + + AsyncDataBufRead<'a, AsciiTable> + + AsyncDataBufRead<'a, BinTable> + + 'a, +{ + /// Returns a boolean to know if we are at EOF + async fn consume_until_next_hdu(&mut self) -> Result { + // 1. Check if there are still bytes to be read to get to the end of data + if self.num_remaining_bytes_in_cur_hdu > 0 { + // Then read them + >::read_n_bytes_exact( + &mut self.reader, + self.num_remaining_bytes_in_cur_hdu as u64, + ) + .await?; + } + + // 2. We are at the end of the real data. As FITS standard stores data in block of 2880 bytes + // we must read until the next block of data to get the location of the next HDU + + let is_remaining_bytes = (self.num_bytes_in_cur_hdu % 2880) > 0; + // Skip the remaining bytes to set the reader where a new HDU begins + if is_remaining_bytes { + let mut block_mem_buf: [u8; 2880] = [0; 2880]; + + let num_off_bytes = (2880 - (self.num_bytes_in_cur_hdu % 2880)) as usize; + match self + .reader + .read_exact(&mut block_mem_buf[..num_off_bytes]) + .await + { + // An error like unexpected EOF is not permitted by the standard but we make it pass + // interpreting it as the last HDU in the file + Err(ref e) if e.kind() == std::io::ErrorKind::UnexpectedEof => return Ok(true), + Err(e) => return Err(e.into()), + Ok(()) => {} + } + } + + let eof = self.reader.fill_buf().await?.is_empty(); + Ok(eof) + } +} + +use futures::task::Context; +use futures::task::Poll; +impl<'a, R> Stream for AsyncFits +where + R: AsyncDataBufRead<'a, Image> + + AsyncDataBufRead<'a, BinTable> + + AsyncDataBufRead<'a, AsciiTable> + + 'a, +{ + type Item = Result; + + /// Attempt to resolve the next item in the stream. + /// Returns `Poll::Pending` if not ready, `Poll::Ready(Some(x))` if a value + /// is ready, and `Poll::Ready(None)` if the stream has completed. + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + if self.error_parsing_encountered { + Poll::Ready(None) + } else { + let hdu = if !self.start { + // We must consume the bytes until the next header is found + // if eof then the iterator finishes + let mut consume_tokens_until_next_hdu = self.consume_until_next_hdu(); + let eof = match std::pin::pin!(consume_tokens_until_next_hdu).poll(cx) { + Poll::Pending => return Poll::Pending, + // The future finished returning the eof information + Poll::Ready(r) => r, + }; + + match eof { + Ok(eof) => { + if !eof { + // parse the extension HDU + let r = &mut self.reader; + let mut parse_x_hdu = hdu::AsyncHDU::new_xtension(r); + match std::pin::pin!(parse_x_hdu).poll(cx) { + Poll::Pending => return Poll::Pending, + // the future finished, returning the parsed hdu or the error while parsing it + Poll::Ready(r) => Some(r), + } + } else { + None + } + } + Err(e) => Some(Err(e)), + } + } else { + // parse the primary HDU + let mut parse_first_hdu = hdu::AsyncHDU::new_primary(&mut self.reader); + match std::pin::pin!(parse_first_hdu).poll(cx) { + Poll::Pending => return Poll::Pending, + // the future finished, returning the parsed hdu or the error while parsing it + Poll::Ready(r) => Some(r), + } + }; + + self.start = false; + + match hdu { + Some(Ok(hdu)) => { + self.num_bytes_in_cur_hdu = match &hdu { + hdu::AsyncHDU::XImage(h) | hdu::AsyncHDU::Primary(h) => { + let xtension = h.get_header().get_xtension(); + xtension.get_num_bytes_data_block() as usize + } + hdu::AsyncHDU::XASCIITable(h) => { + let xtension = h.get_header().get_xtension(); + xtension.get_num_bytes_data_block() as usize + } + hdu::AsyncHDU::XBinaryTable(h) => { + let xtension = h.get_header().get_xtension(); + xtension.get_num_bytes_data_block() as usize + } + }; + + self.num_remaining_bytes_in_cur_hdu = self.num_bytes_in_cur_hdu; + + Poll::Ready(Some(Ok(hdu))) + } + Some(Err(e)) => { + // an error has been found we return it and ends the iterator for future next calls + self.error_parsing_encountered = true; + + Poll::Ready(Some(Err(e))) + } + None => Poll::Ready(None), + } + } + } +} + +#[derive(Debug)] +pub struct AsyncHDU +where + X: Xtension, +{ + /// The header part that stores all the cards + header: Header, +} + +use futures::AsyncReadExt; +impl AsyncHDU +where + X: Xtension + std::fmt::Debug, +{ + pub async fn new<'a, R>( + reader: &mut R, + num_bytes_read: &mut usize, + card_80_bytes_buf: &mut [u8; 80], + ) -> Result + where + R: AsyncDataBufRead<'a, X> + 'a, + { + /* 1. Parse the header first */ + let header = Header::parse_async(reader, num_bytes_read, card_80_bytes_buf).await?; + /* 2. Skip the next bytes to a new 2880 multiple of bytes + This is where the data block should start */ + let is_remaining_bytes = ((*num_bytes_read) % 2880) > 0; + + // Skip the remaining bytes to set the reader where a new HDU begins + if is_remaining_bytes { + let mut block_mem_buf: [u8; 2880] = [0; 2880]; + + let num_off_bytes = (2880 - ((*num_bytes_read) % 2880)) as usize; + reader + .read_exact(&mut block_mem_buf[..num_off_bytes]) + .await + .map_err(|_| Error::StaticError("EOF reached"))?; + + *num_bytes_read += num_off_bytes; + } + + // Data block + + Ok(Self { header }) + } + + pub fn get_header(&self) -> &Header { + &self.header + } + + // Retrieve the iterator or in memory data from the reader + // This has the effect of consuming the HDU + pub fn get_data<'a, R>( + self, + hdu_list: &'a mut AsyncFits, + ) -> >::Data + where + R: AsyncDataBufRead<'a, X> + + AsyncDataBufRead<'a, Image> + + AsyncDataBufRead<'a, BinTable> + + AsyncDataBufRead<'a, AsciiTable>, + { + // Unroll the internal fits parsing parameters to give it to the data reader + let AsyncFits { + num_remaining_bytes_in_cur_hdu, + reader, + .. + } = hdu_list; + let xtension = self.header.get_xtension(); + >::prepare_data_reading( + xtension, + num_remaining_bytes_in_cur_hdu, + reader, + ) + } +} diff --git a/src/fits.rs b/src/fits.rs index 3bfdcd3..9d79f63 100644 --- a/src/fits.rs +++ b/src/fits.rs @@ -1,55 +1,67 @@ -use std::io::BufRead; - use serde::Serialize; -use crate::hdu::data::DataBufRead; -use crate::hdu::extension::XtensionHDU; +use crate::hdu; use crate::hdu::header::extension::asciitable::AsciiTable; use crate::hdu::header::extension::bintable::BinTable; use crate::hdu::header::extension::image::Image; -use crate::hdu::header::extension::Xtension; use crate::hdu::header::Header; - -//use crate::hdu::data::{DataAsyncBufRead, DataBufRead}; +use crate::hdu::header::Xtension; #[derive(Debug, Serialize)] pub struct Fits { start: bool, - num_bytes_read: usize, + // Store the number of bytes that remains to read so that the current HDU data finishes + // When getting the next HDU, we will first consume those bytes if there are some + num_remaining_bytes_in_cur_hdu: usize, + // Keep track of the number of total bytes for the current HDU as we might + // skip the trailing bytes to get to a multiple of 2880 bytes + num_bytes_in_cur_hdu: usize, + // If an error has been encountered, the HDU iterator ends error_parsing_encountered: bool, reader: R, } use crate::error::Error; -use crate::hdu::primary::PrimaryHDU; impl<'a, R> Fits { /// Parse a FITS file /// # Params /// * `reader` - a reader created i.e. from the opening of a file - pub fn from_reader(reader: R) -> Result { - //let hdu = PrimaryHDU::new(reader)?; - - Ok(Self { + pub fn from_reader(reader: R) -> Self { + Self { reader, - num_bytes_read: 0, + num_remaining_bytes_in_cur_hdu: 0, + num_bytes_in_cur_hdu: 0, error_parsing_encountered: false, start: true, - }) + } } } -impl Fits +use hdu::data::DataBufRead; +impl<'a, R> Fits where - R: BufRead, + R: DataBufRead<'a, Image> + DataBufRead<'a, AsciiTable> + DataBufRead<'a, BinTable> + 'a, { /// Returns a boolean to know if we are at EOF fn consume_until_next_hdu(&mut self) -> Result { - let is_remaining_bytes = (self.num_bytes_read % 2880) > 0; + // 1. Check if there are still bytes to be read to get to the end of data + if self.num_remaining_bytes_in_cur_hdu > 0 { + // Then read them + >::read_n_bytes_exact( + &mut self.reader, + self.num_remaining_bytes_in_cur_hdu as u64, + )?; + } + + // 2. We are at the end of the real data. As FITS standard stores data in block of 2880 bytes + // we must read until the next block of data to get the location of the next HDU + + let is_remaining_bytes = (self.num_bytes_in_cur_hdu % 2880) > 0; // Skip the remaining bytes to set the reader where a new HDU begins if is_remaining_bytes { let mut block_mem_buf: [u8; 2880] = [0; 2880]; - let num_off_bytes = (2880 - (self.num_bytes_read % 2880)) as usize; + let num_off_bytes = (2880 - (self.num_bytes_in_cur_hdu % 2880)) as usize; match self.reader.read_exact(&mut block_mem_buf[..num_off_bytes]) { // An error like unexpected EOF is not permitted by the standard but we make it pass // interpreting it as the last HDU in the file @@ -57,8 +69,6 @@ where Err(e) => return Err(e.into()), Ok(()) => {} } - - self.num_bytes_read += dbg!(num_off_bytes); } let eof = self.reader.fill_buf()?.is_empty(); @@ -68,39 +78,63 @@ where impl<'a, R> Iterator for Fits where - //R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, - R: DataBufRead<'a, Image> + 'a, + R: DataBufRead<'a, Image> + DataBufRead<'a, AsciiTable> + DataBufRead<'a, BinTable> + 'a, { - type Item = Result; + type Item = Result; fn next(&mut self) -> Option { if self.error_parsing_encountered { None - } else if self.start { - self.start = false; - - if let Ok(prim_hdu) = PrimaryHDU::new(&mut self.reader, &mut self.num_bytes_read) { - Some(Ok(XtensionHDU::Image(prim_hdu.0))) - } else { - None - } } else { - // We must consume the bytes until the next header is found - // if eof then the iterator finishes - match self.consume_until_next_hdu() { - Ok(eof) => { - if dbg!(eof) { - None - } else { - Some(XtensionHDU::new(&mut self.reader, &mut self.num_bytes_read)) + let n = if !self.start { + // We must consume the bytes until the next header is found + // if eof then the iterator finishes + match self.consume_until_next_hdu() { + Ok(eof) => { + if !eof { + Some(hdu::HDU::new_xtension(&mut self.reader)) + } else { + None + } } + Err(e) => Some(Err(e)), } - // an error has been found we return it and ends the iterator for future next calls - Err(e) => { + } else { + // primary HDU parsing + let hdu = hdu::HDU::new_primary(&mut self.reader); + Some(hdu) + }; + + self.start = false; + + match n { + Some(Ok(hdu)) => { + self.num_bytes_in_cur_hdu = match &hdu { + hdu::HDU::XImage(h) | hdu::HDU::Primary(h) => { + let xtension = h.get_header().get_xtension(); + xtension.get_num_bytes_data_block() as usize + } + hdu::HDU::XASCIITable(h) => { + let xtension = h.get_header().get_xtension(); + xtension.get_num_bytes_data_block() as usize + } + hdu::HDU::XBinaryTable(h) => { + let xtension = h.get_header().get_xtension(); + xtension.get_num_bytes_data_block() as usize + } + }; + + self.num_remaining_bytes_in_cur_hdu = self.num_bytes_in_cur_hdu; + + Some(Ok(hdu)) + } + Some(Err(e)) => { + // an error has been found we return it and ends the iterator for future next calls self.error_parsing_encountered = true; Some(Err(e)) } + None => None, } } } @@ -113,8 +147,6 @@ where { /// The header part that stores all the cards header: Header, - // We do not store the the data part. it will be given when the data are asked by the user - //data: >::Data, } impl HDU @@ -160,73 +192,19 @@ where // This has the effect of consuming the HDU pub fn get_data<'a, R>(self, hdu_list: &'a mut Fits) -> >::Data where - R: DataBufRead<'a, X> + DataBufRead<'a, Image>, //+ DataBufRead<'a, BinTable> - //+ DataBufRead<'a, AsciiTable>, + R: DataBufRead<'a, X> + 'a, { // Unroll the internal fits parsing parameters to give it to the data reader let Fits { - num_bytes_read, + num_remaining_bytes_in_cur_hdu, reader, .. } = hdu_list; let xtension = self.header.get_xtension(); - >::prepare_data_reading(xtension, num_bytes_read, reader) + >::prepare_data_reading( + xtension, + num_remaining_bytes_in_cur_hdu, + reader, + ) } } - -/* -#[derive(Debug)] -pub struct AsyncFits<'a, R> -where - R: DataAsyncBufRead<'a, Image> - + DataAsyncBufRead<'a, BinTable> - + DataAsyncBufRead<'a, AsciiTable>, -{ - pub hdu: AsyncPrimaryHDU<'a, R>, -} - -impl<'a, R> AsyncFits<'a, R> -where - R: DataAsyncBufRead<'a, Image> - + DataAsyncBufRead<'a, BinTable> - + DataAsyncBufRead<'a, AsciiTable>, -{ - /// Parse a FITS file - /// # Params - /// * `reader` - a reader created i.e. from the opening of a file - pub async fn from_reader(reader: &'a mut R) -> Result, Error> { - let hdu = AsyncPrimaryHDU::new(reader).await?; - - Ok(Self { hdu }) - } - - pub fn get_primary_hdu(self) -> AsyncPrimaryHDU<'a, R> { - self.hdu - } - - pub async fn get_xtension_hdu(self, mut idx: usize) -> Result, Error> { - let mut hdu_ext = self.hdu.next().await?; - if idx == 0 { - if let Some(hdu) = hdu_ext { - Ok(hdu) - } else { - Err(Error::StaticError("No more ext HDU found")) - } - } else { - while let Some(hdu) = hdu_ext { - hdu_ext = hdu.next().await?; - idx -= 1; - - if idx == 0 { - break; - } - } - - if let Some(hdu) = hdu_ext { - Ok(hdu) - } else { - Err(Error::StaticError("No more ext HDU found")) - } - } - } -}*/ diff --git a/src/hdu/data/asciitable.rs b/src/hdu/data/asciitable.rs index 1a449de..c836584 100644 --- a/src/hdu/data/asciitable.rs +++ b/src/hdu/data/asciitable.rs @@ -1,73 +1,43 @@ use async_trait::async_trait; -use futures::AsyncRead; -use std::cell::UnsafeCell; +use futures::AsyncReadExt; use std::fmt::Debug; use std::io::{BufReader, Cursor, Read}; -use crate::error::Error; - -use super::iter; -use super::stream; +use super::{iter, Data}; +use super::{stream, AsyncDataBufRead}; use crate::hdu::header::extension::asciitable::AsciiTable; use crate::hdu::DataBufRead; use crate::hdu::header::extension::Xtension; -//use super::DataAsyncBufRead; -/* impl<'a, R> DataBufRead<'a, AsciiTable> for Cursor where R: AsRef<[u8]> + Debug + Read + 'a, { type Data = Data<'a>; - fn new_data_block(&'a mut self, ctx: &AsciiTable) -> Self::Data - where - Self: Sized, - { - let num_bytes_read = ctx.get_num_bytes_data_block() as usize; + fn prepare_data_reading( + ctx: &AsciiTable, + _num_remaining_bytes_in_cur_hdu: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data { + let num_bytes_of_data = ctx.get_num_bytes_data_block() as usize; + + let start_byte_pos = reader.position() as usize; - let bytes = self.get_ref(); - let bytes = bytes.as_ref(); + let r = reader.get_ref(); + let bytes = r.as_ref(); - let pos = self.position() as usize; - let start_byte_pos = pos; - let end_byte_pos = pos + num_bytes_read; + let end_byte_pos = start_byte_pos + num_bytes_of_data; let bytes = &bytes[start_byte_pos..end_byte_pos]; - let c = bytes as *const [u8] as *mut UnsafeCell<[u8]>; - unsafe { - let cell: &UnsafeCell<[u8]> = &*c; - let x_mut_ref = &mut *cell.get(); + let num_pixels = num_bytes_of_data as usize; - let (_, data, _) = x_mut_ref.align_to_mut::(); - let data = &data[..num_bytes_read]; + debug_assert!(bytes.len() >= num_pixels); - Data { - data: InMemData::U8(data), - reader: self, - num_bytes_read, - } - } - } - - fn consume_data_block( - &mut self, - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&mut Self, Error> { - let Data { - reader, - num_bytes_read: num_bytes, - .. - } = data; - *num_bytes_read = num_bytes as u64; - - reader.set_position(reader.position() + num_bytes as u64); - - Ok(reader) + Data::U8(bytes) } } @@ -75,73 +45,29 @@ impl<'a, R> DataBufRead<'a, AsciiTable> for BufReader where R: Read + Debug + 'a, { - type Data = iter::Iter<'a, Self, u8>; - - fn new_data_block(&'a mut self, ctx: &AsciiTable) -> Self::Data { - let num_bytes_to_read = ctx.get_num_bytes_data_block(); - iter::Iter::new(self, num_bytes_to_read) - } - - fn consume_data_block( - &mut self, - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&mut Self, Error> { - let iter::Iter { - reader, - num_bytes_read: num_bytes_already_read, - num_bytes_to_read, - .. - } = data; - - let remaining_bytes_to_read = num_bytes_to_read - num_bytes_already_read; - >::read_n_bytes_exact(reader, remaining_bytes_to_read)?; - - // All the data block have been read - *num_bytes_read = num_bytes_to_read; - - Ok(reader) + type Data = iter::It<'a, Self, u8>; + + fn prepare_data_reading( + _ctx: &AsciiTable, + num_remaining_bytes_in_cur_hdu: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data { + iter::It::new(reader, num_remaining_bytes_in_cur_hdu) } } -*/ -/* + #[async_trait(?Send)] -impl<'a, R> DataAsyncBufRead<'a, AsciiTable> for futures::io::BufReader +impl<'a, R> AsyncDataBufRead<'a, AsciiTable> for futures::io::BufReader where - R: AsyncRead + Debug + 'a + std::marker::Unpin, + R: AsyncReadExt + 'a + std::marker::Unpin, { type Data = stream::St<'a, Self, u8>; - fn new_data_block(&'a mut self, ctx: &AsciiTable) -> Self::Data { - let num_bytes_to_read = ctx.get_num_bytes_data_block(); - stream::St::new(self, num_bytes_to_read) - } - - async fn consume_data_block( - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> - where - 'a: 'async_trait, - { - let stream::St { - reader, - num_bytes_to_read, - num_bytes_read: num_bytes_already_read, - .. - } = data; - - let remaining_bytes_to_read = num_bytes_to_read - num_bytes_already_read; - >::read_n_bytes_exact( - reader, - remaining_bytes_to_read, - ) - .await?; - - // All the data block have been read - *num_bytes_read = num_bytes_to_read; - - Ok(reader) + fn prepare_data_reading( + _ctx: &AsciiTable, + num_remaining_bytes_in_cur_hdu: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data { + stream::St::new(reader, num_remaining_bytes_in_cur_hdu) } } -*/ diff --git a/src/hdu/data/bintable.rs b/src/hdu/data/bintable.rs index 2abfe9b..1dfba5d 100644 --- a/src/hdu/data/bintable.rs +++ b/src/hdu/data/bintable.rs @@ -1,72 +1,45 @@ -use std::cell::UnsafeCell; use std::fmt::Debug; use std::io::{BufReader, Cursor, Read}; use async_trait::async_trait; -use futures::AsyncRead; - -use super::iter; -use super::stream; -use crate::error::Error; +use futures::AsyncReadExt; +use super::{iter, Data}; +use super::{stream, AsyncDataBufRead}; use crate::hdu::header::extension::bintable::BinTable; use crate::hdu::DataBufRead; use crate::hdu::header::extension::Xtension; //use super::DataAsyncBufRead; -/* + impl<'a, R> DataBufRead<'a, BinTable> for Cursor where R: AsRef<[u8]> + Debug + Read + 'a, { type Data = Data<'a>; - fn new_data_block(&'a mut self, ctx: &BinTable) -> Self::Data - where - Self: Sized, - { - let num_bytes_read = ctx.get_num_bytes_data_block() as usize; + fn prepare_data_reading( + ctx: &BinTable, + _num_remaining_bytes_in_cur_hdu: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data { + let num_bytes_of_data = ctx.get_num_bytes_data_block() as usize; - let bytes = self.get_ref(); - let bytes = bytes.as_ref(); + let start_byte_pos = reader.position() as usize; - let pos = self.position() as usize; - let start_byte_pos = pos; - let end_byte_pos = pos + num_bytes_read; - - let bytes = &bytes[start_byte_pos..end_byte_pos]; + let r = reader.get_ref(); + let bytes = r.as_ref(); - let c = bytes as *const [u8] as *mut UnsafeCell<[u8]>; - unsafe { - let cell: &UnsafeCell<[u8]> = &*c; - let x_mut_ref = &mut *cell.get(); + let end_byte_pos = start_byte_pos + num_bytes_of_data; - let (_, data, _) = x_mut_ref.align_to_mut::(); - let data = &data[..num_bytes_read]; - - Data { - data: InMemData::U8(data), - //reader: self, - num_bytes_read, - } - } - } + let bytes = &bytes[start_byte_pos..end_byte_pos]; - fn consume_data_block( - &mut self, - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&mut Self, Error> { - let Data { - num_bytes_read: num_bytes, - .. - } = data; - *num_bytes_read = num_bytes as u64; + let num_pixels = num_bytes_of_data as usize; - self.set_position(self.position() + num_bytes as u64); + debug_assert!(bytes.len() >= num_pixels); - Ok(self) + Data::U8(bytes) } } @@ -74,72 +47,28 @@ impl<'a, R> DataBufRead<'a, BinTable> for BufReader where R: Read + Debug + 'a, { - type Data = iter::Iter<'a, Self, u8>; - - fn new_data_block(&'a mut self, ctx: &BinTable) -> Self::Data { - let num_bytes_to_read = ctx.get_num_bytes_data_block(); - iter::Iter::new(self, num_bytes_to_read) - } - - fn consume_data_block( - &mut self, - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&mut Self, Error> { - let iter::Iter { - reader, - num_bytes_read: num_bytes_already_read, - num_bytes_to_read, - .. - } = data; - - let remaining_bytes_to_read = num_bytes_to_read - num_bytes_already_read; - >::read_n_bytes_exact(reader, remaining_bytes_to_read)?; - - // All the data block have been read - *num_bytes_read = num_bytes_to_read; - - Ok(reader) + type Data = iter::It<'a, Self, u8>; + + fn prepare_data_reading( + _ctx: &BinTable, + num_remaining_bytes_in_cur_hdu: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data { + iter::It::new(reader, num_remaining_bytes_in_cur_hdu) } } -*/ -/* #[async_trait(?Send)] -impl<'a, R> DataAsyncBufRead<'a, BinTable> for futures::io::BufReader +impl<'a, R> AsyncDataBufRead<'a, BinTable> for futures::io::BufReader where - R: AsyncRead + Debug + 'a + std::marker::Unpin, + R: AsyncReadExt + Debug + 'a + std::marker::Unpin, { type Data = stream::St<'a, Self, u8>; - fn new_data_block(&'a mut self, ctx: &BinTable) -> Self::Data { - let num_bytes_to_read = ctx.get_num_bytes_data_block(); - stream::St::new(self, num_bytes_to_read) + fn prepare_data_reading( + _ctx: &BinTable, + num_remaining_bytes_in_cur_hdu: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data { + stream::St::new(reader, num_remaining_bytes_in_cur_hdu) } - - async fn consume_data_block( - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> - where - 'a: 'async_trait, - { - let stream::St { - reader, - num_bytes_to_read, - num_bytes_read: num_bytes_already_read, - .. - } = data; - - let remaining_bytes_to_read = num_bytes_to_read - num_bytes_already_read; - >::read_n_bytes_exact( - reader, - remaining_bytes_to_read, - ) - .await?; - - // All the data block have been read - *num_bytes_read = num_bytes_to_read; - - Ok(reader) - } -}*/ +} diff --git a/src/hdu/data/image.rs b/src/hdu/data/image.rs index 7b3927c..bc4950d 100644 --- a/src/hdu/data/image.rs +++ b/src/hdu/data/image.rs @@ -1,19 +1,15 @@ //pub use super::Access; //use super::DataAsyncBufRead; -use crate::error::Error; -use crate::fits::Fits; -use crate::hdu::header::extension::asciitable::AsciiTable; -use crate::hdu::header::extension::bintable::BinTable; + use crate::hdu::header::BitpixValue; use async_trait::async_trait; use byteorder::{BigEndian, ByteOrder}; -use futures::AsyncRead; -use std::cell::UnsafeCell; +use futures::AsyncReadExt; use std::io::{BufReader, Cursor, Read}; use std::fmt::Debug; -use super::{iter, InMemoryData, Slice}; +use super::{iter, AsyncDataBufRead, Data, DataIter, DataStream}; use crate::hdu::header::extension::image::Image; use crate::hdu::header::extension::Xtension; use crate::hdu::DataBufRead; @@ -22,289 +18,154 @@ impl<'a, R> DataBufRead<'a, Image> for Cursor where R: AsRef<[u8]> + Debug + Read + 'a, { - type Data = Slice<'a>; + type Data = Data<'a>; fn prepare_data_reading( ctx: &Image, - num_bytes_read: &'a mut usize, + _num_remaining_bytes_in_cur_hdu: &'a mut usize, reader: &'a mut Self, ) -> Self::Data { let num_bytes_of_data = ctx.get_num_bytes_data_block() as usize; - // propagate the number of bytes read to the hdu_list iterator so that it knows where the reader is. - *num_bytes_read += num_bytes_of_data; let bitpix = ctx.get_bitpix(); - let bytes = reader.get_ref(); - let bytes = bytes.as_ref(); + let start_byte_pos = reader.position() as usize; - let pos = reader.position() as usize; + let r = reader.get_ref(); + let bytes = r.as_ref(); - let start_byte_pos = pos; - let end_byte_pos = pos + num_bytes_of_data; + let end_byte_pos = start_byte_pos + num_bytes_of_data; let bytes = &bytes[start_byte_pos..end_byte_pos]; - let c = bytes as *const [u8] as *mut UnsafeCell<[u8]>; - unsafe { - let cell: &UnsafeCell<[u8]> = &*c; - let x_mut_ref = &mut *cell.get(); + match bitpix { + BitpixValue::U8 => { + let num_pixels = num_bytes_of_data as usize; - match bitpix { - BitpixValue::U8 => { - let (_, data, _) = x_mut_ref.align_to_mut::(); - let num_pixels = num_bytes_of_data as usize; + debug_assert!(bytes.len() >= num_pixels); - debug_assert!(data.len() >= num_pixels); - let data = &data[..num_pixels]; + Data::U8(bytes) + } + BitpixValue::I16 => { + let data = bytes + .chunks(2) + .map(|item| BigEndian::read_i16(item)) + .collect::>(); - Slice::U8(data) - } - BitpixValue::I16 => { - // 1. Verify the alignement - let (_, data, _) = x_mut_ref.align_to_mut::(); - // 2. Convert to big endianness. This is O(N) over the size of the data - BigEndian::from_slice_i16(data); + debug_assert!(data.len() == num_bytes_of_data / std::mem::size_of::()); - // 3. Keep only the pixels - let num_pixels = (num_bytes_of_data as usize) / std::mem::size_of::(); - debug_assert!(data.len() >= num_pixels); - let data = &data[..num_pixels]; + Data::I16(data.into_boxed_slice()) + } + BitpixValue::I32 => { + let data = bytes + .chunks(4) + .map(|item| BigEndian::read_i32(item)) + .collect::>(); - Slice::I16(data) - } - BitpixValue::I32 => { - // 1. Verify the alignement - let (_, data, _) = x_mut_ref.align_to_mut::(); - // 2. Convert to big endianness. This is O(N) over the size of the data - BigEndian::from_slice_i32(data); + debug_assert!(data.len() == num_bytes_of_data / std::mem::size_of::()); - // 3. Keep only the pixels - let num_pixels = (num_bytes_of_data as usize) / std::mem::size_of::(); - debug_assert!(data.len() >= num_pixels); - let data = &data[..num_pixels]; + Data::I32(data.into_boxed_slice()) + } + BitpixValue::I64 => { + let data = bytes + .chunks(8) + .map(|item| BigEndian::read_i64(item)) + .collect::>(); - Slice::I32(data) - } - BitpixValue::I64 => { - // 1. Verify the alignement - let (_, data, _) = x_mut_ref.align_to_mut::(); - // 2. Convert to big endianness. This is O(N) over the size of the data - BigEndian::from_slice_i64(data); - // 3. Keep only the pixels - let num_pixels = num_bytes_of_data / std::mem::size_of::(); - debug_assert!(data.len() >= num_pixels); - let data = &data[..num_pixels]; + debug_assert!(data.len() == num_bytes_of_data / std::mem::size_of::()); - Slice::I64(data) - } - BitpixValue::F32 => { - // 1. Verify the alignement - let (_, data, _) = x_mut_ref.align_to_mut::(); - // 2. Convert to big endianness. This is O(N) over the size of the data - BigEndian::from_slice_f32(data); - // 3. Keep only the pixels - let num_pixels = num_bytes_of_data / std::mem::size_of::(); - debug_assert!(data.len() >= num_pixels); - let data = &data[..num_pixels]; + Data::I64(data.into_boxed_slice()) + } + BitpixValue::F32 => { + let data = bytes + .chunks(4) + .map(|item| BigEndian::read_f32(item)) + .collect::>(); - Slice::F32(data) - } - BitpixValue::F64 => { - // 1. Verify the alignement - let (_, data, _) = x_mut_ref.align_to_mut::(); - // 2. Convert to big endianness. This is O(N) over the size of the data - BigEndian::from_slice_f64(data); - // 3. Keep only the pixels - let num_pixels = num_bytes_of_data / std::mem::size_of::(); - debug_assert!(data.len() >= num_pixels); - let data = &data[..num_pixels]; + debug_assert!(data.len() == num_bytes_of_data / std::mem::size_of::()); - Slice::F64(data) - } + Data::F32(data.into_boxed_slice()) } - } - } - - /*fn consume_data_block(self, data: Self::Data, num_bytes_read: &mut u64) -> Result { - let Data { - num_bytes_read: num_bytes, - .. - } = data; - *num_bytes_read = num_bytes as u64; + BitpixValue::F64 => { + let data = bytes + .chunks(8) + .map(|item| BigEndian::read_f64(item)) + .collect::>(); - self.set_position(self.position() + num_bytes as u64); + debug_assert!(data.len() == num_bytes_of_data / std::mem::size_of::()); - Ok(self) - }*/ + Data::F64(data.into_boxed_slice()) + } + } + } } impl<'a, R> DataBufRead<'a, Image> for BufReader where R: Read + Debug + 'a, { - type Data = iter::Iter<'a, Self>; + type Data = DataIter<'a, Self>; fn prepare_data_reading( ctx: &Image, - num_bytes_read: &'a mut usize, + num_remaining_bytes_in_cur_hdu: &'a mut usize, reader: &'a mut Self, ) -> Self::Data { - let num_bytes_to_read = ctx.get_num_bytes_data_block() as usize; let bitpix = ctx.get_bitpix(); match bitpix { - BitpixValue::U8 => { - iter::Iter::U8(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) - } + BitpixValue::U8 => DataIter::U8(iter::It::new(reader, num_remaining_bytes_in_cur_hdu)), BitpixValue::I16 => { - iter::Iter::I16(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + DataIter::I16(iter::It::new(reader, num_remaining_bytes_in_cur_hdu)) } BitpixValue::I32 => { - iter::Iter::I32(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + DataIter::I32(iter::It::new(reader, num_remaining_bytes_in_cur_hdu)) } BitpixValue::I64 => { - iter::Iter::I64(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + DataIter::I64(iter::It::new(reader, num_remaining_bytes_in_cur_hdu)) } BitpixValue::F32 => { - iter::Iter::F32(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + DataIter::F32(iter::It::new(reader, num_remaining_bytes_in_cur_hdu)) } BitpixValue::F64 => { - iter::Iter::F64(iter::It::new(reader, num_bytes_read, num_bytes_to_read)) + DataIter::F64(iter::It::new(reader, num_remaining_bytes_in_cur_hdu)) } } } - - /* - fn consume_data_block( - &mut self, - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&mut Self, Error> { - let (reader, num_bytes_already_read, num_bytes_to_read) = match data { - iter::Data::U8(iter::Iter { - reader, - num_bytes_read: num_bytes_already_read, - num_bytes_to_read, - .. - }) => (reader, num_bytes_already_read, num_bytes_to_read), - iter::Data::I16(iter::Iter { - reader, - num_bytes_read: num_bytes_already_read, - num_bytes_to_read, - .. - }) => (reader, num_bytes_already_read, num_bytes_to_read), - iter::Data::I32(iter::Iter { - reader, - num_bytes_read: num_bytes_already_read, - num_bytes_to_read, - .. - }) => (reader, num_bytes_already_read, num_bytes_to_read), - iter::Data::I64(iter::Iter { - reader, - num_bytes_read: num_bytes_already_read, - num_bytes_to_read, - .. - }) => (reader, num_bytes_already_read, num_bytes_to_read), - iter::Data::F32(iter::Iter { - reader, - num_bytes_read: num_bytes_already_read, - num_bytes_to_read, - .. - }) => (reader, num_bytes_already_read, num_bytes_to_read), - iter::Data::F64(iter::Iter { - reader, - num_bytes_read: num_bytes_already_read, - num_bytes_to_read, - .. - }) => (reader, num_bytes_already_read, num_bytes_to_read), - }; - - let remaining_bytes_to_read = num_bytes_to_read - num_bytes_already_read; - >::read_n_bytes_exact(reader, remaining_bytes_to_read)?; - - // All the data block have been read - *num_bytes_read = num_bytes_to_read; - - Ok(reader) - }*/ } -/* use super::stream; #[async_trait(?Send)] -impl<'a, R> DataAsyncBufRead<'a, Image> for futures::io::BufReader +impl<'a, R> AsyncDataBufRead<'a, Image> for futures::io::BufReader where - R: AsyncRead + Debug + 'a + Unpin, + R: AsyncReadExt + Debug + 'a + Unpin, { - type Data = super::stream::Data<'a, Self>; + type Data = DataStream<'a, Self>; - fn new_data_block(&'a mut self, ctx: &Image) -> Self::Data { - let num_bytes_to_read = ctx.get_num_bytes_data_block(); + fn prepare_data_reading( + ctx: &Image, + num_remaining_bytes_in_cur_hdu: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data { let bitpix = ctx.get_bitpix(); match bitpix { - BitpixValue::U8 => stream::Data::U8(stream::St::new(self, num_bytes_to_read)), - BitpixValue::I16 => stream::Data::I16(stream::St::new(self, num_bytes_to_read)), - BitpixValue::I32 => stream::Data::I32(stream::St::new(self, num_bytes_to_read)), - BitpixValue::I64 => stream::Data::I64(stream::St::new(self, num_bytes_to_read)), - BitpixValue::F32 => stream::Data::F32(stream::St::new(self, num_bytes_to_read)), - BitpixValue::F64 => stream::Data::F64(stream::St::new(self, num_bytes_to_read)), + BitpixValue::U8 => { + DataStream::U8(stream::St::new(reader, num_remaining_bytes_in_cur_hdu)) + } + BitpixValue::I16 => { + DataStream::I16(stream::St::new(reader, num_remaining_bytes_in_cur_hdu)) + } + BitpixValue::I32 => { + DataStream::I32(stream::St::new(reader, num_remaining_bytes_in_cur_hdu)) + } + BitpixValue::I64 => { + DataStream::I64(stream::St::new(reader, num_remaining_bytes_in_cur_hdu)) + } + BitpixValue::F32 => { + DataStream::F32(stream::St::new(reader, num_remaining_bytes_in_cur_hdu)) + } + BitpixValue::F64 => { + DataStream::F64(stream::St::new(reader, num_remaining_bytes_in_cur_hdu)) + } } } - - async fn consume_data_block( - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> - where - 'a: 'async_trait, - { - let (reader, num_bytes_to_read, num_bytes_already_read) = match data { - stream::Data::U8(stream::St { - reader, - num_bytes_to_read, - num_bytes_read, - .. - }) => (reader, num_bytes_to_read, num_bytes_read), - stream::Data::I16(stream::St { - reader, - num_bytes_to_read, - num_bytes_read, - .. - }) => (reader, num_bytes_to_read, num_bytes_read), - stream::Data::I32(stream::St { - reader, - num_bytes_to_read, - num_bytes_read, - .. - }) => (reader, num_bytes_to_read, num_bytes_read), - stream::Data::I64(stream::St { - reader, - num_bytes_to_read, - num_bytes_read, - .. - }) => (reader, num_bytes_to_read, num_bytes_read), - stream::Data::F32(stream::St { - reader, - num_bytes_to_read, - num_bytes_read, - .. - }) => (reader, num_bytes_to_read, num_bytes_read), - stream::Data::F64(stream::St { - reader, - num_bytes_to_read, - num_bytes_read, - .. - }) => (reader, num_bytes_to_read, num_bytes_read), - }; - - let remaining_bytes_to_read = num_bytes_to_read - num_bytes_already_read; - >::read_n_bytes_exact(reader, remaining_bytes_to_read) - .await?; - - // All the data block have been read - *num_bytes_read = num_bytes_to_read; - - Ok(reader) - } } -*/ diff --git a/src/hdu/data/iter.rs b/src/hdu/data/iter.rs index 6bf3a8d..ad13c0a 100644 --- a/src/hdu/data/iter.rs +++ b/src/hdu/data/iter.rs @@ -15,7 +15,7 @@ use crate::byteorder::ReadBytesExt; /// for non in-memory readers (typically BufReader) that ensures /// a file may not fit in memory #[derive(Serialize, Debug)] -pub enum Iter<'a, R> +pub enum DataIter<'a, R> where R: BufRead, { @@ -33,8 +33,7 @@ where R: BufRead, { pub reader: &'a mut R, - pub num_bytes_read: &'a mut usize, - pub num_bytes_to_read: usize, + pub num_remaining_bytes_in_cur_hdu: &'a mut usize, phantom: std::marker::PhantomData, } @@ -42,11 +41,10 @@ impl<'a, R, T> It<'a, R, T> where R: BufRead, { - pub fn new(reader: &'a mut R, num_bytes_read: &'a mut usize, num_bytes_to_read: usize) -> Self { + pub fn new(reader: &'a mut R, num_remaining_bytes_in_cur_hdu: &'a mut usize) -> Self { Self { reader, - num_bytes_to_read: *num_bytes_read + num_bytes_to_read, - num_bytes_read: num_bytes_read, + num_remaining_bytes_in_cur_hdu, phantom: std::marker::PhantomData, } } @@ -59,13 +57,13 @@ where type Item = u8; fn next(&mut self) -> Option { - if self.num_bytes_to_read == *self.num_bytes_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { None } else { let item = self.reader.read_u8(); let num_bytes_item = std::mem::size_of::(); - *self.num_bytes_read += num_bytes_item; + *self.num_remaining_bytes_in_cur_hdu -= num_bytes_item; item.ok() } @@ -79,13 +77,13 @@ where type Item = i16; fn next(&mut self) -> Option { - if self.num_bytes_to_read == *self.num_bytes_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { None } else { let item = self.reader.read_i16::(); let num_bytes_item = std::mem::size_of::(); - *self.num_bytes_read += num_bytes_item; + *self.num_remaining_bytes_in_cur_hdu -= num_bytes_item; item.ok() } @@ -99,13 +97,13 @@ where type Item = i32; fn next(&mut self) -> Option { - if self.num_bytes_to_read == *self.num_bytes_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { None } else { let item = self.reader.read_i32::(); let num_bytes_item = std::mem::size_of::(); - *self.num_bytes_read += num_bytes_item; + *self.num_remaining_bytes_in_cur_hdu -= num_bytes_item; item.ok() } @@ -119,13 +117,13 @@ where type Item = i64; fn next(&mut self) -> Option { - if self.num_bytes_to_read == *self.num_bytes_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { None } else { let item = self.reader.read_i64::(); let num_bytes_item = std::mem::size_of::(); - *self.num_bytes_read += num_bytes_item; + *self.num_remaining_bytes_in_cur_hdu -= num_bytes_item; item.ok() } @@ -139,13 +137,13 @@ where type Item = f32; fn next(&mut self) -> Option { - if self.num_bytes_to_read == *self.num_bytes_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { None } else { let item = self.reader.read_f32::(); let num_bytes_item = std::mem::size_of::(); - *self.num_bytes_read += num_bytes_item; + *self.num_remaining_bytes_in_cur_hdu -= num_bytes_item; item.ok() } @@ -159,13 +157,13 @@ where type Item = f64; fn next(&mut self) -> Option { - if self.num_bytes_to_read == *self.num_bytes_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { None } else { let item = self.reader.read_f64::(); let num_bytes_item = std::mem::size_of::(); - *self.num_bytes_read += num_bytes_item; + *self.num_remaining_bytes_in_cur_hdu -= num_bytes_item; item.ok() } diff --git a/src/hdu/data/layout.rs b/src/hdu/data/layout.rs deleted file mode 100644 index e569b06..0000000 --- a/src/hdu/data/layout.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::io::BufRead; - -use super::Slice; - -pub trait MemoryLayout<'a> { - type Type; - - fn get_data(&'a self) -> Self::Type; - //fn get_data_mut(&mut self) -> &mut Self::Type; -} -impl<'a> MemoryLayout<'a> for Slice<'a> { - type Type = &'a Self; - - fn get_data(&'a self) -> Self::Type { - self - } -} -use super::iter::Iter; -impl<'a, R> MemoryLayout<'a> for Iter<'a, R> -where - R: BufRead, -{ - type Type = &'a Self; - - fn get_data(&'a self) -> Self::Type { - self - } -} diff --git a/src/hdu/data/mod.rs b/src/hdu/data/mod.rs index 9c233e4..0d2c731 100644 --- a/src/hdu/data/mod.rs +++ b/src/hdu/data/mod.rs @@ -2,19 +2,20 @@ pub mod asciitable; pub mod bintable; pub mod image; pub mod iter; -pub mod layout; pub mod stream; use serde::Serialize; use std::fmt::Debug; -use std::io::{BufRead, Read}; +use std::io::BufRead; use std::marker::Unpin; use crate::error::Error; -use crate::fits::Fits; -use crate::hdu::Xtension; +use crate::hdu::header::Xtension; + +pub use iter::DataIter; +pub use stream::DataStream; // reader must impl this pub trait DataBufRead<'a, X>: BufRead @@ -25,28 +26,12 @@ where fn prepare_data_reading( ctx: &X, - num_bytes_read: &'a mut usize, + num_remaining_bytes_in_cur_hdu: &'a mut usize, reader: &'a mut Self, ) -> Self::Data where Self: Sized; - /// Consume the data to return back the reader at the position - /// of the end of the data block - /// - /// If the data has not been fully read, we skip the remaining data - /// bytes to go to the end of the data block - /// - /// # Params - /// * `data` - a reader created i.e. from the opening of a file - /*fn consume_data_block( - &'a mut self, - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&'a mut Self, Error> - where - Self: Sized;*/ - fn read_n_bytes_exact(&mut self, num_bytes_to_read: u64) -> Result<(), Error> { let mut num_bytes_read = 0; @@ -90,35 +75,18 @@ use async_trait::async_trait; use futures::io::AsyncBufRead; use futures::AsyncBufReadExt; -use super::header::extension::asciitable::AsciiTable; -use super::header::extension::bintable::BinTable; -use super::header::extension::image::Image; - -/* #[async_trait(?Send)] -pub trait DataAsyncBufRead: AsyncBufRead + Unpin +pub trait AsyncDataBufRead<'a, X>: AsyncBufRead + Unpin where X: Xtension, { - type Data: Debug; - - fn new_data_block(&mut self, ctx: &X) -> Self::Data - where - Self: Sized; + type Data: 'a; - /// Consume the data to return back the reader at the position - /// of the end of the data block - /// - /// If the data has not been fully read, we skip the remaining data - /// bytes to go to the end of the data block - /// - /// # Params - /// * `data` - a reader created i.e. from the opening of a file - async fn consume_data_block( - &mut self, - data: Self::Data, - num_bytes_read: &mut u64, - ) -> Result<&mut Self, Error> + fn prepare_data_reading( + ctx: &X, + num_remaining_bytes_in_cur_hdu: &'a mut usize, + reader: &'a mut Self, + ) -> Self::Data where Self: Sized; @@ -159,7 +127,7 @@ where Ok(()) } } -}*/ +} /// The full slice of data found in-memory /// This is an enum whose content depends on the @@ -169,15 +137,13 @@ where /// for in-memory readers (typically for `&[u8]` or a `Cursor>`) that ensures /// all the data fits in memory /// -#[derive(Serialize, Debug)] -pub struct InMemoryData<'a>(Slice<'a>); #[derive(Serialize, Debug, Clone)] -pub enum Slice<'a> { +pub enum Data<'a> { U8(&'a [u8]), - I16(&'a [i16]), - I32(&'a [i32]), - I64(&'a [i64]), - F32(&'a [f32]), - F64(&'a [f64]), + I16(Box<[i16]>), + I32(Box<[i32]>), + I64(Box<[i64]>), + F32(Box<[f32]>), + F64(Box<[f64]>), } diff --git a/src/hdu/data/stream.rs b/src/hdu/data/stream.rs index 86fc20d..278d483 100644 --- a/src/hdu/data/stream.rs +++ b/src/hdu/data/stream.rs @@ -8,9 +8,8 @@ use futures::AsyncReadExt; /// The data part is expressed as a `DataOwned` structure /// for non in-memory readers (typically BufReader) that ensures /// a file may not fit in memory -/* #[derive(Serialize, Debug)] -pub enum Data<'a, R> +pub enum DataStream<'a, R> where R: AsyncBufRead + Unpin, { @@ -20,40 +19,26 @@ where I64(St<'a, R, i64>), F32(St<'a, R, f32>), F64(St<'a, R, f64>), -}*/ -/* -impl<'a, R> Access<'a> for Data<'a, R> -where - R: AsyncBufRead + Unpin, -{ - type Type = &'a mut Self; - - fn get_data(&'a mut self) -> Self::Type { - self - } } -*/ + #[derive(Serialize, Debug)] pub struct St<'a, R, T> where - R: AsyncBufReadExt + Unpin, + R: AsyncBufRead + Unpin, { pub reader: &'a mut R, - pub num_bytes_to_read: u64, - pub num_bytes_read: u64, + pub num_remaining_bytes_in_cur_hdu: &'a mut usize, phantom: std::marker::PhantomData, } impl<'a, R, T> St<'a, R, T> where - R: AsyncBufReadExt + Unpin, + R: AsyncBufRead + Unpin, { - pub fn new(reader: &'a mut R, num_bytes_to_read: u64) -> Self { - let num_bytes_read = 0; + pub fn new(reader: &'a mut R, num_remaining_bytes_in_cur_hdu: &'a mut usize) -> Self { Self { reader, - num_bytes_read, - num_bytes_to_read, + num_remaining_bytes_in_cur_hdu, phantom: std::marker::PhantomData, } } @@ -62,17 +47,15 @@ where use futures::task::Context; use futures::task::Poll; use futures::AsyncBufRead; -use futures::AsyncBufReadExt; use futures::Future; -use futures::Stream; use serde::Serialize; use std::pin::Pin; //use super::Access; -impl<'a, R> Stream for St<'a, R, u8> +impl<'a, R> futures::Stream for St<'a, R, u8> where - R: AsyncBufReadExt + Unpin, + R: AsyncBufRead + Unpin, { /// The type of the value yielded by the stream. type Item = Result<[u8; 1], futures::io::Error>; @@ -81,7 +64,7 @@ where /// Returns `Poll::Pending` if not ready, `Poll::Ready(Some(x))` if a value /// is ready, and `Poll::Ready(None)` if the stream has completed. fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if self.num_bytes_read == self.num_bytes_to_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { // The stream has finished Poll::Ready(None) } else { @@ -92,7 +75,7 @@ where Poll::Pending => Poll::Pending, Poll::Ready(Err(e)) => Poll::Ready(Some(Err(e))), Poll::Ready(Ok(())) => { - self.num_bytes_read += 1; + *self.num_remaining_bytes_in_cur_hdu -= 1; Poll::Ready(Some(Ok(buf))) } } @@ -100,9 +83,9 @@ where } } -impl<'a, R> Stream for St<'a, R, i16> +impl<'a, R> futures::Stream for St<'a, R, i16> where - R: AsyncBufReadExt + Unpin, + R: AsyncBufRead + Unpin, { /// The type of the value yielded by the stream. type Item = Result<[i16; 1], futures::io::Error>; @@ -111,7 +94,7 @@ where /// Returns `Poll::Pending` if not ready, `Poll::Ready(Some(x))` if a value /// is ready, and `Poll::Ready(None)` if the stream has completed. fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if self.num_bytes_to_read == self.num_bytes_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { // The stream has finished Poll::Ready(None) } else { @@ -122,7 +105,7 @@ where Poll::Ready(Err(e)) => Poll::Ready(Some(Err(e))), Poll::Ready(Ok(())) => { let item = byteorder::BigEndian::read_i16(&buf); - self.num_bytes_read += std::mem::size_of::() as u64; + *self.num_remaining_bytes_in_cur_hdu -= std::mem::size_of::(); Poll::Ready(Some(Ok([item]))) } } @@ -132,7 +115,7 @@ where impl<'a, R> futures::Stream for St<'a, R, i32> where - R: AsyncBufReadExt + Unpin, + R: AsyncBufRead + Unpin, { /// The type of the value yielded by the stream. type Item = Result<[i32; 1], futures::io::Error>; @@ -141,7 +124,7 @@ where /// Returns `Poll::Pending` if not ready, `Poll::Ready(Some(x))` if a value /// is ready, and `Poll::Ready(None)` if the stream has completed. fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if self.num_bytes_to_read == self.num_bytes_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { // The stream has finished Poll::Ready(None) } else { @@ -152,7 +135,7 @@ where Poll::Ready(Err(e)) => Poll::Ready(Some(Err(e))), Poll::Ready(Ok(())) => { let item = byteorder::BigEndian::read_i32(&buf); - self.num_bytes_read += std::mem::size_of::() as u64; + *self.num_remaining_bytes_in_cur_hdu -= std::mem::size_of::(); Poll::Ready(Some(Ok([item]))) } @@ -163,7 +146,7 @@ where impl<'a, R> futures::Stream for St<'a, R, i64> where - R: AsyncBufReadExt + Unpin, + R: AsyncBufRead + Unpin, { /// The type of the value yielded by the stream. type Item = Result<[i64; 1], futures::io::Error>; @@ -172,7 +155,7 @@ where /// Returns `Poll::Pending` if not ready, `Poll::Ready(Some(x))` if a value /// is ready, and `Poll::Ready(None)` if the stream has completed. fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if self.num_bytes_to_read == self.num_bytes_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { // The stream has finished Poll::Ready(None) } else { @@ -183,7 +166,7 @@ where Poll::Ready(Err(e)) => Poll::Ready(Some(Err(e))), Poll::Ready(Ok(())) => { let item = byteorder::BigEndian::read_i64(&buf); - self.num_bytes_read += std::mem::size_of::() as u64; + *self.num_remaining_bytes_in_cur_hdu -= std::mem::size_of::(); Poll::Ready(Some(Ok([item]))) } } @@ -193,7 +176,7 @@ where impl<'a, R> futures::Stream for St<'a, R, f32> where - R: AsyncBufReadExt + Unpin, + R: AsyncBufRead + Unpin, { /// The type of the value yielded by the stream. type Item = Result<[f32; 1], futures::io::Error>; @@ -202,7 +185,7 @@ where /// Returns `Poll::Pending` if not ready, `Poll::Ready(Some(x))` if a value /// is ready, and `Poll::Ready(None)` if the stream has completed. fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if self.num_bytes_to_read == self.num_bytes_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { // The stream has finished Poll::Ready(None) } else { @@ -213,7 +196,7 @@ where Poll::Ready(Err(e)) => Poll::Ready(Some(Err(e))), Poll::Ready(Ok(())) => { let item = byteorder::BigEndian::read_f32(&buf); - self.num_bytes_read += std::mem::size_of::() as u64; + *self.num_remaining_bytes_in_cur_hdu -= std::mem::size_of::(); Poll::Ready(Some(Ok([item]))) } } @@ -223,7 +206,7 @@ where impl<'a, R> futures::Stream for St<'a, R, f64> where - R: AsyncBufReadExt + Unpin, + R: AsyncBufRead + Unpin, { /// The type of the value yielded by the stream. type Item = Result<[f64; 1], futures::io::Error>; @@ -232,7 +215,7 @@ where /// Returns `Poll::Pending` if not ready, `Poll::Ready(Some(x))` if a value /// is ready, and `Poll::Ready(None)` if the stream has completed. fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { - if self.num_bytes_read == self.num_bytes_to_read { + if *self.num_remaining_bytes_in_cur_hdu == 0 { // The stream has finished Poll::Ready(None) } else { @@ -243,7 +226,7 @@ where Poll::Ready(Err(e)) => Poll::Ready(Some(Err(e))), Poll::Ready(Ok(())) => { let item = byteorder::BigEndian::read_f64(&buf); - self.num_bytes_read += std::mem::size_of::() as u64; + *self.num_remaining_bytes_in_cur_hdu -= std::mem::size_of::(); Poll::Ready(Some(Ok([item]))) } } diff --git a/src/hdu/extension.rs b/src/hdu/extension.rs index 0571d14..8b13789 100644 --- a/src/hdu/extension.rs +++ b/src/hdu/extension.rs @@ -1,160 +1 @@ -use crate::hdu::header::extension::asciitable::AsciiTable; -use crate::hdu::header::extension::bintable::BinTable; -use crate::hdu::header::extension::image::Image; -//use super::data::DataAsyncBufRead; -use super::header::consume_next_card_async; -use super::header::extension::XtensionType; -//use super::AsyncHDU; -use crate::error::Error; -use crate::fits::HDU; -use crate::hdu::header::extension::parse_xtension_card; -use crate::hdu::primary::consume_next_card; - -use crate::hdu::DataBufRead; - -#[derive(Debug)] -pub enum XtensionHDU { - Image(HDU), - AsciiTable(HDU), - BinTable(HDU), -} - -impl XtensionHDU { - pub fn new<'a, R>(reader: &mut R, num_bytes_read: &mut usize) -> Result - where - //R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, - R: DataBufRead<'a, Image> + 'a, - { - let mut card_80_bytes_buf = [0; 80]; - - // XTENSION - consume_next_card(reader, &mut card_80_bytes_buf, num_bytes_read)?; - let xtension_type = parse_xtension_card(&card_80_bytes_buf)?; - - let hdu = match xtension_type { - XtensionType::Image => XtensionHDU::Image(HDU::::new( - reader, - num_bytes_read, - &mut card_80_bytes_buf, - )?), - XtensionType::BinTable => { - todo!(); - /*XtensionHDU::BinTable(HDU::::new( - reader, - &mut num_bytes_read, - &mut card_80_bytes_buf, - )?)*/ - } - XtensionType::AsciiTable => { - todo!(); - /*XtensionHDU::AsciiTable(HDU::::new( - reader, - &mut num_bytes_read, - &mut card_80_bytes_buf, - )?),*/ - } - }; - - Ok(hdu) - } - - /*fn consume<'a, R>(self, reader: &'a mut R) -> Result, Error> - where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, - { - match self { - XtensionHDU::Image(hdu) => hdu.consume(reader), - XtensionHDU::AsciiTable(hdu) => hdu.consume(reader), - XtensionHDU::BinTable(hdu) => hdu.consume(reader), - } - } - - pub fn next<'a, R>(self, reader: &'a mut R) -> Result, Error> - where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, - { - if let Some(reader) = self.consume(reader)? { - let hdu = Self::new(reader)?; - - Ok(Some(hdu)) - } else { - Ok(None) - } - }*/ -} - -/* -#[derive(Debug)] -pub enum AsyncXtensionHDU<'a, R> -where - R: DataAsyncBufRead<'a, Image> - + DataAsyncBufRead<'a, BinTable> - + DataAsyncBufRead<'a, AsciiTable> - + 'a, -{ - Image(AsyncHDU<'a, R, Image>), - AsciiTable(AsyncHDU<'a, R, AsciiTable>), - BinTable(AsyncHDU<'a, R, BinTable>), -} - -impl<'a, R> AsyncXtensionHDU<'a, R> -where - R: DataAsyncBufRead<'a, Image> - + DataAsyncBufRead<'a, BinTable> - + DataAsyncBufRead<'a, AsciiTable> - + 'a, -{ - pub async fn new(reader: &'a mut R) -> Result, Error> { - let mut num_bytes_read = 0; - let mut card_80_bytes_buf = [0; 80]; - - // XTENSION - consume_next_card_async(reader, &mut card_80_bytes_buf, &mut num_bytes_read).await?; - let xtension_type = parse_xtension_card(&card_80_bytes_buf)?; - - let hdu = match xtension_type { - XtensionType::Image => AsyncXtensionHDU::Image( - AsyncHDU::<'a, R, Image>::new(reader, &mut num_bytes_read, &mut card_80_bytes_buf) - .await?, - ), - XtensionType::BinTable => AsyncXtensionHDU::BinTable( - AsyncHDU::<'a, R, BinTable>::new( - reader, - &mut num_bytes_read, - &mut card_80_bytes_buf, - ) - .await?, - ), - XtensionType::AsciiTable => AsyncXtensionHDU::AsciiTable( - AsyncHDU::<'a, R, AsciiTable>::new( - reader, - &mut num_bytes_read, - &mut card_80_bytes_buf, - ) - .await?, - ), - }; - - Ok(hdu) - } - - async fn consume(self) -> Result, Error> { - match self { - AsyncXtensionHDU::Image(hdu) => hdu.consume().await, - AsyncXtensionHDU::AsciiTable(hdu) => hdu.consume().await, - AsyncXtensionHDU::BinTable(hdu) => hdu.consume().await, - } - } - - pub async fn next(self) -> Result>, Error> { - if let Some(reader) = self.consume().await? { - let hdu = Self::new(reader).await?; - - Ok(Some(hdu)) - } else { - Ok(None) - } - } -} -*/ diff --git a/src/hdu/header/extension/asciitable.rs b/src/hdu/header/extension/asciitable.rs index 657c2d4..ec6b35d 100644 --- a/src/hdu/header/extension/asciitable.rs +++ b/src/hdu/header/extension/asciitable.rs @@ -13,10 +13,10 @@ use crate::hdu::header::parse_gcount_card; use crate::hdu::header::parse_naxis_card; use crate::hdu::header::parse_pcount_card; use crate::hdu::header::BitpixValue; +use crate::hdu::header::Xtension; use crate::hdu::header::NAXIS_KW; use crate::hdu::primary::check_card_keyword; use crate::hdu::primary::consume_next_card; -use crate::hdu::Xtension; #[derive(Debug, PartialEq, Serialize, Clone)] pub struct AsciiTable { @@ -380,24 +380,26 @@ mod tests { use super::{AsciiTable, TFormAsciiTable}; use crate::{ fits::Fits, - hdu::{extension::XtensionHDU, header::BitpixValue}, + hdu::{header::BitpixValue, HDU}, }; use std::{fs::File, io::BufReader}; - /* + fn compare_ascii_ext(filename: &str, ascii_table: AsciiTable) { let f = File::open(filename).unwrap(); - let mut reader = BufReader::new(f); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); + let reader = BufReader::new(f); + let hdu_list = Fits::from_reader(reader); // Get the first HDU extension, // this should be the table for these fits examples - let hdu = hdu + let hdu = hdu_list + // skip the primary hdu + .skip(1) .next() .expect("Should contain an extension HDU") .unwrap(); match hdu { - XtensionHDU::AsciiTable(hdu) => { + HDU::XASCIITable(hdu) => { let xtension = hdu.get_header().get_xtension(); assert_eq!(xtension.clone(), ascii_table); } @@ -588,5 +590,5 @@ mod tests { gcount: 1, }, ); - }*/ + } } diff --git a/src/hdu/header/extension/bintable.rs b/src/hdu/header/extension/bintable.rs index 1c975d3..2c69d60 100644 --- a/src/hdu/header/extension/bintable.rs +++ b/src/hdu/header/extension/bintable.rs @@ -13,10 +13,10 @@ use crate::hdu::header::parse_gcount_card; use crate::hdu::header::parse_naxis_card; use crate::hdu::header::parse_pcount_card; use crate::hdu::header::BitpixValue; +use crate::hdu::header::Xtension; use crate::hdu::header::NAXIS_KW; use crate::hdu::primary::check_card_keyword; use crate::hdu::primary::consume_next_card; -use crate::hdu::Xtension; use crate::card::Value; @@ -391,24 +391,27 @@ mod tests { use super::{BinTable, TFormBinaryTable, TFormBinaryTableType}; use crate::{ fits::Fits, - hdu::{extension::XtensionHDU, header::BitpixValue}, + hdu::{header::BitpixValue, HDU}, }; use std::{fs::File, io::BufReader}; - /* + fn compare_bintable_ext(filename: &str, bin_table: BinTable) { let f = File::open(filename).unwrap(); - let mut reader = BufReader::new(f); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); + let reader = BufReader::new(f); + let hdu_list = Fits::from_reader(reader); // Get the first HDU extension, // this should be the table for these fits examples - let hdu = hdu + let hdu = hdu_list + // skip the primary hdu + .skip(1) .next() .expect("Should contain an extension HDU") .unwrap(); + match hdu { - XtensionHDU::BinTable(hdu) => { + HDU::XBinaryTable(hdu) => { let xtension = hdu.get_header().get_xtension(); assert_eq!(xtension.clone(), bin_table); } @@ -445,5 +448,5 @@ mod tests { gcount: 1, }, ); - }*/ + } } diff --git a/src/hdu/header/extension/image.rs b/src/hdu/header/extension/image.rs index 90c7e9d..a9c92a7 100644 --- a/src/hdu/header/extension/image.rs +++ b/src/hdu/header/extension/image.rs @@ -12,10 +12,10 @@ use crate::hdu::header::consume_next_card_async; use crate::hdu::header::parse_bitpix_card; use crate::hdu::header::parse_naxis_card; use crate::hdu::header::BitpixValue; +use crate::hdu::header::Xtension; use crate::hdu::header::NAXIS_KW; use crate::hdu::primary::check_card_keyword; use crate::hdu::primary::consume_next_card; -use crate::hdu::Xtension; #[derive(Debug, PartialEq, Serialize, Clone)] pub struct Image { diff --git a/src/hdu/header/mod.rs b/src/hdu/header/mod.rs index e69e85e..4992acf 100644 --- a/src/hdu/header/mod.rs +++ b/src/hdu/header/mod.rs @@ -7,6 +7,8 @@ use serde::Serialize; pub mod extension; +pub use extension::Xtension; + use std::collections::hash_map::Keys; use std::collections::HashMap; use std::io::Read; @@ -15,8 +17,6 @@ use crate::card::*; use crate::card::{self, Card}; use crate::error::Error; -use crate::hdu::Xtension; - pub fn consume_next_card( reader: &mut R, buf: &mut [u8; 80], @@ -308,62 +308,74 @@ mod tests { } use crate::fits::Fits; + use crate::hdu::HDU; + use std::fs::File; use std::io::Cursor; use std::io::Read; - /* #[test] fn test_keywords_iter() { let f = File::open("samples/misc/SN2923fxjA.fits").unwrap(); let bytes: Result, _> = f.bytes().collect(); let buf = bytes.unwrap(); - let mut reader = Cursor::new(&buf[..]); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); - - let header = hdu.get_header(); - let mut keywords = header - .cards() - .map(|c| c.keyword().unwrap().to_owned()) - .collect::>(); - keywords.sort_unstable(); - - assert_eq!( - keywords, - vec![ - "BAYERIND", "BITCAMPX", "CALPHOT", "CCD-TEMP", "CD1_1", "CD1_2", "CD2_1", "CD2_2", - "CDELT1", "CDELT2", "CDELTM1", "CDELTM2", "COMMENT", "COMPRESS", "CRPIX1", - "CRPIX2", "CRVAL1", "CRVAL2", "CTYPE1", "CTYPE2", "CUNIT1", "CUNIT2", "CVF", - "DATAMAX", "DATAMIN", "DATE", "DATE-OBS", "DEC", "DEWPOINT", "DIAMETER", "ERRFLUX", - "EXPOSURE", "FILTERS", "FOCAL", "FOCUSPOS", "FOCUSTMP", "GAIN_ELE", "HISTORY", - "HUMIDITY", "IMGTYPE", "INSTRUME", "MAGREF", "MIRORX", "NAXIS", "NAXIS1", "NAXIS2", - "OBJCTDEC", "OBJCTRA", "OBSERVER", "OFFSET_E", "ORIGIN", "P3DSPHER", "PCXASTRO", - "PCYASTRO", "PDEC_REF", "PDIMPOL", "PIERSIDE", "PPLATESD", "PPXC", "PPYC", - "PRADIUSX", "PRADIUSY", "PRA_REF", "PRESSURE", "PSOLDC1", "PSOLDC10", "PSOLDC11", - "PSOLDC12", "PSOLDC13", "PSOLDC14", "PSOLDC15", "PSOLDC16", "PSOLDC17", "PSOLDC18", - "PSOLDC19", "PSOLDC2", "PSOLDC20", "PSOLDC21", "PSOLDC22", "PSOLDC23", "PSOLDC24", - "PSOLDC25", "PSOLDC26", "PSOLDC27", "PSOLDC28", "PSOLDC29", "PSOLDC3", "PSOLDC30", - "PSOLDC31", "PSOLDC32", "PSOLDC33", "PSOLDC34", "PSOLDC35", "PSOLDC36", "PSOLDC4", - "PSOLDC5", "PSOLDC6", "PSOLDC7", "PSOLDC8", "PSOLDC9", "PSOLRA1", "PSOLRA10", - "PSOLRA11", "PSOLRA12", "PSOLRA13", "PSOLRA14", "PSOLRA15", "PSOLRA16", "PSOLRA17", - "PSOLRA18", "PSOLRA19", "PSOLRA2", "PSOLRA20", "PSOLRA21", "PSOLRA22", "PSOLRA23", - "PSOLRA24", "PSOLRA25", "PSOLRA26", "PSOLRA27", "PSOLRA28", "PSOLRA29", "PSOLRA3", - "PSOLRA30", "PSOLRA31", "PSOLRA32", "PSOLRA33", "PSOLRA34", "PSOLRA35", "PSOLRA36", - "PSOLRA4", "PSOLRA5", "PSOLRA6", "PSOLRA7", "PSOLRA8", "PSOLRA9", "PSOLX1", - "PSOLX10", "PSOLX11", "PSOLX12", "PSOLX13", "PSOLX14", "PSOLX15", "PSOLX16", - "PSOLX17", "PSOLX18", "PSOLX19", "PSOLX2", "PSOLX20", "PSOLX21", "PSOLX22", - "PSOLX23", "PSOLX24", "PSOLX25", "PSOLX26", "PSOLX27", "PSOLX28", "PSOLX29", - "PSOLX3", "PSOLX30", "PSOLX31", "PSOLX32", "PSOLX33", "PSOLX34", "PSOLX35", - "PSOLX36", "PSOLX4", "PSOLX5", "PSOLX6", "PSOLX7", "PSOLX8", "PSOLX9", "PSOLY1", - "PSOLY10", "PSOLY11", "PSOLY12", "PSOLY13", "PSOLY14", "PSOLY15", "PSOLY16", - "PSOLY17", "PSOLY18", "PSOLY19", "PSOLY2", "PSOLY20", "PSOLY21", "PSOLY22", - "PSOLY23", "PSOLY24", "PSOLY25", "PSOLY26", "PSOLY27", "PSOLY28", "PSOLY29", - "PSOLY3", "PSOLY30", "PSOLY31", "PSOLY32", "PSOLY33", "PSOLY34", "PSOLY35", - "PSOLY36", "PSOLY4", "PSOLY5", "PSOLY6", "PSOLY7", "PSOLY8", "PSOLY9", "PSSX", - "PSSY", "RA", "READOUTT", "REFFLUX", "SITELAT", "SITELONG", "STACKNB", "STARCNT", - "SWCREATE", "TELESCOP", "TEMPEXT", "UT", "WINDIR", "WINSPEED", "X1", "X2", - "XPIXELSZ", "XPIXSZ", "Y1", "Y2", "YPIXELSZ", "YPIXSZ" - ] - ); - }*/ + let reader = Cursor::new(&buf[..]); + let mut hdu_list = Fits::from_reader(reader); + + let hdu = hdu_list.next().unwrap().unwrap(); + match hdu { + HDU::Primary(hdu) => { + let mut keywords = hdu + .get_header() + .cards() + .map(|c| c.keyword().map(|k| k.to_owned())) + .collect::, _>>() + .unwrap(); + keywords.sort_unstable(); + + assert_eq!( + keywords, + vec![ + "BAYERIND", "BITCAMPX", "CALPHOT", "CCD-TEMP", "CD1_1", "CD1_2", "CD2_1", + "CD2_2", "CDELT1", "CDELT2", "CDELTM1", "CDELTM2", "COMMENT", "COMPRESS", + "CRPIX1", "CRPIX2", "CRVAL1", "CRVAL2", "CTYPE1", "CTYPE2", "CUNIT1", + "CUNIT2", "CVF", "DATAMAX", "DATAMIN", "DATE", "DATE-OBS", "DEC", + "DEWPOINT", "DIAMETER", "ERRFLUX", "EXPOSURE", "FILTERS", "FOCAL", + "FOCUSPOS", "FOCUSTMP", "GAIN_ELE", "HISTORY", "HUMIDITY", "IMGTYPE", + "INSTRUME", "MAGREF", "MIRORX", "NAXIS", "NAXIS1", "NAXIS2", "OBJCTDEC", + "OBJCTRA", "OBSERVER", "OFFSET_E", "ORIGIN", "P3DSPHER", "PCXASTRO", + "PCYASTRO", "PDEC_REF", "PDIMPOL", "PIERSIDE", "PPLATESD", "PPXC", "PPYC", + "PRADIUSX", "PRADIUSY", "PRA_REF", "PRESSURE", "PSOLDC1", "PSOLDC10", + "PSOLDC11", "PSOLDC12", "PSOLDC13", "PSOLDC14", "PSOLDC15", "PSOLDC16", + "PSOLDC17", "PSOLDC18", "PSOLDC19", "PSOLDC2", "PSOLDC20", "PSOLDC21", + "PSOLDC22", "PSOLDC23", "PSOLDC24", "PSOLDC25", "PSOLDC26", "PSOLDC27", + "PSOLDC28", "PSOLDC29", "PSOLDC3", "PSOLDC30", "PSOLDC31", "PSOLDC32", + "PSOLDC33", "PSOLDC34", "PSOLDC35", "PSOLDC36", "PSOLDC4", "PSOLDC5", + "PSOLDC6", "PSOLDC7", "PSOLDC8", "PSOLDC9", "PSOLRA1", "PSOLRA10", + "PSOLRA11", "PSOLRA12", "PSOLRA13", "PSOLRA14", "PSOLRA15", "PSOLRA16", + "PSOLRA17", "PSOLRA18", "PSOLRA19", "PSOLRA2", "PSOLRA20", "PSOLRA21", + "PSOLRA22", "PSOLRA23", "PSOLRA24", "PSOLRA25", "PSOLRA26", "PSOLRA27", + "PSOLRA28", "PSOLRA29", "PSOLRA3", "PSOLRA30", "PSOLRA31", "PSOLRA32", + "PSOLRA33", "PSOLRA34", "PSOLRA35", "PSOLRA36", "PSOLRA4", "PSOLRA5", + "PSOLRA6", "PSOLRA7", "PSOLRA8", "PSOLRA9", "PSOLX1", "PSOLX10", "PSOLX11", + "PSOLX12", "PSOLX13", "PSOLX14", "PSOLX15", "PSOLX16", "PSOLX17", + "PSOLX18", "PSOLX19", "PSOLX2", "PSOLX20", "PSOLX21", "PSOLX22", "PSOLX23", + "PSOLX24", "PSOLX25", "PSOLX26", "PSOLX27", "PSOLX28", "PSOLX29", "PSOLX3", + "PSOLX30", "PSOLX31", "PSOLX32", "PSOLX33", "PSOLX34", "PSOLX35", + "PSOLX36", "PSOLX4", "PSOLX5", "PSOLX6", "PSOLX7", "PSOLX8", "PSOLX9", + "PSOLY1", "PSOLY10", "PSOLY11", "PSOLY12", "PSOLY13", "PSOLY14", "PSOLY15", + "PSOLY16", "PSOLY17", "PSOLY18", "PSOLY19", "PSOLY2", "PSOLY20", "PSOLY21", + "PSOLY22", "PSOLY23", "PSOLY24", "PSOLY25", "PSOLY26", "PSOLY27", + "PSOLY28", "PSOLY29", "PSOLY3", "PSOLY30", "PSOLY31", "PSOLY32", "PSOLY33", + "PSOLY34", "PSOLY35", "PSOLY36", "PSOLY4", "PSOLY5", "PSOLY6", "PSOLY7", + "PSOLY8", "PSOLY9", "PSSX", "PSSY", "RA", "READOUTT", "REFFLUX", "SITELAT", + "SITELONG", "STACKNB", "STARCNT", "SWCREATE", "TELESCOP", "TEMPEXT", "UT", + "WINDIR", "WINSPEED", "X1", "X2", "XPIXELSZ", "XPIXSZ", "Y1", "Y2", + "YPIXELSZ", "YPIXSZ" + ] + ); + } + _ => unreachable!(), + } + } } diff --git a/src/hdu/mod.rs b/src/hdu/mod.rs index f80ee3e..402d536 100644 --- a/src/hdu/mod.rs +++ b/src/hdu/mod.rs @@ -4,162 +4,156 @@ pub mod data; pub mod extension; pub mod primary; -use crate::hdu::header::extension::Xtension; -use crate::{fits::Fits, hdu::data::DataBufRead}; -use futures::{AsyncBufReadExt, AsyncReadExt}; -use header::Header; +use crate::hdu::data::DataBufRead; //use self::data::DataAsyncBufRead; use crate::error::Error; -use self::data::layout::MemoryLayout; +use self::data::AsyncDataBufRead; +use self::header::consume_next_card_async; use self::header::extension::asciitable::AsciiTable; use self::header::extension::bintable::BinTable; use self::header::extension::image::Image; +use self::header::extension::XtensionType; +use self::primary::check_card_keyword; + +//use super::data::DataAsyncBufRead; +//use super::AsyncHDU; +use crate::async_fits; +use crate::fits; +use crate::hdu::header::extension::parse_xtension_card; +use crate::hdu::primary::consume_next_card; -/* -// Async variant #[derive(Debug)] -pub struct AsyncHDU<'a, R, X> -where - X: Xtension, - R: DataAsyncBufRead<'a, X>, -{ - /// The header part that stores all the cards - header: Header, - /// The data part - data: >::Data, +pub enum HDU { + Primary(fits::HDU), + XImage(fits::HDU), + XBinaryTable(fits::HDU), + XASCIITable(fits::HDU), } -impl<'a, R, X> AsyncHDU<'a, R, X> -where - X: Xtension + std::fmt::Debug, - R: DataAsyncBufRead<'a, X> + 'a, -{ - pub async fn new( - reader: &'a mut R, - num_bytes_read: &mut u64, - card_80_bytes_buf: &mut [u8; 80], - ) -> Result, Error> { - /* 1. Parse the header first */ - let header = Header::parse_async(reader, num_bytes_read, card_80_bytes_buf).await?; - /* 2. Skip the next bytes to a new 2880 multiple of bytes - This is where the data block should start */ - let is_remaining_bytes = ((*num_bytes_read) % 2880) > 0; - - // Skip the remaining bytes to set the reader where a new HDU begins - if is_remaining_bytes { - let mut block_mem_buf: [u8; 2880] = [0; 2880]; - - let num_off_bytes = (2880 - ((*num_bytes_read) % 2880)) as usize; - reader - .read_exact(&mut block_mem_buf[..num_off_bytes]) - .await - .map_err(|_| Error::StaticError("EOF reached"))?; - } - - // Data block - let xtension = header.get_xtension(); - let data = reader.new_data_block(xtension); - - Ok(Self { header, data }) - } - - async fn consume(self) -> Result, Error> { +impl HDU { + pub(crate) fn new_xtension<'a, R>(reader: &mut R) -> Result + where + R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, + { let mut num_bytes_read = 0; - let reader = - >::consume_data_block(self.data, &mut num_bytes_read) - .await?; - let is_remaining_bytes = (num_bytes_read % 2880) > 0; - // Skip the remaining bytes to set the reader where a new HDU begins - let reader = if is_remaining_bytes { - let mut block_mem_buf: [u8; 2880] = [0; 2880]; - - let num_off_bytes = (2880 - (num_bytes_read % 2880)) as usize; - reader - .read_exact(&mut block_mem_buf[..num_off_bytes]) - .await - .ok() // An error like unexpected EOF is not standard frendly but we make it pass - // interpreting it as the last HDU in the file - .map(|_| reader) - } else { - // We are at a multiple of 2880 byte - Some(reader) + let mut card_80_bytes_buf = [0; 80]; + + // XTENSION + consume_next_card(reader, &mut card_80_bytes_buf, &mut num_bytes_read)?; + let xtension_type = parse_xtension_card(&card_80_bytes_buf)?; + + let hdu = match xtension_type { + XtensionType::Image => HDU::XImage(fits::HDU::::new( + reader, + &mut num_bytes_read, + &mut card_80_bytes_buf, + )?), + XtensionType::BinTable => HDU::XBinaryTable(fits::HDU::::new( + reader, + &mut num_bytes_read, + &mut card_80_bytes_buf, + )?), + XtensionType::AsciiTable => HDU::XASCIITable(fits::HDU::::new( + reader, + &mut num_bytes_read, + &mut card_80_bytes_buf, + )?), }; - if let Some(reader) = reader { - let is_eof = reader - .fill_buf() - .await - .map_err(|_| { - Error::StaticError("Unable to fill the buffer to check if data is remaining") - })? - .is_empty(); - if !is_eof { - Ok(Some(reader)) - } else { - Ok(None) - } - } else { - Ok(None) - } + Ok(hdu) } - pub fn get_header(&self) -> &Header { - &self.header - } + pub(crate) fn new_primary<'a, R>(reader: &mut R) -> Result + where + //R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, + R: DataBufRead<'a, Image> + 'a, + { + let mut num_bytes_read = 0; + let mut card_80_bytes_buf = [0; 80]; + + // SIMPLE + consume_next_card(reader, &mut card_80_bytes_buf, &mut num_bytes_read)?; + let _ = check_card_keyword(&card_80_bytes_buf, b"SIMPLE ")?; + + let hdu = fits::HDU::::new(reader, &mut num_bytes_read, &mut card_80_bytes_buf)?; - /*pub fn get_data(&'a mut self) -> <>::Data as Access<'a>>::Type { - self.data.get_data() - }*/ + Ok(HDU::Primary(hdu)) + } +} - /*pub fn get_data_mut(&mut self) -> &mut <>::Data as Access>::Type { - self.data.get_data_mut() - }*/ +#[derive(Debug)] +pub enum AsyncHDU { + Primary(async_fits::AsyncHDU), + XImage(async_fits::AsyncHDU), + XBinaryTable(crate::async_fits::AsyncHDU), + XASCIITable(crate::async_fits::AsyncHDU), } -*/ -/* -impl Drop for HDU -where - X: Xtension + std::fmt::Debug, -{ - fn drop(&mut self) { + +impl AsyncHDU { + pub(crate) async fn new_xtension<'a, R>(reader: &mut R) -> Result + where + R: AsyncDataBufRead<'a, Image> + + AsyncDataBufRead<'a, BinTable> + + AsyncDataBufRead<'a, AsciiTable> + + 'a, + { let mut num_bytes_read = 0; - let xtension = self.header.get_xtension(); - let num_bytes_read = self.num_bytes_read; - - let is_remaining_bytes = (num_bytes_read % 2880) > 0; - // Skip the remaining bytes to set the reader where a new HDU begins - let reader = if is_remaining_bytes { - let mut block_mem_buf: [u8; 2880] = [0; 2880]; - - let num_off_bytes = (2880 - (num_bytes_read % 2880)) as usize; - reader - .read_exact(&mut block_mem_buf[..num_off_bytes]) - .ok() // An error like unexpected EOF is not standard frendly but we make it pass - // interpreting it as the last HDU in the file - .map(|_| reader) - } else { - // We are at a multiple of 2880 byte - Some(reader) + let mut card_80_bytes_buf = [0; 80]; + + // XTENSION + consume_next_card_async(reader, &mut card_80_bytes_buf, &mut num_bytes_read).await?; + let xtension_type = parse_xtension_card(&card_80_bytes_buf)?; + + let hdu = match xtension_type { + XtensionType::Image => AsyncHDU::XImage( + async_fits::AsyncHDU::::new( + reader, + &mut num_bytes_read, + &mut card_80_bytes_buf, + ) + .await?, + ), + XtensionType::BinTable => AsyncHDU::XBinaryTable( + async_fits::AsyncHDU::::new( + reader, + &mut num_bytes_read, + &mut card_80_bytes_buf, + ) + .await?, + ), + XtensionType::AsciiTable => AsyncHDU::XASCIITable( + async_fits::AsyncHDU::::new( + reader, + &mut num_bytes_read, + &mut card_80_bytes_buf, + ) + .await?, + ), }; - if let Some(reader) = reader { - let is_eof = reader - .fill_buf() - .map_err(|_| { - Error::StaticError("Unable to fill the buffer to check if data is remaining") - })? - .is_empty(); - if !is_eof { - Ok(Some(reader)) - } else { - Ok(None) - } - } else { - Ok(None) - } + Ok(hdu) + } + + pub(crate) async fn new_primary<'a, R>(reader: &mut R) -> Result + where + //R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, + R: AsyncDataBufRead<'a, Image> + 'a, + { + let mut num_bytes_read = 0; + let mut card_80_bytes_buf = [0; 80]; + + // SIMPLE + consume_next_card_async(reader, &mut card_80_bytes_buf, &mut num_bytes_read).await?; + let _ = check_card_keyword(&card_80_bytes_buf, b"SIMPLE ")?; + + let hdu = + async_fits::AsyncHDU::::new(reader, &mut num_bytes_read, &mut card_80_bytes_buf) + .await?; + + Ok(AsyncHDU::Primary(hdu)) } -}*/ +} diff --git a/src/hdu/primary.rs b/src/hdu/primary.rs index d519bab..2ce737a 100644 --- a/src/hdu/primary.rs +++ b/src/hdu/primary.rs @@ -1,21 +1,9 @@ -use super::{ - //data::DataAsyncBufRead, - //extension::{AsyncXtensionHDU, XtensionHDU}, - header::consume_next_card_async, - //AsyncHDU, -}; -use crate::hdu::extension::XtensionHDU; use std::fmt::Debug; -use crate::hdu::header::extension::asciitable::AsciiTable; -use crate::hdu::header::extension::bintable::BinTable; use crate::hdu::header::extension::image::Image; -use crate::hdu::data::DataBufRead; - use crate::fits::HDU; -use crate::error::Error; pub use crate::hdu::header::{check_card_keyword, consume_next_card}; use std::ops::Deref; @@ -25,43 +13,6 @@ use std::ops::Deref; #[derive(Debug)] pub struct PrimaryHDU(pub HDU); -impl PrimaryHDU { - pub fn new<'a, R>(reader: &mut R, num_bytes_read: &mut usize) -> Result - where - //R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, - R: DataBufRead<'a, Image> + 'a, - { - let mut card_80_bytes_buf = [0; 80]; - - // SIMPLE - consume_next_card(reader, &mut card_80_bytes_buf, num_bytes_read)?; - let _ = check_card_keyword(&card_80_bytes_buf, b"SIMPLE ")?; - - let hdu = HDU::::new(reader, num_bytes_read, &mut card_80_bytes_buf)?; - - Ok(PrimaryHDU(hdu)) - } - - /*fn consume<'a, R>(self, reader: &mut R) -> Result, Error> - where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, - { - self.0.consume(reader) - } - - pub fn next<'a, R>(self, reader: &'a mut R) -> Result, Error> - where - R: DataBufRead<'a, Image> + DataBufRead<'a, BinTable> + DataBufRead<'a, AsciiTable> + 'a, - { - if let Some(reader) = self.consume(reader)? { - let hdu = XtensionHDU::new(reader)?; - Ok(Some(hdu)) - } else { - Ok(None) - } - }*/ -} - impl Deref for PrimaryHDU { type Target = HDU; diff --git a/src/lib.rs b/src/lib.rs index dfd501d..23aa587 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,42 +8,52 @@ //! use std::fs::File; //! use std::io::BufReader; //! -//! use fitsrs::{fits::Fits, hdu::HDU}; -//! use fitsrs::hdu::data::iter; +//! use fitsrs::{Fits, HDU}; +//! use fitsrs::hdu::data::DataIter; //! //! let f = File::open("samples/fits.gsfc.nasa.gov/HST_FOC.fits").unwrap(); -//! let mut reader = BufReader::new(f); -//! let Fits { mut hdu } = Fits::from_reader(&mut reader).unwrap(); -//! let xtension = hdu.get_header().get_xtension(); -//! let naxis1 = *xtension.get_naxisn(1).unwrap() as usize; -//! let naxis2 = *xtension.get_naxisn(2).unwrap() as usize; +//! let reader = BufReader::new(f); +//! let mut hdu_list = Fits::from_reader(reader); +//! let hdu = hdu_list.next(); +//! if let Some(Ok(HDU::Primary(hdu))) = hdu { +//! let xtension = hdu.get_header().get_xtension(); +//! let naxis1 = *xtension.get_naxisn(1).unwrap() as usize; +//! let naxis2 = *xtension.get_naxisn(2).unwrap() as usize; //! -//! if let iter::Data::F32(it) = hdu.get_data_mut() { -//! let data = it.collect::>(); -//! assert_eq!(data.len(), naxis1 * naxis2); -//! } else { -//! panic!("expected data block containing f32"); +//! if let DataIter::F32(it) = hdu.get_data(&mut hdu_list) { +//! let data = it.collect::>(); +//! assert_eq!(data.len(), naxis1 * naxis2); +//! } else { +//! panic!("expected data block containing f32"); +//! } //! } //! ``` +#[doc = include_str!("../README.md")] extern crate async_trait; extern crate byteorder; #[macro_use] extern crate quick_error; +pub mod async_fits; pub mod card; pub mod error; pub mod fits; pub mod hdu; +pub use async_fits::AsyncFits; +pub use fits::Fits; +pub use hdu::{AsyncHDU, HDU}; + #[cfg(test)] mod tests { + use crate::async_fits::AsyncFits; use crate::fits::Fits; - use crate::hdu::data::stream; + use crate::hdu::data::{DataIter, DataStream}; + use crate::hdu::AsyncHDU; //use crate::hdu::data::InMemData; - use crate::hdu::data::{iter, Slice}; + use crate::hdu::data::Data; //use crate::hdu::extension::AsyncXtensionHDU; - use crate::hdu::extension::XtensionHDU; use crate::hdu::header::extension::Xtension; use crate::hdu::header::BitpixValue; @@ -51,41 +61,42 @@ mod tests { use std::io::Cursor; use std::io::{BufReader, Read}; - use futures::{StreamExt, TryStreamExt}; + use futures::StreamExt; use test_case::test_case; - /*#[test] + #[test] fn test_fits_image_mandatory_kw() { let f = File::open("samples/hipsgen/Npix208.fits").unwrap(); let bytes: Result, _> = f.bytes().collect(); let buf = bytes.unwrap(); - let mut reader = Cursor::new(&buf[..]); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); - - let header = hdu.get_header(); - assert_eq!(header.get_xtension().get_naxisn(1), Some(&64)); - assert_eq!(header.get_xtension().get_naxisn(2), Some(&64)); - assert_eq!(header.get_xtension().get_naxis(), 2); - assert_eq!(header.get_xtension().get_bitpix(), BitpixValue::F32); - if let Ok(None) = hdu.next() { - assert!(true); - } else { - assert!(false); + let reader = Cursor::new(&buf[..]); + let mut hdu_list = Fits::from_reader(reader); + let hdu = hdu_list.next().unwrap().unwrap(); + assert!(matches!(hdu, HDU::Primary(_))); + + if let HDU::Primary(hdu) = hdu { + let header = hdu.get_header(); + assert_eq!(header.get_xtension().get_naxisn(1), Some(&64)); + assert_eq!(header.get_xtension().get_naxisn(2), Some(&64)); + assert_eq!(header.get_xtension().get_naxis(), 2); + assert_eq!(header.get_xtension().get_bitpix(), BitpixValue::F32); } + + assert!(hdu_list.next().is_none()); } - #[test_case("samples/fits.gsfc.nasa.gov/Astro_UIT.fits", 1, 0, 0)] - #[test_case("samples/fits.gsfc.nasa.gov/EUVE.fits", 5, 0, 4)] - #[test_case("samples/fits.gsfc.nasa.gov/HST_FGS.fits", 1, 1, 0)] - #[test_case("samples/fits.gsfc.nasa.gov/IUE_LWP.fits", 1, 0, 1)] - #[test_case("samples/misc/ngc5457K.fits", 1, 0, 0)] - #[test_case("samples/fits.gsfc.nasa.gov/HST_FOC.fits", 1, 1, 0)] - #[test_case("samples/fits.gsfc.nasa.gov/HST_FOS.fits", 1, 1, 0)] - #[test_case("samples/fits.gsfc.nasa.gov/HST_HRS.fits", 1, 1, 0)] - #[test_case("samples/fits.gsfc.nasa.gov/HST_NICMOS.fits", 6, 0, 0)] - #[test_case("samples/fits.gsfc.nasa.gov/HST_WFPC_II.fits", 1, 1, 0)] - #[test_case("samples/fits.gsfc.nasa.gov/HST_WFPC_II_bis.fits", 1, 0, 0)] + #[test_case("samples/fits.gsfc.nasa.gov/Astro_UIT.fits", 2, 0, 0)] + #[test_case("samples/fits.gsfc.nasa.gov/EUVE.fits", 6, 0, 4)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_FGS.fits", 2, 1, 0)] + #[test_case("samples/fits.gsfc.nasa.gov/IUE_LWP.fits", 2, 0, 1)] + #[test_case("samples/misc/ngc5457K.fits", 2, 0, 0)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_FOC.fits", 2, 1, 0)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_FOS.fits", 2, 1, 0)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_HRS.fits", 2, 1, 0)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_NICMOS.fits", 7, 0, 0)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_WFPC_II.fits", 2, 1, 0)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_WFPC_II_bis.fits", 2, 0, 0)] fn test_count_hdu( filename: &str, num_image_ext: usize, @@ -96,29 +107,25 @@ mod tests { let bytes: Result, _> = f.bytes().collect(); let buf = bytes.unwrap(); - let mut reader = Cursor::new(&buf[..]); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); + let reader = Cursor::new(&buf[..]); + let mut hdu_list = Fits::from_reader(reader); let mut n_image_ext = 1; // because the primary hdu is an image let mut n_bintable_ext = 0; let mut n_asciitable_ext = 0; - let mut hdu_ext = hdu.next(); - - while let Ok(Some(hdu)) = hdu_ext { + while let Some(Ok(hdu)) = hdu_list.next() { match &hdu { - XtensionHDU::Image(_) => { + HDU::Primary(_) | HDU::XImage(_) => { n_image_ext += 1; } - XtensionHDU::BinTable(_) => { + HDU::XBinaryTable(_) => { n_bintable_ext += 1; } - XtensionHDU::AsciiTable(_) => { + HDU::XASCIITable(_) => { n_asciitable_ext += 1; } } - - hdu_ext = hdu.next(); } assert_eq!(n_image_ext, num_image_ext); @@ -132,18 +139,23 @@ mod tests { let bytes: Result, _> = f.bytes().collect(); let buf = bytes.unwrap(); - let mut reader = Cursor::new(&buf[..]); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); - - let header = hdu.get_header(); - let num_pixels = header.get_xtension().get_naxisn(1).unwrap() - * header.get_xtension().get_naxisn(2).unwrap(); - let data = hdu.get_data(); - match data { - InMemData::F32(slice) => { - assert!(slice.len() as u64 == num_pixels); + let reader = Cursor::new(&buf[..]); + let mut hdu_list = Fits::from_reader(reader); + + let hdu = hdu_list.next().unwrap().unwrap(); + assert!(matches!(hdu, HDU::Primary(_))); + if let HDU::Primary(hdu) = hdu { + let header = hdu.get_header(); + let num_pixels = header.get_xtension().get_naxisn(1).unwrap() + * header.get_xtension().get_naxisn(2).unwrap(); + match hdu.get_data(&mut hdu_list) { + Data::F32(slice) => { + assert!(slice.len() as u64 == num_pixels); + } + _ => unreachable!(), } - _ => unreachable!(), + } else { + unreachable!(); } } @@ -153,82 +165,118 @@ mod tests { let mut raw_bytes = Vec::::new(); f.read_to_end(&mut raw_bytes).unwrap(); - let mut reader = Cursor::new(&raw_bytes[..]); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); - let xtension = hdu.get_header().get_xtension(); - match hdu.get_data() { - &InMemData::I16(data) => { - assert!( - data.len() as u64 - == xtension.get_naxisn(1).unwrap() * xtension.get_naxisn(2).unwrap() - ) + let reader = Cursor::new(&raw_bytes[..]); + let mut hdu_list = Fits::from_reader(reader); + + let hdu = hdu_list.next().unwrap().unwrap(); + assert!(matches!(hdu, HDU::Primary(_))); + if let HDU::Primary(hdu) = hdu { + let header = hdu.get_header(); + let num_pixels = header.get_xtension().get_naxisn(1).unwrap() + * header.get_xtension().get_naxisn(2).unwrap(); + match hdu.get_data(&mut hdu_list) { + Data::I16(data) => { + assert!(data.len() as u64 == num_pixels) + } + _ => unreachable!(), } - _ => unreachable!(), + } else { + unreachable!(); } } - #[test_case("samples/hipsgen/Npix8.fits")] - #[test_case("samples/hipsgen/Npix9.fits")] - #[test_case("samples/hipsgen/Npix132.fits")] - #[test_case("samples/hipsgen/Npix133.fits")] - #[test_case("samples/hipsgen/Npix134.fits")] - #[test_case("samples/hipsgen/Npix140.fits")] - #[test_case("samples/hipsgen/Npix208.fits")] - #[test_case("samples/hipsgen/Npix282.fits")] - #[test_case("samples/hipsgen/Npix4906.fits")] - #[test_case("samples/hipsgen/Npix691539.fits")] - #[test_case("samples/hips2fits/allsky_panstarrs.fits")] - #[test_case("samples/hips2fits/cutout-CDS_P_HST_PHAT_F475W.fits")] - #[test_case("samples/fits.gsfc.nasa.gov/Astro_UIT.fits")] - #[test_case("samples/fits.gsfc.nasa.gov/EUVE.fits")] - #[test_case("samples/fits.gsfc.nasa.gov/HST_FGS.fits")] - #[test_case("samples/fits.gsfc.nasa.gov/HST_FOC.fits")] - #[test_case("samples/fits.gsfc.nasa.gov/HST_FOS.fits")] - #[test_case("samples/fits.gsfc.nasa.gov/HST_HRS.fits")] - #[test_case("samples/fits.gsfc.nasa.gov/HST_NICMOS.fits")] - #[test_case("samples/fits.gsfc.nasa.gov/HST_WFPC_II.fits")] - #[test_case("samples/fits.gsfc.nasa.gov/HST_WFPC_II_bis.fits")] - #[test_case("samples/vizier/NVSSJ235137-362632r.fits")] - #[test_case("samples/vizier/VAR.358.R.fits")] - #[test_case("samples/fits.gsfc.nasa.gov/IUE_LWP.fits")] - #[test_case("samples/misc/bonn.fits")] - #[test_case("samples/misc/EUC_MER_MOSAIC-VIS-FLAG_TILE100158585-1EC1C5_20221211T132329.822037Z_00.00.fits")] - #[test_case("samples/misc/P122_49.fits")] - #[test_case("samples/misc/skv1678175163788.fits")] - #[test_case("samples/misc/SN2923fxjA.fits")] - fn test_fits_opening(filename: &str) { + #[test_case("samples/fits.gsfc.nasa.gov/Astro_UIT.fits", true)] + #[test_case("samples/hipsgen/Npix8.fits", false)] + #[test_case("samples/hipsgen/Npix9.fits", false)] + #[test_case("samples/hipsgen/Npix132.fits", false)] + #[test_case("samples/hipsgen/Npix133.fits", false)] + #[test_case("samples/hipsgen/Npix134.fits", false)] + #[test_case("samples/hipsgen/Npix140.fits", false)] + #[test_case("samples/hipsgen/Npix208.fits", false)] + #[test_case("samples/hipsgen/Npix282.fits", false)] + #[test_case("samples/hipsgen/Npix4906.fits", false)] + #[test_case("samples/hipsgen/Npix691539.fits", false)] + #[test_case("samples/hips2fits/allsky_panstarrs.fits", false)] + #[test_case("samples/hips2fits/cutout-CDS_P_HST_PHAT_F475W.fits", false)] + #[test_case("samples/fits.gsfc.nasa.gov/EUVE.fits", false)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_FGS.fits", false)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_FOC.fits", false)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_FOS.fits", false)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_HRS.fits", false)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_NICMOS.fits", false)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_WFPC_II.fits", false)] + #[test_case("samples/fits.gsfc.nasa.gov/HST_WFPC_II_bis.fits", false)] + #[test_case("samples/vizier/NVSSJ235137-362632r.fits", false)] + #[test_case("samples/vizier/VAR.358.R.fits", false)] + #[test_case("samples/fits.gsfc.nasa.gov/IUE_LWP.fits", false)] + #[test_case("samples/misc/bonn.fits", false)] + #[test_case("samples/misc/EUC_MER_MOSAIC-VIS-FLAG_TILE100158585-1EC1C5_20221211T132329.822037Z_00.00.fits", false)] + #[test_case("samples/misc/P122_49.fits", false)] + #[test_case("samples/misc/skv1678175163788.fits", false)] + #[test_case("samples/misc/SN2923fxjA.fits", false)] + fn test_fits_opening(filename: &str, corrupted: bool) { use std::fs::File; let mut f = File::open(filename).unwrap(); let mut buf = Vec::new(); f.read_to_end(&mut buf).unwrap(); - let mut reader = Cursor::new(&buf[..]); - let fits = Fits::from_reader(&mut reader); - assert!(fits.is_ok()); + let reader = Cursor::new(&buf[..]); + let hdu_list = Fits::from_reader(reader); + let mut correctly_opened = true; + for hdu in hdu_list { + match hdu { + Err(_) => { + correctly_opened = false; + } + _ => (), + } + } + + assert_eq!(!corrupted, correctly_opened); } #[test] - fn test_fits_image_owned() { + fn test_fits_not_fitting_in_memory() { use std::fs::File; use std::io::BufReader; let f = File::open("samples/fits.gsfc.nasa.gov/EUVE.fits").unwrap(); - let mut reader = BufReader::new(f); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); + let reader = BufReader::new(f); + let mut hdu_list = Fits::from_reader(reader); - if let Ok(Some(XtensionHDU::Image(mut image))) = hdu.next() { - let xtension = image.get_header().get_xtension(); + while let Some(Ok(HDU::XImage(hdu))) = hdu_list.next() { + let xtension = hdu.get_header().get_xtension(); let naxis1 = *xtension.get_naxisn(1).unwrap(); let naxis2 = *xtension.get_naxisn(2).unwrap(); - let data = image.get_data_mut(); - match data { - iter::Data::I16(it) => { + let num_pixels = (naxis1 * naxis2) as usize; + + match hdu.get_data(&mut hdu_list) { + DataIter::I16(it) => { let data = it.collect::>(); - assert_eq!(data.len(), (naxis1 * naxis2) as usize); + assert_eq!(data.len(), num_pixels); + } + DataIter::U8(it) => { + let data = it.collect::>(); + assert_eq!(data.len(), num_pixels); + } + DataIter::I32(it) => { + let data = it.collect::>(); + assert_eq!(data.len(), num_pixels); + } + DataIter::I64(it) => { + let data = it.collect::>(); + assert_eq!(data.len(), num_pixels); + } + DataIter::F32(it) => { + let data = it.collect::>(); + assert_eq!(data.len(), num_pixels); + } + DataIter::F64(it) => { + let data = it.collect::>(); + assert_eq!(data.len(), num_pixels); } - _ => unreachable!(), } } } @@ -241,20 +289,23 @@ mod tests { let mut buf = Vec::new(); f.read_to_end(&mut buf).unwrap(); - let mut reader = Cursor::new(&buf[..]); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); + let reader = Cursor::new(&buf[..]); + let mut hdu_list = Fits::from_reader(reader); - let naxis1 = *hdu.get_header().get_xtension().get_naxisn(1).unwrap(); - let naxis2 = *hdu.get_header().get_xtension().get_naxisn(2).unwrap(); - let data = hdu.get_data(); - match data { - &InMemData::F32(data) => { - assert_eq!(data.len(), (naxis1 * naxis2) as usize); + if let Some(Ok(HDU::Primary(hdu))) = hdu_list.next() { + let xtension = hdu.get_header().get_xtension(); + let naxis1 = *xtension.get_naxisn(1).unwrap(); + let naxis2 = *xtension.get_naxisn(2).unwrap(); + match hdu.get_data(&mut hdu_list) { + Data::F32(data) => { + assert_eq!(data.len(), (naxis1 * naxis2) as usize); + } + _ => unreachable!(), } - _ => unreachable!(), } - }*/ + } + use super::hdu::HDU; #[test] fn test_fits_images_data_block() { use std::fs::File; @@ -264,14 +315,12 @@ mod tests { f.read_to_end(&mut buf).unwrap(); let reader = Cursor::new(&buf[..]); - let mut hdu_list = Fits::from_reader(reader).unwrap(); - - //let mut hdu_ext = hdu.next(); + let mut hdu_list = Fits::from_reader(reader); - while let Some(hdu) = hdu_list.next() { - match hdu.unwrap() { - XtensionHDU::Image(xhdu) => { - let xtension = dbg!(xhdu.get_header().get_xtension()); + while let Some(Ok(hdu)) = hdu_list.next() { + match hdu { + HDU::XImage(hdu) | HDU::Primary(hdu) => { + let xtension = dbg!(hdu.get_header().get_xtension()); let naxis1 = xtension.get_naxisn(1); let naxis2 = xtension.get_naxisn(2); @@ -280,106 +329,99 @@ mod tests { (Some(naxis1), Some(naxis2)) => { let num_pixels = (naxis2 * naxis1) as usize; - let data = xhdu.get_data(&mut hdu_list); + let data = hdu.get_data(&mut hdu_list); match data { - Slice::U8(mem) => assert_eq!(num_pixels, mem.len()), - Slice::I16(mem) => assert_eq!(num_pixels, mem.len()), - Slice::I32(mem) => assert_eq!(num_pixels, mem.len()), - Slice::I64(mem) => assert_eq!(num_pixels, mem.len()), - Slice::F32(mem) => assert_eq!(num_pixels, mem.len()), - Slice::F64(mem) => assert_eq!(num_pixels, mem.len()), + Data::U8(mem) => assert_eq!(num_pixels, mem.len()), + Data::I16(mem) => assert_eq!(num_pixels, mem.len()), + Data::I32(mem) => assert_eq!(num_pixels, mem.len()), + Data::I64(mem) => assert_eq!(num_pixels, mem.len()), + Data::F32(mem) => assert_eq!(num_pixels, mem.len()), + Data::F64(mem) => assert_eq!(num_pixels, mem.len()), } } _ => (), }; } - XtensionHDU::BinTable(xhdu) => { - let num_bytes = xhdu.get_header().get_xtension().get_num_bytes_data_block(); - todo!(); - /*match xhdu.get_data(&mut hdu_list) { - InMemData::U8(mem) => assert_eq!(num_bytes as usize, mem.len()), + HDU::XBinaryTable(hdu) => { + let num_bytes = hdu.get_header().get_xtension().get_num_bytes_data_block(); + match hdu.get_data(&mut hdu_list) { + Data::U8(mem) => assert_eq!(num_bytes as usize, mem.len()), _ => unreachable!(), - }*/ + } } - XtensionHDU::AsciiTable(xhdu) => { - let num_bytes = xhdu.get_header().get_xtension().get_num_bytes_data_block(); - todo!(); - /*let num_bytes = xhdu.get_header().get_xtension().get_num_bytes_data_block(); - - match xhdu.get_data() { - InMemData::U8(mem) => assert_eq!(num_bytes as usize, mem.len()), + HDU::XASCIITable(hdu) => { + let num_bytes = hdu.get_header().get_xtension().get_num_bytes_data_block(); + match hdu.get_data(&mut hdu_list) { + Data::U8(mem) => assert_eq!(num_bytes as usize, mem.len()), _ => unreachable!(), - }*/ + } } } } } - /*#[test] + #[test] fn test_fits_images_data_block_bufreader() { use std::fs::File; let f = File::open("samples/fits.gsfc.nasa.gov/EUVE.fits").unwrap(); - let mut reader = BufReader::new(f); + let reader = BufReader::new(f); - let Fits { hdu } = Fits::from_reader(&mut reader).unwrap(); + let mut hdu_list = Fits::from_reader(reader); - let mut hdu_ext = hdu.next(); - - while let Ok(Some(mut xhdu)) = hdu_ext { - match &mut xhdu { - XtensionHDU::Image(xhdu) => { - let xtension = xhdu.get_header().get_xtension(); + while let Some(Ok(hdu)) = hdu_list.next() { + match hdu { + HDU::XImage(hdu) => { + let xtension = hdu.get_header().get_xtension(); let naxis1 = *xtension.get_naxisn(1).unwrap(); let naxis2 = *xtension.get_naxisn(2).unwrap(); let num_pixels = naxis2 * naxis1; - match xhdu.get_data_mut() { - iter::Data::U8(it) => { + match hdu.get_data(&mut hdu_list) { + DataIter::U8(it) => { let data = it.collect::>(); assert_eq!(num_pixels as usize, data.len()) } - iter::Data::I16(it) => { + DataIter::I16(it) => { let data = it.collect::>(); assert_eq!(num_pixels as usize, data.len()) } - iter::Data::I32(it) => { + DataIter::I32(it) => { let data = it.collect::>(); assert_eq!(num_pixels as usize, data.len()) } - iter::Data::I64(it) => { + DataIter::I64(it) => { let data = it.collect::>(); assert_eq!(num_pixels as usize, data.len()) } - iter::Data::F32(it) => { + DataIter::F32(it) => { let data = it.collect::>(); assert_eq!(num_pixels as usize, data.len()) } - iter::Data::F64(it) => { + DataIter::F64(it) => { let data = it.collect::>(); assert_eq!(num_pixels as usize, data.len()) } } } - XtensionHDU::BinTable(xhdu) => { - let num_bytes = xhdu.get_header().get_xtension().get_num_bytes_data_block(); + HDU::XBinaryTable(hdu) => { + let num_bytes = hdu.get_header().get_xtension().get_num_bytes_data_block(); - let it_bytes = xhdu.get_data_mut(); + let it_bytes = hdu.get_data(&mut hdu_list); let data = it_bytes.collect::>(); assert_eq!(num_bytes as usize, data.len()); } - XtensionHDU::AsciiTable(xhdu) => { - let num_bytes = xhdu.get_header().get_xtension().get_num_bytes_data_block(); + HDU::XASCIITable(hdu) => { + let num_bytes = hdu.get_header().get_xtension().get_num_bytes_data_block(); - let it_bytes = xhdu.get_data_mut(); + let it_bytes = hdu.get_data(&mut hdu_list); let data = it_bytes.collect::>(); assert_eq!(num_bytes as usize, data.len()); } + _ => (), } - - hdu_ext = xhdu.next(); } } @@ -400,8 +442,9 @@ mod tests { 101, 114, 118, 101, 114, 46, 60, 47, 112, 62, 10, 60, 47, 98, 111, 100, 121, 62, 60, 47, 104, 116, 109, 108, 62, 10, ]; - let mut reader = Cursor::new(bytes); - assert!(Fits::from_reader(&mut reader).is_err()); + let reader = Cursor::new(bytes); + let mut hdu_list = Fits::from_reader(reader); + assert!(hdu_list.next().unwrap().is_err()); } #[test_case("samples/misc/EUC_MER_MOSAIC-VIS-FLAG_TILE100158585-1EC1C5_20221211T132329.822037Z_00.00.fits")] @@ -410,8 +453,6 @@ mod tests { #[test_case("samples/vizier/new_url.fits")] #[tokio::test] async fn test_fits_images_data_block_bufreader_async(filename: &str) { - use std::fs::File; - // Put it all in memory first (this is for the exemple) // It is not good to do so for performance reasons // Better prefer to pipe to a ReadableStream instead @@ -419,101 +460,62 @@ mod tests { let mut buf = Vec::new(); f.read_to_end(&mut buf).unwrap(); - let mut reader = futures::io::BufReader::new(&buf[..]); - - let AsyncFits { mut hdu } = AsyncFits::from_reader(&mut reader).await.unwrap(); - let xtension = hdu.get_header().get_xtension(); - - if xtension.get_naxis() == 2 { - let naxis1 = *xtension.get_naxisn(1).unwrap(); - let naxis2 = *xtension.get_naxisn(2).unwrap(); - - let num_pixels = (naxis2 * naxis1) as usize; - - match hdu.get_data_mut() { - stream::Data::U8(stream) => { - let data = stream.try_collect::>().await.unwrap(); - assert_eq!(num_pixels, data.len()) - } - stream::Data::I16(stream) => { - let data = stream.try_collect::>().await.unwrap(); - assert_eq!(num_pixels, data.len()) - } - stream::Data::I32(stream) => { - let data = stream.try_collect::>().await.unwrap(); - assert_eq!(num_pixels, data.len()); - } - stream::Data::I64(stream) => { - let data = stream.try_collect::>().await.unwrap(); - assert_eq!(num_pixels, data.len()) - } - stream::Data::F32(stream) => { - let data = stream.try_collect::>().await.unwrap(); - assert_eq!(num_pixels, data.len()) - } - stream::Data::F64(stream) => { - let data = stream.try_collect::>().await.unwrap(); - assert_eq!(num_pixels, data.len()) - } - } - } - - let mut hdu_ext = hdu.next().await; - - while let Ok(Some(mut xhdu)) = hdu_ext { - match &mut xhdu { - AsyncXtensionHDU::Image(xhdu) => { - let xtension = xhdu.get_header().get_xtension(); + let reader = futures::io::BufReader::new(&buf[..]); - let naxis1 = *xtension.get_naxisn(1).unwrap(); - let naxis2 = *xtension.get_naxisn(2).unwrap(); + let mut hdu_list = AsyncFits::from_reader(reader); - let num_pixels = (naxis2 * naxis1) as usize; + while let Some(Ok(hdu)) = hdu_list.next().await { + match hdu { + AsyncHDU::XImage(hdu) | AsyncHDU::Primary(hdu) => { + let xtension = hdu.get_header().get_xtension(); + let naxis1 = xtension.get_naxisn(1); + let naxis2 = xtension.get_naxisn(2); + if let (Some(naxis1), Some(naxis2)) = (naxis1, naxis2) { + let num_pixels = (*naxis2 * *naxis1) as usize; - match xhdu.get_data_mut() { - stream::Data::U8(stream) => { - let data = stream.collect::>().await; - assert_eq!(num_pixels, data.len()) - } - stream::Data::I16(stream) => { - let data = stream.collect::>().await; - assert_eq!(num_pixels, data.len()) - } - stream::Data::I32(stream) => { - let data = stream.collect::>().await; - assert_eq!(num_pixels, data.len()); - } - stream::Data::I64(stream) => { - let data = stream.collect::>().await; - assert_eq!(num_pixels, data.len()) - } - stream::Data::F32(stream) => { - let data = stream.collect::>().await; - assert_eq!(num_pixels, data.len()) - } - stream::Data::F64(stream) => { - let data = stream.collect::>().await; - assert_eq!(num_pixels, data.len()) + match hdu.get_data(&mut hdu_list) { + DataStream::U8(st) => { + let data = st.collect::>().await; + assert_eq!(num_pixels, data.len()) + } + DataStream::I16(stream) => { + let data = stream.collect::>().await; + assert_eq!(num_pixels, data.len()) + } + DataStream::I32(stream) => { + let data = stream.collect::>().await; + assert_eq!(num_pixels, data.len()); + } + DataStream::I64(stream) => { + let data = stream.collect::>().await; + assert_eq!(num_pixels, data.len()) + } + DataStream::F32(stream) => { + let data = stream.collect::>().await; + assert_eq!(num_pixels, data.len()) + } + DataStream::F64(stream) => { + let data = stream.collect::>().await; + assert_eq!(num_pixels, data.len()) + } } } } - AsyncXtensionHDU::BinTable(xhdu) => { - let num_bytes = xhdu.get_header().get_xtension().get_num_bytes_data_block(); + AsyncHDU::XBinaryTable(hdu) => { + let num_bytes = hdu.get_header().get_xtension().get_num_bytes_data_block(); - let it_bytes = xhdu.get_data_mut(); + let it_bytes = hdu.get_data(&mut hdu_list); let data = it_bytes.collect::>().await; assert_eq!(num_bytes as usize, data.len()); } - AsyncXtensionHDU::AsciiTable(xhdu) => { + AsyncHDU::XASCIITable(xhdu) => { let num_bytes = xhdu.get_header().get_xtension().get_num_bytes_data_block(); - let it_bytes = xhdu.get_data_mut(); + let it_bytes = xhdu.get_data(&mut hdu_list); let data = it_bytes.collect::>().await; assert_eq!(num_bytes as usize, data.len()); } } - - hdu_ext = xhdu.next().await; } - }*/ + } } From 0c928ad25f77c5d53404644261d5402cb1b81db9 Mon Sep 17 00:00:00 2001 From: Matthieu Baumann Date: Fri, 10 Jan 2025 16:46:33 +0100 Subject: [PATCH 3/3] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 03eea07..b5dcece 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ use std::io::Cursor; use fitsrs::hdu::HDU; use fitsrs::hdu::data::DataIter; use fitsrs::fits::Fits; -use fitsrs::hdu::header::extension::Xtension; +use fitsrs::hdu::header::Xtension; use std::io::{BufReader, Read};