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)]
18pub enum Framing {
19 Fixed(u64),
21 Variable(u64),
23}
24
25impl Framing {
26 pub const fn max_frame_len(self) -> u64 {
28 match self {
29 Self::Fixed(size) | Self::Variable(size) => size,
30 }
31 }
32}
33
34#[derive(Clone, Copy, Debug, Eq, PartialEq)]
36#[repr(u8)]
37pub enum Compression {
38 None = 0,
40 Lz4 = 1,
42}
43
44#[derive(Clone, Copy, Debug, Eq, PartialEq)]
46#[repr(u8)]
47pub enum Encryption {
48 None = 0,
50 Aes256Gcm = 1,
52}
53
54impl Encryption {
55 pub const fn tag_len(self) -> usize {
57 match self {
58 Self::None => 0,
59 Self::Aes256Gcm => TAG_LEN,
60 }
61 }
62}
63
64#[derive(Clone, Copy, Debug, Eq, PartialEq)]
66pub struct Config {
67 framing: Framing,
68 compression: Compression,
69 encryption: Encryption,
70}
71
72impl Config {
73 pub fn new(framing: Framing, compression: Compression, encryption: Encryption) -> Result<Self> {
76 let max = framing.max_frame_len();
77 if max == 0 {
78 return Err(Error::InvalidFrameSize);
79 }
80 buffer_len(
81 max.checked_add(encryption.tag_len() as u64)
82 .ok_or(Error::Overflow)?,
83 )?;
84 if compression == Compression::Lz4 && max > 0x7e00_0000 {
86 return Err(Error::InvalidFrameSize);
87 }
88 if encryption == Encryption::Aes256Gcm && max > AES_MAX_FRAME_LEN {
89 return Err(Error::InvalidFrameSize);
90 }
91 Ok(Self {
92 framing,
93 compression,
94 encryption,
95 })
96 }
97
98 pub const fn framing(self) -> Framing {
100 self.framing
101 }
102 pub const fn compression(self) -> Compression {
104 self.compression
105 }
106 pub const fn encryption(self) -> Encryption {
108 self.encryption
109 }
110 pub const fn max_frame_len(self) -> u64 {
112 self.framing.max_frame_len()
113 }
114
115 pub fn max_frames(self) -> u64 {
118 match self.encryption {
119 Encryption::None => u64::MAX,
120 Encryption::Aes256Gcm => AES_MAX_FRAMES.min(AES_MAX_BYTES / self.max_frame_len()),
121 }
122 }
123
124 pub(crate) fn validate_frame(self, index: u64, raw: u64, payload: u64) -> Result<()> {
125 if raw == 0 || raw > self.max_frame_len() {
126 return Err(Error::InvalidFrameSize);
127 }
128 if payload == 0
129 || payload > raw
130 || (self.compression == Compression::None && payload != raw)
131 {
132 return Err(Error::InvalidMetadata);
133 }
134 if index >= self.max_frames() {
135 return Err(Error::UsageLimit);
136 }
137 Ok(())
138 }
139}