sqlx_sqlite/connection/
intmap.rs

1// Bad casts in this module SHOULD NOT result in a SQL injection
2// https://github.com/launchbadge/sqlx/issues/3440
3#![allow(
4    clippy::cast_possible_truncation,
5    clippy::cast_possible_wrap,
6    clippy::cast_sign_loss
7)]
8use std::cmp::Ordering;
9use std::{fmt::Debug, hash::Hash};
10
11/// Simplistic map implementation built on a Vec of Options (index = key)
12#[derive(Debug, Clone, Eq)]
13pub(crate) struct IntMap<V>(Vec<Option<V>>);
14
15impl<V> Default for IntMap<V> {
16    fn default() -> Self {
17        IntMap(Vec::new())
18    }
19}
20
21impl<V> IntMap<V> {
22    pub(crate) fn new() -> Self {
23        Self(Vec::new())
24    }
25
26    pub(crate) fn expand(&mut self, size: i64) -> usize {
27        let idx = size.try_into().expect("negative column index unsupported");
28        while self.0.len() <= idx {
29            self.0.push(None);
30        }
31        idx
32    }
33
34    pub(crate) fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
35        self.0.iter_mut().filter_map(Option::as_mut)
36    }
37
38    pub(crate) fn values(&self) -> impl Iterator<Item = &V> {
39        self.0.iter().filter_map(Option::as_ref)
40    }
41
42    pub(crate) fn get(&self, idx: &i64) -> Option<&V> {
43        let idx: usize = (*idx)
44            .try_into()
45            .expect("negative column index unsupported");
46
47        match self.0.get(idx) {
48            Some(Some(v)) => Some(v),
49            _ => None,
50        }
51    }
52
53    pub(crate) fn get_mut(&mut self, idx: &i64) -> Option<&mut V> {
54        let idx: usize = (*idx)
55            .try_into()
56            .expect("negative column index unsupported");
57        match self.0.get_mut(idx) {
58            Some(Some(v)) => Some(v),
59            _ => None,
60        }
61    }
62
63    pub(crate) fn insert(&mut self, idx: i64, value: V) -> Option<V> {
64        let idx: usize = self.expand(idx);
65
66        std::mem::replace(&mut self.0[idx], Some(value))
67    }
68
69    pub(crate) fn remove(&mut self, idx: &i64) -> Option<V> {
70        let idx: usize = (*idx)
71            .try_into()
72            .expect("negative column index unsupported");
73
74        let item = self.0.get_mut(idx);
75        match item {
76            Some(content) => content.take(),
77            None => None,
78        }
79    }
80
81    pub(crate) fn iter(&self) -> impl Iterator<Item = Option<&V>> {
82        self.0.iter().map(Option::as_ref)
83    }
84
85    pub(crate) fn iter_entries(&self) -> impl Iterator<Item = (i64, &V)> {
86        self.0
87            .iter()
88            .enumerate()
89            .filter_map(|(i, v)| v.as_ref().map(|v: &V| (i as i64, v)))
90    }
91
92    pub(crate) fn last_index(&self) -> Option<i64> {
93        self.0.iter().rposition(|v| v.is_some()).map(|i| i as i64)
94    }
95}
96
97impl<V: Default> IntMap<V> {
98    pub(crate) fn get_mut_or_default<'a>(&'a mut self, idx: &i64) -> &'a mut V {
99        let idx: usize = self.expand(*idx);
100
101        let item: &mut Option<V> = &mut self.0[idx];
102        if item.is_none() {
103            *item = Some(V::default());
104        }
105
106        return self.0[idx].as_mut().unwrap();
107    }
108}
109
110impl<V: Clone> IntMap<V> {
111    pub(crate) fn from_elem(elem: V, len: usize) -> Self {
112        Self(vec![Some(elem); len])
113    }
114    pub(crate) fn from_dense_record(record: &[V]) -> Self {
115        Self(record.iter().cloned().map(Some).collect())
116    }
117}
118
119impl<V: Eq> IntMap<V> {
120    /// get the additions to this intmap compared to the prev intmap
121    pub(crate) fn diff<'a, 'b, 'c>(
122        &'a self,
123        prev: &'b Self,
124    ) -> impl Iterator<Item = (usize, Option<&'c V>)>
125    where
126        'a: 'c,
127        'b: 'c,
128    {
129        let self_pad = if prev.0.len() > self.0.len() {
130            prev.0.len() - self.0.len()
131        } else {
132            0
133        };
134        self.iter()
135            .chain(std::iter::repeat(None).take(self_pad))
136            .zip(prev.iter().chain(std::iter::repeat(None)))
137            .enumerate()
138            .filter(|(_i, (n, p))| n != p)
139            .map(|(i, (n, _p))| (i, n))
140    }
141}
142
143impl<V: Hash> Hash for IntMap<V> {
144    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
145        for value in self.values() {
146            value.hash(state);
147        }
148    }
149}
150
151impl<V: PartialEq> PartialEq for IntMap<V> {
152    fn eq(&self, other: &Self) -> bool {
153        match self.0.len().cmp(&other.0.len()) {
154            Ordering::Greater => {
155                self.0[..other.0.len()] == other.0
156                    && self.0[other.0.len()..].iter().all(Option::is_none)
157            }
158            Ordering::Less => {
159                other.0[..self.0.len()] == self.0
160                    && other.0[self.0.len()..].iter().all(Option::is_none)
161            }
162            Ordering::Equal => self.0 == other.0,
163        }
164    }
165}
166
167impl<V: Debug> FromIterator<(i64, V)> for IntMap<V> {
168    fn from_iter<I>(iter: I) -> Self
169    where
170        I: IntoIterator<Item = (i64, V)>,
171    {
172        let mut result = Self(Vec::new());
173        for (idx, val) in iter {
174            let idx = result.expand(idx);
175            result.0[idx] = Some(val);
176        }
177        result
178    }
179}