ms_pdb/
utils.rs

1//! Misc utilities
2
3pub mod align;
4pub mod io;
5pub mod iter;
6pub mod path;
7pub mod swizzle;
8pub mod vec;
9
10use std::ops::Range;
11use zerocopy::{FromBytes, Immutable, IntoBytes};
12
13/// Copies a value that implements `FromBytes`, by simply copying its byte representation.
14pub fn copy_from_bytes<T>(t: &T) -> T
15where
16    T: IntoBytes + FromBytes + Immutable,
17{
18    FromBytes::read_from_bytes(t.as_bytes()).unwrap()
19}
20
21/// Helps decode records that are indexed using "starts" arrays.
22pub struct StartsOf<'a, T> {
23    /// The "starts" array
24    pub starts: &'a [u32],
25    /// The items that are being indexed.
26    pub items: &'a [T],
27}
28
29impl<'a, T> StartsOf<'a, T> {
30    /// Initializes a new starts-based array accessor.
31    pub fn new(starts: &'a [u32], items: &'a [T]) -> Self {
32        debug_assert!(!starts.is_empty());
33        debug_assert_eq!(starts[0], 0);
34        debug_assert_eq!(*starts.last().unwrap() as usize, items.len());
35        debug_assert!(starts.windows(2).all(|w| w[0] <= w[1]));
36
37        Self { starts, items }
38    }
39}
40
41impl<'a, T> std::ops::Index<usize> for StartsOf<'a, T> {
42    type Output = [T];
43
44    fn index(&self, i: usize) -> &[T] {
45        let start = self.starts[i] as usize;
46        let end = self.starts[i + 1] as usize;
47        &self.items[start..end]
48    }
49}
50
51/// True if `n` is a multiple of 4.
52pub fn is_aligned_4(n: usize) -> bool {
53    (n & 3) == 0
54}
55
56/// Align n up to the next multiple of 4, if it is not already a multiple of 4.
57pub fn align_4(n: usize) -> usize {
58    (n + 3) & !3
59}
60
61/// Iterates ranges of items within a slice that share a common property.
62pub fn iter_similar_ranges<'a, T, F>(items: &'a [T], is_eq: F) -> IterSimilarRanges<'a, T, F> {
63    IterSimilarRanges {
64        items,
65        is_eq,
66        start: 0,
67    }
68}
69
70/// Iterates ranges of items within a slice that share a common property.
71pub struct IterSimilarRanges<'a, T, F> {
72    items: &'a [T],
73    is_eq: F,
74    start: usize,
75}
76
77impl<'a, T, F> Iterator for IterSimilarRanges<'a, T, F>
78where
79    F: FnMut(&T, &T) -> bool,
80{
81    type Item = Range<usize>;
82
83    fn next(&mut self) -> Option<Self::Item> {
84        if self.items.is_empty() {
85            return None;
86        }
87
88        let first = &self.items[0];
89
90        let mut i = 1;
91        while i < self.items.len() && (self.is_eq)(first, &self.items[i]) {
92            i += 1;
93        }
94
95        let start = self.start;
96        self.start += i;
97        self.items = &self.items[i..];
98
99        Some(start..start + i)
100    }
101}
102
103/// Iterates ranges of items within a slice that share a common property.
104pub fn iter_similar_slices<'a, T, F>(items: &'a [T], is_eq: F) -> IterSimilarSlices<'a, T, F> {
105    IterSimilarSlices { items, is_eq }
106}
107
108/// Iterates slices of items within a slice that share a common property.
109pub struct IterSimilarSlices<'a, T, F> {
110    items: &'a [T],
111    is_eq: F,
112}
113
114impl<'a, T, F> Iterator for IterSimilarSlices<'a, T, F>
115where
116    F: FnMut(&T, &T) -> bool,
117{
118    type Item = &'a [T];
119
120    fn next(&mut self) -> Option<Self::Item> {
121        if self.items.is_empty() {
122            return None;
123        }
124
125        let first = &self.items[0];
126
127        let mut i = 1;
128        while i < self.items.len() && (self.is_eq)(first, &self.items[i]) {
129            i += 1;
130        }
131
132        let (lo, hi) = self.items.split_at(i);
133        self.items = hi;
134        Some(lo)
135    }
136}
137
138/// Iterates ranges of items within a slice that share a common property.
139pub fn iter_similar_slices_mut<'a, T, F>(
140    items: &'a mut [T],
141    is_eq: F,
142) -> IterSimilarSlicesMut<'a, T, F> {
143    IterSimilarSlicesMut { items, is_eq }
144}
145
146/// Iterates slices of items within a slice that share a common property.
147pub struct IterSimilarSlicesMut<'a, T, F> {
148    items: &'a mut [T],
149    is_eq: F,
150}
151
152impl<'a, T, F> Iterator for IterSimilarSlicesMut<'a, T, F>
153where
154    F: FnMut(&T, &T) -> bool,
155{
156    type Item = &'a mut [T];
157
158    fn next(&mut self) -> Option<Self::Item> {
159        if self.items.is_empty() {
160            return None;
161        }
162
163        let items = std::mem::take(&mut self.items);
164        let first = &items[0];
165
166        let mut i = 1;
167        while i < items.len() && (self.is_eq)(first, &items[i]) {
168            i += 1;
169        }
170
171        let (lo, hi) = items.split_at_mut(i);
172        self.items = hi;
173        Some(lo)
174    }
175}