1use crate::model_types::DntSealOptions;
14use crate::{DntError, DntResult};
15
16pub const DNT_FLAG_PAYLOAD_DEFLATE: u32 = 0x0000_0001;
18
19pub const DNT_INTERNAL_FLAG_MASK: u32 = 0x0000_FFFF;
21pub const DNT_USER_FLAG_MASK: u32 = 0xFFFF_0000;
23pub const DNT_USER_FLAG_OFFSET: u8 = 16;
25pub const DNT_USER_FLAG_COUNT: u8 = 16;
27
28const KNOWN_INTERNAL_FLAGS: u32 = DNT_FLAG_PAYLOAD_DEFLATE;
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub struct DntFlags(u32);
33
34impl DntFlags {
35 pub const fn empty() -> Self {
37 Self(0)
38 }
39
40 pub fn from_bits(bits: u32) -> DntResult<Self> {
42 validate_flags(bits)?;
43 Ok(Self(bits))
44 }
45
46 pub const fn bits(self) -> u32 {
48 self.0
49 }
50
51 pub const fn internal_bits(self) -> u32 {
53 self.0 & DNT_INTERNAL_FLAG_MASK
54 }
55
56 pub const fn user_bits(self) -> u32 {
58 self.0 & DNT_USER_FLAG_MASK
59 }
60
61 pub const fn compact_payload(self) -> Self {
63 Self(self.0 | DNT_FLAG_PAYLOAD_DEFLATE)
64 }
65
66 pub fn with_user_flag(self, index: u8) -> DntResult<Self> {
68 Ok(Self(self.0 | dnt_user_flag(index)?))
69 }
70}
71
72impl DntSealOptions {
73 pub fn compact_payload(mut self) -> Self {
78 self.flags |= DNT_FLAG_PAYLOAD_DEFLATE;
79 self
80 }
81
82 pub fn with_user_flag(mut self, index: u8) -> DntResult<Self> {
84 self.flags = DntFlags::from_bits(self.flags)?
85 .with_user_flag(index)?
86 .bits();
87 Ok(self)
88 }
89}
90
91pub fn dnt_user_flag(index: u8) -> DntResult<u32> {
93 if index >= DNT_USER_FLAG_COUNT {
94 return Err(DntError::InvalidFlags);
95 }
96 1u32.checked_shl(u32::from(DNT_USER_FLAG_OFFSET + index))
97 .ok_or(DntError::InvalidFlags)
98}
99
100pub fn dnt_compose_flags(internal_flags: u32, user_flags: u32) -> DntResult<u32> {
102 if internal_flags & !KNOWN_INTERNAL_FLAGS != 0 || user_flags & !DNT_USER_FLAG_MASK != 0 {
103 return Err(DntError::InvalidFlags);
104 }
105 Ok(internal_flags | user_flags)
106}
107
108pub(crate) fn validate_flags(flags: u32) -> DntResult<()> {
109 let unknown_internal_flags = flags & DNT_INTERNAL_FLAG_MASK & !KNOWN_INTERNAL_FLAGS;
110 if unknown_internal_flags != 0 {
111 return Err(DntError::InvalidFlags);
112 }
113 Ok(())
114}