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 skip_module_prefix(&mut self) {
50 if self.data.len() >= 4 {
51 self.data = &self.data[4..];
52 }
53 }
54
55 pub fn for_module_syms(data: &'a [u8]) -> Self {
60 Self {
61 data: if data.len() < 4 { &[] } else { &data[4..] },
62 }
63 }
64
65 pub fn get_signature(&mut self) -> Result<[u8; 4], ParserError> {
67 let mut p = Parser::new(self.data);
68 let sig = p.copy()?;
69 self.data = p.into_rest();
70 Ok(sig)
71 }
72
73 pub fn rest(&self) -> &'a [u8] {
75 self.data
76 }
77
78 pub fn one(data: &'a [u8]) -> Option<Sym<'a>> {
80 Self::new(data).next()
81 }
82}
83
84impl<'a> Iterator for SymIter<'a> {
85 type Item = Sym<'a>;
86
87 fn next(&mut self) -> Option<Self::Item> {
88 if self.data.is_empty() {
89 return None;
90 }
91
92 let mut p = Parser::new(self.data);
93 let record_len = p.u16().ok()?;
94 if record_len < 2 {
95 error!(
96 invalid_record_len = record_len,
97 iterator_pos = self.data.len(),
98 "type record has invalid len"
99 );
100 return None;
101 }
102
103 let kind = SymKind(p.u16().ok()?);
104 let record_data = p.bytes(record_len as usize - 2).ok()?;
105
106 self.data = p.into_rest();
107
108 Some(Sym {
109 kind,
110 data: record_data,
111 })
112 }
113}
114
115#[test]
116fn test_sym_iter() {
117 #[rustfmt::skip]
118 let data: &[u8] = &[
119 6, 0, 0x4c, 0x11, 1, 2, 3, 4, 10, 0, 0x24, 0x11, b'b', b'o', b'o', b's', b't', 0,
129 0xf1, 0xf2, 10, 0, 0x24, 0x11, b'a', b'b', b'c', b'd', b'e', b'f', b'g', 0, ];
139
140 let mut i = SymIter::new(data);
141
142 assert_eq!(i.rest_len(), 0x20);
144 let s0 = i.next().unwrap();
145 assert_eq!(s0.kind, SymKind::S_BUILDINFO);
146 let s0_data = s0.parse().unwrap();
147 assert!(matches!(s0_data, SymData::BuildInfo(_)));
148
149 assert_eq!(i.rest_len(), 0x18);
151 let s1 = i.next().unwrap();
152 assert_eq!(s1.kind, SymKind::S_UNAMESPACE);
153 match s1.parse() {
154 Ok(SymData::UsingNamespace(ns)) => assert_eq!(ns.namespace, "boost"),
155 sd => panic!("wrong: {sd:?}"),
156 }
157
158 assert_eq!(i.rest_len(), 0xc);
160 let s1 = i.next().unwrap();
161 assert_eq!(s1.kind, SymKind::S_UNAMESPACE);
162 match s1.parse() {
163 Ok(SymData::UsingNamespace(ns)) => assert_eq!(ns.namespace, "abcdefg"),
164 sd => panic!("wrong: {sd:?}"),
165 }
166
167 assert_eq!(i.rest_len(), 0);
169 assert!(i.next().is_none());
170}
171
172impl<'a> SymIterMut<'a> {
173 pub fn new(data: &'a mut [u8]) -> Self {
175 Self { data }
176 }
177
178 pub fn rest(&self) -> &[u8] {
180 self.data
181 }
182
183 pub fn rest_mut(&mut self) -> &mut [u8] {
185 self.data
186 }
187
188 pub fn into_rest(self) -> &'a mut [u8] {
190 self.data
191 }
192}
193
194impl<'a> Iterator for SymIterMut<'a> {
195 type Item = SymMut<'a>;
196
197 fn next(&mut self) -> Option<Self::Item> {
198 if self.data.len() < 4 {
199 return None;
200 }
201
202 let d = core::mem::take(&mut self.data);
204
205 let mut p = Parser::new(d);
206 let record_len = p.u16().ok()?;
207 if record_len < 2 {
208 error!(
209 record_len,
210 iterator_len = self.data.len(),
211 "type record has invalid len"
212 );
213 self.data = d;
214 return None;
215 }
216
217 let kind = SymKind(p.u16().ok()?);
218
219 let (entire_record_data, hi) = d.split_at_mut(2 + record_len as usize);
220 self.data = hi;
221
222 let record_data = &mut entire_record_data[4..];
223
224 Some(SymMut {
225 kind,
226 data: record_data,
227 })
228 }
229}