irox_tools/
vec.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2025 IROX Contributors
3//
4
5//!
6//! Bolt-ons for [`Vec`] and [`VecDeque`] - better displays and iteration tools
7
8extern crate alloc;
9use crate::buf::ZeroedBuffer;
10use alloc::collections::VecDeque;
11use alloc::string::String;
12use alloc::{vec, vec::Vec};
13use core::fmt::{Display, Formatter, UpperHex, Write};
14
15///
16/// This struct purely exists to implement [`Display`] and [`UpperHex`] for a borrowed Vec, whose elements implement [`Display`] or [`UpperHex`]
17pub struct PrettyVec<'a, T>(pub &'a Vec<T>);
18
19///
20/// This struct purely exists to implement [`Display`] and [`UpperHex`] for a borrowed VecDeque, whose elements implement [`Display`] or [`UpperHex`]
21pub struct PrettyVecDeque<'a, T>(pub &'a VecDeque<T>);
22
23impl<T> Display for PrettyVec<'_, T>
24where
25    T: Display,
26{
27    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
28        let vals: Vec<String> = self.0.iter().map(|f| format!("{f}")).collect();
29        if f.alternate() {
30            f.write_fmt(format_args!("{vals:#?}"))
31        } else {
32            f.write_fmt(format_args!("{vals:?}"))
33        }
34    }
35}
36
37impl<T> UpperHex for PrettyVec<'_, T>
38where
39    T: UpperHex,
40{
41    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
42        let mut buf = String::new();
43        for val in self.0 {
44            buf.write_fmt(format_args!("{val:0X}"))?;
45        }
46        f.write_fmt(format_args!("{buf}"))
47    }
48}
49
50impl<T> UpperHex for PrettyVecDeque<'_, T>
51where
52    T: UpperHex,
53{
54    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
55        let mut buf = String::new();
56        for val in self.0 {
57            buf.write_fmt(format_args!("{val:0X}"))?;
58        }
59        f.write_fmt(format_args!("{buf}"))
60    }
61}
62
63///
64/// The `retain+take` operation is exactly what it sounds like.  Retain only those elements that
65/// match the predicate, but return whole owned copies of the items.  For efficiency's sake, some
66/// implementations *may* iterate backwards through the container.
67pub trait RetainTake<T> {
68    fn retain_take<F>(&mut self, predicate: F) -> Vec<T>
69    where
70        F: FnMut(&T) -> bool;
71}
72
73impl<T> RetainTake<T> for Vec<T> {
74    fn retain_take<F>(&mut self, mut predicate: F) -> Vec<T>
75    where
76        F: FnMut(&T) -> bool,
77    {
78        let mut idx = self.len();
79        let mut out: Vec<T> = Vec::new();
80        loop {
81            idx -= 1;
82            if let Some(elem) = self.get(idx) {
83                if !predicate(elem) {
84                    out.push(self.swap_remove(idx));
85                }
86            }
87            if idx == 0 {
88                break;
89            }
90        }
91        out
92    }
93}
94
95impl<T> RetainTake<T> for VecDeque<T> {
96    fn retain_take<F>(&mut self, mut predicate: F) -> Vec<T>
97    where
98        F: FnMut(&T) -> bool,
99    {
100        let mut idx = self.len();
101        let mut out: Vec<T> = Vec::new();
102        loop {
103            idx -= 1;
104            if let Some(elem) = self.get(idx) {
105                if !predicate(elem) {
106                    if let Some(elem) = self.swap_remove_back(idx) {
107                        out.push(elem);
108                    }
109                }
110            }
111            if idx == 0 {
112                break;
113            }
114        }
115        out
116    }
117}
118
119impl<T: Default + Sized + Copy> ZeroedBuffer for Vec<T> {
120    type Output = Self;
121
122    fn new_zeroed(capacity: usize) -> Self::Output {
123        vec![T::default(); capacity]
124    }
125}
126
127impl<T: Default + Sized + Copy> ZeroedBuffer for VecDeque<T> {
128    type Output = Self;
129
130    fn new_zeroed(capacity: usize) -> Self::Output {
131        VecDeque::from(vec![T::default(); capacity])
132    }
133}