1 use super::{fseek_locked, ftell_locked, FILE, SEEK_SET}; 2 use crate::{ 3 core_io::Read, 4 platform::types::off_t, 5 }; 6 struct LookAheadBuffer { 7 buf: *const u8, 8 pos: isize, 9 look_ahead: isize, 10 } 11 impl LookAheadBuffer { 12 fn look_ahead(&mut self) -> Result<Option<u8>, i32> { 13 let byte = unsafe { *self.buf.offset(self.look_ahead) }; 14 if byte == 0 { 15 Ok(None) 16 } else { 17 self.look_ahead += 1; 18 Ok(Some(byte)) 19 } 20 } 21 22 fn commit(&mut self) { 23 self.pos = self.look_ahead; 24 } 25 } 26 27 impl From<*const u8> for LookAheadBuffer { 28 fn from(buff: *const u8) -> LookAheadBuffer { 29 LookAheadBuffer { 30 buf: buff, 31 pos: 0, 32 look_ahead: 0, 33 } 34 } 35 } 36 37 struct LookAheadFile<'a> { 38 f: &'a mut FILE, 39 look_ahead: i64, 40 } 41 42 impl<'a> LookAheadFile<'a> { 43 fn look_ahead(&mut self) -> Result<Option<u8>, i32> { 44 let buf = &mut [0]; 45 let seek = unsafe { ftell_locked(self.f) }; 46 unsafe { fseek_locked(self.f, self.look_ahead as off_t, SEEK_SET) }; 47 let ret = match self.f.read(buf) { 48 Ok(0) => Ok(None), 49 Ok(_) => Ok(Some(buf[0])), 50 Err(_) => Err(-1), 51 }; 52 unsafe { fseek_locked(self.f, seek, SEEK_SET) }; 53 self.look_ahead += 1; 54 ret 55 } 56 57 fn commit(&mut self) { 58 unsafe { fseek_locked(self.f, self.look_ahead as off_t, SEEK_SET) }; 59 } 60 } 61 62 impl<'a> From<&'a mut FILE> for LookAheadFile<'a> { 63 fn from(f: &'a mut FILE) -> LookAheadFile<'a> { 64 let look_ahead = unsafe { ftell_locked(f) } as i64; 65 LookAheadFile { f, look_ahead } 66 } 67 } 68 69 enum LookAheadReaderEnum<'a> { 70 FILE(LookAheadFile<'a>), 71 // (buffer, location) 72 BUFFER(LookAheadBuffer), 73 } 74 75 pub struct LookAheadReader<'a>(LookAheadReaderEnum<'a>); 76 77 impl<'a> LookAheadReader<'a> { 78 pub fn lookahead1(&mut self) -> Result<Option<u8>, i32> { 79 match &mut self.0 { 80 LookAheadReaderEnum::FILE(f) => f.look_ahead(), 81 LookAheadReaderEnum::BUFFER(b) => b.look_ahead(), 82 } 83 } 84 pub fn commit(&mut self) { 85 match &mut self.0 { 86 LookAheadReaderEnum::FILE(f) => f.commit(), 87 LookAheadReaderEnum::BUFFER(b) => b.commit(), 88 } 89 } 90 } 91 92 impl<'a> From<&'a mut FILE> for LookAheadReader<'a> { 93 fn from(f: &'a mut FILE) -> LookAheadReader { 94 LookAheadReader(LookAheadReaderEnum::FILE(f.into())) 95 } 96 } 97 98 impl<'a> From<*const u8> for LookAheadReader<'a> { 99 fn from(buff: *const u8) -> LookAheadReader<'a> { 100 LookAheadReader(LookAheadReaderEnum::BUFFER(buff.into())) 101 } 102 } 103