escpos_db/
int_map.rs

1use std::borrow::Borrow;
2use std::ops::Deref;
3use std::{fmt, mem};
4
5/// A mapping from a `u8` to `T`.
6///
7/// Printer capabilities represented with this type will generally involve
8/// sending a key in this map as part of a command to the printer. For example,
9/// for [character fonts], sending `[0x1b, b'M']` followed by `0x03` to the
10/// printer selects "font D", and correspondingly, `profile.fonts.get(3)` will
11/// return information about the printer's "font D", if it exists.
12///
13/// [character fonts]: crate::Profile::fonts
14#[repr(transparent)]
15pub struct IntMap<T> {
16    // sorted
17    entries: [(u8, T)],
18}
19
20fn key_f<T>((k, _): &(u8, T)) -> u8 {
21    *k
22}
23
24impl<T> Default for &IntMap<T> {
25    fn default() -> Self {
26        IntMap::empty()
27    }
28}
29
30impl<T> IntMap<T> {
31    #[inline]
32    const fn from_entries_unchecked(entries: &[(u8, T)]) -> &Self {
33        unsafe { &*(entries as *const _ as *const Self) }
34    }
35
36    /// An empty `IntMap`.
37    #[inline]
38    pub const fn empty<'a>() -> &'a Self {
39        Self::from_entries_unchecked(&[])
40    }
41
42    /// Create an `IntMap` from the given map entries.
43    ///
44    /// # Panics
45    ///
46    /// This function will panic if `entries` is not ordered by the first field of the tuple, or has duplicates.
47    pub const fn from_entries(entries: &[(u8, T)]) -> &Self {
48        if !entries.is_empty() {
49            let mut prev = entries[0].0;
50            let mut i = 1;
51            while i < entries.len() {
52                let cur = entries[i].0;
53                if cur <= prev {
54                    panic!("invalid entries array");
55                }
56                prev = cur;
57                i += 1;
58            }
59        }
60        Self::from_entries_unchecked(entries)
61    }
62
63    /// Lookup a value by the given key.
64    pub fn get(&self, k: u8) -> Option<&T> {
65        let i = self.entries.binary_search_by_key(&k, key_f).ok()?;
66        Some(&self.entries[i].1)
67    }
68
69    /// Returns an iterator over the entries of this map.
70    pub fn iter(&self) -> IntMapIter<'_, T> {
71        self.into_iter()
72    }
73}
74
75impl<T> AsRef<IntMap<T>> for IntMap<T> {
76    fn as_ref(&self) -> &IntMap<T> {
77        self
78    }
79}
80
81impl<T: fmt::Debug> fmt::Debug for IntMap<T> {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        f.debug_map().entries(self).finish()
84    }
85}
86
87impl<'a, T> IntoIterator for &'a IntMap<T> {
88    type Item = (u8, &'a T);
89    type IntoIter = IntMapIter<'a, T>;
90    fn into_iter(self) -> Self::IntoIter {
91        IntMapIter {
92            inner: self.entries.iter(),
93        }
94    }
95}
96
97/// An iterator over an [`IntMap`].
98pub struct IntMapIter<'a, T> {
99    inner: std::slice::Iter<'a, (u8, T)>,
100}
101
102impl<'a, T> Iterator for IntMapIter<'a, T> {
103    type Item = (u8, &'a T);
104    fn next(&mut self) -> Option<Self::Item> {
105        self.inner.next().map(|(k, v)| (*k, v))
106    }
107}
108
109impl<T> ToOwned for IntMap<T> {
110    type Owned = OwnedIntMap<T>;
111    fn to_owned(&self) -> Self::Owned {
112        todo!()
113    }
114}
115
116/// An owned version of [`IntMap`].
117pub struct OwnedIntMap<T> {
118    entries: Vec<(u8, T)>,
119}
120
121impl<T> Deref for OwnedIntMap<T> {
122    type Target = IntMap<T>;
123    fn deref(&self) -> &Self::Target {
124        IntMap::from_entries_unchecked(&self.entries)
125    }
126}
127
128impl<T> Borrow<IntMap<T>> for OwnedIntMap<T> {
129    fn borrow(&self) -> &IntMap<T> {
130        self
131    }
132}
133
134impl<T> OwnedIntMap<T> {
135    /// Insert a new entry into the map, returning the previous value at `key` if it existed.
136    pub fn insert(&mut self, key: u8, val: T) -> Option<T> {
137        match self.entries.binary_search_by_key(&key, key_f) {
138            Ok(i) => Some(mem::replace(&mut self.entries[i].1, val)),
139            Err(i) => {
140                self.entries.insert(i, (key, val));
141                None
142            }
143        }
144    }
145}
146
147impl<T: fmt::Debug> fmt::Debug for OwnedIntMap<T> {
148    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149        (**self).fmt(f)
150    }
151}
152
153impl<T> FromIterator<(u8, T)> for OwnedIntMap<T> {
154    fn from_iter<I: IntoIterator<Item = (u8, T)>>(iter: I) -> Self {
155        let mut entries = iter.into_iter().collect::<Vec<_>>();
156        entries.sort_by_key(key_f);
157        Self { entries }
158    }
159}
160
161impl<T> Extend<(u8, T)> for OwnedIntMap<T> {
162    fn extend<I: IntoIterator<Item = (u8, T)>>(&mut self, iter: I) {
163        struct DropGuard<'a, T> {
164            entries: &'a mut Vec<(u8, T)>,
165            reset_len: usize,
166        }
167        impl<T> Drop for DropGuard<'_, T> {
168            fn drop(&mut self) {
169                self.entries.truncate(self.reset_len);
170            }
171        }
172        let guard = DropGuard {
173            reset_len: self.entries.len(),
174            entries: &mut self.entries,
175        };
176        guard.entries.extend(iter);
177        mem::forget(guard);
178        self.entries.sort_by_key(key_f);
179    }
180}