From 4deac1e38c0db43479cb1295dd4028e1599ee0bc Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Fri, 24 May 2019 16:49:34 +0200 Subject: add support for partially parsing an EVTC file --- src/raw/parser.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/raw/parser.rs b/src/raw/parser.rs index a3a1cd5..fa3b36c 100644 --- a/src/raw/parser.rs +++ b/src/raw/parser.rs @@ -97,6 +97,16 @@ pub struct Evtc { pub events: Vec, } +/// A partially-parsed EVTC file, containing everything but the events. +/// This can speed up parsing for applications which can work with the header. +#[derive(Clone, Debug)] +pub struct PartialEvtc { + pub header: Header, + pub skill_count: u32, + pub agents: Vec, + pub skills: Vec, +} + quick_error! { #[derive(Debug)] pub enum ParseError { @@ -391,25 +401,54 @@ pub fn parse_event_rev1(input: &mut T) -> ParseResult { is_offcycle, }) } -/// Parse a complete EVTC file. + + + +/// Parse a partial EVTC file. /// /// * `input` - Input stream. -pub fn parse_file(input: &mut T) -> ParseResult { +pub fn parse_partial_file(input: &mut T) -> ParseResult { let header = parse_header(input)?; let agents = parse_agents(input, header.agent_count)?; let skill_count = input.read_u32::()?; let skills = parse_skills(input, skill_count)?; - let events = match header.revision { + + Ok(PartialEvtc { + header, + skill_count, + agents, + skills, + }) +} + + + +/// Finish a partial EVTC by reading the events. +/// +/// * `partial` - The partial EVTC. +/// * `input` - The input stream. +pub fn finish_parsing(partial: PartialEvtc, input: &mut T) -> ParseResult { + let events = match partial.header.revision { 0 => parse_events(input, parse_event_rev0)?, 1 => parse_events(input, parse_event_rev1)?, x => return Err(ParseError::UnknownRevision(x)), }; Ok(Evtc { - header, - skill_count, - agents, - skills, + header: partial.header, + skill_count: partial.skill_count, + agents: partial.agents, + skills: partial.skills, events, }) } + + + +/// Parse a complete EVTC file. +/// +/// * `input` - Input stream. +pub fn parse_file(input: &mut T) -> ParseResult { + let partial = parse_partial_file(input)?; + finish_parsing(partial, input) +} -- cgit v1.2.3 From 3c94665d71d4b9be746d5e3456c3d2ef7521b7fd Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Fri, 24 May 2019 17:41:09 +0200 Subject: add public method to parse raw::Agent to Agent --- src/lib.rs | 121 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 63 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 010944f..a3bf64d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -133,6 +133,68 @@ pub struct Agent { master_agent: Option, } +impl Agent { + /// Parse a raw agent. + pub fn from_raw(raw_agent: &raw::Agent) -> Result { + let kind = if raw_agent.is_character() { + AgentKind::Character(raw_agent.prof as u16) + } else if raw_agent.is_gadget() { + AgentKind::Gadget(raw_agent.prof as u16) + } else if raw_agent.is_player() { + AgentKind::Player { + profession: raw_agent.prof, + elite: raw_agent.is_elite, + } + } else { + return Err(EvtcError::InvalidData); + }; + + let name = if raw_agent.is_player() { + let first = raw_agent + .name + .iter() + .cloned() + .take_while(|c| *c != 0) + .collect::>(); + let second = raw_agent + .name + .iter() + .cloned() + .skip(first.len() + 1) + .take_while(|c| *c != 0) + .collect::>(); + let third = raw_agent.name[first.len() + second.len() + 2] - b'0'; + AgentName::Player { + character_name: String::from_utf8(first)?, + account_name: String::from_utf8(second)?, + subgroup: third, + } + } else { + let name = raw_agent + .name + .iter() + .cloned() + .take_while(|c| *c != 0) + .collect::>(); + AgentName::Single(String::from_utf8(name)?) + }; + + Ok(Agent { + addr: raw_agent.addr, + kind, + toughness: raw_agent.toughness, + concentration: raw_agent.concentration, + healing: raw_agent.healing, + condition: raw_agent.condition, + name, + instance_id: 0, + first_aware: 0, + last_aware: u64::max_value(), + master_agent: None, + }) + } +} + /// A fully processed log file. #[derive(Debug, Clone)] pub struct Log { @@ -243,64 +305,7 @@ fn setup_agents(data: &raw::Evtc) -> Result, EvtcError> { let mut agents = Vec::with_capacity(data.agents.len()); for raw_agent in &data.agents { - let kind = if raw_agent.is_character() { - AgentKind::Character(raw_agent.prof as u16) - } else if raw_agent.is_gadget() { - AgentKind::Gadget(raw_agent.prof as u16) - } else if raw_agent.is_player() { - AgentKind::Player { - profession: raw_agent.prof, - elite: raw_agent.is_elite, - } - } else { - return Err(EvtcError::InvalidData); - }; - - let name = if raw_agent.is_player() { - let first = raw_agent - .name - .iter() - .cloned() - .take_while(|c| *c != 0) - .collect::>(); - let second = raw_agent - .name - .iter() - .cloned() - .skip(first.len() + 1) - .take_while(|c| *c != 0) - .collect::>(); - let third = raw_agent.name[first.len() + second.len() + 2] - b'0'; - AgentName::Player { - character_name: String::from_utf8(first)?, - account_name: String::from_utf8(second)?, - subgroup: third, - } - } else { - let name = raw_agent - .name - .iter() - .cloned() - .take_while(|c| *c != 0) - .collect::>(); - AgentName::Single(String::from_utf8(name)?) - }; - - let agent = Agent { - addr: raw_agent.addr, - kind, - toughness: raw_agent.toughness, - concentration: raw_agent.concentration, - healing: raw_agent.healing, - condition: raw_agent.condition, - name, - instance_id: 0, - first_aware: 0, - last_aware: u64::max_value(), - master_agent: None, - }; - - agents.push(agent); + agents.push(Agent::from_raw(raw_agent)?); } Ok(agents) } -- cgit v1.2.3