irox_tools/
vec.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
// SPDX-License-Identifier: MIT
// Copyright 2025 IROX Contributors
//

//!
//! Bolt-ons for [`Vec`] and [`VecDeque`] - better displays and iteration tools

extern crate alloc;
use crate::buf::ZeroedBuffer;
use alloc::collections::VecDeque;
use alloc::string::String;
use alloc::{vec, vec::Vec};
use core::fmt::{Display, Formatter, UpperHex, Write};

///
/// This struct purely exists to implement [`Display`] and [`UpperHex`] for a borrowed Vec, whose elements implement [`Display`] or [`UpperHex`]
pub struct PrettyVec<'a, T>(pub &'a Vec<T>);

///
/// This struct purely exists to implement [`Display`] and [`UpperHex`] for a borrowed VecDeque, whose elements implement [`Display`] or [`UpperHex`]
pub struct PrettyVecDeque<'a, T>(pub &'a VecDeque<T>);

impl<'a, T> Display for PrettyVec<'a, T>
where
    T: Display,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        let vals: Vec<String> = self.0.iter().map(|f| format!("{f}")).collect();
        if f.alternate() {
            f.write_fmt(format_args!("{vals:#?}"))
        } else {
            f.write_fmt(format_args!("{vals:?}"))
        }
    }
}

impl<'a, T> UpperHex for PrettyVec<'a, T>
where
    T: UpperHex,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        let mut buf = String::new();
        for val in self.0 {
            buf.write_fmt(format_args!("{val:0X}"))?;
        }
        f.write_fmt(format_args!("{buf}"))
    }
}

impl<'a, T> UpperHex for PrettyVecDeque<'a, T>
where
    T: UpperHex,
{
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
        let mut buf = String::new();
        for val in self.0 {
            buf.write_fmt(format_args!("{val:0X}"))?;
        }
        f.write_fmt(format_args!("{buf}"))
    }
}

///
/// The `retain+take` operation is exactly what it sounds like.  Retain only those elements that
/// match the predicate, but return whole owned copies of the items.  For efficiency's sake, some
/// implementations *may* iterate backwards through the container.
pub trait RetainTake<T> {
    fn retain_take<F>(&mut self, predicate: F) -> Vec<T>
    where
        F: FnMut(&T) -> bool;
}

impl<T> RetainTake<T> for Vec<T> {
    fn retain_take<F>(&mut self, mut predicate: F) -> Vec<T>
    where
        F: FnMut(&T) -> bool,
    {
        let mut idx = self.len();
        let mut out: Vec<T> = Vec::new();
        loop {
            idx -= 1;
            if let Some(elem) = self.get(idx) {
                if !predicate(elem) {
                    out.push(self.swap_remove(idx));
                }
            }
            if idx == 0 {
                break;
            }
        }
        out
    }
}

impl<T> RetainTake<T> for VecDeque<T> {
    fn retain_take<F>(&mut self, mut predicate: F) -> Vec<T>
    where
        F: FnMut(&T) -> bool,
    {
        let mut idx = self.len();
        let mut out: Vec<T> = Vec::new();
        loop {
            idx -= 1;
            if let Some(elem) = self.get(idx) {
                if !predicate(elem) {
                    if let Some(elem) = self.swap_remove_back(idx) {
                        out.push(elem);
                    }
                }
            }
            if idx == 0 {
                break;
            }
        }
        out
    }
}

impl<T: Default + Sized + Copy> ZeroedBuffer for Vec<T> {
    type Output = Self;

    fn new_zeroed(capacity: usize) -> Self::Output {
        vec![T::default(); capacity]
    }
}

impl<T: Default + Sized + Copy> ZeroedBuffer for VecDeque<T> {
    type Output = Self;

    fn new_zeroed(capacity: usize) -> Self::Output {
        VecDeque::from(vec![T::default(); capacity])
    }
}