rust_3d/
dynamic_precision_index_vec.rs

1/*
2Copyright 2020 Martin Buck
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"),
6to deal in the Software without restriction, including without limitation the
7rights to use, copy, modify, merge, publish, distribute, sublicense,
8and/or sell copies of the Software, and to permit persons to whom the Software
9is furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall
12be included all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
20OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21*/
22
23//! DynamicPrecisionIndexVec is a memory efficient container with a usize interface. It uses u8 -> u16 -> u32 -> usize for storage depending on the largest index's size
24
25use crate::{IsIndexContainer, IsIndexContainerIterator};
26
27use std::{u16, u32, u8, usize};
28
29//------------------------------------------------------------------------------
30
31#[derive(Clone, Default)]
32/// DynamicPrecisionIndexVec is a memory efficient container with a usize interface. It uses u8 -> u16 -> u32 -> usize for storage depending on the largest index's size
33pub struct DynamicPrecisionIndexVec {
34    mode: Mode,
35}
36
37//@todo implement as much of the Vec interface as possible
38impl DynamicPrecisionIndexVec {
39    /// Creates a new DynamicPrecisionIndexVec with u8 precision
40    pub fn new() -> Self {
41        Self {
42            mode: Mode::U8(Vec::new()),
43        }
44    }
45    /// If storage is currently done with u8 precision, returns a reference to the inner Vec
46    pub fn get_u8(&self) -> Option<&Vec<u8>> {
47        match self.mode {
48            Mode::U8(ref vec) => Some(vec),
49            _ => None,
50        }
51    }
52    /// If storage is currently done with u8 precision, returns a mutable reference to the inner Vec
53    pub fn get_u8_mut(&mut self) -> Option<&mut Vec<u8>> {
54        match self.mode {
55            Mode::U8(ref mut vec) => Some(vec),
56            _ => None,
57        }
58    }
59    /// If storage is currently done with u16 precision, returns a reference to the inner Vec
60    pub fn get_u16(&self) -> Option<&Vec<u16>> {
61        match self.mode {
62            Mode::U16(ref vec) => Some(vec),
63            _ => None,
64        }
65    }
66    /// If storage is currently done with u16 precision, returns a mutable reference to the inner Vec
67    pub fn get_u16_mut(&mut self) -> Option<&mut Vec<u16>> {
68        match self.mode {
69            Mode::U16(ref mut vec) => Some(vec),
70            _ => None,
71        }
72    }
73    /// If storage is currently done with u32 precision, returns a reference to the inner Vec
74    pub fn get_u32(&self) -> Option<&Vec<u32>> {
75        match self.mode {
76            Mode::U32(ref vec) => Some(vec),
77            _ => None,
78        }
79    }
80    /// If storage is currently done with u32 precision, returns a mutable reference to the inner Vec
81    pub fn get_u32_mut(&mut self) -> Option<&mut Vec<u32>> {
82        match self.mode {
83            Mode::U32(ref mut vec) => Some(vec),
84            _ => None,
85        }
86    }
87    /// If storage is currently done with usize precision, returns a reference to the inner Vec
88    pub fn get_usize(&mut self) -> Option<&Vec<usize>> {
89        match self.mode {
90            Mode::Usize(ref vec) => Some(vec),
91            _ => None,
92        }
93    }
94    /// If storage is currently done with usize precision, returns a mutable reference to the inner Vec
95    pub fn get_usize_mut(&mut self) -> Option<&mut Vec<usize>> {
96        match self.mode {
97            Mode::Usize(ref mut vec) => Some(vec),
98            _ => None,
99        }
100    }
101    /// First promotes the precision to usize, then returns a reference to the Vec<usize>. Calling this might unnecessarily increase memory usage
102    pub fn get_usize_upgraded(&mut self) -> &Vec<usize> {
103        self.upgrade_to_usize();
104        match self.mode {
105            Mode::Usize(ref vec) => vec,
106            _ => panic!("Logic error in get_usize_upgraded of DynamicPrecisionIndexVec"),
107        }
108    }
109    /// First promotes the precision to usize, then returns a mutable reference to the Vec<usize>. Calling this might unnecessarily increase memory usage
110    pub fn get_usize_upgraded_mut(&mut self) -> &mut Vec<usize> {
111        self.upgrade_to_usize();
112        match self.mode {
113            Mode::Usize(ref mut vec) => vec,
114            _ => panic!("Logic error in get_usize_upgraded_mut of DynamicPrecisionIndexVec"),
115        }
116    }
117
118    fn upgrade_to_usize(&mut self) {
119        if let Some(new_mode) = match self.mode {
120            Mode::U8(ref vec) => {
121                let new = vec.iter().map(|x| *x as usize).collect();
122                Some(Mode::Usize(new))
123            }
124            Mode::U16(ref vec) => {
125                let new = vec.iter().map(|x| *x as usize).collect();
126                Some(Mode::Usize(new))
127            }
128            Mode::U32(ref vec) => {
129                let new = vec.iter().map(|x| *x as usize).collect();
130                Some(Mode::Usize(new))
131            }
132            Mode::Usize(_) => None,
133        } {
134            self.mode = new_mode;
135        }
136    }
137
138    fn upgrade_to_u32(&mut self) {
139        if let Some(new_mode) = match self.mode {
140            Mode::U8(ref vec) => {
141                let new = vec.iter().map(|x| *x as u32).collect();
142                Some(Mode::U32(new))
143            }
144            Mode::U16(ref vec) => {
145                let new = vec.iter().map(|x| *x as u32).collect();
146                Some(Mode::U32(new))
147            }
148            Mode::U32(_) => None,
149            Mode::Usize(_) => None,
150        } {
151            self.mode = new_mode;
152        }
153    }
154
155    fn upgrade_to_u16(&mut self) {
156        if let Some(new_mode) = match self.mode {
157            Mode::U8(ref vec) => {
158                let new = vec.iter().map(|x| *x as u16).collect();
159                Some(Mode::U16(new))
160            }
161            Mode::U16(_) => None,
162            Mode::U32(_) => None,
163            Mode::Usize(_) => None,
164        } {
165            self.mode = new_mode;
166        }
167    }
168
169    fn allowed_max(&self) -> usize {
170        match self.mode {
171            Mode::U8(_) => u8::MAX as usize,
172            Mode::U16(_) => u16::MAX as usize,
173            Mode::U32(_) => u32::MAX as usize,
174            Mode::Usize(_) => usize::MAX,
175        }
176    }
177}
178
179//------------------------------------------------------------------------------
180
181impl IsIndexContainer for DynamicPrecisionIndexVec {
182    fn ensure_supported(&mut self, x: usize) {
183        if x <= self.allowed_max() {
184            return;
185        }
186
187        if x > u32::MAX as usize {
188            self.upgrade_to_usize();
189        } else if x > u16::MAX as usize {
190            self.upgrade_to_u32();
191        } else if x > u8::MAX as usize {
192            self.upgrade_to_u16();
193        }
194    }
195
196    fn get(&self, i: usize) -> usize {
197        match self.mode {
198            Mode::U8(ref vec) => vec[i] as usize,
199            Mode::U16(ref vec) => vec[i] as usize,
200            Mode::U32(ref vec) => vec[i] as usize,
201            Mode::Usize(ref vec) => vec[i] as usize,
202        }
203    }
204
205    fn set(&mut self, i: usize, x: usize) {
206        self.ensure_supported(x);
207
208        match self.mode {
209            Mode::U8(ref mut vec) => vec[i] = x as u8,
210            Mode::U16(ref mut vec) => vec[i] = x as u16,
211            Mode::U32(ref mut vec) => vec[i] = x as u32,
212            Mode::Usize(ref mut vec) => vec[i] = x,
213        }
214    }
215
216    fn push(&mut self, x: usize) {
217        self.ensure_supported(x);
218
219        match self.mode {
220            Mode::U8(ref mut vec) => vec.push(x as u8),
221            Mode::U16(ref mut vec) => vec.push(x as u16),
222            Mode::U32(ref mut vec) => vec.push(x as u32),
223            Mode::Usize(ref mut vec) => vec.push(x),
224        }
225    }
226
227    fn len(&self) -> usize {
228        match self.mode {
229            Mode::U8(ref vec) => vec.len(),
230            Mode::U16(ref vec) => vec.len(),
231            Mode::U32(ref vec) => vec.len(),
232            Mode::Usize(ref vec) => vec.len(),
233        }
234    }
235
236    fn reserve(&mut self, n: usize) {
237        match self.mode {
238            Mode::U8(ref mut vec) => vec.reserve(n),
239            Mode::U16(ref mut vec) => vec.reserve(n),
240            Mode::U32(ref mut vec) => vec.reserve(n),
241            Mode::Usize(ref mut vec) => vec.reserve(n),
242        }
243    }
244
245    fn iter(&self) -> IsIndexContainerIterator<Self> {
246        IsIndexContainerIterator::new(self)
247    }
248}
249
250impl From<&Vec<usize>> for DynamicPrecisionIndexVec {
251    fn from(vec: &Vec<usize>) -> Self {
252        let mut result = Self::new();
253        if let Some(max) = vec.iter().max() {
254            result.ensure_supported(max);
255            result.reserve(vec.len());
256            for x in vec.iter() {
257                result.push(x)
258            }
259        }
260
261        result
262    }
263}
264
265impl From<Vec<usize>> for DynamicPrecisionIndexVec {
266    fn from(vec: Vec<usize>) -> Self {
267        Self::from(&vec)
268    }
269}
270
271impl From<&Vec<u32>> for DynamicPrecisionIndexVec {
272    fn from(vec: &Vec<u32>) -> Self {
273        let mut result = Self::new();
274        if let Some(max) = vec.iter().max() {
275            result.ensure_supported(*max as usize);
276            result.reserve(vec.len());
277            for x in vec.iter() {
278                result.push(*x as usize)
279            }
280        }
281
282        result
283    }
284}
285
286impl From<Vec<u32>> for DynamicPrecisionIndexVec {
287    fn from(vec: Vec<u32>) -> Self {
288        Self::from(&vec)
289    }
290}
291
292impl From<&Vec<u16>> for DynamicPrecisionIndexVec {
293    fn from(vec: &Vec<u16>) -> Self {
294        let mut result = Self::new();
295        if let Some(max) = vec.iter().max() {
296            result.ensure_supported(*max as usize);
297            result.reserve(vec.len());
298            for x in vec.iter() {
299                result.push(*x as usize)
300            }
301        }
302
303        result
304    }
305}
306
307impl From<Vec<u16>> for DynamicPrecisionIndexVec {
308    fn from(vec: Vec<u16>) -> Self {
309        Self::from(&vec)
310    }
311}
312
313impl From<&Vec<u8>> for DynamicPrecisionIndexVec {
314    fn from(vec: &Vec<u8>) -> Self {
315        Self::from(vec.clone())
316    }
317}
318
319impl From<Vec<u8>> for DynamicPrecisionIndexVec {
320    fn from(vec: Vec<u8>) -> Self {
321        Self {
322            mode: Mode::U8(vec),
323        }
324    }
325}
326
327//------------------------------------------------------------------------------
328
329#[derive(Clone)]
330enum Mode {
331    U8(Vec<u8>),
332    U16(Vec<u16>),
333    U32(Vec<u32>),
334    Usize(Vec<usize>),
335}
336
337impl Default for Mode {
338    fn default() -> Self {
339        Self::U8(Vec::new())
340    }
341}