1use crate::{Error, Result, error::buffer_len};
2
3pub const FORMAT_VERSION: u8 = 1;
5pub const METADATA_SCHEMA_VERSION: u16 = 2;
7pub const TAG_LEN: usize = 16;
9
10pub const AES_MAX_BYTES: u64 = 1 << 36;
13pub const AES_MAX_FRAMES: u64 = 1 << 32;
15pub const AES_MAX_FRAME_LEN: u64 = 1 << 24;
17
18#[derive(Clone, Copy, Debug, Eq, PartialEq)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub enum Framing {
22 Fixed(u64),
24 Variable(u64),
26}
27
28impl Framing {
29 pub const fn max_frame_len(self) -> u64 {
31 match self {
32 Self::Fixed(size) | Self::Variable(size) => size,
33 }
34 }
35}
36
37#[derive(Clone, Copy, Debug, Eq, PartialEq)]
39#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
40#[repr(u8)]
41pub enum Compression {
42 None = 0,
44 Lz4 = 1,
46}
47
48#[derive(Clone, Eq, PartialEq)]
50#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
51pub enum Encryption {
52 None,
54 Aes256Gcm {
56 key: [u8; 32],
58 },
59}
60
61impl std::fmt::Debug for Encryption {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 match self {
64 Self::None => f.write_str("None"),
65 Self::Aes256Gcm { .. } => f.write_str("Aes256Gcm { key: [REDACTED] }"),
66 }
67 }
68}
69
70impl Encryption {
71 pub const fn tag_len(&self) -> usize {
73 match self {
74 Self::None => 0,
75 Self::Aes256Gcm { .. } => TAG_LEN,
76 }
77 }
78}
79
80#[derive(Clone, Debug, Eq, PartialEq)]
82#[cfg_attr(feature = "serde", derive(serde::Serialize))]
83pub struct Config {
84 framing: Framing,
85 compression: Compression,
86 encryption: Encryption,
87}
88
89#[cfg(feature = "serde")]
90impl<'de> serde::Deserialize<'de> for Config {
91 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
92 where
93 D: serde::Deserializer<'de>,
94 {
95 #[derive(serde::Deserialize)]
96 struct Fields {
97 framing: Framing,
98 compression: Compression,
99 encryption: Encryption,
100 }
101
102 let fields = <Fields as serde::Deserialize>::deserialize(deserializer)?;
103 Self::new(fields.framing, fields.compression, fields.encryption)
104 .map_err(serde::de::Error::custom)
105 }
106}
107
108impl Config {
109 pub fn new(framing: Framing, compression: Compression, encryption: Encryption) -> Result<Self> {
112 let max = framing.max_frame_len();
113 if max == 0 {
114 return Err(Error::InvalidFrameSize);
115 }
116 buffer_len(
117 max.checked_add(encryption.tag_len() as u64)
118 .ok_or(Error::Overflow)?,
119 )?;
120 if compression == Compression::Lz4 && max > 0x7e00_0000 {
122 return Err(Error::InvalidFrameSize);
123 }
124 if matches!(encryption, Encryption::Aes256Gcm { .. }) && max > AES_MAX_FRAME_LEN {
125 return Err(Error::InvalidFrameSize);
126 }
127 Ok(Self {
128 framing,
129 compression,
130 encryption,
131 })
132 }
133
134 pub const fn framing(&self) -> Framing {
136 self.framing
137 }
138 pub const fn compression(&self) -> Compression {
140 self.compression
141 }
142 pub const fn encryption(&self) -> &Encryption {
144 &self.encryption
145 }
146 pub const fn max_frame_len(&self) -> u64 {
148 self.framing.max_frame_len()
149 }
150
151 pub fn max_frames(&self) -> u64 {
154 match &self.encryption {
155 Encryption::None => u64::MAX,
156 Encryption::Aes256Gcm { .. } => AES_MAX_BYTES
157 .checked_div(self.max_frame_len())
158 .map_or(0, |frames| AES_MAX_FRAMES.min(frames)),
159 }
160 }
161
162 pub(crate) fn validate_frame(&self, index: u64, raw: u64, payload: u64) -> Result<()> {
163 if raw == 0 || raw > self.max_frame_len() {
164 return Err(Error::InvalidFrameSize);
165 }
166 if payload == 0
167 || payload > raw
168 || (self.compression == Compression::None && payload != raw)
169 {
170 return Err(Error::InvalidMetadata);
171 }
172 if index >= self.max_frames() {
173 return Err(Error::UsageLimit);
174 }
175 Ok(())
176 }
177}