Skip to content

Commit

Permalink
fix for off by one error in file
Browse files Browse the repository at this point in the history
  • Loading branch information
casperhart committed Oct 25, 2023
1 parent ad311b6 commit 4253570
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 28 deletions.
34 changes: 26 additions & 8 deletions src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ impl<'a, T> Debug for FieldRef<'a, T> {

impl<'a, T> FieldRef<'a, T> {
fn position_in_source(&self) -> u64 {
let record_position = self
.file
.header
.record_position(self.record_index.0)
.unwrap() as u64;
let record_position = self.file.record_position(self.record_index.0).unwrap() as u64;
let position_in_record = self.file.fields_info[..self.field_index.0]
.iter()
.map(|i| i.field_length as u64)
Expand Down Expand Up @@ -195,7 +191,7 @@ impl<'a, T> RecordRef<'a, T> {
}

fn position_in_source(&self) -> u64 {
self.file.header.record_position(self.index.0).unwrap() as u64
self.file.record_position(self.index.0).unwrap() as u64
}
}

Expand Down Expand Up @@ -358,6 +354,7 @@ impl<'a, T> FileRecordIterator<'a, T> {
pub struct File<T> {
pub(crate) inner: T,
pub(crate) header: Header,
pub(crate) record_length: u16,
pub(crate) fields_info: Vec<FieldInfo>,
pub(crate) encoding: DynEncoding,
/// Non-Memo field length is stored on a u8,
Expand Down Expand Up @@ -388,6 +385,17 @@ impl<T> File<T> {
pub fn set_options(&mut self, options: ReadingOptions) {
self.options = options;
}

pub(crate) fn record_position(&self, index: usize) -> Option<usize> {
if index >= self.header.num_records as usize {
None
} else {
let offset = self.header.offset_to_first_record as usize
+ (index * (self.record_length as usize + DELETION_FLAG_SIZE))
+ DELETION_FLAG_SIZE;
Some(offset)
}
}
}

impl<T: Read + Seek> File<T> {
Expand Down Expand Up @@ -430,10 +438,14 @@ impl<T: Read + Seek> File<T> {
let field_error = FieldIOError::new(UnsupportedCodePage(header.code_page_mark), None);
Error::new(field_error, 0)
})?;

let record_length = fields_info.iter().map(|x| x.length() as u16).sum();

Ok(Self {
inner: source,
// memo_reader: None,
header,
record_length,
fields_info,
encoding,
field_data_buffer: [0u8; 255],
Expand Down Expand Up @@ -470,9 +482,16 @@ impl<T: Write + Seek> File<T> {
pub fn create_new(mut dst: T, table_info: TableInfo) -> Result<Self, Error> {
write_header_parts(&mut dst, &table_info.header, &table_info.fields_info)?;

let record_length = table_info
.fields_info
.iter()
.map(|x| x.field_length as u16)
.sum();

Ok(Self {
inner: dst,
header: table_info.header,
record_length: record_length,
fields_info: table_info.fields_info,
encoding: table_info.encoding,
field_data_buffer: [0u8; 255],
Expand Down Expand Up @@ -501,8 +520,7 @@ impl<T: Write + Seek> File<T> {
);

let end_of_last_record = self.header.offset_to_first_record as u64
+ self.num_records() as u64
* (DELETION_FLAG_SIZE as u64 + self.header.size_of_record as u64);
+ self.num_records() as u64 * (DELETION_FLAG_SIZE as u64 + self.record_length as u64);
self.inner
.seek(SeekFrom::Start(end_of_last_record))
.map_err(|error| Error::io_error(error, self.num_records()))?;
Expand Down
12 changes: 0 additions & 12 deletions src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::encoding::DynEncoding;
use std::io::{Read, Write};

use crate::field::types::Date;
use crate::field::DELETION_FLAG_SIZE;
use crate::memo::MemoFileType;

// Used this as source: https://blog.codetitans.pl/post/dbf-and-language-code-page/
Expand Down Expand Up @@ -407,17 +406,6 @@ impl Header {
dest.write_u8(0)?;
Ok(())
}

pub(crate) fn record_position(&self, index: usize) -> Option<usize> {
if index >= self.num_records as usize {
None
} else {
let offset = self.offset_to_first_record as usize
+ (index * (self.size_of_record as usize + DELETION_FLAG_SIZE))
+ DELETION_FLAG_SIZE;
Some(offset)
}
}
}

#[cfg(test)]
Expand Down
15 changes: 7 additions & 8 deletions src/reading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ impl<T: Read + Seek, E: Encoding + 'static> ReaderBuilder<T, E> {
source: file.inner,
memo_reader,
header: file.header,
record_length: file.record_length,
fields_info: file.fields_info,
encoding: self
.encoding
Expand All @@ -171,6 +172,7 @@ pub struct Reader<T: Read + Seek> {
memo_reader: Option<MemoReader<T>>,
header: Header,
fields_info: Vec<FieldInfo>,
record_length: u16,
encoding: DynEncoding,
options: ReadingOptions,
}
Expand Down Expand Up @@ -208,6 +210,7 @@ impl<T: Read + Seek> Reader<T> {
source: file.inner,
memo_reader: None,
header: file.header,
record_length: file.record_length,
fields_info: file.fields_info,
encoding: file.encoding,
options: ReadingOptions::default(),
Expand Down Expand Up @@ -243,16 +246,12 @@ impl<T: Read + Seek> Reader<T> {

/// Creates an iterator of records of the type you want
pub fn iter_records_as<R: ReadableRecord>(&mut self) -> RecordIterator<T, R> {
let record_size: usize = self
.fields_info
.iter()
.map(|i| i.field_length as usize)
.sum();
let record_length = self.record_length as usize;
RecordIterator {
reader: self,
record_type: std::marker::PhantomData,
current_record: 0,
record_data_buffer: std::io::Cursor::new(vec![0u8; record_size]),
record_data_buffer: std::io::Cursor::new(vec![0u8; record_length]),
field_data_buffer: [0u8; 255],
}
}
Expand Down Expand Up @@ -289,8 +288,8 @@ impl<T: Read + Seek> Reader<T> {

/// Seek to the start of the record at `index`
pub fn seek(&mut self, index: usize) -> Result<(), Error> {
let offset = self.header.offset_to_first_record as usize
+ (index * self.header.size_of_record as usize);
let offset =
self.header.offset_to_first_record as usize + (index * self.record_length as usize);
self.source
.seek(SeekFrom::Start(offset as u64))
.map_err(|err| Error::io_error(err, 0))?;
Expand Down

0 comments on commit 4253570

Please sign in to comment.