Skip to main content

fib_quant/
receipt.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    codebook::CODEBOOK_SCHEMA,
5    codec::CODE_SCHEMA,
6    profile::{FibQuantProfileV1, NormFormat, PROFILE_SCHEMA},
7    rotation::ROTATION_ALGORITHM_VERSION,
8};
9
10pub const RECEIPT_SCHEMA: &str = "fib_quant_compression_receipt_v1";
11
12/// Compression receipt emitted by `encode_with_receipt`.
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub struct FibQuantCompressionReceiptV1 {
15    /// Stable schema marker.
16    pub schema_version: String,
17    /// Profile digest.
18    pub profile_digest: String,
19    /// Codebook digest.
20    pub codebook_digest: String,
21    /// Rotation digest.
22    pub rotation_digest: String,
23    /// Digest over the canonical source vector bytes.
24    pub source_vector_digest: String,
25    /// Encoded payload digest.
26    pub encoded_digest: String,
27    /// Norm payload format used by the encoded artifact.
28    pub norm_format: NormFormat,
29    /// Encoded artifact schema marker.
30    pub code_schema_version: String,
31    /// Profile schema marker.
32    pub profile_schema_version: String,
33    /// Codebook schema marker.
34    pub codebook_schema_version: String,
35    /// Ambient dimension `d`.
36    pub ambient_dim: u32,
37    /// Block dimension `k`.
38    pub block_dim: u32,
39    /// Codebook size `N`.
40    pub codebook_size: u32,
41    /// Paper rate.
42    pub paper_rate_bits_per_coord: f64,
43    /// Wire index bits.
44    pub wire_index_bits: u8,
45    /// Wire rate.
46    pub wire_bits_per_coord: f64,
47    /// Rotation seed.
48    pub rotation_seed: u64,
49    /// Rotation algorithm identity.
50    pub rotation_algorithm_version: String,
51    /// Codebook seed.
52    pub codebook_seed: u64,
53    /// Optional reconstruction MSE if measured.
54    pub mse: Option<f64>,
55    /// Optional cosine similarity if measured.
56    pub cosine_similarity: Option<f64>,
57    /// Whether a fallback codec was available.
58    pub fallback_available: bool,
59    /// Unix timestamp seconds, supplied by caller path.
60    pub recorded_unix_seconds: i64,
61}
62
63impl FibQuantCompressionReceiptV1 {
64    pub(crate) fn new(
65        profile: &FibQuantProfileV1,
66        profile_digest: String,
67        codebook_digest: String,
68        rotation_digest: String,
69        source_vector_digest: String,
70        encoded_digest: String,
71    ) -> Self {
72        Self {
73            schema_version: RECEIPT_SCHEMA.into(),
74            profile_digest,
75            codebook_digest,
76            rotation_digest,
77            source_vector_digest,
78            encoded_digest,
79            norm_format: profile.norm_format.clone(),
80            code_schema_version: CODE_SCHEMA.into(),
81            profile_schema_version: PROFILE_SCHEMA.into(),
82            codebook_schema_version: CODEBOOK_SCHEMA.into(),
83            ambient_dim: profile.ambient_dim,
84            block_dim: profile.block_dim,
85            codebook_size: profile.codebook_size,
86            paper_rate_bits_per_coord: profile.paper_rate_bits_per_coord,
87            wire_index_bits: profile.wire_index_bits,
88            wire_bits_per_coord: profile.wire_bits_per_coord,
89            rotation_seed: profile.rotation_seed,
90            rotation_algorithm_version: ROTATION_ALGORITHM_VERSION.into(),
91            codebook_seed: profile.codebook_seed,
92            mse: None,
93            cosine_similarity: None,
94            fallback_available: false,
95            recorded_unix_seconds: current_unix_seconds(),
96        }
97    }
98}
99
100fn current_unix_seconds() -> i64 {
101    std::time::SystemTime::now()
102        .duration_since(std::time::UNIX_EPOCH)
103        .map(|duration| duration.as_secs() as i64)
104        .unwrap_or(0)
105}