escpos_db/
int_map.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
use std::borrow::Borrow;
use std::ops::Deref;
use std::{fmt, mem};

/// A mapping from a `u8` to `T`.
///
/// Printer capabilities represented with this type will generally involve
/// sending a key in this map as part of a command to the printer. For example,
/// for [character fonts], sending `[0x1b, b'M']` followed by `0x03` to the
/// printer selects "font D", and correspondingly, `profile.fonts.get(3)` will
/// return information about the printer's "font D", if it exists.
///
/// [character fonts]: crate::Profile::fonts
#[repr(transparent)]
pub struct IntMap<T> {
    // sorted
    entries: [(u8, T)],
}

fn key_f<T>((k, _): &(u8, T)) -> u8 {
    *k
}

impl<T> Default for &IntMap<T> {
    fn default() -> Self {
        IntMap::empty()
    }
}

impl<T> IntMap<T> {
    #[inline]
    const fn from_entries_unchecked(entries: &[(u8, T)]) -> &Self {
        unsafe { &*(entries as *const _ as *const Self) }
    }

    /// An empty `IntMap`.
    #[inline]
    pub const fn empty<'a>() -> &'a Self {
        Self::from_entries_unchecked(&[])
    }

    /// Create an `IntMap` from the given map entries.
    ///
    /// # Panics
    ///
    /// This function will panic if `entries` is not ordered by the first field of the tuple, or has duplicates.
    pub const fn from_entries(entries: &[(u8, T)]) -> &Self {
        if !entries.is_empty() {
            let mut prev = entries[0].0;
            let mut i = 1;
            while i < entries.len() {
                let cur = entries[i].0;
                if cur <= prev {
                    panic!("invalid entries array");
                }
                prev = cur;
                i += 1;
            }
        }
        Self::from_entries_unchecked(entries)
    }

    /// Lookup a value by the given key.
    pub fn get(&self, k: u8) -> Option<&T> {
        let i = self.entries.binary_search_by_key(&k, key_f).ok()?;
        Some(&self.entries[i].1)
    }

    /// Returns an iterator over the entries of this map.
    pub fn iter(&self) -> IntMapIter<'_, T> {
        self.into_iter()
    }
}

impl<T> AsRef<IntMap<T>> for IntMap<T> {
    fn as_ref(&self) -> &IntMap<T> {
        self
    }
}

impl<T: fmt::Debug> fmt::Debug for IntMap<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_map().entries(self).finish()
    }
}

impl<'a, T> IntoIterator for &'a IntMap<T> {
    type Item = (u8, &'a T);
    type IntoIter = IntMapIter<'a, T>;
    fn into_iter(self) -> Self::IntoIter {
        IntMapIter {
            inner: self.entries.iter(),
        }
    }
}

/// An iterator over an [`IntMap`].
pub struct IntMapIter<'a, T> {
    inner: std::slice::Iter<'a, (u8, T)>,
}

impl<'a, T> Iterator for IntMapIter<'a, T> {
    type Item = (u8, &'a T);
    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().map(|(k, v)| (*k, v))
    }
}

impl<T> ToOwned for IntMap<T> {
    type Owned = OwnedIntMap<T>;
    fn to_owned(&self) -> Self::Owned {
        todo!()
    }
}

/// An owned version of [`IntMap`].
pub struct OwnedIntMap<T> {
    entries: Vec<(u8, T)>,
}

impl<T> Deref for OwnedIntMap<T> {
    type Target = IntMap<T>;
    fn deref(&self) -> &Self::Target {
        IntMap::from_entries_unchecked(&self.entries)
    }
}

impl<T> Borrow<IntMap<T>> for OwnedIntMap<T> {
    fn borrow(&self) -> &IntMap<T> {
        self
    }
}

impl<T> OwnedIntMap<T> {
    /// Insert a new entry into the map, returning the previous value at `key` if it existed.
    pub fn insert(&mut self, key: u8, val: T) -> Option<T> {
        match self.entries.binary_search_by_key(&key, key_f) {
            Ok(i) => Some(mem::replace(&mut self.entries[i].1, val)),
            Err(i) => {
                self.entries.insert(i, (key, val));
                None
            }
        }
    }
}

impl<T: fmt::Debug> fmt::Debug for OwnedIntMap<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (**self).fmt(f)
    }
}

impl<T> FromIterator<(u8, T)> for OwnedIntMap<T> {
    fn from_iter<I: IntoIterator<Item = (u8, T)>>(iter: I) -> Self {
        let mut entries = iter.into_iter().collect::<Vec<_>>();
        entries.sort_by_key(key_f);
        Self { entries }
    }
}

impl<T> Extend<(u8, T)> for OwnedIntMap<T> {
    fn extend<I: IntoIterator<Item = (u8, T)>>(&mut self, iter: I) {
        struct DropGuard<'a, T> {
            entries: &'a mut Vec<(u8, T)>,
            reset_len: usize,
        }
        impl<T> Drop for DropGuard<'_, T> {
            fn drop(&mut self) {
                self.entries.truncate(self.reset_len);
            }
        }
        let guard = DropGuard {
            reset_len: self.entries.len(),
            entries: &mut self.entries,
        };
        guard.entries.extend(iter);
        mem::forget(guard);
        self.entries.sort_by_key(key_f);
    }
}