1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use ;
/// Compact, self-contained encoding of **all** encryption-time settings —
/// suitable for plaintext storage within a ciphertext header.
///
/// Produced by [`pack`] and supplied to [`timelock`](super::timelock) or
/// [`timelock_async`](super::timelock_async) as `params: Some(header)` on the
/// **decryption side**. Only the cadence variant discriminant is recorded; the
/// actual calendar values (weekday, day-of-month, month) are not stored and
/// are instead read from the live system clock during decryption.
///
/// | Field | Encoding / Notes |
/// |--------------------|-----------------------------------------------------------|
/// | `time_precision` | `0`=Hour · `1`=Quarter · `2`=Minute |
/// | `time_format` | `0`=12 hr (`Hour12`) · `1`=24 hr (`Hour24`) |
/// | `cadence_variant` | `0`=None · `1`=DayOfWeek · `2`=DayOfMonth |
/// | | `3`=MonthOfYear · `4`=DayOfWeekInMonth |
/// | | `5`=DayOfMonthInMonth · `6`=DayOfWeekAndDayOfMonth |
/// | `salts` | Three 32-byte salts (not secret; prevent precomputation) |
/// | `kdf_params` | Argon2id + scrypt work factors |
/// Encode [`TimePrecision`], [`TimeFormat`], and a [`TimeLockCadence`] reference
/// into a compact [`TimeLockParams`] for storage in a ciphertext header.
///
/// Only the **variant discriminant** of `cadence` is recorded; the actual day,
/// weekday, or month values are intentionally discarded.
///
/// # Example
///
/// ```no_run
/// # use toolkit_zero::encryption::timelock::*;
/// let salts = TimeLockSalts::generate();
/// let kdf = KdfPreset::Balanced.params();
/// let p = pack(
/// TimePrecision::Minute,
/// TimeFormat::Hour24,
/// &TimeLockCadence::DayOfWeek(Weekday::Tuesday),
/// salts,
/// kdf,
/// );
/// // p.time_precision == 2, p.time_format == 1, p.cadence_variant == 1
/// ```
/// Decode a [`TimeLockParams`] into its constituent [`TimePrecision`],
/// [`TimeFormat`], and raw cadence variant discriminant.
///
/// The returned `u8` maps as follows:
/// `0` = None, `1` = DayOfWeek, `2` = DayOfMonth, `3` = MonthOfYear,
/// `4` = DayOfWeekInMonth, `5` = DayOfMonthInMonth, `6` = DayOfWeekAndDayOfMonth.
/// Any unrecognised value defaults to `0` (None).
///
/// # Example
///
/// ```no_run
/// # use toolkit_zero::encryption::timelock::*;
/// let params = pack(
/// TimePrecision::Minute,
/// TimeFormat::Hour24,
/// &TimeLockCadence::DayOfWeekInMonth(Weekday::Tuesday, Month::February),
/// TimeLockSalts::generate(),
/// KdfPreset::Balanced.params(),
/// );
/// let (precision, format, variant) = unpack(¶ms);
/// // precision == TimePrecision::Minute, format == TimeFormat::Hour24, variant == 4
/// ```