1use crate::{Error, Result, error::buffer_len};
2
3pub const FORMAT_VERSION: u8 = 1;
5pub const TAG_LEN: usize = 16;
7
8pub const AES_MAX_BYTES: u64 = 1 << 36;
11pub const AES_MAX_FRAMES: u64 = 1 << 32;
13pub const AES_MAX_FRAME_LEN: u64 = 1 << 24;
15
16#[derive(Clone, Copy, Debug, Eq, PartialEq)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub enum Framing {
20 Fixed(u64),
22 Variable(u64),
24}
25
26impl Framing {
27 pub const fn max_frame_len(self) -> u64 {
29 match self {
30 Self::Fixed(size) | Self::Variable(size) => size,
31 }
32 }
33}
34
35#[derive(Clone, Copy, Debug, Eq, PartialEq)]
37#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
38#[repr(u8)]
39pub enum Compression {
40 None = 0,
42 Lz4 = 1,
44}
45
46#[derive(Clone, Copy, Debug, Eq, PartialEq)]
48#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49#[repr(u8)]
50pub enum Encryption {
51 None = 0,
53 Aes256Gcm = 1,
55}
56
57impl Encryption {
58 pub const fn tag_len(self) -> usize {
60 match self {
61 Self::None => 0,
62 Self::Aes256Gcm => TAG_LEN,
63 }
64 }
65}
66
67#[derive(Clone, Copy, Debug, Eq, PartialEq)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize))]
70pub struct Config {
71 framing: Framing,
72 compression: Compression,
73 encryption: Encryption,
74}
75
76#[cfg(feature = "serde")]
77impl<'de> serde::Deserialize<'de> for Config {
78 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
79 where
80 D: serde::Deserializer<'de>,
81 {
82 #[derive(serde::Deserialize)]
83 struct Fields {
84 framing: Framing,
85 compression: Compression,
86 encryption: Encryption,
87 }
88
89 let fields = <Fields as serde::Deserialize>::deserialize(deserializer)?;
90 Self::new(fields.framing, fields.compression, fields.encryption)
91 .map_err(serde::de::Error::custom)
92 }
93}
94
95impl Config {
96 pub fn new(framing: Framing, compression: Compression, encryption: Encryption) -> Result<Self> {
99 let max = framing.max_frame_len();
100 if max == 0 {
101 return Err(Error::InvalidFrameSize);
102 }
103 buffer_len(
104 max.checked_add(encryption.tag_len() as u64)
105 .ok_or(Error::Overflow)?,
106 )?;
107 if compression == Compression::Lz4 && max > 0x7e00_0000 {
109 return Err(Error::InvalidFrameSize);
110 }
111 if encryption == Encryption::Aes256Gcm && max > AES_MAX_FRAME_LEN {
112 return Err(Error::InvalidFrameSize);
113 }
114 Ok(Self {
115 framing,
116 compression,
117 encryption,
118 })
119 }
120
121 pub const fn framing(self) -> Framing {
123 self.framing
124 }
125 pub const fn compression(self) -> Compression {
127 self.compression
128 }
129 pub const fn encryption(self) -> Encryption {
131 self.encryption
132 }
133 pub const fn max_frame_len(self) -> u64 {
135 self.framing.max_frame_len()
136 }
137
138 pub fn max_frames(self) -> u64 {
141 match self.encryption {
142 Encryption::None => u64::MAX,
143 Encryption::Aes256Gcm => AES_MAX_FRAMES.min(AES_MAX_BYTES / self.max_frame_len()),
144 }
145 }
146
147 pub(crate) fn validate_frame(self, index: u64, raw: u64, payload: u64) -> Result<()> {
148 if raw == 0 || raw > self.max_frame_len() {
149 return Err(Error::InvalidFrameSize);
150 }
151 if payload == 0
152 || payload > raw
153 || (self.compression == Compression::None && payload != raw)
154 {
155 return Err(Error::InvalidMetadata);
156 }
157 if index >= self.max_frames() {
158 return Err(Error::UsageLimit);
159 }
160 Ok(())
161 }
162}