Skip to main content

deep_time/time_parts/
to_bin_ccsds.rs

1use crate::{Dt, DtErr, TimeParts};
2
3impl TimeParts {
4    /// Formats this [`TimeParts`] as a **CCSDS C (CUC)** binary time code.
5    ///
6    /// - Fully configurable for round-tripping with [`from_ccsds_c`].
7    /// - Conforms to **CCSDS 301.0-B-4 §3.2 (Level 1)**, including full support
8    ///   for the extended P-field (second octet) when `n_coarse > 4` or `n_frac > 3`.
9    ///
10    /// ## Parameters
11    ///
12    /// - `n_coarse`: 1–7 (number of coarse-time octets)
13    /// - `n_frac`:   0–10 (number of fractional octets)
14    /// - `extension`: advisory flag (ignored when larger sizes force the second octet)
15    #[inline]
16    pub fn to_ccsds_c(
17        &self,
18        n_coarse: u8,
19        n_frac: u8,
20        extension: bool,
21    ) -> Result<([u8; Dt::CCSDS_C_AND_D_MAX_SIZE], usize), DtErr> {
22        self.to_dt()?.to_ccsds_c(n_coarse, n_frac, extension)
23    }
24
25    /// Formats this [`TimeParts`] as a **CCSDS D (CDS)** binary time code.
26    ///
27    /// - Fully configurable for round-tripping with [`from_ccsds_d`].
28    /// - Conforms to CCSDS 301.0-B-4 §3.3 (Level 1): UTC day count + ms-of-day since
29    ///   1958-01-01 UTC.
30    #[inline]
31    pub fn to_ccsds_d(
32        &self,
33        n_day: u8,
34        sub_ms_code: u8,
35        extension: bool,
36    ) -> Result<([u8; Dt::CCSDS_C_AND_D_MAX_SIZE], usize), DtErr> {
37        self.to_dt()?.to_ccsds_d(n_day, sub_ms_code, extension)
38    }
39
40    /// Formats this [`TimeParts`] as a **CCSDS CCS (Calendar Segmented Time Code)**.
41    ///
42    /// Implements **CCSDS 301.0-B-4 §3.4** (Level 1 only).
43    ///
44    /// ## Parameters
45    ///
46    /// - `use_doy`: `false` = Month/Day variant (most common), `true` = Day-of-Year variant
47    /// - `n_subsec`: Number of subsecond BCD octets (`0`–`6`). Each octet holds 2 decimal digits.
48    ///
49    /// ## Returns
50    ///
51    /// `(buffer, written_len)` — the P-field + T-field (big-endian BCD).
52    ///
53    /// ## Precision & Rounding
54    ///
55    /// Fractional seconds are rounded to the nearest representable value at the chosen precision
56    /// (exactly as `to_ccsds_d` does for milliseconds).
57    #[inline]
58    pub fn to_ccsds_ccs(
59        &self,
60        use_doy: bool,
61        n_subsec: u8,
62    ) -> Result<([u8; Dt::CCSDS_CCS_MAX_SIZE], usize), DtErr> {
63        self.to_dt()?.to_ccsds_ccs(use_doy, n_subsec)
64    }
65
66    /// Convenience method that automatically selects the most appropriate
67    /// CCSDS binary time code based on this `TimeParts`’s [`Scale`].
68    ///
69    /// ## Automatic selection (matches common mission practice)
70    ///
71    /// - `Scale::TAI` → **CUC** (4 coarse + 4 fractional bytes)
72    /// - Any other `Scale` (UTC, TT, GPS, TCG, …) → converted to UTC and uses **CDS**
73    ///   (2 day bytes + 4 ms bytes + 2-byte sub-ms)
74    #[inline]
75    pub fn to_ccsds_bin(&self) -> Result<([u8; Dt::CCSDS_C_AND_D_MAX_SIZE], usize), DtErr> {
76        self.to_dt()?.to_ccsds_bin()
77    }
78}