From 6379987988890bcf82c903b9706373cd86b3a4a6 Mon Sep 17 00:00:00 2001 From: Berke DURAK Date: Fri, 9 Aug 2024 11:42:45 +0200 Subject: [PATCH 1/3] Use anyhow for errors --- Cargo.toml | 1 + src/api/fits.rs | 6 ++- src/extensions.rs | 6 ++- src/extensions/image/image_parser.rs | 12 +++--- src/extensions/image/typed_image.rs | 49 ++++++++++++------------ src/extensions/table/ascii_table.rs | 6 ++- src/extensions/table/ascii_tbl_parser.rs | 6 ++- src/fits.rs | 5 ++- src/header.rs | 12 +++--- src/header_data_unit.rs | 11 +++--- src/intern.rs | 4 +- src/raw/header_block.rs | 7 ++-- src/raw/keyword_record.rs | 3 +- src/raw/raw_io.rs | 15 +++++--- 14 files changed, 84 insertions(+), 59 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 38a8c36..827aba6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,6 +45,7 @@ rayon = "1" dyn-clone = "1" indexmap = "1" rustronomy-core = "0.1" +anyhow = "1" [dev-dependencies] dirs = "4" diff --git a/src/api/fits.rs b/src/api/fits.rs index 807b0f2..c1d0090 100644 --- a/src/api/fits.rs +++ b/src/api/fits.rs @@ -49,6 +49,8 @@ use std::{error::Error, fmt::Display, path::Path}; +use anyhow::{Result}; + use rustronomy_core::universal_containers::*; use super::hdu::Hdu; @@ -60,7 +62,7 @@ pub struct Fits { } impl Fits { - pub fn read(path: &Path) -> Result> { + pub fn read(path: &Path) -> Result { //(1) First we try to open the file let mut reader = crate::intern::FitsReader::new(path)?; @@ -68,7 +70,7 @@ impl Fits { let (global_tags, hdu0) = crate::intern::read_primary_hdu(&mut reader)?; todo!() } - pub fn write(self, path: &Path) -> Result<(), Box> { + pub fn write(self, path: &Path) -> Result<()> { todo!() } pub fn empty() -> Self { diff --git a/src/extensions.rs b/src/extensions.rs index 7b40db9..16099a6 100644 --- a/src/extensions.rs +++ b/src/extensions.rs @@ -22,6 +22,8 @@ use std::{ fmt::{Display, Formatter}, }; +use anyhow::Result; + use crate::{ io_err::{self, InvalidFitsFileErr as IFFErr}, raw::{raw_io::RawFitsWriter, BlockSized}, @@ -72,10 +74,10 @@ impl Display for Extension { } impl Extension { - pub(crate) fn write_to_buffer(self, writer: &mut RawFitsWriter) -> Result<(), Box> { + pub(crate) fn write_to_buffer(self, writer: &mut RawFitsWriter) -> Result<()> { use Extension::*; match self { - Corrupted => return Err(Box::new(IFFErr::new(io_err::CORRUPTED))), + Corrupted => return Err(IFFErr::new(io_err::CORRUPTED).into()), Image(img) => ImgParser::encode_img(img, writer), AsciiTable(tbl) => AsciiTblParser::encode_tbl(tbl, writer), } diff --git a/src/extensions/image/image_parser.rs b/src/extensions/image/image_parser.rs index 632ae77..8aa1b26 100644 --- a/src/extensions/image/image_parser.rs +++ b/src/extensions/image/image_parser.rs @@ -30,6 +30,8 @@ use std::{ mem::size_of, }; +use anyhow::Result; + //Rustronomy Imports use rustronomy_core::data_type_traits::io_utils::{Decode, Encode}; @@ -60,7 +62,7 @@ impl ImgParser { reader: &mut RawFitsReader, shape: &Vec, bitpix: Bitpix, - ) -> Result> { + ) -> Result { use Bitpix::*; use TypedImage::*; @@ -77,7 +79,7 @@ impl ImgParser { fn decode_helper( reader: &mut RawFitsReader, shape: &Vec, - ) -> Result, Box> + ) -> Result> where T: Debug + Num + Sized + Decode + Encode + Display + Clone + Send, { @@ -156,7 +158,7 @@ impl ImgParser { pub(crate) fn encode_img( typed_img: TypedImage, writer: &mut RawFitsWriter, - ) -> Result<(), Box> { + ) -> Result<()> { //This function only matches the typed image and calls the appropriate //helper function use TypedImage::*; @@ -174,7 +176,7 @@ impl ImgParser { Ok(()) } - fn encode_helper(img: Image, writer: &mut RawFitsWriter) -> Result<(), Box> + fn encode_helper(img: Image, writer: &mut RawFitsWriter) -> Result<()> where T: Debug + Num + Sized + Decode + Encode + Display + Clone, { @@ -207,7 +209,7 @@ impl ImgParser { match img.get_data().as_slice_memory_order() { None => { //Data is NOT continuous, return error! - return Err(Box::new(IMLErr::new())); + return Err(IMLErr::new().into()); } _ => {} //Data IS continuous, continue! } diff --git a/src/extensions/image/typed_image.rs b/src/extensions/image/typed_image.rs index 99ba8cb..2a4eb6a 100644 --- a/src/extensions/image/typed_image.rs +++ b/src/extensions/image/typed_image.rs @@ -22,6 +22,7 @@ use std::{ fmt::{Display, Write}, }; +use anyhow::Result; use ndarray::{Array, IxDyn}; use crate::{ @@ -128,87 +129,87 @@ impl TypedImage { } } - pub fn as_u8_array(&self) -> Result<&Array, Box> { + pub fn as_u8_array(&self) -> Result<&Array> { match &self { Self::ByteImg(img) => Ok(img.get_data()), - &var => Err(Box::new(WITErr::new(var, Bitpix::byte()))), + &var => Err(WITErr::new(var, Bitpix::byte()).into()), } } - pub fn as_i16_array(&self) -> Result<&Array, Box> { + pub fn as_i16_array(&self) -> Result<&Array> { match &self { Self::I16Img(img) => Ok(img.get_data()), - &var => Err(Box::new(WITErr::new(var, Bitpix::short()))), + &var => Err(WITErr::new(var, Bitpix::short()).into()), } } - pub fn as_i32_array(&self) -> Result<&Array, Box> { + pub fn as_i32_array(&self) -> Result<&Array> { match &self { Self::I32Img(img) => Ok(img.get_data()), - &var => Err(Box::new(WITErr::new(var, Bitpix::int()))), + &var => Err(WITErr::new(var, Bitpix::int()).into()), } } - pub fn as_i64_array(&self) -> Result<&Array, Box> { + pub fn as_i64_array(&self) -> Result<&Array> { match &self { Self::I64Img(img) => Ok(img.get_data()), - &var => Err(Box::new(WITErr::new(var, Bitpix::long()))), + &var => Err(WITErr::new(var, Bitpix::long()).into()), } } - pub fn as_f32_array(&self) -> Result<&Array, Box> { + pub fn as_f32_array(&self) -> Result<&Array> { match &self { Self::SpfImg(img) => Ok(img.get_data()), - &var => Err(Box::new(WITErr::new(var, Bitpix::spf()))), + &var => Err(WITErr::new(var, Bitpix::spf()).into()), } } - pub fn as_f64_array(&self) -> Result<&Array, Box> { + pub fn as_f64_array(&self) -> Result<&Array> { match &self { Self::DpfImg(img) => Ok(img.get_data()), - &var => Err(Box::new(WITErr::new(var, Bitpix::dpf()))), + &var => Err(WITErr::new(var, Bitpix::dpf()).into()), } } - pub fn as_owned_u8_array(self) -> Result, Box> { + pub fn as_owned_u8_array(self) -> Result> { match self { Self::ByteImg(img) => Ok(img.get_data_owned()), - var => Err(Box::new(WITErr::new(&var, Bitpix::byte()))), + var => Err(WITErr::new(&var, Bitpix::byte()).into()), } } - pub fn as_owned_i16_array(self) -> Result, Box> { + pub fn as_owned_i16_array(self) -> Result> { match self { Self::I16Img(img) => Ok(img.get_data_owned()), - var => Err(Box::new(WITErr::new(&var, Bitpix::short()))), + var => Err(WITErr::new(&var, Bitpix::short()).into()), } } - pub fn as_owned_i32_array(self) -> Result, Box> { + pub fn as_owned_i32_array(self) -> Result> { match self { Self::I32Img(img) => Ok(img.get_data_owned()), - var => Err(Box::new(WITErr::new(&var, Bitpix::int()))), + var => Err(WITErr::new(&var, Bitpix::int()).into()), } } - pub fn as_owned_i64_array(self) -> Result, Box> { + pub fn as_owned_i64_array(self) -> Result> { match self { Self::I64Img(img) => Ok(img.get_data_owned()), - var => Err(Box::new(WITErr::new(&var, Bitpix::long()))), + var => Err(WITErr::new(&var, Bitpix::long()).into()), } } - pub fn as_owned_f32_array(self) -> Result, Box> { + pub fn as_owned_f32_array(self) -> Result> { match self { Self::SpfImg(img) => Ok(img.get_data_owned()), - var => Err(Box::new(WITErr::new(&var, Bitpix::spf()))), + var => Err(WITErr::new(&var, Bitpix::spf()).into()), } } - pub fn as_owned_f64_array(self) -> Result, Box> { + pub fn as_owned_f64_array(self) -> Result> { match self { Self::DpfImg(img) => Ok(img.get_data_owned()), - var => Err(Box::new(WITErr::new(&var, Bitpix::dpf()))), + var => Err(WITErr::new(&var, Bitpix::dpf()).into()), } } } diff --git a/src/extensions/table/ascii_table.rs b/src/extensions/table/ascii_table.rs index f53fa99..f69cf79 100644 --- a/src/extensions/table/ascii_table.rs +++ b/src/extensions/table/ascii_table.rs @@ -22,6 +22,8 @@ use std::{ fmt::{self, Display, Formatter}, }; +use anyhow::Result; + use crate::{ extensions::ExtensionPrint, raw::{table_entry_format::TableEntryFormat, BlockSized}, @@ -138,10 +140,10 @@ impl AsciiTable { AsciiTable { cols: cols, block_size: Some(size) } } - pub(crate) fn add_row(&mut self, row: Vec) -> Result<(), Box> { + pub(crate) fn add_row(&mut self, row: Vec) -> Result<()> { //Adds row to table if row.len() != self.cols.len() { - return Err(Box::new(ShapeMisMatchErr::new(&row, &self))); + return Err(ShapeMisMatchErr::new(&row, &self).into()); } //Add row to the table diff --git a/src/extensions/table/ascii_tbl_parser.rs b/src/extensions/table/ascii_tbl_parser.rs index 53f0561..70107c9 100644 --- a/src/extensions/table/ascii_tbl_parser.rs +++ b/src/extensions/table/ascii_tbl_parser.rs @@ -26,6 +26,8 @@ use std::{ str::{self, Utf8Error}, }; +use anyhow::Result; + use crate::{ extensions::{table::column::AsciiCol, Extension}, raw::{ @@ -49,7 +51,7 @@ impl AsciiTblParser { row_index_col_start: Vec, //row index where each column starts field_format: Vec, //data format (incl length) of each field field_labels: Option>, //field labels - ) -> Result> { + ) -> Result { /* (1) Tables are usually pretty small compared to images. Hence it's probably ok to read the whole table in one go. We should be careful @@ -190,7 +192,7 @@ impl AsciiTblParser { pub(crate) fn encode_tbl( tbl: AsciiTable, writer: &mut RawFitsWriter, - ) -> Result<(), Box> { + ) -> Result<()> { /* Note: This parser assumes that certain necessary keywords to decode a HDU containing a table have already been set while encoding the header diff --git a/src/fits.rs b/src/fits.rs index 5d15f2f..49274b4 100644 --- a/src/fits.rs +++ b/src/fits.rs @@ -27,6 +27,7 @@ use std::{ fmt::{Display, Formatter}, path::Path, }; +use anyhow::Result; use crate::{ header_data_unit::HeaderDataUnit, @@ -42,7 +43,7 @@ pub struct Fits { } impl Fits { - pub fn open(path: &Path) -> Result> { + pub fn open>(path: P) -> Result { //(1) Construct a RawFitsReader let mut reader = RawFitsReader::new(path)?; @@ -57,7 +58,7 @@ impl Fits { Ok(Fits { hdus: hdus }) } - pub fn write(self, path: &Path) -> Result<(), Box> { + pub fn write(self, path: &Path) -> Result<()> { //(1) Construct a RawFitsWriter let mut writer = RawFitsWriter::new(path)?; diff --git a/src/header.rs b/src/header.rs index 817734c..23df2ae 100644 --- a/src/header.rs +++ b/src/header.rs @@ -24,6 +24,8 @@ use std::{ str::FromStr, }; +use anyhow::Result; + use chrono::{Datelike, Utc}; use indexmap::IndexMap; @@ -50,7 +52,7 @@ pub struct Header { } impl Header { - pub fn decode_header(raw: &mut RawFitsReader) -> Result> { + pub fn decode_header(raw: &mut RawFitsReader) -> Result { /* Setup: We'll keep reading headerblocks (= FITS blocks) until we encounter the END keyword. We'll also have to keep track of the block size of @@ -75,7 +77,7 @@ impl Header { Ok(Self::from_parts(hbs, block_len)?) } - fn from_parts(hbs: Vec, block_len: usize) -> Result> { + fn from_parts(hbs: Vec, block_len: usize) -> Result { //Parse the Keywordrecords to plain Key-Data pairs let mut parsed_map: IndexMap, KeywordRecord> = IndexMap::new(); @@ -116,7 +118,7 @@ impl Header { Ok(Header { records: parsed_map, block_len: block_len }) } - pub fn encode_header(self, writer: &mut RawFitsWriter) -> Result<(), Box> { + pub fn encode_header(self, writer: &mut RawFitsWriter) -> Result<()> { //Buffer to write whole header in one go. //Also keeps track of number of bytes we wrote to the header! let mut buf = Vec::new(); @@ -207,10 +209,10 @@ impl Header { } //Helper function for parsing keyword records - pub fn get_value_as(&self, keyword: &str) -> Result> + pub fn get_value_as(&self, keyword: &str) -> Result where T: FromStr, - ::Err: 'static + Error, + ::Err: 'static + Error + Send + Sync, { match self.get_value(&keyword.to_string()) { None => Err(MissingRecordError::new(keyword))?, diff --git a/src/header_data_unit.rs b/src/header_data_unit.rs index 8b31c86..08da23e 100644 --- a/src/header_data_unit.rs +++ b/src/header_data_unit.rs @@ -19,6 +19,7 @@ use core::fmt; use std::{borrow::Cow, error::Error, fmt::Display}; +use anyhow::Result; use crate::{ bitpix::Bitpix, @@ -44,7 +45,7 @@ impl HeaderDataUnit { INTERNAL CODE */ - pub(crate) fn decode_hdu(raw: &mut RawFitsReader) -> Result> { + pub(crate) fn decode_hdu(raw: &mut RawFitsReader) -> Result { //(1) Read the header let header = Header::decode_header(raw)?; @@ -84,7 +85,7 @@ impl HeaderDataUnit { Ok(HeaderDataUnit { header: header, data: extension }) } - fn read_table(raw: &mut RawFitsReader, header: &Header) -> Result> { + fn read_table(raw: &mut RawFitsReader, header: &Header) -> Result { /* To parse a table we need to know the following keywords: TFIELDS => #fields in a row @@ -163,7 +164,7 @@ impl HeaderDataUnit { ttype_keyword.pop(); header.get_value_as(ttype_keyword.trim()) }) - .collect::, Box>>()?, + .collect::>>()?, ) } }; @@ -183,7 +184,7 @@ impl HeaderDataUnit { Ok(tbl) } - fn read_img(raw: &mut RawFitsReader, header: &Header) -> Result> { + fn read_img(raw: &mut RawFitsReader, header: &Header) -> Result { //Let's start by getting the number of axes from the NAXIS keyword let naxis: usize = header.get_value_as("NAXIS")?; @@ -200,7 +201,7 @@ impl HeaderDataUnit { Ok(ImgParser::decode_img(raw, &axes, bitpix)?) } - pub(crate) fn encode_hdu(self, writer: &mut RawFitsWriter) -> Result<(), Box> { + pub(crate) fn encode_hdu(self, writer: &mut RawFitsWriter) -> Result<()> { //(1) Write header self.header.encode_header(writer)?; diff --git a/src/intern.rs b/src/intern.rs index 67aef67..7722f10 100644 --- a/src/intern.rs +++ b/src/intern.rs @@ -1,6 +1,8 @@ //Std imports use std::error::Error; +use anyhow::Result; + //external imports use rustronomy_core::universal_containers::*; @@ -27,7 +29,7 @@ pub struct FitsOptions { pub fn read_primary_hdu( reader: &mut FitsReader, -) -> Result<(meta_only::MetaOnly, Hdu), Box> { +) -> Result<(meta_only::MetaOnly, Hdu)> { //Max. number of records in a FITS block const MAX_RECS: usize = crate::BLOCK_SIZE / crate::RECORD_SIZE; diff --git a/src/raw/header_block.rs b/src/raw/header_block.rs index 254603e..d54adca 100644 --- a/src/raw/header_block.rs +++ b/src/raw/header_block.rs @@ -18,6 +18,7 @@ */ use std::error::Error; +use anyhow::Result; use crate::header_err::{self, HeaderBlockBufferErr as HBBErr}; @@ -66,14 +67,14 @@ impl HeaderBlock { return Ok((HeaderBlock { records: records }, is_final)); } - pub(crate) fn encode_fill_buff(self, buf: &mut Vec) -> Result<(), Box> { + pub(crate) fn encode_fill_buff(self, buf: &mut Vec) -> Result<()> { for record in self.records { record.encode_fill_buff(buf)?; } Ok(()) } - pub(crate) fn encode_to_bytes(self) -> Result, Box> { + pub(crate) fn encode_to_bytes(self) -> Result> { //Fill buf with data let mut buf: Vec = Vec::new(); self.encode_fill_buff(&mut buf)?; @@ -84,7 +85,7 @@ impl HeaderBlock { buf.append(&mut vec![0u8; 2880 - buf.len()]); return Ok(buf); } else if buf.len() > 2880 { - return Err(Box::new(HBBErr::new(header_err::BUFFER_LEN))); + return Err(HBBErr::new(header_err::BUFFER_LEN).into()); } else { return Ok(buf); } diff --git a/src/raw/keyword_record.rs b/src/raw/keyword_record.rs index dc3bd5e..e70c811 100644 --- a/src/raw/keyword_record.rs +++ b/src/raw/keyword_record.rs @@ -23,6 +23,7 @@ use std::{ rc::Rc, str, }; +use anyhow::Result; use crate::keyword_err::{self, KeywordRecordBufferErr as KRBufErr, ProtectedKeywordErr as PKWErr}; use rustronomy_core::data_type_traits::io_utils::Encode; @@ -193,7 +194,7 @@ impl KeywordRecord { }) } - pub(crate) fn encode_fill_buff(self, buf: &mut Vec) -> Result<(), Box> { + pub(crate) fn encode_fill_buff(self, buf: &mut Vec) -> Result<()> { //keep track of how long the last keyword is let mut one_rec_buf = Vec::new(); diff --git a/src/raw/raw_io.rs b/src/raw/raw_io.rs index 575765b..28e5f14 100644 --- a/src/raw/raw_io.rs +++ b/src/raw/raw_io.rs @@ -24,6 +24,11 @@ use std::{ path::Path, }; +use anyhow::{ + bail, + Result +}; + use crate::io_err::{self, InvalidFitsFileErr}; //Get block size from root @@ -46,7 +51,7 @@ pub struct RawFitsReader { } impl RawFitsReader { - pub(crate) fn new(path: &Path) -> Result> { + pub(crate) fn new>(path: P) -> Result { //(1) Open the file let f = File::open(path)?; @@ -55,7 +60,7 @@ impl RawFitsReader { if meta.len() as usize % BLOCK_SIZE != 0 { //Throw an error for files that are not integer multiples of 2880 - return Err(Box::new(InvalidFitsFileErr::new(io_err::FILE_BLOCK_DIV))); + return Err(InvalidFitsFileErr::new(io_err::FILE_BLOCK_DIV).into()); } let n_blocks = meta.len() as usize / BLOCK_SIZE; @@ -102,7 +107,7 @@ pub struct RawFitsWriter { } impl RawFitsWriter { - pub(crate) fn new(path: &Path) -> Result> { + pub(crate) fn new(path: &Path) -> Result { //(1) Open the file if it exists, create it if it doesn't let out = File::create(path)?; @@ -113,10 +118,10 @@ impl RawFitsWriter { Ok(RawFitsWriter { file_meta: meta, writer_handle: out }) } - pub(crate) fn write_blocks(&mut self, buffer: &[u8]) -> Result> { + pub(crate) fn write_blocks(&mut self, buffer: &[u8]) -> Result { //(1) Check if the buffer is an integer number of FITS blocks if buffer.len() % BLOCK_SIZE != 0 { - return Err(Box::new(InvalidFitsFileErr::new(io_err::BUF_BLOCK_DIV))); + return Err(InvalidFitsFileErr::new(io_err::BUF_BLOCK_DIV).into()); } //(2) Write the thing From f8464a6125da968b5dc4c41de66a4c62cdf7533a Mon Sep 17 00:00:00 2001 From: Berke DURAK Date: Fri, 9 Aug 2024 12:30:56 +0200 Subject: [PATCH 2/3] Add get_hdus() --- src/fits.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/fits.rs b/src/fits.rs index 49274b4..764c5c7 100644 --- a/src/fits.rs +++ b/src/fits.rs @@ -84,6 +84,10 @@ impl Fits { } Some(self.hdus.remove(index)) } + + pub fn get_hdus(&self)->&[HeaderDataUnit] { + &self.hdus + } } impl BlockSized for Fits { From 862ad61aee944b280d1a14622075e3c38c6bba89 Mon Sep 17 00:00:00 2001 From: Berke DURAK Date: Fri, 9 Aug 2024 12:42:44 +0200 Subject: [PATCH 3/3] Silence warnings about dead code and unused imports and variables; implement Display for Image and GenericImage --- src/extensions/image/generic_image.rs | 15 +++++++++++++++ src/extensions/image/typed_image.rs | 12 ++++++++++-- src/lib.rs | 4 ++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/extensions/image/generic_image.rs b/src/extensions/image/generic_image.rs index bacd390..6630675 100644 --- a/src/extensions/image/generic_image.rs +++ b/src/extensions/image/generic_image.rs @@ -49,6 +49,21 @@ where } } +impl Display for Image +where + T: Debug + Num + Sized + Decode + Encode + Display + Clone, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for (i,&n) in self.shape.iter().enumerate() { + if i > 0 { + write!(f,"x")?; + } + write!(f,"{}",n)?; + } + write!(f,"/{}",self.block_size) + } +} + impl Image where T: Debug + Num + Sized + Decode + Encode + Display + Clone, diff --git a/src/extensions/image/typed_image.rs b/src/extensions/image/typed_image.rs index 2a4eb6a..c8fc334 100644 --- a/src/extensions/image/typed_image.rs +++ b/src/extensions/image/typed_image.rs @@ -109,8 +109,16 @@ impl ExtensionPrint for TypedImage { impl Display for TypedImage { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - //TODO: make pretty display for image! - todo!() + write!(f,"TypedImage(")?; + match self { + Self::ByteImg(img) => write!(f,"u16,{}",img)?, + Self::I16Img(img)=> write!(f,"i16,{}",img)?, + Self::I32Img(img)=> write!(f,"i32,{}",img)?, + Self::I64Img(img)=> write!(f,"i64,{}",img)?, + Self::SpfImg(img)=> write!(f,"f32,{}",img)?, + Self::DpfImg(img)=> write!(f,"f64,{}",img)?, + } + write!(f,")") } } diff --git a/src/lib.rs b/src/lib.rs index 5195d09..e2ea660 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,10 @@ along with rustronomy. If not, see . */ +#![allow(dead_code)] +#![allow(unused_imports)] +#![allow(unused_variables)] + //Module structure mod bitpix; mod err;