1use crate::{DbcHeader, Error, FieldType, Record, Result, Schema, StringBlock, Value};
4use std::io::{Cursor, Read};
5use std::sync::Arc;
6
7pub struct LazyRecordIterator<'a> {
9 cursor: Cursor<&'a [u8]>,
11 header: &'a DbcHeader,
13 schema: Option<&'a Schema>,
15 current_index: u32,
17 total_records: u32,
19}
20
21impl<'a> LazyRecordIterator<'a> {
22 pub fn new(
24 data: &'a [u8],
25 header: &'a DbcHeader,
26 schema: Option<&'a Schema>,
27 _string_block: Arc<StringBlock>,
28 ) -> Self {
29 let mut cursor = Cursor::new(data);
30 cursor.set_position(DbcHeader::SIZE as u64);
31
32 Self {
33 cursor,
34 header,
35 schema,
36 current_index: 0,
37 total_records: header.record_count,
38 }
39 }
40}
41
42impl Iterator for LazyRecordIterator<'_> {
43 type Item = Result<Record>;
44
45 fn next(&mut self) -> Option<Self::Item> {
46 if self.current_index >= self.total_records {
47 return None;
48 }
49
50 let record = if let Some(schema) = self.schema {
51 self.parse_record_with_schema(schema)
52 } else {
53 self.parse_record_raw()
54 };
55
56 self.current_index += 1;
57 Some(record)
58 }
59}
60
61impl LazyRecordIterator<'_> {
62 fn parse_record_with_schema(&mut self, schema: &Schema) -> Result<Record> {
64 let mut values = Vec::with_capacity(schema.fields.len());
65
66 for field in &schema.fields {
67 let value = if field.is_array {
68 let array_size = field.array_size.unwrap_or(0);
69 let mut array_values = Vec::with_capacity(array_size);
70
71 for _ in 0..array_size {
72 array_values.push(self.parse_field_value(field.field_type)?);
73 }
74
75 Value::Array(array_values)
76 } else {
77 self.parse_field_value(field.field_type)?
78 };
79
80 values.push(value);
81 }
82
83 Ok(Record::new(values, Some(Arc::new(schema.clone()))))
84 }
85
86 fn parse_record_raw(&mut self) -> Result<Record> {
88 let mut values = Vec::with_capacity(self.header.field_count as usize);
89
90 for _ in 0..self.header.field_count {
91 let mut buf = [0u8; 4];
93 self.cursor.read_exact(&mut buf)?;
94 let value = u32::from_le_bytes(buf);
95 values.push(Value::UInt32(value));
96 }
97
98 Ok(Record::new(values, None))
99 }
100
101 fn parse_field_value(&mut self, field_type: FieldType) -> Result<Value> {
103 crate::field_parser::parse_field_value(&mut self.cursor, field_type)
104 }
105}
106
107pub struct LazyDbcParser<'a> {
109 header: &'a DbcHeader,
111 schema: Option<&'a Schema>,
113 data: &'a [u8],
115 string_block: Arc<StringBlock>,
117}
118
119impl<'a> LazyDbcParser<'a> {
120 pub fn new(
122 data: &'a [u8],
123 header: &'a DbcHeader,
124 schema: Option<&'a Schema>,
125 string_block: Arc<StringBlock>,
126 ) -> Self {
127 Self {
128 data,
129 header,
130 schema,
131 string_block,
132 }
133 }
134
135 pub fn record_iterator(&self) -> LazyRecordIterator<'a> {
137 LazyRecordIterator::new(
138 self.data,
139 self.header,
140 self.schema,
141 Arc::clone(&self.string_block),
142 )
143 }
144
145 pub fn get_record(&self, index: u32) -> Result<Record> {
147 if index >= self.header.record_count {
148 return Err(Error::OutOfBounds(format!(
149 "Record index out of bounds: {} (max: {})",
150 index,
151 self.header.record_count - 1
152 )));
153 }
154
155 let mut cursor = Cursor::new(self.data);
156 let record_position =
157 DbcHeader::SIZE as u64 + (index as u64 * self.header.record_size as u64);
158 cursor.set_position(record_position);
159
160 if let Some(schema) = self.schema {
161 self.parse_record_with_schema(&mut cursor, schema)
162 } else {
163 self.parse_record_raw(&mut cursor)
164 }
165 }
166
167 fn parse_record_with_schema(
169 &self,
170 cursor: &mut Cursor<&'a [u8]>,
171 schema: &Schema,
172 ) -> Result<Record> {
173 let mut values = Vec::with_capacity(schema.fields.len());
174
175 for field in &schema.fields {
176 let value = if field.is_array {
177 let array_size = field.array_size.unwrap_or(0);
178 let mut array_values = Vec::with_capacity(array_size);
179
180 for _ in 0..array_size {
181 array_values.push(self.parse_field_value(cursor, field.field_type)?);
182 }
183
184 Value::Array(array_values)
185 } else {
186 self.parse_field_value(cursor, field.field_type)?
187 };
188
189 values.push(value);
190 }
191
192 Ok(Record::new(values, Some(Arc::new(schema.clone()))))
193 }
194
195 fn parse_record_raw(&self, cursor: &mut Cursor<&'a [u8]>) -> Result<Record> {
197 let mut values = Vec::with_capacity(self.header.field_count as usize);
198
199 for _ in 0..self.header.field_count {
200 let mut buf = [0u8; 4];
202 cursor.read_exact(&mut buf)?;
203 let value = u32::from_le_bytes(buf);
204 values.push(Value::UInt32(value));
205 }
206
207 Ok(Record::new(values, None))
208 }
209
210 fn parse_field_value(
212 &self,
213 cursor: &mut Cursor<&'a [u8]>,
214 field_type: FieldType,
215 ) -> Result<Value> {
216 crate::field_parser::parse_field_value(cursor, field_type)
217 }
218
219 pub fn header(&self) -> &DbcHeader {
221 self.header
222 }
223
224 pub fn schema(&self) -> Option<&Schema> {
226 self.schema
227 }
228
229 pub fn string_block(&self) -> &StringBlock {
231 &self.string_block
232 }
233}