1use super::*;
2use crate::utils::iter::HasRestLen;
3use std::mem::take;
4use tracing::error;
5
6#[derive(Clone)]
8pub struct SymIter<'a> {
9 data: &'a [u8],
10}
11
12impl<'a> HasRestLen for SymIter<'a> {
13 fn rest_len(&self) -> usize {
14 self.data.len()
15 }
16}
17
18pub struct SymIterMut<'a> {
23 data: &'a mut [u8],
24}
25
26impl<'a> SymIterMut<'a> {
27 pub fn get_signature(&mut self) -> Result<[u8; 4], ParserError> {
29 let mut p = ParserMut::new(take(&mut self.data));
30 let sig = p.copy()?;
31 self.data = p.into_rest();
32 Ok(sig)
33 }
34}
35
36impl<'a> HasRestLen for SymIterMut<'a> {
37 fn rest_len(&self) -> usize {
38 self.data.len()
39 }
40}
41
42impl<'a> SymIter<'a> {
43 pub fn new(data: &'a [u8]) -> Self {
45 Self { data }
46 }
47
48 pub fn get_signature(&mut self) -> Result<[u8; 4], ParserError> {
50 let mut p = Parser::new(self.data);
51 let sig = p.copy()?;
52 self.data = p.into_rest();
53 Ok(sig)
54 }
55
56 pub fn rest(&self) -> &'a [u8] {
58 self.data
59 }
60
61 pub fn one(data: &'a [u8]) -> Option<Sym<'a>> {
63 Self::new(data).next()
64 }
65}
66
67impl<'a> Iterator for SymIter<'a> {
68 type Item = Sym<'a>;
69
70 fn next(&mut self) -> Option<Self::Item> {
71 if self.data.is_empty() {
72 return None;
73 }
74
75 let mut p = Parser::new(self.data);
76 let record_len = p.u16().ok()?;
77 if record_len < 2 {
78 error!(
79 invalid_record_len = record_len,
80 iterator_pos = self.data.len(),
81 "type record has invalid len"
82 );
83 return None;
84 }
85
86 let kind = SymKind(p.u16().ok()?);
87 let record_data = p.bytes(record_len as usize - 2).ok()?;
88
89 self.data = p.into_rest();
90
91 Some(Sym {
92 kind,
93 data: record_data,
94 })
95 }
96}
97
98#[test]
99fn test_sym_iter() {
100 #[rustfmt::skip]
101 let data: &[u8] = &[
102 6, 0, 0x4c, 0x11, 1, 2, 3, 4, 10, 0, 0x24, 0x11, b'b', b'o', b'o', b's', b't', 0,
112 0xf1, 0xf2, 10, 0, 0x24, 0x11, b'a', b'b', b'c', b'd', b'e', b'f', b'g', 0, ];
122
123 let mut i = SymIter::new(data);
124
125 assert_eq!(i.rest_len(), 0x20);
127 let s0 = i.next().unwrap();
128 assert_eq!(s0.kind, SymKind::S_BUILDINFO);
129 let s0_data = s0.parse().unwrap();
130 assert!(matches!(s0_data, SymData::BuildInfo(_)));
131
132 assert_eq!(i.rest_len(), 0x18);
134 let s1 = i.next().unwrap();
135 assert_eq!(s1.kind, SymKind::S_UNAMESPACE);
136 match s1.parse() {
137 Ok(SymData::UsingNamespace(ns)) => assert_eq!(ns.namespace, "boost"),
138 sd => panic!("wrong: {sd:?}"),
139 }
140
141 assert_eq!(i.rest_len(), 0xc);
143 let s1 = i.next().unwrap();
144 assert_eq!(s1.kind, SymKind::S_UNAMESPACE);
145 match s1.parse() {
146 Ok(SymData::UsingNamespace(ns)) => assert_eq!(ns.namespace, "abcdefg"),
147 sd => panic!("wrong: {sd:?}"),
148 }
149
150 assert_eq!(i.rest_len(), 0);
152 assert!(i.next().is_none());
153}
154
155impl<'a> SymIterMut<'a> {
156 pub fn new(data: &'a mut [u8]) -> Self {
158 Self { data }
159 }
160
161 pub fn rest(&self) -> &[u8] {
163 self.data
164 }
165
166 pub fn rest_mut(&mut self) -> &mut [u8] {
168 self.data
169 }
170
171 pub fn into_rest(self) -> &'a mut [u8] {
173 self.data
174 }
175}
176
177impl<'a> Iterator for SymIterMut<'a> {
178 type Item = SymMut<'a>;
179
180 fn next(&mut self) -> Option<Self::Item> {
181 if self.data.len() < 4 {
182 return None;
183 }
184
185 let d = core::mem::take(&mut self.data);
187
188 let mut p = Parser::new(d);
189 let record_len = p.u16().ok()?;
190 if record_len < 2 {
191 error!(
192 record_len,
193 iterator_len = self.data.len(),
194 "type record has invalid len"
195 );
196 self.data = d;
197 return None;
198 }
199
200 let kind = SymKind(p.u16().ok()?);
201
202 let (entire_record_data, hi) = d.split_at_mut(2 + record_len as usize);
203 self.data = hi;
204
205 let record_data = &mut entire_record_data[4..];
206
207 Some(SymMut {
208 kind,
209 data: record_data,
210 })
211 }
212}