From f87419f62fdd015e69798982a7d8f09b55743ff5 Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Wed, 29 Apr 2020 14:35:06 +0200 Subject: implement TryFrom for non-references --- src/event.rs | 33 ++++++++++++++++++++++++++++++++ src/lib.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/src/event.rs b/src/event.rs index 40dcc02..44d9bc1 100644 --- a/src/event.rs +++ b/src/event.rs @@ -176,6 +176,28 @@ pub enum EventKind { } /// A higher-level representation of a combat event. +/// +/// Events can be many things, from damage events to general status messages (e.g. there's +/// [`EventKind::MapId`][EventKind::MapId] to give information about the current map). The main way +/// to use events is to match on the [`EventKind`][EventKind] stored in [`.kind`][Event::kind] and +/// then decide how to proceed. Note that all [`Event`][Event]s have certain fields that are always +/// present, but they might not always be useful or contain sensible information. This is just an +/// artifact of how arcdps saves the events. +/// +/// The main way to deal with events is to iterate/use the [`.events()`][super::Log::events] +/// provided by a parsed [`Log`][super::Log]. However, if you end up working with raw events +/// ([`CbtEvent`][raw::CbtEvent]), then you can convert them to a "high-level" event using the +/// standard [`TryFrom`][TryFrom]/[`TryInto`][std::convert::TryInto] mechanisms: +/// +/// ```no_run +/// # use evtclib::{raw, Event}; +/// use std::convert::TryInto; +/// let raw_event: raw::CbtEvent = panic!(); +/// let event: Event = raw_event.try_into().unwrap(); +/// ``` +/// +/// Note that if you plan on re-using the raw event afterwards, you should use the implementation +/// that works on a reference instead: `Event::try_from(&raw_event)`. #[derive(Clone, Debug, PartialEq)] pub struct Event { /// The time when the event happened. @@ -201,6 +223,17 @@ pub struct Event { pub is_shields: bool, } +impl TryFrom for Event { + type Error = FromRawEventError; + /// Convenience method to avoid manual borrowing. + /// + /// Note that this conversion will consume the event, so if you plan on re-using it, use the + /// `TryFrom<&raw::CbtEvent>` implementation that works with a reference. + fn try_from(raw_event: raw::CbtEvent) -> Result { + Event::try_from(&raw_event) + } +} + impl TryFrom<&raw::CbtEvent> for Event { type Error = FromRawEventError; diff --git a/src/lib.rs b/src/lib.rs index 3f098e1..b463ac3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -124,6 +124,24 @@ impl Character { } /// The type of an agent. +/// +/// arcdps differentiates between three types of agents: [`Player`][Player], +/// [`Character`][Character] and [`Gadget`][Gadget]. This enum unifies handling between them by +/// allowing you to pattern match or use one of the accessor methods. +/// +/// The main way to obtain a `AgentKind` is by using the [`.kind()`][Agent::kind] method on an +/// [`Agent`][Agent]. In cases where you already have a [`raw::Agent`][raw::Agent] available, you +/// can also use the [`TryFrom`][TryFrom]/[`TryInto`][std::convert::TryInto] traits to convert a +/// `raw::Agent` or `&raw::Agent` to a `AgentKind`: +/// +/// ```no_run +/// # use evtclib::{AgentKind, raw}; +/// use std::convert::TryInto; +/// // Get a raw::Agent from somewhere +/// let raw_agent: raw::Agent = panic!(); +/// // Convert it +/// let agent: AgentKind = raw_agent.try_into().unwrap(); +/// ``` #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum AgentKind { Player(Player), @@ -220,6 +238,17 @@ impl AgentKind { } } +impl TryFrom for AgentKind { + type Error = EvtcError; + /// Convenience method to avoid manual borrowing. + /// + /// Note that this conversion will consume the agent, so if you plan on re-using it, use the + /// `TryFrom<&raw::Agent>` implementation that works with a reference. + fn try_from(raw_agent: raw::Agent) -> Result { + Self::try_from(&raw_agent) + } +} + impl TryFrom<&raw::Agent> for AgentKind { type Error = EvtcError; @@ -264,6 +293,26 @@ impl TryFrom<&raw::Agent> for AgentKind { /// All of these agents share some common fields, which are the ones accessible in `Agent`. /// The kind can be retrieved using [`.kind()`][Agent::kind], which can be matched on. /// +/// # Obtaining an agent +/// +/// The normal way to obtain the agents is to use the [`.agents()`](Log::agents) method on a +/// [`Log`][Log], or one of the other accessor methods (like [`.players()`][Log::players] or +/// [`.agent_by_addr()`][Log::agent_by_addr]). +/// +/// In the cases where you already have a [`raw::Agent`][raw::Agent] available, you can also +/// convert it to an [`Agent`][Agent] by using the standard +/// [`TryFrom`][TryFrom]/[`TryInto`][std::convert::TryInto] traits: +/// +/// ```no_run +/// # use evtclib::{Agent, raw}; +/// use std::convert::TryInto; +/// let raw_agent: raw::Agent = panic!(); +/// let agent: Agent = raw_agent.try_into().unwrap(); +/// ``` +/// +/// Note that you can convert references as well, so if you plan on re-using the raw agent +/// afterwards, you should opt for `Agent::try_from(&raw_agent)` instead. +/// /// # The `Kind` parameter /// /// The type parameter is not actually used and only exists at the type level. It can be used to @@ -375,6 +424,18 @@ impl TryFrom<&raw::Agent> for Agent { } } +impl TryFrom for Agent { + type Error = EvtcError; + + /// Convenience method to avoid manual borrowing. + /// + /// Note that this conversion will consume the agent, so if you plan on re-using it, use the + /// `TryFrom<&raw::Agent>` implementation that works with a reference. + fn try_from(raw_agent: raw::Agent) -> Result { + Agent::try_from(&raw_agent) + } +} + impl Agent { /// Unconditionally change the tagged type. #[inline] -- cgit v1.2.3