fits_well/lib.rs
1//! A blazing-fast reader and writer for **FITS** (Flexible Image Transport
2//! System) files — the standard data format of astronomy.
3//!
4//! # Layering
5//!
6//! The format's structure maps onto a stack of layers, so the hot decode path
7//! stays lean and the semantic layers compute only on demand. WCS (§8) and time
8//! (§9) are dependency-free pure math, always compiled and surfaced directly as
9//! [`Header`] getters ([`Header::wcs`], [`Header::time`]); tiled compression carries
10//! a dependency and stays behind the `compression` feature.
11//!
12//! ```text
13//! bytes ─► block layer ─► HDU layer ─► header model ─► typed data
14//! (2880 grid, (boundary (ordered (images,
15//! padding, scan, lazy records + tables,
16//! I/O quantum) seeking) keyword index) heap, VLAs)
17//! ```
18//!
19//! - [`BLOCK_SIZE`] — the 2880-byte block grid, padding rules, and rounding math.
20//! - [`Bitpix`] — the array element type selector (`BITPIX`).
21//! - [`Header`], [`Value`] — an *ordered* header model (an internal `Card` list)
22//! that round-trips byte-for-byte, with a side index for O(1) keyword lookup; it
23//! also parses the WCS and time layers on request ([`Header::wcs`]/[`Header::time`]).
24//! - [`HduKind`] — HDU classification and the data-unit sizing formula that makes
25//! boundaries computable from headers alone (no data read required).
26//! - [`FitsReader`] — lazy, seeking access to the HDU sequence of a file.
27//!
28//! # Status
29//!
30//! The structural spine (blocks, headers, HDU boundaries, lazy reading) plus
31//! typed image decode/encode ([`Image`]), the multi-HDU writer ([`FitsWriter`]),
32//! ASCII/binary tables, WCS, time coordinates, and tiled image+table compression
33//! are implemented and tested — see each module's docs for its design.
34#![cfg_attr(docsrs, feature(doc_cfg))]
35
36mod ascii;
37mod bitpix;
38mod block;
39mod checksum;
40#[cfg(feature = "compression")]
41mod compress;
42mod data;
43mod endian;
44mod error;
45mod groups;
46mod hdu;
47mod header;
48mod keyword;
49mod reader;
50mod table;
51mod time;
52mod wcs;
53mod writer;
54
55pub use ascii::{AsciiColumn, AsciiColumnReader, AsciiKind, AsciiTable};
56pub use bitpix::Bitpix;
57
58/// Re-exported so callers can name the borrowed [`bitvec::slice::BitSlice`] rows that
59/// a [`BitColumn`] (from [`ColumnReader::bits`]/[`ColumnReader::vla_bits`]) yields —
60/// to index, iterate, or `.to_bitvec()` them — without taking their own
61/// version-skewed `bitvec` dependency.
62pub use bitvec;
63#[cfg(feature = "compression")]
64pub use compress::{CompressOptions, DitherMethod};
65#[cfg(feature = "ndarray")]
66pub use data::ImageArray;
67pub use data::{Image, ImageData, ImageView, RawImage, SampleType, Scaling, UnsignedView};
68pub use error::{FitsError, Result};
69pub use groups::RandomGroups;
70pub use hdu::HduKind;
71pub use header::Header;
72pub use header::HeaderEntry;
73pub use header::value::Value;
74/// The complex element type of `C`/`M` columns — the ecosystem-standard
75/// [`num_complex::Complex`]. Re-exported (crate and type) so callers can name it and
76/// stay on the same version this crate returns.
77pub use num_complex;
78pub use num_complex::Complex;
79#[cfg(feature = "mmap")]
80pub use reader::MmapReader;
81#[cfg(feature = "mmap")]
82pub use reader::source::MmapSource;
83pub use reader::source::{SliceSource, Source, StreamSource};
84pub use reader::{ChecksumReport, DataUnit, FitsReader, Hdu, SliceReader, StreamReader};
85pub use table::{
86 BinTable, BitColumn, Column, ColumnData, ColumnReader, TDisp, TDispKind, Tform, TformKind,
87};
88pub use time::{
89 Datetime, Epoch, EpochTime, FitsTime, GtiInterval, PhaseAxis, TimeAxisKind, TimeBounds,
90 TimeScale,
91};
92pub use wcs::{Projection, Wcs};
93pub use writer::{AsciiWriteColumn, FitsWriter, WriteColumn};
94
95pub use block::{BLOCK_SIZE, CARD_SIZE};
96
97/// Hot internal entry points re-exposed **for benchmarking only** (the `internals`
98/// feature). These wrap crate-private functions so the benches under `benches/`
99/// can measure them in isolation; they are **not** a stable API — do not depend on
100/// them.
101#[cfg(feature = "internals")]
102pub mod internals {
103 use crate::bitpix::Bitpix;
104 use crate::data::ImageData;
105
106 /// Decode a big-endian data unit into host-endian samples — the per-element
107 /// byte-swap (`ImageData::decode`).
108 pub fn decode_image(bytes: &[u8], bitpix: Bitpix) -> ImageData {
109 ImageData::decode(bytes, bitpix)
110 }
111
112 /// Encode samples back to a big-endian buffer — the inverse swap
113 /// (`ImageData::encode_into` into a fresh buffer).
114 pub fn encode_image(data: &ImageData) -> Vec<u8> {
115 let mut out = Vec::new();
116 data.encode_into(&mut out);
117 out
118 }
119}