Skip to main content

atlas/
config.rs

1/// Compression codec applied when writing new array blocks.
2///
3/// The codec is stored per-variable in `atlas.json` so that each array
4/// can be reopened with the correct codec regardless of the store-level default.
5/// Existing blocks are always decompressed using whatever codec they were
6/// originally written with, so the choice only affects the write path.
7///
8/// Also reused for metadata compression via
9/// [`StoreConfig::meta_compression`] — the same three options apply.
10#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
11pub enum Codec {
12    /// Zstd compression (default). Best compression ratio at moderate speed.
13    #[default]
14    Zstd,
15    /// LZ4 compression. Faster than Zstd, larger files.
16    Lz4,
17    /// No compression. Fastest write path, no size reduction.
18    Uncompressed,
19}
20
21/// On-disk encoding for the store's metadata file.
22///
23/// The format choice lives in the filename (`atlas.json` vs `atlas.msgpack`,
24/// with optional `.zst` / `.lz4` suffix) rather than inside the file, so
25/// [`crate::Atlas::open`] can detect it without a caller-supplied hint.
26#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
27pub enum MetaFormat {
28    /// Pretty-printed JSON (`atlas.json`). Human-readable, default for
29    /// backwards compatibility with stores created before this option existed.
30    #[default]
31    Json,
32    /// MessagePack (`atlas.msgpack`). Compact binary encoding — typically
33    /// 30–50% smaller than JSON and faster to parse, but not human-readable.
34    MsgPack,
35}
36
37impl MetaFormat {
38    /// Filename used for this format / compression pair. All six combinations
39    /// resolve to a `&'static str` so the result can be passed straight to
40    /// [`object_store::path::Path::from`].
41    pub(crate) const fn filename(self, compression: Codec) -> &'static str {
42        match (self, compression) {
43            (MetaFormat::Json, Codec::Uncompressed) => "atlas.json",
44            (MetaFormat::Json, Codec::Zstd) => "atlas.json.zst",
45            (MetaFormat::Json, Codec::Lz4) => "atlas.json.lz4",
46            (MetaFormat::MsgPack, Codec::Uncompressed) => "atlas.msgpack",
47            (MetaFormat::MsgPack, Codec::Zstd) => "atlas.msgpack.zst",
48            (MetaFormat::MsgPack, Codec::Lz4) => "atlas.msgpack.lz4",
49        }
50    }
51}
52
53/// The six (format, compression) pairs in priority order — used by `open`
54/// to disambiguate when multiple metadata files happen to coexist.
55/// Uncompressed comes before compressed within each format, and JSON comes
56/// before MsgPack overall (preserving the existing "JSON wins if both
57/// exist" precedent from the format-detection logic).
58pub(crate) const META_VARIANTS: [(MetaFormat, Codec); 6] = [
59    (MetaFormat::Json, Codec::Uncompressed),
60    (MetaFormat::Json, Codec::Zstd),
61    (MetaFormat::Json, Codec::Lz4),
62    (MetaFormat::MsgPack, Codec::Uncompressed),
63    (MetaFormat::MsgPack, Codec::Zstd),
64    (MetaFormat::MsgPack, Codec::Lz4),
65];
66
67/// Configuration for opening or creating an [`Atlas`](crate::Atlas).
68#[derive(Debug, Clone)]
69pub struct StoreConfig {
70    /// Compression codec used when writing array blocks. Defaults to [`Codec::Zstd`].
71    pub codec: Codec,
72    /// On-disk encoding for the metadata file. Defaults to [`MetaFormat::Json`].
73    /// Only consulted by `create`; `open` detects the format from the filename
74    /// present on disk.
75    pub meta_format: MetaFormat,
76    /// Compression applied to the encoded metadata bytes. Defaults to
77    /// [`Codec::Uncompressed`] so the on-disk filename matches the format
78    /// (`atlas.json` / `atlas.msgpack`). Only consulted by `create`; `open`
79    /// detects compression from the filename suffix on disk.
80    pub meta_compression: Codec,
81}
82
83// Manual Default — `meta_compression` defaults to `Uncompressed`, not
84// `Codec::default()` (which is `Zstd`), so new stores keep the legacy
85// `atlas.json` / `atlas.msgpack` filenames unless the caller opts in.
86impl Default for StoreConfig {
87    fn default() -> Self {
88        Self {
89            codec: Codec::default(),
90            meta_format: MetaFormat::default(),
91            meta_compression: Codec::Uncompressed,
92        }
93    }
94}