Skip to content

Commit

Permalink
Fix explode on copy level (#784)
Browse files Browse the repository at this point in the history
This change fixes splitting a record on copy level when multiple,
consecutive local fields are present.

Closes: #770

Signed-off-by: Nico Wagner <[email protected]>
  • Loading branch information
nwagner84 authored May 29, 2024
1 parent 3efe646 commit c41e38f
Showing 1 changed file with 26 additions and 12 deletions.
38 changes: 26 additions & 12 deletions crates/pica-toolkit/src/commands/explode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ macro_rules! push_record {
($records:expr, $main:expr, $local:expr, $acc:expr) => {
if !$acc.is_empty() {
let mut record = $main.clone();
if let Some(local) = $local {
record.push(local);
if !$local.is_empty() {
record.extend_from_slice(&$local);
}
record.extend_from_slice(&$acc);

Expand Down Expand Up @@ -144,32 +144,40 @@ fn process_copy(
options: &MatcherOptions,
writer: &mut Box<dyn ByteRecordWrite>,
) -> io::Result<()> {
let mut main = vec![];
let mut acc = vec![];
let mut last = Level::Main;
let mut records = vec![];
let mut local = None;
let mut main = vec![];
let mut local = vec![];
let mut copy = vec![];
let mut count = None;

for field in record.iter() {
match field.level() {
Level::Main => main.push(field),
Level::Local => {
push_record!(records, main, local, acc);
local = Some(field);
count = None;
if last == Level::Copy {
push_record!(records, main, local, copy);
local.clear();
count = None;
}

local.push(field);
}
Level::Copy => {
if count != field.occurrence() {
push_record!(records, main, local, acc);
push_record!(records, main, local, copy);
count = field.occurrence();
}

acc.push(field);
copy.push(field);
}
}

last = field.level();
}

push_record!(records, main, local, acc);
push_record!(records, main, local, copy);

for fields in records {
let data = record_bytes!(fields);
let record =
Expand All @@ -196,16 +204,22 @@ fn process_local(
let mut main = vec![];
let mut acc = vec![];
let mut records = vec![];
let mut last = Level::Main;

for field in record.iter() {
match field.level() {
Level::Main => main.push(field),
Level::Copy => acc.push(field),
Level::Local => {
push_record!(records, main, acc);
if last == Level::Copy {
push_record!(records, main, acc);
}

acc.push(field)
}
}

last = field.level();
}

push_record!(records, main, acc);
Expand Down

0 comments on commit c41e38f

Please sign in to comment.