Skip to content

Commit

Permalink
Fix off by one error in dbase::File
Browse files Browse the repository at this point in the history
dbase::File calculated the position of the record/field
assuming the record size by using the header's info
which includes the implicit deletion flag size, and dbase::File
added the deletion flag size again resulting of bad readings.
  • Loading branch information
tmontaigu committed Oct 24, 2023
1 parent ddb11cb commit de94c80
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 15 deletions.
4 changes: 2 additions & 2 deletions src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl<'a, T> FieldRef<'a, T> {
.map(|i| i.field_length as u64)
.sum::<u64>();

record_position + position_in_record
record_position + position_in_record + DELETION_FLAG_SIZE as u64
}
}

Expand Down Expand Up @@ -227,7 +227,7 @@ where
/// - true -> the record is marked as deleted
/// - false -> the record is **not** marked as deleted
pub fn is_deleted(&mut self) -> Result<bool, Error> {
let deletion_flag_pos = self.position_in_source() - DELETION_FLAG_SIZE as u64;
let deletion_flag_pos = self.position_in_source();
self.file
.inner
.seek(SeekFrom::Start(deletion_flag_pos))
Expand Down
6 changes: 2 additions & 4 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 @@ -412,9 +411,8 @@ impl Header {
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;
let offset =
self.offset_to_first_record as usize + (index * self.size_of_record as usize);
Some(offset)
}
}
Expand Down
29 changes: 20 additions & 9 deletions tests/test_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,37 +299,48 @@ fn test_file_char_trimming() -> Result<(), Box<dyn std::error::Error>> {
}
);

let mut file = dbase::File::open_read_only("tests/data/stations.dbf")?;
let reading = dbase::ReadingOptions::default().character_trim(dbase::TrimOption::End);
file.set_options(reading);

let expected_trim_end = StationRecord {
name: format!("{}", " Franconia-Springfield",),
marker_col: format!("{}", " #0000ff",),
marker_sym: format!("{}", " rail-metro",),
line: format!("{}", " blue",),
};

let record = file.record(1).unwrap().read_as::<StationRecord>()?;
assert_eq!(record, expected_trim_end);

let mut file = dbase::File::open_read_only("tests/data/stations.dbf")?;
let reading = dbase::ReadingOptions::default().character_trim(dbase::TrimOption::Begin);
file.set_options(reading);

let expected = StationRecord {
let expected_trim_begin = StationRecord {
name: format!(
"{:width$}",
"Franconia-Springfield",
width = file.fields()[0].length() as usize
width = file.fields()[0].length() as usize - 2
),
marker_col: format!(
"{:width$}",
"#0000ff",
width = file.fields()[0].length() as usize
width = file.fields()[0].length() as usize - 2
),
marker_sym: format!(
"{:width$}",
"rail-metro",
width = file.fields()[0].length() as usize
width = file.fields()[0].length() as usize - 2
),
line: format!(
"{:width$}",
"blue",
width = file.fields()[0].length() as usize
width = file.fields()[0].length() as usize - 2
),
};

let record = file.record(1).unwrap().read_as::<StationRecord>()?;

assert_eq!(record, expected);

assert_eq!(record, expected_trim_begin);
Ok(())
}

Expand Down

0 comments on commit de94c80

Please sign in to comment.