diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index cc1f834..ea928d1 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -14,7 +14,6 @@ jobs: matrix: rust: - stable - - 1.66.0 steps: - name: Checkout sources uses: actions/checkout@v2 @@ -38,7 +37,6 @@ jobs: matrix: rust: - stable - - 1.66.0 steps: - name: Checkout sources uses: actions/checkout@v2 @@ -62,7 +60,6 @@ jobs: matrix: rust: - stable - - 1.66.0 steps: - name: Checkout sources uses: actions/checkout@v2 @@ -89,7 +86,6 @@ jobs: matrix: rust: - stable - - 1.66.0 steps: - name: Checkout sources uses: actions/checkout@v2 diff --git a/README.md b/README.md index 8b401fc..bb8bff4 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,9 @@ fn main() { # Compatibility -Official minimum supported Rust version is 1.65.0, because this is the version magnus requires. However, building without Ruby bindings should be fine on any compiler version that supports Rust 2021, though this isn't officially supported. +`vault` is tested against stable Rust, and older versions aren't officially supported. However, you +should be able to compile on older versions, you just might have to pin dependencies to supported +versions. Ruby bindings have some additional compatibility requirements, such as `libclang` and minimum Ruby version requirements. For more information see [magnus compatibility](https://github.com/matsadler/magnus#compatibility). diff --git a/src/data/chunks/chunk.rs b/src/data/chunks/chunk.rs index 145bea9..a21808c 100644 --- a/src/data/chunks/chunk.rs +++ b/src/data/chunks/chunk.rs @@ -17,7 +17,7 @@ impl Chunk { move |input: Span| { let (input, header) = Header::parse(input)?; - return match &header.chunk_kind as &str { + match &header.chunk_kind as &str { "DATA" => match &header.chunk_type as &str { "AUTO" => DataAutoChunk::parse(input, header), "DATA" => DataDataChunk::parse(input, header), @@ -26,7 +26,7 @@ impl Chunk { }, "FOLD" => FoldChunk::parse(input, header, version), _ => panic!(), - }; + } } } } diff --git a/src/errors.rs b/src/errors.rs index cc62026..305bc97 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -6,5 +6,4 @@ use crate::data::Span; /// that is, the first failure point hit will exit with an error. This type returns an error that /// includes information on the segment of bytes being parsed and the location of the cursor at /// time of failure. - pub type ParseError<'a> = nom::Err>>; diff --git a/src/player.rs b/src/player.rs index aac43d6..10c3d59 100644 --- a/src/player.rs +++ b/src/player.rs @@ -26,6 +26,8 @@ pub struct Player { faction: Faction, team: Team, battlegroup: Option, + battlegroup_selected_at: Option, + ai_takeover_at: Option, steam_id: Option, profile_id: Option, messages: Vec, @@ -60,6 +62,15 @@ impl Player { pub fn battlegroup(&self) -> Option { self.battlegroup } + /// The tick at which the player selected their battlegroup, or `None` if no battlegroup was selected. + pub fn battlegroup_selected_at(&self) -> Option { + self.battlegroup_selected_at + } + /// The tick at which the player dropped from the game and AI took over their army, or `None` if the + /// player never dropped from the game. + pub fn ai_takeover_at(&self) -> Option { + self.ai_takeover_at + } /// The Steam ID of the player, or `None` if the player is AI. This ID can be used to uniquely /// identify a player between replays, and connect them to their Steam profile. pub fn steam_id(&self) -> Option { @@ -146,6 +157,8 @@ pub(crate) fn player_from_data( .cloned() .unwrap_or_default(), battlegroup: None, + battlegroup_selected_at: None, + ai_takeover_at: None, }; if player.human { @@ -153,12 +166,25 @@ pub(crate) fn player_from_data( player.profile_id = Some(player_data.profile_id); } - player.battlegroup = match player + match player .commands .iter() .find(|&command| matches!(command, Command::SelectBattlegroup(_))) { - Some(Command::SelectBattlegroup(command)) => Some(command.pbgid()), + Some(Command::SelectBattlegroup(command)) => { + player.battlegroup = Some(command.pbgid()); + player.battlegroup_selected_at = Some(command.tick()); + } + Some(_) => panic!(), + None => {} + }; + + player.ai_takeover_at = match player + .commands + .iter() + .find(|&command| matches!(command, Command::AITakeover(_))) + { + Some(Command::AITakeover(command)) => Some(command.tick()), Some(_) => panic!(), None => None, }; diff --git a/src/replay.rs b/src/replay.rs index f95b56b..72a983e 100644 --- a/src/replay.rs +++ b/src/replay.rs @@ -43,7 +43,7 @@ impl Replay { /// assert!(replay.is_ok()) /// } /// ``` - pub fn from_bytes(input: &[u8]) -> Result { + pub fn from_bytes(input: &[u8]) -> Result> { let info = TracableInfo::new().parser_width(64).fold("term"); let input: Span = LocatedSpan::new_extra(input, info); let (_, replay) = ReplayData::from_span(input)?;