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