diff options
| author | Daniel Schadt <kingdread@gmx.de> | 2019-05-31 02:49:09 +0200 | 
|---|---|---|
| committer | Daniel Schadt <kingdread@gmx.de> | 2019-05-31 02:49:09 +0200 | 
| commit | 9a1b5445679acc7034a3540e6b58b543941102a2 (patch) | |
| tree | 648140771e143b3917b6638f9e0da3286b35180f /src | |
| parent | 73117465dd82b30de3bb91b9e9885bf46f7f8de2 (diff) | |
| parent | 3c94665d71d4b9be746d5e3456c3d2ef7521b7fd (diff) | |
| download | evtclib-9a1b5445679acc7034a3540e6b58b543941102a2.tar.gz evtclib-9a1b5445679acc7034a3540e6b58b543941102a2.tar.bz2 evtclib-9a1b5445679acc7034a3540e6b58b543941102a2.zip | |
Merge branch 'partial-parsing'
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib.rs | 121 | ||||
| -rw-r--r-- | src/raw/parser.rs | 53 | 
2 files changed, 109 insertions, 65 deletions
| @@ -133,6 +133,68 @@ pub struct Agent {      master_agent: Option<u64>,  } +impl Agent { +    /// Parse a raw agent. +    pub fn from_raw(raw_agent: &raw::Agent) -> Result<Agent, EvtcError> { +        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::<Vec<_>>(); +            let second = raw_agent +                .name +                .iter() +                .cloned() +                .skip(first.len() + 1) +                .take_while(|c| *c != 0) +                .collect::<Vec<_>>(); +            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::<Vec<_>>(); +            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<Vec<Agent>, 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::<Vec<_>>(); -            let second = raw_agent -                .name -                .iter() -                .cloned() -                .skip(first.len() + 1) -                .take_while(|c| *c != 0) -                .collect::<Vec<_>>(); -            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::<Vec<_>>(); -            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)  } 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<CbtEvent>,  } +/// 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<Agent>, +    pub skills: Vec<Skill>, +} +  quick_error! {      #[derive(Debug)]      pub enum ParseError { @@ -391,25 +401,54 @@ pub fn parse_event_rev1<T: Read>(input: &mut T) -> ParseResult<CbtEvent> {          is_offcycle,      })  } -/// Parse a complete EVTC file. + + + +/// Parse a partial EVTC file.  ///  /// * `input` - Input stream. -pub fn parse_file<T: Read>(input: &mut T) -> ParseResult<Evtc> { +pub fn parse_partial_file<T: Read>(input: &mut T) -> ParseResult<PartialEvtc> {      let header = parse_header(input)?;      let agents = parse_agents(input, header.agent_count)?;      let skill_count = input.read_u32::<LittleEndian>()?;      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<T: Read>(partial: PartialEvtc, input: &mut T) -> ParseResult<Evtc> { +    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<T: Read>(input: &mut T) -> ParseResult<Evtc> { +    let partial = parse_partial_file(input)?; +    finish_parsing(partial, input) +} | 
