use std::borrow::Borrow;
use std::collections::{HashMap,HashSet};
use std::collections::hash_map::Entry;
use std::fmt;
use std::iter::FromIterator;
use std::mem;
use std::str::FromStr;
use constant::{FIX_4_0_BEGIN_STRING,FIX_4_1_BEGIN_STRING,FIX_4_2_BEGIN_STRING,FIX_4_3_BEGIN_STRING,FIX_4_4_BEGIN_STRING,FIXT_1_1_BEGIN_STRING,TAG_END,VALUE_END};
use dictionary::messages::{Logon,NullMessage};
use dictionary::fields::{ApplVerID,SenderCompID,TargetCompID};
use dictionary::field_types::other::DefaultApplVerIDFieldType;
use field::Field;
use field_tag::FieldTag;
use field_type::FieldType;
use fix_version::FIXVersion;
use fixt::message::{BuildFIXTMessage,FIXTMessage};
use hash::BuildFieldHasher;
use message::{BuildMessage,FieldHashMap,FieldHashSet,Meta,Message,SetValueError};
use message_version::MessageVersion;
use rule::Rule;
const BEGINSTR_TAG_BYTES: &'static [u8] = b"8";
const BEGINSTR_TAG: FieldTag = FieldTag(8);
const BODYLENGTH_TAG_BYTES: &'static [u8] = b"9";
const BODYLENGTH_TAG: FieldTag = FieldTag(9);
const MSGTYPE_TAG: FieldTag = FieldTag(35);
const CHECKSUM_TAG_BYTES: &'static [u8] = b"10";
const CHECKSUM_TAG: FieldTag = FieldTag(10);
pub enum ParseError {
MissingRequiredTag(FieldTag,Box<FIXTMessage + Send>), MissingConditionallyRequiredTag(FieldTag,Box<FIXTMessage + Send>), BeginStrNotFirstTag,
BodyLengthNotSecondTag,
BodyLengthNotNumber,
MsgTypeNotThirdTag,
MsgTypeUnknown(Vec<u8>), SenderCompIDNotFourthTag,
TargetCompIDNotFifthTag,
ApplVerIDNotSixthTag, ChecksumNotLastTag, ChecksumDoesNotMatch(u8,u8), ChecksumWrongFormat,
DuplicateTag(FieldTag),
UnexpectedTag(FieldTag), UnknownTag(FieldTag), WrongFormatTag(FieldTag),
OutOfRangeTag(FieldTag),
NoValueAfterTag(FieldTag),
MissingPrecedingLengthTag(FieldTag), MissingFollowingLengthTag(FieldTag), NonRepeatingGroupTagInRepeatingGroup(FieldTag), RepeatingGroupTagWithNoRepeatingGroup(FieldTag), MissingFirstRepeatingGroupTagAfterNumberOfRepeatingGroupTag(FieldTag), MessageSizeTooBig,
}
fn tag_to_string(tag: &[u8]) -> String {
String::from_utf8_lossy(tag).into_owned()
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ParseError::MissingRequiredTag(ref tag,_) => write!(f,"ParseError::MissingRequiredTag({})",tag),
ParseError::MissingConditionallyRequiredTag(ref tag,_) => write!(f,"ParseError::MissingConditionallyRequiredTag({})",tag),
ParseError::BeginStrNotFirstTag => write!(f,"ParseError::BeginStrNotFirstTag"),
ParseError::BodyLengthNotSecondTag => write!(f,"ParseError::BodyLengthNotSecondTag"),
ParseError::BodyLengthNotNumber => write!(f,"ParseError::BodyLengthNotNumber"),
ParseError::MsgTypeNotThirdTag => write!(f,"ParseError::MsgTypeNotThirdTag"),
ParseError::MsgTypeUnknown(ref msg_type) => write!(f,"ParseError::MsgTypeUnknown({})",tag_to_string(msg_type)),
ParseError::SenderCompIDNotFourthTag => write!(f,"ParseError::SenderCompIDNotFourthTag"),
ParseError::TargetCompIDNotFifthTag => write!(f,"ParseError::TargetCompIDNotFifthTag"),
ParseError::ApplVerIDNotSixthTag => write!(f,"ParseError::ApplVerIDNotSixthTag"),
ParseError::ChecksumNotLastTag => write!(f,"ParseError::ChecksumNotLastTag"),
ParseError::ChecksumDoesNotMatch(ref calculated_checksum,ref stated_checksum) => write!(f,"ParseError::ChecksumDoesNotMatch({},{})",calculated_checksum,stated_checksum),
ParseError::ChecksumWrongFormat => write!(f,"ParseError::ChecksumWrongFormat"),
ParseError::DuplicateTag(ref tag) => write!(f,"ParseError::DuplicateTag({})",tag),
ParseError::UnexpectedTag(ref tag) => write!(f,"ParseError::UnexpectedTag({})",tag),
ParseError::UnknownTag(ref tag) => write!(f,"ParseError::UnknownTag({})",tag),
ParseError::WrongFormatTag(ref tag) => write!(f,"ParseError::WrongFormatTag({})",tag),
ParseError::OutOfRangeTag(ref tag) => write!(f,"ParseError::OutOfRangeTag({})",tag),
ParseError::NoValueAfterTag(ref tag) => write!(f,"ParseError::NoValueAfterTag({})",tag),
ParseError::MissingPrecedingLengthTag(ref value_tag) => write!(f,"ParseError::MissingPrecedingLengthTag({})",value_tag),
ParseError::MissingFollowingLengthTag(ref length_tag) => write!(f,"ParseError::MissingFollowingLengthTag({})",length_tag),
ParseError::NonRepeatingGroupTagInRepeatingGroup(ref tag) => write!(f,"ParseError::NonRepeatingGroupTagInRepeatingGroup({})",tag),
ParseError::RepeatingGroupTagWithNoRepeatingGroup(ref tag) => write!(f,"ParseError::RepeatingGroupTagWithNoRepeatingGroup({})",tag),
ParseError::MissingFirstRepeatingGroupTagAfterNumberOfRepeatingGroupTag(ref number_of_tag) => write!(f,"ParseError::MissingFirstRepeatingGroupTagAfterNumberOfRepeatingGroupTag({})",number_of_tag),
ParseError::MessageSizeTooBig => write!(f,"ParseError::MessageSizeTooBig"),
}
}
}
impl fmt::Debug for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<ParseError as fmt::Display>::fmt(self,f)
}
}
struct ParseGroupState {
remaining_fields: FieldHashMap,
remaining_required_fields: FieldHashSet,
message: Box<Message>,
}
struct ParseRepeatingGroupState {
number_of_tag: FieldTag,
group_count: usize,
group_builder: Box<BuildMessage>,
first_tag: FieldTag,
groups: Vec<ParseGroupState>,
}
impl ParseRepeatingGroupState {
fn check_last_group_complete(&self,message_version: MessageVersion,missing_tag: &mut FieldTag,missing_conditional_tag: &mut FieldTag) {
if !missing_tag.is_empty() || !missing_conditional_tag.is_empty() {
return;
}
if let Some(last_group) = self.groups.last() {
if let Some(tag) = last_group.remaining_required_fields.iter().next() {
*missing_tag = *tag;
return;
}
for tag in last_group.message.conditional_required_fields(message_version) {
if last_group.remaining_fields.contains_key(&tag) {
*missing_conditional_tag = tag;
return;
}
}
}
}
}
enum TagRuleMode {
LengthThenValue(FieldTag,usize),
RepeatingGroups(Box<ParseRepeatingGroupState>),
RepeatingGroupStart(FieldTag),
}
#[derive(PartialEq)]
enum FoundMessage {
NotFound,
FirstByte,
SecondByte,
}
#[derive(PartialEq)]
enum MessageEnd {
Yes,
YesButStop,
No
}
fn ascii_to_integer<T: FromStr>(ascii_bytes: &Vec<u8>) -> Result<T,<T as FromStr>::Err> {
T::from_str(String::from_utf8_lossy(ascii_bytes.as_slice()).borrow())
}
fn set_message_value<T: Message + ?Sized>(message: &mut T,tag: FieldTag,bytes: &[u8]) -> Result<(),ParseError> {
if let Err(e) = message.set_value(tag,bytes) {
match e {
SetValueError::WrongFormat => return Err(ParseError::WrongFormatTag(tag)),
SetValueError::OutOfRange => return Err(ParseError::OutOfRangeTag(tag)),
};
}
Ok(())
}
pub struct Parser {
message_dictionary: HashMap<&'static [u8],Box<BuildFIXTMessage + Send>>,
max_message_length: u64,
default_message_version: MessageVersion,
default_message_type_version: HashMap<&'static [u8],MessageVersion>,
value_to_length_tags: HashMap<FieldTag,FieldTag>,
found_message: FoundMessage,
current_tag: FieldTag, current_bytes: Vec<u8>, fix_version: FIXVersion,
message_version: MessageVersion,
body_length: u64,
message_type: Vec<u8>,
checksum: u8,
sender_comp_id: Vec<u8>,
target_comp_id: Vec<u8>,
body_remaining_length: u64, previous_tag: FieldTag,
next_tag_checksum: bool,
tag_rule_mode_stack: Vec<Box<TagRuleMode>>,
fast_track_bytes_remaining: usize,
found_tag_count: usize,
remaining_fields: FieldHashMap,
remaining_required_fields: FieldHashSet,
missing_tag: FieldTag,
missing_conditional_tag: FieldTag,
current_message: Box<FIXTMessage + Send>,
pub messages: Vec<Box<FIXTMessage + Send>>,
}
impl Parser {
pub fn new(message_dictionary: HashMap<&'static [u8],Box<BuildFIXTMessage + Send>>,max_message_length: u64) -> Parser {
Parser::validate_message_dictionary(&message_dictionary);
let mut value_to_length_tags = HashMap::new();
let mut builder_stack = Vec::from_iter(message_dictionary.iter().map(|(_,builder)| { BuildMessage::new_into_box(&**builder) }));
while let Some(mut builder) = builder_stack.pop() {
for message_version in MessageVersion::all() {
for (tag,rule) in builder.fields(message_version) {
match rule {
Rule::ConfirmPreviousTag{ previous_tag } => {
value_to_length_tags.insert(tag,previous_tag);
},
Rule::BeginGroup{ builder_func } => {
builder_stack.push(builder_func());
},
_ => {}
}
}
}
}
Parser {
message_dictionary: message_dictionary,
max_message_length: max_message_length,
default_message_version: DefaultApplVerIDFieldType::default_value(),
default_message_type_version: HashMap::new(),
value_to_length_tags: value_to_length_tags,
found_message: FoundMessage::NotFound,
current_tag: FieldTag::empty(),
current_bytes: Vec::with_capacity(64),
fix_version: FIXVersion::FIX_4_0,
message_version: MessageVersion::FIX40,
body_length: 0,
message_type: Vec::new(),
checksum: 0,
sender_comp_id: Vec::new(),
target_comp_id: Vec::new(),
body_remaining_length: 0,
previous_tag: FieldTag::empty(),
next_tag_checksum: false,
tag_rule_mode_stack: Vec::new(),
fast_track_bytes_remaining: 0,
found_tag_count: 0,
remaining_fields: HashMap::with_hasher(BuildFieldHasher),
remaining_required_fields: HashSet::with_hasher(BuildFieldHasher),
missing_tag: FieldTag::empty(),
missing_conditional_tag: FieldTag::empty(),
current_message: Box::new(NullMessage {}),
messages: Vec::new(),
}
}
pub fn reset_parser(&mut self) {
self.found_message = FoundMessage::NotFound;
self.current_tag = FieldTag::empty();
self.current_bytes.clear();
self.body_length = 0;
self.message_type.clear();
self.checksum = 0;
self.sender_comp_id.clear();
self.target_comp_id.clear();
self.body_remaining_length = 0;
self.previous_tag = FieldTag::empty();
self.next_tag_checksum = false;
self.tag_rule_mode_stack.clear();
self.fast_track_bytes_remaining = 0;
self.found_tag_count = 0;
self.remaining_fields.clear();
self.remaining_required_fields.clear();
self.missing_tag = FieldTag::empty();
self.missing_conditional_tag = FieldTag::empty();
self.current_message = Box::new(NullMessage {});
}
pub fn set_default_message_version(&mut self,message_version: MessageVersion) {
self.default_message_version = message_version;
}
pub fn clear_default_message_type_versions(&mut self) {
self.default_message_type_version.clear();
}
pub fn set_default_message_type_version(&mut self,tag: &[u8],message_version: MessageVersion) {
for message_dictionary_key in self.message_dictionary.keys() {
if **message_dictionary_key == *tag {
if let Entry::Vacant(entry) = self.default_message_type_version.entry(message_dictionary_key) {
entry.insert(message_version);
}
break;
}
}
}
pub fn max_message_size(&self) -> u64 {
self.max_message_length
}
pub fn validate_message_dictionary(message_dictionary: &HashMap<&'static [u8],Box<BuildFIXTMessage + Send>>) {
enum MessageType {
Standard,
RepeatingGroup,
}
let mut all_messages = Vec::new();
let mut builder_stack = Vec::from_iter(message_dictionary.iter().map(|(_,builder)| { (MessageType::Standard,BuildMessage::new_into_box(&**builder)) }));
while let Some((message_type,mut builder)) = builder_stack.pop() {
let mut found_repeating_groups = HashSet::new();
for message_version in MessageVersion::all() {
for (tag,rule) in builder.fields(message_version) {
if found_repeating_groups.contains(&tag) {
continue;
}
if let Rule::BeginGroup{ builder_func } = rule {
builder_stack.push((MessageType::RepeatingGroup,builder_func()));
found_repeating_groups.insert(tag);
}
}
}
all_messages.push((message_type,builder));
}
for &mut (ref message_type,ref mut builder) in &mut all_messages {
let mut no_fields = true;
let mut first_field_not_in_fields = true;
let mut repeating_group_first_field_not_in_required_fields = true;
for message_version in MessageVersion::all() {
let fields = builder.fields(message_version);
no_fields = fields.is_empty();
let first_field = builder.first_field(message_version);
first_field_not_in_fields = !fields.contains_key(&first_field);
repeating_group_first_field_not_in_required_fields = false;
let repeating_group = if let MessageType::RepeatingGroup = *message_type {
let required_fields = builder.required_fields(message_version);
repeating_group_first_field_not_in_required_fields = !required_fields.contains(&first_field);
true
}
else {
false
};
if !no_fields && !first_field_not_in_fields && (!repeating_group_first_field_not_in_required_fields || !repeating_group) {
repeating_group_first_field_not_in_required_fields = false;
break;
}
}
if no_fields {
panic!("Found message with no fields.");
}
else if first_field_not_in_fields {
panic!("Found message where first_field() is not in fields().");
}
else if repeating_group_first_field_not_in_required_fields {
panic!("Found message where first_field() is not in required_fields().");
}
}
for message_version in MessageVersion::all() {
for &mut (_,ref mut builder) in &mut all_messages {
let fields = builder.fields(message_version);
let required_fields = builder.required_fields(message_version);
for required_field in required_fields {
if !fields.contains_key(&required_field) {
panic!("Found message where required_fields() is not a subset of fields().");
}
}
}
for &mut (_,ref mut builder) in &mut all_messages {
let fields = builder.fields(message_version);
for (tag,rule) in &fields {
match *rule {
Rule::PrepareForBytes{ bytes_tag } => {
if let Some(bytes_tag_rule) = fields.get(&bytes_tag) {
if let Rule::ConfirmPreviousTag{ previous_tag } = *bytes_tag_rule {
if previous_tag != *tag {
panic!("Found field \"{}\" that defines Rule::PrepareForBytes but matching \"{}\" field's Rule::ConfirmPreviousTag is not circular.",tag,bytes_tag);
}
}
else {
panic!("Found field \"{}\" that defines Rule::PrepareForBytes but matching \"{}\" field does not define Rule::ConfirmPreviousTag.",tag,bytes_tag);
}
}
else {
panic!("Found field \"{}\" that defines Rule::PrepareForBytes but no matching \"{}\" field was found.",tag,bytes_tag);
}
},
Rule::ConfirmPreviousTag{ previous_tag } => {
if let Some(previous_tag_rule) = fields.get(&previous_tag) {
if let Rule::PrepareForBytes{ bytes_tag } = *previous_tag_rule {
if bytes_tag != *tag {
panic!("Found field \"{}\" that defines Rule::ConfirmPreviousTag but matching \"{}\" field's Rule::PrepareForBytes is not circular.",tag,previous_tag);
}
}
else {
panic!("Found field \"{}\" that defines Rule::ConfirmPreviousTag but matching \"{}\" field does not define Rule::PrepareForBytes.",tag,previous_tag)
}
}
else {
panic!("Found field \"{}\" that defines Rule::ConfirmPreviousTag but no matching \"{}\" field was found.",tag,previous_tag);
}
},
_ => {},
}
}
}
}
}
fn update_book_keeping(&mut self,c: u8) -> Result<(),ParseError> {
self.checksum = self.checksum.overflowing_add(c).0;
self.body_remaining_length = self.body_remaining_length.overflowing_sub(1).0;
if self.body_remaining_length == 0 {
if c != VALUE_END {
return Err(ParseError::ChecksumNotLastTag);
}
self.next_tag_checksum = true;
}
Ok(())
}
fn prepare_for_message(&mut self) -> Result<(),ParseError> {
if let Some(builder) = self.message_dictionary.get_mut(&self.message_type[..]) {
self.current_message = BuildFIXTMessage::build(&**builder);
self.remaining_fields = builder.fields(self.message_version);
self.remaining_required_fields = builder.required_fields(self.message_version);
return Ok(());
}
Err(ParseError::MsgTypeUnknown(self.message_type.clone()))
}
fn if_checksum_then_is_last_tag(&self) -> Result<(),ParseError> {
if (self.current_tag == CHECKSUM_TAG && !self.next_tag_checksum) || (self.current_tag != CHECKSUM_TAG && self.next_tag_checksum) {
return Err(ParseError::ChecksumNotLastTag);
}
Ok(())
}
fn validate_checksum(&mut self) -> Result<(),ParseError> {
if self.current_bytes.len() != 3 {
return Err(ParseError::ChecksumWrongFormat);
}
let mut checksum = self.checksum.overflowing_sub(CHECKSUM_TAG_BYTES[0] + CHECKSUM_TAG_BYTES[1] + TAG_END + VALUE_END).0;
let checksum_bytes = &self.current_bytes;
for c in checksum_bytes {
checksum = checksum.overflowing_sub(*c).0;
}
match ascii_to_integer::<u8>(checksum_bytes) {
Ok(stated_checksum) => if checksum != stated_checksum {
return Err(ParseError::ChecksumDoesNotMatch(checksum,stated_checksum));
},
Err(_) => return Err(ParseError::ChecksumWrongFormat),
}
self.checksum = checksum;
Ok(())
}
fn scan_for_message(&mut self,index: &mut usize,message_bytes: &[u8]) {
if self.found_message == FoundMessage::SecondByte {
return;
}
let mut previous_byte = match self.found_message {
FoundMessage::NotFound => 0,
FoundMessage::FirstByte => BEGINSTR_TAG_BYTES[0],
_ => unreachable!(),
};
while *index < message_bytes.len() {
let byte = message_bytes[*index];
if byte == TAG_END && previous_byte == BEGINSTR_TAG_BYTES[0] {
self.found_message = FoundMessage::SecondByte;
break;
}
previous_byte = byte;
*index += 1;
}
if self.found_message == FoundMessage::SecondByte {
self.current_tag = BEGINSTR_TAG;
self.checksum = BEGINSTR_TAG_BYTES[0] + TAG_END;
*index += 1;
}
else if previous_byte == b'8' && *index == message_bytes.len() {
self.found_message = FoundMessage::FirstByte;
}
}
fn fast_track_read_bytes(&mut self,index: &mut usize,message_bytes: &[u8]) -> Result<(),ParseError> {
loop {
if *index >= message_bytes.len() || self.fast_track_bytes_remaining == 0 {
break;
}
let c = message_bytes[*index];
try!(self.update_book_keeping(c));
self.current_bytes.push(c);
*index += 1;
self.fast_track_bytes_remaining -= 1;
}
Ok(())
}
#[allow(match_same_arms)]
fn handle_rule_after_value(&mut self,rule: &Rule) -> Result<bool,ParseError> {
let mut skip_set_value = false;
match rule {
&Rule::Nothing => {}, &Rule::BeginGroup{ builder_func: repeating_group_builder_func } => {
let repeating_group_builder = repeating_group_builder_func();
match ascii_to_integer::<usize>(&self.current_bytes) {
Ok(group_count) if group_count > 0 => {
let first_field = repeating_group_builder.first_field(self.message_version);
self.tag_rule_mode_stack.push(Box::new(TagRuleMode::RepeatingGroups(Box::new(ParseRepeatingGroupState {
number_of_tag: self.current_tag,
group_count: group_count,
first_tag: repeating_group_builder.first_field(self.message_version),
groups: Vec::new(),
group_builder: repeating_group_builder,
}))));
self.tag_rule_mode_stack.push(Box::new(TagRuleMode::RepeatingGroupStart(first_field)));
},
Ok(_) => {}, Err(_) => return Err(ParseError::WrongFormatTag(self.current_tag.clone())),
}
skip_set_value = true;
},
&Rule::PrepareForBytes{ ref bytes_tag } => {
match ascii_to_integer::<usize>(&self.current_bytes) {
Ok(byte_count) => self.tag_rule_mode_stack.push(Box::new(TagRuleMode::LengthThenValue(*bytes_tag,byte_count))),
Err(_) => return Err(ParseError::WrongFormatTag(self.current_tag)),
}
skip_set_value = true;
},
&Rule::ConfirmPreviousTag{ .. } => {}, &Rule::RequiresFIXVersion{ .. } => {}, }
Ok(skip_set_value)
}
fn fold_top_repeating_group_down(&mut self) {
let mut folded_down = false;
{
let mut tag_rule_mode_stack_iter = self.tag_rule_mode_stack.iter_mut().rev();
if let Some(first_tag_rule_mode) = tag_rule_mode_stack_iter.next() {
if let TagRuleMode::RepeatingGroups(ref mut prgs) = **first_tag_rule_mode {
for tag_rule_mode in tag_rule_mode_stack_iter {
if let TagRuleMode::RepeatingGroups(ref mut parent_prgs) = **tag_rule_mode {
let mut groups = mem::replace(&mut prgs.groups,Vec::new());
parent_prgs.groups.last_mut().unwrap().message.set_groups(
prgs.number_of_tag,
&Vec::from_iter(groups.drain(0..).map(|group| { group.message }))
);
folded_down = true;
}
}
if !folded_down {
let mut groups = mem::replace(&mut prgs.groups,Vec::new());
self.current_message.set_groups(
prgs.number_of_tag,
&Vec::from_iter(groups.drain(0..).map(|group| { group.message }))
);
folded_down = true;
}
}
}
}
if folded_down {
self.tag_rule_mode_stack.pop();
}
else {
unreachable!();
}
}
fn match_tag_end(&mut self,index: &mut usize,message_bytes: &[u8]) -> Result<(),ParseError> {
self.current_tag = FieldTag::from(&self.current_bytes[..]);
self.current_bytes.clear();
try!(self.if_checksum_then_is_last_tag());
if let Some(tag_rule_mode) = self.tag_rule_mode_stack.pop() {
match *tag_rule_mode {
TagRuleMode::LengthThenValue(ref value_tag,byte_count) => {
if self.current_tag != *value_tag {
return Err(ParseError::MissingFollowingLengthTag(self.previous_tag.clone()));
}
self.fast_track_bytes_remaining = byte_count;
*index += 1;
try!(self.fast_track_read_bytes(index,&message_bytes));
*index -= 1;
},
TagRuleMode::RepeatingGroupStart(first_repeating_group_tag) => {
if self.current_tag != first_repeating_group_tag {
return Err(ParseError::MissingFirstRepeatingGroupTagAfterNumberOfRepeatingGroupTag(self.previous_tag));
}
},
_ => self.tag_rule_mode_stack.push(tag_rule_mode),
}
}
else if let Some(required_preceding_tag) = self.value_to_length_tags.get(&self.current_tag) {
if *required_preceding_tag != self.previous_tag {
return Err(ParseError::MissingPrecedingLengthTag(self.current_tag.clone()));
}
}
Ok(())
}
fn match_value_end(&mut self,index: &mut usize,message_bytes: &[u8]) -> Result<MessageEnd,ParseError> {
if self.found_tag_count == 0 {
if self.current_tag != BEGINSTR_TAG {
return Err(ParseError::BeginStrNotFirstTag);
}
let (fix_version,message_version) = match &self.current_bytes[..] {
FIX_4_0_BEGIN_STRING => (FIXVersion::FIX_4_0,MessageVersion::FIX40),
FIX_4_1_BEGIN_STRING => (FIXVersion::FIX_4_1,MessageVersion::FIX41),
FIX_4_2_BEGIN_STRING => (FIXVersion::FIX_4_2,MessageVersion::FIX42),
FIX_4_3_BEGIN_STRING => (FIXVersion::FIX_4_3,MessageVersion::FIX43),
FIX_4_4_BEGIN_STRING => (FIXVersion::FIX_4_4,MessageVersion::FIX44),
FIXT_1_1_BEGIN_STRING => (FIXVersion::FIXT_1_1,self.default_message_version),
_ => return Err(ParseError::WrongFormatTag(BEGINSTR_TAG)),
};
self.fix_version = fix_version;
self.message_version = message_version;
self.current_bytes.clear();
}
else if self.found_tag_count == 1 {
if self.current_tag != BODYLENGTH_TAG {
return Err(ParseError::BodyLengthNotSecondTag);
}
match ascii_to_integer::<u64>(&self.current_bytes) {
Ok(length) => {
self.body_length = length;
self.body_remaining_length = length;
},
Err(_) => return Err(ParseError::BodyLengthNotNumber),
}
let total_message_length = BEGINSTR_TAG_BYTES.len() as u64 + b"=\x01".len() as u64 + self.fix_version.begin_string().len() as u64 +
BODYLENGTH_TAG_BYTES.len() as u64 + b"=\x01".len() as u64 + self.current_bytes.len() as u64 +
self.body_length +
CHECKSUM_TAG_BYTES.len() as u64 + b"=000\x01".len() as u64;
if total_message_length > self.max_message_length {
return Err(ParseError::MessageSizeTooBig);
}
}
else if self.found_tag_count == 2 {
if self.current_tag != MSGTYPE_TAG {
return Err(ParseError::MsgTypeNotThirdTag);
}
self.message_type = self.current_bytes.clone();
if self.fix_version != FIXVersion::FIXT_1_1 {
try!(self.prepare_for_message());
}
}
else if self.found_tag_count == 3 && self.fix_version == FIXVersion::FIXT_1_1 {
if self.current_tag != SenderCompID::tag() {
return Err(ParseError::SenderCompIDNotFourthTag);
}
self.sender_comp_id = self.current_bytes.clone();
}
else if self.found_tag_count == 4 && self.fix_version == FIXVersion::FIXT_1_1 {
if self.current_tag != TargetCompID::tag() {
return Err(ParseError::TargetCompIDNotFifthTag);
}
self.target_comp_id = self.current_bytes.clone();
}
else if self.current_bytes.is_empty() {
return Err(ParseError::NoValueAfterTag(self.current_tag.clone()));
}
else {
let mut skip_set_value = false;
if self.found_tag_count == 5 && self.fix_version == FIXVersion::FIXT_1_1 {
if self.current_tag == ApplVerID::tag() {
if let Some(appl_ver_id) = MessageVersion::from_bytes(&self.current_bytes[..]) {
self.message_version = appl_ver_id;
skip_set_value = true;
}
else {
return Err(ParseError::OutOfRangeTag(self.current_tag.clone()));
}
}
else {
self.message_version = *self.default_message_type_version.get(&self.message_type[..]).unwrap_or(&self.default_message_version);
}
try!(self.prepare_for_message());
try!(set_message_value(&mut *self.current_message,SenderCompID::tag(),&self.sender_comp_id[..]));
self.remaining_fields.remove(&SenderCompID::tag());
self.remaining_required_fields.remove(&SenderCompID::tag());
try!(set_message_value(&mut *self.current_message,TargetCompID::tag(),&self.target_comp_id[..]));
self.remaining_fields.remove(&TargetCompID::tag());
self.remaining_required_fields.remove(&TargetCompID::tag());
self.current_message.set_appl_ver_id(self.message_version);
self.remaining_fields.remove(&ApplVerID::tag());
}
let is_message_end = if self.current_tag == CHECKSUM_TAG {
try!(self.validate_checksum());
true
}
else {
false
};
let mut tag_in_group = false;
let mut group_end = false;
loop {
let mut some_rule = None;
if let Some(ref mut tag_rule_mode) = self.tag_rule_mode_stack.last_mut() {
if let TagRuleMode::RepeatingGroups(ref mut prgs) = ***tag_rule_mode {
if self.current_tag == prgs.first_tag {
prgs.check_last_group_complete(self.message_version,&mut self.missing_tag,&mut self.missing_conditional_tag);
let group = prgs.group_builder.build();
let remaining_fields = prgs.group_builder.fields(self.message_version);
let remaining_required_fields = prgs.group_builder.required_fields(self.message_version);
prgs.groups.push(ParseGroupState {
message: group,
remaining_fields: remaining_fields,
remaining_required_fields: remaining_required_fields,
});
if prgs.groups.len() > prgs.group_count {
return Err(ParseError::RepeatingGroupTagWithNoRepeatingGroup(self.current_tag));
}
}
if let Some(group) = prgs.groups.last_mut() {
if let Some(rule) = group.remaining_fields.remove(&self.current_tag) {
group.remaining_required_fields.remove(&self.current_tag);
if let Rule::BeginGroup{ .. } = rule {} else {
try!(set_message_value(&mut *group.message,self.current_tag,&self.current_bytes[..]));
}
some_rule = Some(rule);
tag_in_group = true;
}
}
if !tag_in_group {
if prgs.group_builder.fields(self.message_version).contains_key(&self.current_tag) {
return Err(ParseError::DuplicateTag(self.current_tag.clone()));
}
else if prgs.groups.len() < prgs.group_count {
return Err(ParseError::NonRepeatingGroupTagInRepeatingGroup(self.current_tag));
}
prgs.check_last_group_complete(self.message_version,&mut self.missing_tag,&mut self.missing_conditional_tag);
group_end = true;
}
}
}
if let Some(rule) = some_rule {
try!(self.handle_rule_after_value(&rule));
}
if group_end {
self.fold_top_repeating_group_down();
group_end = false;
}
else {
break;
}
}
if !skip_set_value && !is_message_end && !tag_in_group {
self.remaining_required_fields.remove(&self.current_tag);
if let Some(rule) = self.remaining_fields.remove(&self.current_tag) {
skip_set_value = try!(self.handle_rule_after_value(&rule));
}
else {
if self.is_current_tag_known() {
let current_message_builder = self.message_dictionary.get_mut(&self.message_type[..]).unwrap();
if current_message_builder.fields(self.message_version).contains_key(&self.current_tag) {
if self.current_tag == ApplVerID::tag() {
return Err(ParseError::ApplVerIDNotSixthTag);
}
return Err(ParseError::DuplicateTag(self.current_tag.clone()));
}
else {
return Err(ParseError::UnexpectedTag(self.current_tag.clone()));
}
}
else {
return Err(ParseError::UnknownTag(self.current_tag.clone()));
}
}
}
if !is_message_end && !tag_in_group && !skip_set_value {
try!(set_message_value(&mut *self.current_message,self.current_tag,&self.current_bytes[..]));
}
if is_message_end {
if !self.missing_tag.is_empty() {
return Err(
ParseError::MissingRequiredTag(
self.missing_tag,
mem::replace(&mut self.current_message,Box::new(NullMessage {}))));
}
else if !self.missing_conditional_tag.is_empty() {
return Err(
ParseError::MissingConditionallyRequiredTag(
self.missing_conditional_tag,
mem::replace(&mut self.current_message,Box::new(NullMessage {}))));
}
if let Some(tag) = self.remaining_required_fields.iter().next() {
return Err(
ParseError::MissingRequiredTag(
*tag,
mem::replace(&mut self.current_message,Box::new(NullMessage {}))));
}
for tag in self.current_message.conditional_required_fields(self.message_version) {
if self.remaining_fields.contains_key(&tag) {
return Err(
ParseError::MissingConditionallyRequiredTag(
tag,
mem::replace(&mut self.current_message,Box::new(NullMessage {}))));
}
}
self.current_message.set_meta(Meta {
begin_string: self.fix_version,
body_length: self.body_length,
checksum: self.checksum,
});
let is_logon_message = self.current_message.msg_type() == Logon::msg_type();
self.messages.push(mem::replace(&mut self.current_message,Box::new(NullMessage {})));
self.reset_parser();
*index += 1;
if is_logon_message {
return Ok(MessageEnd::YesButStop);
}
self.scan_for_message(index,message_bytes);
return Ok(MessageEnd::Yes);
}
}
self.previous_tag = self.current_tag;
self.current_tag = FieldTag::empty();
self.current_bytes.clear();
self.found_tag_count += 1;
Ok(MessageEnd::No)
}
fn is_current_tag_known(&mut self) -> bool {
for message in self.message_dictionary.values_mut() {
if message.fields(self.message_version).contains_key(&self.current_tag) {
return true;
}
}
false
}
pub fn parse(&mut self,message_bytes: &[u8]) -> (usize,Result<(),ParseError>) {
let mut index = 0;
match self.parse_private(&mut index,message_bytes) {
Ok(_) => (index,Ok(())),
Err(err) => {
self.reset_parser();
(index,Err(err))
}
}
}
fn parse_private(&mut self,index: &mut usize,message_bytes: &[u8]) -> Result<(),ParseError> {
self.scan_for_message(index,message_bytes);
try!(self.fast_track_read_bytes(index,&message_bytes));
while *index < message_bytes.len() {
let c = message_bytes[*index];
try!(self.update_book_keeping(c));
match c {
b'=' if self.current_tag.is_empty() => {
try!(self.match_tag_end(index,message_bytes));
},
b'\x01' => { match self.match_value_end(index,message_bytes) {
Ok(ref result) if *result == MessageEnd::Yes => {
continue;
},
Ok(ref result) if *result == MessageEnd::YesButStop => {
return Ok(());
},
Err(e) => {
*index += 1;
return Err(e);
},
_ => {}, };
},
_ => {
self.current_bytes.push(c);
}
}
*index += 1;
}
Ok(())
}
}