http_data/
data_kinds.rs

1use std::ops::Deref;
2
3use enumflags2::BitFlags;
4
5// should this have an emergent ordering or should it be configurable by the user/implementer
6#[enumflags2::bitflags]
7#[repr(u8)]
8#[derive(Copy, Clone, PartialEq)]
9pub enum DataKind {
10    Bytes = 1 << 0,
11    Str = 1 << 1,
12    Parsed = 1 << 2,
13}
14impl DataKind {
15    pub(crate) const fn count() -> usize {
16        <BitFlags<DataKind>>::ALL.bits_c().count_ones() as usize
17    }
18}
19#[repr(transparent)]
20pub struct DataKinds(BitFlags<DataKind>);
21impl DataKinds {
22    pub const fn from_slice(s: &[DataKind]) -> Self {
23        let mut i = 0;
24        let mut res = BitFlags::EMPTY;
25        while i < s.len() {
26            let item: BitFlags<DataKind, u8> =
27                BitFlags::<DataKind, u8>::from_bits_truncate_c(s[i] as u8, BitFlags::CONST_TOKEN);
28            res = BitFlags::<DataKind, u8>::union_c(res, item);
29            i += 1;
30        }
31        Self(res)
32    }
33}
34impl Deref for DataKinds {
35    type Target = BitFlags<DataKind>;
36
37    fn deref(&self) -> &Self::Target {
38        &self.0
39    }
40}
41
42/// Allow the trait user to specify its data preferences
43pub struct DataKindPreference {
44    // invariant: filled left to right
45    ordering: [Option<DataKind>; DataKind::count()],
46}
47impl DataKindPreference {
48    pub const BYTES_PREF: Self =
49        Self::from_slice(&[DataKind::Bytes, DataKind::Str, DataKind::Parsed]);
50
51    pub const PARSED_PREF: Self =
52        Self::from_slice(&[DataKind::Parsed, DataKind::Str, DataKind::Bytes]);
53
54    pub const STR_PREF: Self =
55        Self::from_slice(&[DataKind::Str, DataKind::Bytes, DataKind::Parsed]);
56
57    pub const fn from_slice(ordering_slice: &[DataKind]) -> Self {
58        let mut ordering = [None; DataKind::count()];
59        let mut i = 0;
60        while i < ordering.len() && i < ordering_slice.len() {
61            ordering[i] = Some(ordering_slice[i]);
62            i += 1;
63        }
64
65        Self { ordering }
66    }
67
68    pub const fn top(&self, provided: DataKinds) -> Option<DataKind> {
69        let mut i = 0;
70        while i < self.ordering.len() {
71            if let Some(item) = self.ordering[i] {
72                let bf_item =
73                    BitFlags::<_, u8>::from_bits_truncate_c(item as u8, BitFlags::CONST_TOKEN);
74                let contained = provided.0.intersection_c(bf_item).bits_c() == 0;
75                if contained {
76                    return Some(item);
77                }
78            }
79            i += 1;
80        }
81
82        None
83    }
84}