1use crate::records::*;
13use crate::stdf_codec::*;
14use crate::stdf_error::{StdfError, StdfErrorKind};
15#[cfg(feature = "bzip")]
16use bzip2::bufread::BzDecoder;
17#[cfg(feature = "gzip")]
18use flate2::bufread::GzDecoder;
19use std::io::{self, BufReader, SeekFrom}; use std::io::{BufRead, Read, Seek};
21use std::{fs, path::Path}; #[cfg(feature = "zipfile")]
23use zip::{read::ZipFile, ZipArchive};
24
25#[cfg(feature = "zipfile")]
30pub(crate) struct ZipBundle<R> {
31 file: Option<ZipFile<'static>>,
35 archive: Box<ZipArchive<R>>,
36}
37
38#[allow(clippy::large_enum_variant)]
39pub(crate) enum StdfStream<R> {
40 Binary(R),
41 #[cfg(feature = "gzip")]
42 Gz(GzDecoder<R>),
43 #[cfg(feature = "bzip")]
44 Bz(BzDecoder<R>),
45 #[cfg(feature = "zipfile")]
46 Zip(ZipBundle<R>),
47}
48
49pub struct StdfReader<R> {
103 endianness: ByteOrder,
104 stream: StdfStream<R>,
105}
106
107pub struct RecordIter<'a, R> {
111 inner: &'a mut StdfReader<R>,
112 buffer: Vec<u8>,
114}
115
116pub struct RawDataIter<'a, R> {
120 offset: u64,
121 inner: &'a mut StdfReader<R>,
122}
123
124pub struct RawDataViewIter<'a, R> {
153 offset: u64,
154 inner: &'a mut StdfReader<R>,
155 buffer: Vec<u8>,
157}
158
159impl StdfReader<BufReader<fs::File>> {
162 #[inline(always)]
164 pub fn new<P>(path: P) -> Result<Self, StdfError>
165 where
166 P: AsRef<Path>,
167 {
168 let path_string = path.as_ref().display().to_string();
170 let file_ext = path_string.rsplit('.').next();
171 let compress_type = match file_ext {
172 Some(ext) => match ext {
173 #[cfg(feature = "gzip")]
174 "gz" => CompressType::GzipCompressed,
175 #[cfg(feature = "bzip")]
176 "bz2" => CompressType::BzipCompressed,
177 #[cfg(feature = "zipfile")]
178 "zip" => CompressType::ZipCompressed,
179 _ => CompressType::Uncompressed,
180 },
181 None => CompressType::Uncompressed,
182 };
183 let fp = fs::OpenOptions::new().read(true).open(path)?;
184 let br = BufReader::with_capacity(2 << 20, fp);
185 StdfReader::from(br, &compress_type)
186 }
187}
188
189impl<R: BufRead + Seek> StdfReader<R> {
190 #[inline(always)]
192 pub fn from(in_stream: R, compress_type: &CompressType) -> Result<Self, StdfError> {
193 let mut stream = match compress_type {
194 #[cfg(feature = "gzip")]
195 CompressType::GzipCompressed => StdfStream::Gz(GzDecoder::new(in_stream)),
196 #[cfg(feature = "bzip")]
197 CompressType::BzipCompressed => StdfStream::Bz(BzDecoder::new(in_stream)),
198 #[cfg(feature = "zipfile")]
199 CompressType::ZipCompressed => StdfStream::Zip(ZipBundle::new(in_stream, 0)?),
200 _ => StdfStream::Binary(in_stream),
201 };
202
203 let mut buf = [0u8; 4];
205 stream.read_exact(&mut buf)?;
206 let far_header = RecordHeader::new().read_from_bytes(&buf, &ByteOrder::LittleEndian)?;
208 let endianness = match far_header.len {
209 2 => Ok(ByteOrder::LittleEndian),
210 512 => Ok(ByteOrder::BigEndian),
211 _ => Err(StdfError::new(
212 StdfErrorKind::InvalidStdfFile,
213 String::from("Cannot determine endianness"),
214 )),
215 }?;
216 if (far_header.typ, far_header.sub) != (0, 10) {
218 return Err(StdfError::new(
219 StdfErrorKind::InvalidStdfFile,
220 format!(
221 "FAR header (0, 10) expected, but {:?} is found",
222 (far_header.typ, far_header.sub)
223 ),
224 ));
225 }
226 stream = rewind_stream_position(stream)?;
234
235 Ok(StdfReader { endianness, stream })
236 }
237
238 #[inline(always)]
239 fn read_header(&mut self) -> Result<RecordHeader, StdfError> {
240 let mut buf = [0u8; 4];
241 self.stream.read_exact(&mut buf)?;
242 RecordHeader::new().read_from_bytes(&buf, &self.endianness)
243 }
244
245 #[inline(always)]
250 pub fn get_record_iter(&mut self) -> RecordIter<'_, R> {
251 RecordIter {
252 inner: self,
253 buffer: Vec::with_capacity(1024),
254 }
255 }
256
257 #[inline(always)]
262 pub fn get_rawdata_iter(&mut self) -> RawDataIter<'_, R> {
263 RawDataIter {
264 offset: 0,
265 inner: self,
266 }
267 }
268
269 #[inline(always)]
278 pub fn get_rawdata_view_iter(&mut self) -> RawDataViewIter<'_, R> {
279 RawDataViewIter {
280 offset: 0,
281 inner: self,
282 buffer: Vec::with_capacity(1024),
283 }
284 }
285}
286
287#[cfg(feature = "zipfile")]
288impl<R: BufRead + Seek> ZipBundle<R> {
289 pub(crate) fn new(stream: R, file_index: usize) -> Result<ZipBundle<R>, StdfError> {
292 let archive = ZipArchive::new(stream)?;
293 let mut archive = Box::new(archive);
294
295 let file = unsafe {
300 std::mem::transmute::<ZipFile<'_>, ZipFile<'static>>(archive.by_index(file_index)?)
301 };
302 Ok(ZipBundle {
303 archive,
304 file: Some(file),
305 })
306 }
307
308 pub(crate) fn reopen_file(&mut self, file_index: usize) -> Result<(), StdfError> {
309 self.file = None;
311 let file = unsafe {
313 std::mem::transmute::<ZipFile<'_>, ZipFile<'static>>(self.archive.by_index(file_index)?)
314 };
315 self.file = Some(file);
316 Ok(())
317 }
318}
319
320#[cfg(feature = "zipfile")]
321impl<R: BufRead + Seek> Read for ZipBundle<R> {
322 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
323 self.file.as_mut().unwrap().read(buf)
324 }
325}
326
327impl<R: BufRead + Seek> StdfStream<R> {
328 #[cfg(feature = "atdf")]
329 #[inline(always)]
330 pub(crate) fn read_until(&mut self, delim: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
331 match self {
332 StdfStream::Binary(bstream) => bstream.read_until(delim, buf),
333 #[cfg(feature = "gzip")]
334 StdfStream::Gz(gzstream) => general_read_until(gzstream, delim, buf),
335 #[cfg(feature = "bzip")]
336 StdfStream::Bz(bzstream) => general_read_until(bzstream, delim, buf),
337 #[cfg(feature = "zipfile")]
338 StdfStream::Zip(zipstream) => general_read_until(zipstream, delim, buf),
339 }
340 }
341}
342
343impl<R: BufRead + Seek> Read for StdfStream<R> {
344 #[inline(always)]
345 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
346 match self {
347 StdfStream::Binary(bstream) => bstream.read(buf),
348 #[cfg(feature = "gzip")]
349 StdfStream::Gz(gzstream) => gzstream.read(buf),
350 #[cfg(feature = "bzip")]
351 StdfStream::Bz(bzstream) => bzstream.read(buf),
352 #[cfg(feature = "zipfile")]
353 StdfStream::Zip(zipstream) => zipstream.read(buf),
354 }
355 }
356}
357
358impl<R: BufRead + Seek> Iterator for RecordIter<'_, R> {
369 type Item = Result<StdfRecord, StdfError>;
370
371 #[inline(always)]
372 fn next(&mut self) -> Option<Self::Item> {
373 let header = match self.inner.read_header() {
374 Ok(h) => h,
375 Err(e) => {
376 return match e.kind() {
377 Some(StdfErrorKind::Eof) => None,
380 _ => Some(Err(e)),
381 };
382 }
383 };
384 let len = header.len as usize;
387 if self.buffer.len() < len {
388 self.buffer.resize(len, 0);
389 }
390 if let Err(io_e) = self.inner.stream.read_exact(&mut self.buffer[..len]) {
391 return Some(Err(StdfError::new(StdfErrorKind::Io, io_e.to_string())));
392 }
393
394 let mut rec = StdfRecord::new_from_header(header);
395 rec.read_from_bytes(&self.buffer[..len], &self.inner.endianness);
396 Some(Ok(rec))
397 }
398}
399
400impl<R: BufRead + Seek> Iterator for RawDataIter<'_, R> {
401 type Item = Result<RawDataElement, StdfError>;
402
403 #[inline(always)]
404 fn next(&mut self) -> Option<Self::Item> {
405 let header = match self.inner.read_header() {
406 Ok(h) => h,
407 Err(e) => {
408 return match e.kind() {
409 Some(StdfErrorKind::Eof) => None,
411 _ => Some(Err(e)),
412 };
413 }
414 };
415 self.offset += 4;
417 let data_offset = self.offset;
418 let mut buffer = vec![0u8; header.len as usize];
420 if let Err(io_e) = self.inner.stream.read_exact(&mut buffer) {
421 return Some(Err(StdfError::new(StdfErrorKind::Io, io_e.to_string())));
422 }
423 self.offset += header.len as u64;
424
425 Some(Ok(RawDataElement {
426 offset: data_offset,
427 header,
428 raw_data: buffer,
429 byte_order: self.inner.endianness,
430 }))
431 }
432}
433
434impl<R: BufRead + Seek> RawDataViewIter<'_, R> {
435 #[inline(always)]
442 #[allow(clippy::should_implement_trait)] pub fn next(&mut self) -> Option<Result<RawDataElementView<'_>, StdfError>> {
444 let header = match self.inner.read_header() {
445 Ok(h) => h,
446 Err(e) => {
447 return match e.kind() {
448 Some(StdfErrorKind::Eof) => None,
450 _ => Some(Err(e)),
451 };
452 }
453 };
454 self.offset += 4;
456 let data_offset = self.offset;
457 let len = header.len as usize;
460 if self.buffer.len() < len {
461 self.buffer.resize(len, 0);
462 }
463 if let Err(io_e) = self.inner.stream.read_exact(&mut self.buffer[..len]) {
464 return Some(Err(StdfError::new(StdfErrorKind::Io, io_e.to_string())));
465 }
466 self.offset += header.len as u64;
467
468 Some(Ok(RawDataElementView {
469 offset: data_offset,
470 header,
471 raw_data: &self.buffer[..len],
472 byte_order: self.inner.endianness,
473 }))
474 }
475}
476
477#[inline(always)]
480pub(crate) fn rewind_stream_position<R: BufRead + Seek>(
481 old_stream: StdfStream<R>,
482) -> Result<StdfStream<R>, StdfError> {
483 let new_stream = match old_stream {
484 StdfStream::Binary(mut br) => {
485 br.seek(SeekFrom::Start(0))?;
486 StdfStream::Binary(br)
487 }
488 #[cfg(feature = "gzip")]
489 StdfStream::Gz(gzr) => {
490 let mut fp = gzr.into_inner();
492 fp.seek(SeekFrom::Start(0))?;
493 StdfStream::Gz(GzDecoder::new(fp))
494 }
495 #[cfg(feature = "bzip")]
496 StdfStream::Bz(bzr) => {
497 let mut fp = bzr.into_inner();
499 fp.seek(SeekFrom::Start(0))?;
500 StdfStream::Bz(BzDecoder::new(fp))
501 }
502 #[cfg(feature = "zipfile")]
503 StdfStream::Zip(mut zipr) => {
504 zipr.reopen_file(0)?;
505 StdfStream::Zip(zipr)
506 }
507 };
508 Ok(new_stream)
509}
510
511#[cfg(all(feature = "atdf", any(feature = "gzip", feature = "bzip",)))]
512#[inline(always)]
513fn general_read_until<T: Read>(r: &mut T, delim: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
514 let mut one_byte = [0u8; 1];
515 let mut n: usize = 0;
516 loop {
517 match r.read(&mut one_byte) {
519 Ok(num) => {
520 if num == 0 {
521 break;
523 }
524 }
525 Err(e) => return Err(e),
526 };
527 buf.extend_from_slice(&one_byte);
528 n += 1;
529 if delim == one_byte[0] {
531 break;
532 }
533 }
534 Ok(n)
535}