use crate::edi_parse_error::EdiParseError;
use crate::functional_group::FunctionalGroup;
use crate::tokenizer::SegmentTokens;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::collections::VecDeque;
#[derive(PartialEq, Debug, Serialize, Deserialize)]
pub struct InterchangeControl<'a, 'b> {
#[serde(borrow)]
pub authorization_qualifier: Cow<'a, str>,
#[serde(borrow)]
pub authorization_information: Cow<'a, str>,
#[serde(borrow)]
pub security_qualifier: Cow<'a, str>,
#[serde(borrow)]
pub security_information: Cow<'a, str>,
#[serde(borrow)]
pub sender_qualifier: Cow<'a, str>,
#[serde(borrow)]
pub sender_id: Cow<'a, str>,
#[serde(borrow)]
pub receiver_qualifier: Cow<'a, str>,
#[serde(borrow)]
pub receiver_id: Cow<'a, str>,
#[serde(borrow)]
pub date: Cow<'a, str>, #[serde(borrow)]
pub time: Cow<'a, str>, #[serde(borrow)]
pub standards_id: Cow<'a, str>,
#[serde(borrow)]
pub version: Cow<'a, str>, #[serde(borrow)]
pub interchange_control_number: Cow<'a, str>, #[serde(borrow)]
pub acknowledgement_requested: Cow<'a, str>, #[serde(borrow)]
pub test_indicator: Cow<'a, str>, #[serde(borrow = "'a + 'b")]
pub functional_groups: VecDeque<FunctionalGroup<'a, 'b>>,
}
impl<'a, 'b> InterchangeControl<'a, 'b> {
pub fn parse_from_tokens(
input: SegmentTokens<'a>,
) -> Result<InterchangeControl<'a, 'b>, EdiParseError> {
let elements: Vec<&str> = input.iter().map(|x| x.trim()).collect();
edi_assert!(
elements[0] == "ISA",
"attempted to parse ISA from non-ISA segment"
);
edi_assert!(
elements.len() >= 16,
"ISA segment does not contain enough elements",
elements.len()
);
let (
authorization_qualifier,
authorization_information,
security_qualifier,
security_information,
sender_qualifier,
sender_id,
receiver_qualifier,
receiver_id,
date,
time,
standards_id,
version,
interchange_control_number,
acknowledgement_requested,
test_indicator,
) = (
Cow::from(elements[1]),
Cow::from(elements[2]),
Cow::from(elements[3]),
Cow::from(elements[4]),
Cow::from(elements[5]),
Cow::from(elements[6]),
Cow::from(elements[7]),
Cow::from(elements[8]),
Cow::from(elements[9]),
Cow::from(elements[10]),
Cow::from(elements[11]),
Cow::from(elements[12]),
Cow::from(elements[13]),
Cow::from(elements[14]),
Cow::from(elements[15]),
);
Ok(InterchangeControl {
authorization_qualifier,
authorization_information,
security_qualifier,
security_information,
sender_qualifier,
sender_id,
receiver_qualifier,
receiver_id,
date,
time,
standards_id,
version,
interchange_control_number,
acknowledgement_requested,
test_indicator,
functional_groups: VecDeque::new(),
})
}
pub fn add_functional_group(&mut self, tokens: SegmentTokens<'a>) {
self.functional_groups.push_back(
FunctionalGroup::parse_from_tokens(tokens)
.expect("failed to parse functional group header"),
);
}
pub fn add_transaction(&mut self, tokens: SegmentTokens<'a>) {
self.functional_groups
.back_mut()
.expect("unable to enqueue transaction when no functional groups have been added")
.add_transaction(tokens)
}
pub fn add_generic_segment(&mut self, tokens: SegmentTokens<'a>) {
self.functional_groups
.back_mut()
.expect("unable to enqueue generic segment when no functional groups have been added")
.add_generic_segment(tokens);
}
pub fn validate_interchange_control(
&self,
tokens: SegmentTokens<'a>,
) -> Result<(), EdiParseError> {
edi_assert!(
tokens[0] == "IEA",
"attempted to verify IEA on non-IEA segment"
);
edi_assert!(
str::parse::<usize>(&tokens[1].to_string()).unwrap() == self.functional_groups.len(),
"interchange validation failed: incorrect number of functional groups",
tokens[1].to_string(),
self.functional_groups.len()
);
edi_assert!(
tokens[2] == self.interchange_control_number,
"interchange validation failed: mismatched ID",
tokens[2],
self.interchange_control_number.clone()
);
Ok(())
}
pub fn validate_functional_group(
&self,
tokens: SegmentTokens<'a>,
) -> Result<(), EdiParseError> {
self.functional_groups
.back()
.expect("unable to verify nonexistent functional group")
.validate_functional_group(tokens)
}
pub fn validate_transaction(&self, tokens: SegmentTokens<'a>) -> Result<(), EdiParseError> {
self.functional_groups
.back()
.expect("unable to verify transaction within nonexistent functional group")
.validate_transaction(tokens)
}
}
#[test]
fn construct_interchange_control() {
let expected_result = InterchangeControl {
authorization_qualifier: Cow::from("00"),
authorization_information: Cow::from(""),
security_qualifier: Cow::from("00"),
security_information: Cow::from(""),
sender_qualifier: Cow::from("ZZ"),
sender_id: Cow::from("SENDERISA"),
receiver_qualifier: Cow::from("14"),
receiver_id: Cow::from("0073268795005"),
date: Cow::from("020226"),
time: Cow::from("1534"),
standards_id: Cow::from("U"),
version: Cow::from("00401"),
interchange_control_number: Cow::from("000000001"),
acknowledgement_requested: Cow::from("0"),
test_indicator: Cow::from("T"),
functional_groups: VecDeque::new(),
};
let test_input = vec![
"ISA",
"00",
"",
"00",
"",
"ZZ",
"SENDERISA",
"14",
"0073268795005",
"020226",
"1534",
"U",
"00401",
"000000001",
"0",
"T",
];
assert_eq!(
InterchangeControl::parse_from_tokens(test_input,).unwrap(),
expected_result
);
}