pleiades_compression/lib.rs
1//! Compression codecs and artifact packing helpers for ephemeris data.
2//!
3//! The current implementation defines a small, deterministic artifact format
4//! with explicit versioning, checksums, artifact capability profiles, and
5//! quantized polynomial segments. Optional residual-correction channels are
6//! also supported so denser artifacts can keep a compact base fit while
7//! layering deterministic corrections on top. The format is intentionally
8//! simple enough to audit while still exercising the same segmented lookup flow
9//! and random-access body/segment helpers that later, denser artifacts will use.
10//! See `spec/data-compression.md` for the stored-vs-derived output contract and
11//! `docs/time-observer-policy.md` for the explicit packaged lookup policy that
12//! keeps derived coordinates separate from observer-driven body-position modes.
13//!
14//! Enable the optional `serde` feature to serialize compressed artifacts for
15//! inspection or interchange workflows.
16//!
17//! # Examples
18//!
19//! ```
20//! use pleiades_compression::{ArtifactHeader, BodyArtifact, ChannelKind, CompressedArtifact,
21//! PolynomialChannel, Segment, ARTIFACT_VERSION};
22//! use pleiades_types::{CelestialBody, Instant, JulianDay, TimeScale};
23//!
24//! let artifact = CompressedArtifact::new(
25//! ArtifactHeader::new("demo", "synthetic example data"),
26//! vec![BodyArtifact::new(
27//! CelestialBody::Sun,
28//! vec![Segment::new(
29//! Instant::new(JulianDay::from_days(0.0), TimeScale::Tt),
30//! Instant::new(JulianDay::from_days(1.0), TimeScale::Tt),
31//! vec![PolynomialChannel::linear(ChannelKind::Longitude, 9, 10.0, 11.0)],
32//! )],
33//! )],
34//! );
35//! assert_eq!(artifact.header.version, ARTIFACT_VERSION);
36//! ```
37
38#![forbid(unsafe_code)]
39#![deny(missing_docs)]
40
41use core::fmt;
42
43pub(crate) mod artifact;
44pub(crate) mod channels;
45pub(crate) mod codec;
46pub(crate) mod error;
47pub(crate) mod format;
48mod frame_recombine;
49
50// ── Public re-exports (preserve exact prior public surface) ───────────────────
51
52pub use artifact::CompressedArtifact;
53pub use channels::{BodyArtifact, ChannelKind, PolynomialChannel, Segment, StoredFrame};
54pub use error::{CompressionError, CompressionErrorKind};
55pub use format::{
56 ArtifactHeader, ArtifactOutput, ArtifactOutputSupport, ArtifactProfile,
57 ArtifactProfileCoverageSummary, ArtifactResidualBodyCoverageSummary, EndianPolicy, SpeedPolicy,
58};
59pub use frame_recombine::{
60 cartesian_au_to_ecliptic, cartesian_state_to_spherical, ecliptic_to_cartesian_au,
61 geocentric_from_heliocentric, heliocentric_from_geocentric, spherical_state_to_cartesian,
62 CartesianState, SphericalState,
63};
64
65// ── Crate-level constants ─────────────────────────────────────────────────────
66
67/// Current artifact format version.
68pub const ARTIFACT_VERSION: u16 = 7;
69
70pub(crate) const ARTIFACT_MAGIC: [u8; 8] = *b"PLDEPHEM";
71
72// ── Public formatting helper ──────────────────────────────────────────────────
73
74/// Joins displayable values into a compact comma-separated list.
75///
76/// This helper is used by release-facing summaries that need a stable,
77/// human-readable body or capability listing without introducing an extra
78/// formatting dependency in downstream crates.
79pub fn join_display<T: fmt::Display>(values: &[T]) -> String {
80 values
81 .iter()
82 .map(ToString::to_string)
83 .collect::<Vec<_>>()
84 .join(", ")
85}
86
87#[cfg(test)]
88mod tests;