From 082a46ade2b65c43956c7c572b85b84fbdfb06b5 Mon Sep 17 00:00:00 2001 From: melkor Date: Sun, 29 Oct 2023 11:41:50 -0700 Subject: [PATCH] refactor --- .gitignore | 1 + gen/resources/preamble/frame.rs | 105 +-- gen/resources/preamble/frame/mutable.rs | 84 ++ .../{columnar.rs => frame/transpose.rs} | 0 gen/resources/{frame.json => structs.json} | 0 gen/scripts/columnar | 5 - gen/scripts/frame | 2 +- gen/scripts/frame-mutable | 5 + gen/scripts/frame-transpose | 5 + gen/scripts/regen | 11 +- gen/src/peppi_codegen/common.clj | 33 +- gen/src/peppi_codegen/frame.clj | 175 +--- gen/src/peppi_codegen/frame/mutable.clj | 153 ++++ .../{columnar.clj => frame/transpose.clj} | 6 +- src/lib.rs | 1 - src/model/frame.rs | 754 ++---------------- src/model/frame/mutable.rs | 633 +++++++++++++++ src/model/{columnar.rs => frame/transpose.rs} | 22 +- src/model/game.rs | 63 +- src/serde/de.rs | 52 +- src/serde/ser.rs | 6 +- tests/json.rs | 16 +- tests/peppi.rs | 192 ++--- 23 files changed, 1241 insertions(+), 1083 deletions(-) create mode 100644 gen/resources/preamble/frame/mutable.rs rename gen/resources/preamble/{columnar.rs => frame/transpose.rs} (100%) rename gen/resources/{frame.json => structs.json} (100%) delete mode 100755 gen/scripts/columnar create mode 100755 gen/scripts/frame-mutable create mode 100755 gen/scripts/frame-transpose create mode 100644 gen/src/peppi_codegen/frame/mutable.clj rename gen/src/peppi_codegen/{columnar.clj => frame/transpose.clj} (76%) create mode 100644 src/model/frame/mutable.rs rename src/model/{columnar.rs => frame/transpose.rs} (85%) diff --git a/.gitignore b/.gitignore index 9a9744a..d390148 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ Cargo.lock **/*.rs.bk gen/.cpcache +gen/target diff --git a/gen/resources/preamble/frame.rs b/gen/resources/preamble/frame.rs index cb5644c..2c47217 100644 --- a/gen/resources/preamble/frame.rs +++ b/gen/resources/preamble/frame.rs @@ -1,25 +1,29 @@ -#![allow(unused_parens)] #![allow(unused_variables)] -#![allow(dead_code)] +use std::{ + fmt, + io::{Result, Write}, +}; + +use byteorder::WriteBytesExt; use arrow2::{ - array::{ListArray, MutablePrimitiveArray, PrimitiveArray, StructArray}, + array::{ListArray, PrimitiveArray, StructArray}, buffer::Buffer, datatypes::{DataType, Field}, - offset::{Offsets, OffsetsBuffer}, + offset::OffsetsBuffer, }; -use byteorder::{ReadBytesExt, WriteBytesExt}; -use std::io::{Result, Write}; use crate::{ model::{ - columnar, game::{Port, NUM_PORTS}, slippi::Version, }, serde::de::Event, }; +pub mod mutable; +pub mod transpose; + type BE = byteorder::BigEndian; /// Frame indexes start at -123, and reach 0 at "Go!". @@ -31,6 +35,7 @@ pub struct PortOccupancy { pub follower: bool, } +#[derive(Debug)] pub struct Data { pub pre: Pre, pub post: Post, @@ -113,27 +118,8 @@ impl Data { } } -pub struct MutableData { - pub pre: MutablePre, - pub post: MutablePost, -} - -impl MutableData { - pub fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - pre: MutablePre::with_capacity(capacity, version), - post: MutablePost::with_capacity(capacity, version), - } - } - - pub fn push_none(&mut self, version: Version) { - self.pre.push_none(version); - self.post.push_none(version); - } -} - -impl From for Data { - fn from(d: MutableData) -> Self { +impl From for Data { + fn from(d: mutable::Data) -> Self { Self { pre: d.pre.into(), post: d.post.into(), @@ -141,6 +127,7 @@ impl From for Data { } } +#[derive(Debug)] pub struct PortData { pub port: Port, pub leader: Data, @@ -271,27 +258,8 @@ impl PortData { } -pub struct MutablePortData { - pub port: Port, - pub leader: MutableData, - pub follower: Option, -} - -impl MutablePortData { - pub fn with_capacity(capacity: usize, version: Version, port: PortOccupancy) -> Self { - Self { - port: port.port, - leader: MutableData::with_capacity(capacity, version), - follower: match port.follower { - true => Some(MutableData::with_capacity(capacity, version)), - _ => None, - }, - } - } -} - -impl From for PortData { - fn from(p: MutablePortData) -> Self { +impl From for PortData { + fn from(p: mutable::PortData) -> Self { Self { port: p.port, leader: p.leader.into(), @@ -465,8 +433,8 @@ impl Frame { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::Frame { - columnar::Frame { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::Frame { + transpose::Frame { start: self.start.transpose_one(i, version), end: self.end.transpose_one(i, version), } @@ -496,33 +464,8 @@ impl Frame { } } -pub struct MutableFrame { - pub id: MutablePrimitiveArray, - pub start: MutableStart, - pub end: MutableEnd, - pub port: Vec, - pub item_offset: Offsets, - pub item: MutableItem, -} - -impl MutableFrame { - pub fn with_capacity(capacity: usize, version: Version, ports: &[PortOccupancy]) -> Self { - Self { - id: MutablePrimitiveArray::::with_capacity(capacity), - start: MutableStart::with_capacity(capacity, version), - end: MutableEnd::with_capacity(capacity, version), - port: ports - .iter() - .map(|p| MutablePortData::with_capacity(capacity, version, *p)) - .collect(), - item_offset: Offsets::::with_capacity(capacity), - item: MutableItem::with_capacity(0, version), - } - } -} - -impl From for Frame { - fn from(f: MutableFrame) -> Self { +impl From for Frame { + fn from(f: mutable::Frame) -> Self { Self { id: f.id.into(), start: f.start.into(), @@ -533,3 +476,9 @@ impl From for Frame { } } } + +impl fmt::Debug for Frame { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> { + write!(f, "Frame {{ len: {} }}", self.id.len()) + } +} diff --git a/gen/resources/preamble/frame/mutable.rs b/gen/resources/preamble/frame/mutable.rs new file mode 100644 index 0000000..b074f2f --- /dev/null +++ b/gen/resources/preamble/frame/mutable.rs @@ -0,0 +1,84 @@ +#![allow(unused_parens)] +#![allow(unused_variables)] +#![allow(dead_code)] + +use arrow2::{ + array::MutablePrimitiveArray, + offset::Offsets, +}; + +use byteorder::ReadBytesExt; +use std::io::Result; + +use crate::{ + model::{ + frame::PortOccupancy, + game::Port, + slippi::Version, + }, +}; + +type BE = byteorder::BigEndian; + +pub struct Data { + pub pre: Pre, + pub post: Post, +} + +impl Data { + pub fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + pre: Pre::with_capacity(capacity, version), + post: Post::with_capacity(capacity, version), + } + } + + pub fn push_none(&mut self, version: Version) { + self.pre.push_none(version); + self.post.push_none(version); + } +} + +pub struct PortData { + pub port: Port, + pub leader: Data, + pub follower: Option, +} + +impl PortData { + pub fn with_capacity(capacity: usize, version: Version, port: PortOccupancy) -> Self { + Self { + port: port.port, + leader: Data::with_capacity(capacity, version), + follower: match port.follower { + true => Some(Data::with_capacity(capacity, version)), + _ => None, + }, + } + } +} + +pub struct Frame { + pub id: MutablePrimitiveArray, + pub start: Start, + pub end: End, + pub port: Vec, + pub item_offset: Offsets, + pub item: Item, +} + +impl Frame { + pub fn with_capacity(capacity: usize, version: Version, ports: &[PortOccupancy]) -> Self { + Self { + id: MutablePrimitiveArray::::with_capacity(capacity), + start: Start::with_capacity(capacity, version), + end: End::with_capacity(capacity, version), + port: ports + .iter() + .map(|p| PortData::with_capacity(capacity, version, *p)) + .collect(), + item_offset: Offsets::::with_capacity(capacity), + item: Item::with_capacity(0, version), + } + } +} diff --git a/gen/resources/preamble/columnar.rs b/gen/resources/preamble/frame/transpose.rs similarity index 100% rename from gen/resources/preamble/columnar.rs rename to gen/resources/preamble/frame/transpose.rs diff --git a/gen/resources/frame.json b/gen/resources/structs.json similarity index 100% rename from gen/resources/frame.json rename to gen/resources/structs.json diff --git a/gen/scripts/columnar b/gen/scripts/columnar deleted file mode 100755 index eded626..0000000 --- a/gen/scripts/columnar +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -set -euo pipefail - -cd "$(dirname "$0")/.." -clj -M -m peppi-codegen.columnar resources/frame.json diff --git a/gen/scripts/frame b/gen/scripts/frame index 69cffc0..91de97b 100755 --- a/gen/scripts/frame +++ b/gen/scripts/frame @@ -2,4 +2,4 @@ set -euo pipefail cd "$(dirname "$0")/.." -clj -M -m peppi-codegen.frame resources/frame.json +clj -M -m peppi-codegen.frame resources/structs.json diff --git a/gen/scripts/frame-mutable b/gen/scripts/frame-mutable new file mode 100755 index 0000000..f9bfa99 --- /dev/null +++ b/gen/scripts/frame-mutable @@ -0,0 +1,5 @@ +#!/bin/bash +set -euo pipefail + +cd "$(dirname "$0")/.." +clj -M -m peppi-codegen.frame.mutable resources/structs.json diff --git a/gen/scripts/frame-transpose b/gen/scripts/frame-transpose new file mode 100755 index 0000000..ffd1757 --- /dev/null +++ b/gen/scripts/frame-transpose @@ -0,0 +1,5 @@ +#!/bin/bash +set -euo pipefail + +cd "$(dirname "$0")/.." +clj -M -m peppi-codegen.frame.transpose resources/structs.json diff --git a/gen/scripts/regen b/gen/scripts/regen index b0baf52..07d67f6 100755 --- a/gen/scripts/regen +++ b/gen/scripts/regen @@ -3,8 +3,11 @@ set -euo pipefail cd "$(dirname "$0")/.." -scripts/frame | rustfmt > resources/frame.rs -mv resources/frame.rs ../src/model/ +mkdir -p target/frame -scripts/columnar | rustfmt > resources/columnar.rs -mv resources/columnar.rs ../src/model/ +scripts/frame | rustfmt > target/frame.rs +scripts/frame-mutable | rustfmt > target/frame/mutable.rs +scripts/frame-transpose | rustfmt > target/frame/transpose.rs + +cp target/*.rs ../src/model/ +cp target/frame/*.rs ../src/model/frame/ diff --git a/gen/src/peppi_codegen/common.clj b/gen/src/peppi_codegen/common.clj index e4ed6df..43c3175 100644 --- a/gen/src/peppi_codegen/common.clj +++ b/gen/src/peppi_codegen/common.clj @@ -62,17 +62,12 @@ (def tuple-struct? (complement (comp :name first))) -(defn mutable - [ty] - (str "Mutable" ty)) - (defn wrap-transpose [call] [:method-call {:unwrap true} call "transpose"]) (defn wrap-map [target binding-name method-call] - ;{:pre [(#{:method-call :fn-call} (first method-call))]} (let [map-call [:method-call target "map" @@ -94,6 +89,34 @@ [x] [:method-call x "unwrap"]) +(defn if-ver + ([ver then] + (if-ver ver then nil)) + ([ver then else] + [:if + [:method-call "version" "gte" ver] + (cond->> then + (not= :block (first then)) (conj [:block])) + (cond->> else + (and else (not= :block (first else))) (conj [:block]))])) + +(defn nested-version-ifs + [f fields] + (->> fields + (partition-by :version) + reverse + (reduce (fn [acc fields] + (let [ver (:version (first fields)) + stmts (concat (mapv f fields) acc)] + (if ver + [(if-ver ver (into [:block] stmts))] + stmts))) + []))) + +;;; +;;; AST emitters +;;; + (defmulti emit-expr* (fn [props & _] (:type props))) diff --git a/gen/src/peppi_codegen/frame.clj b/gen/src/peppi_codegen/frame.clj index c090eae..a515ca1 100644 --- a/gen/src/peppi_codegen/frame.clj +++ b/gen/src/peppi_codegen/frame.clj @@ -6,172 +6,17 @@ [clojure.pprint :refer [pprint]] [peppi-codegen.common :refer :all])) -(defn mutable-array-type - [ty] - (if (types ty) - ["MutablePrimitiveArray" ty] - (str "Mutable" ty))) - (defn immutable-array-type [ty] (if (types ty) ["PrimitiveArray" ty] ty)) -(defn mutable-struct-field - [{nm :name, ty :type, ver :version}] - [nm (cond->> (mutable-array-type ty) - ver (conj ["Option"]))]) - (defn immutable-struct-field [{nm :name, ty :type, ver :version}] [nm (cond->> (immutable-array-type ty) - ;(types ty) (conj ["Box"]) ver (conj ["Option"]))]) -(defn if-ver - ([ver then] - (if-ver ver then nil)) - ([ver then else] - [:if - [:method-call "version" "gte" ver] - (cond->> then - (not= :block (first then)) (conj [:block])) - (cond->> else - (and else (not= :block (first else))) (conj [:block]))])) - -(defn push-none - [{nm :name, ty :type, ver :version, idx :index}] - (let [target (cond-> [:field-get "self" (or nm idx)] - ver ((comp unwrap as-mut)))] - (into [:method-call target] - (if (types ty) - ["push" ["None"]] - ["push_none" ["version"]])))) - -(defn nested-version-ifs - [f fields] - (->> fields - (partition-by :version) - reverse - (reduce (fn [acc fields] - (let [ver (:version (first fields)) - stmts (concat (mapv f fields) acc)] - (if ver - [(if-ver ver (into [:block] stmts))] - stmts))) - []))) - -(defn with-capacity-arrow - [arrow-type] - [:fn-call - arrow-type - "with_capacity" - ["capacity"]]) - -(defn with-capacity-custom - [ty] - [:fn-call - ty - "with_capacity" - ["capacity" "version"]]) - -(defn with-capacity - [{ty :type, ver :version :as m}] - (let [expr (if (types ty) - (-> ty mutable-array-type with-capacity-arrow) - (with-capacity-custom (mutable ty)))] - (if ver - [:method-call - [:method-call "version" "gte" ver] - "then" - [[:closure [] [expr]]]] - expr))) - -(defn with-capacity-fn - [fields] - [:fn - {:ret "Self"} - "with_capacity" - [["capacity" "usize"] - ["version" "Version"]] - [:block - [:struct-init - "Self" - (mapv (juxt :name with-capacity) fields)]]]) - -(defn primitive-push-none - [target] - [:method-call target "push" ["None"]]) - -(defn composite-push-none - [target] - [:method-call target "push_none" ["version"]]) - -(defn push-none - [{nm :name, ty :type, ver :version, idx :index}] - (let [target (cond-> [:field-get "self" (or nm idx)] - ver ((comp unwrap as-mut)))] - (if (types ty) - (primitive-push-none target) - (composite-push-none target)))) - -(defn push-none-fn - [fields] - [:fn - {:visibility "pub"} - "push_none" - [["&mut self"] - ["version" "Version"]] - (into [:block] - (nested-version-ifs push-none fields))]) - -(defn primitive-read-push - [target ty] - [:method-call - {:unwrap true} - [:method-call - {:generics (when-not (#{"u8" "i8" "bool"} ty) ["BE"])} - "r" - (str "read_" ty)] - "map" - [[:closure - [["x"]] - [[:method-call - target - "push" - [[:struct-init "Some" [[nil "x"]]]]]]]]]) - -(defn composite-read-push - [target] - [:method-call - {:unwrap true} - target - "read_push" - ["r" "version"]]) - -(defn read-push - [{nm :name, ty :type, ver :version, idx :index}] - (let [target (cond-> [:field-get "self" (or nm idx)] - ver ((comp unwrap as-mut)))] - (if (types ty) - (primitive-read-push target ty) - (composite-read-push target)))) - -(defn read-push-fn - [fields] - [:fn - {:visibility "pub" - :ret ["Result" "()"]} - "read_push" - [["&mut self"] - ["r" "&mut &[u8]"] - ["version" "Version"]] - (->> fields - (nested-version-ifs read-push) - (into [:block]) - (append [:struct-init "Ok" [[nil [:unit]]]]))]) - (defn write-field-primitive [target {ty :type}] [:method-call @@ -280,7 +125,7 @@ (defn transpose-one-fn [nm fields] - (let [ctype (list "columnar" nm)] + (let [ctype (list "transpose" nm)] [:fn {:visibility "pub" :ret ctype} @@ -354,7 +199,7 @@ [(arrow-field f)]])) (into [:block])) [:struct-init - "DataType::Struct" + (list "DataType" "Struct") [[nil "fields"]]]]]) (defn into-immutable @@ -364,9 +209,13 @@ (wrap-map target "x" [:method-call "x" "into" []]) [:method-call target "into" []]))) +(defn mutable + [ty] + (list "mutable" ty)) + (defn immutable-struct [[nm fields]] - [[:struct nm (mapv immutable-struct-field fields)] + [[:struct {:derives #{"Debug"}} nm (mapv immutable-struct-field fields)] [:impl nm [(data-type-fn fields) (into-struct-array-fn fields) (from-struct-array-fn fields) @@ -382,13 +231,6 @@ [:block [:struct-init "Self" (mapv (juxt :name into-immutable) fields)]]]]]]) -(defn mutable-struct - [[nm fields]] - [[:struct (mutable nm) (mapv mutable-struct-field fields)] - [:impl (mutable nm) [(with-capacity-fn fields) - (push-none-fn fields) - (read-push-fn fields)]]]) - (defn normalize-field [idx field] (-> field @@ -400,8 +242,7 @@ (defn -main [path] (let [json (-> (read-json path) (update-vals #(map-indexed normalize-field %))) - decls (concat (mapcat mutable-struct json) - (mapcat immutable-struct json))] + decls (mapcat immutable-struct json)] (println do-not-edit) (println (slurp (io/resource "preamble/frame.rs"))) (println) diff --git a/gen/src/peppi_codegen/frame/mutable.clj b/gen/src/peppi_codegen/frame/mutable.clj new file mode 100644 index 0000000..13a6e6c --- /dev/null +++ b/gen/src/peppi_codegen/frame/mutable.clj @@ -0,0 +1,153 @@ +(ns peppi-codegen.frame.mutable + (:require + [clojure.data.json :as json] + [clojure.java.io :as io] + [clojure.string :as str] + [clojure.pprint :refer [pprint]] + [peppi-codegen.common :refer :all])) + +(defn mutable-array-type + [ty] + (if (types ty) + ["MutablePrimitiveArray" ty] + ty)) + +(defn mutable-struct-field + [{nm :name, ty :type, ver :version}] + [nm (cond->> (mutable-array-type ty) + ver (conj ["Option"]))]) + +(defn with-capacity-arrow + [arrow-type] + [:fn-call + arrow-type + "with_capacity" + ["capacity"]]) + +(defn with-capacity-custom + [ty] + [:fn-call + ty + "with_capacity" + ["capacity" "version"]]) + +(defn with-capacity + [{ty :type, ver :version :as m}] + (let [expr (if (types ty) + (-> ty mutable-array-type with-capacity-arrow) + (with-capacity-custom ty))] + (if ver + [:method-call + [:method-call "version" "gte" ver] + "then" + [[:closure [] [expr]]]] + expr))) + +(defn with-capacity-fn + [fields] + [:fn + {:ret "Self"} + "with_capacity" + [["capacity" "usize"] + ["version" "Version"]] + [:block + [:struct-init + "Self" + (mapv (juxt :name with-capacity) fields)]]]) + +(defn primitive-push-none + [target] + [:method-call target "push" ["None"]]) + +(defn composite-push-none + [target] + [:method-call target "push_none" ["version"]]) + +(defn push-none + [{nm :name, ty :type, ver :version, idx :index}] + (let [target (cond-> [:field-get "self" (or nm idx)] + ver ((comp unwrap as-mut)))] + (if (types ty) + (primitive-push-none target) + (composite-push-none target)))) + +(defn push-none-fn + [fields] + [:fn + {:visibility "pub"} + "push_none" + [["&mut self"] + ["version" "Version"]] + (into [:block] + (nested-version-ifs push-none fields))]) + +(defn primitive-read-push + [target ty] + [:method-call + {:unwrap true} + [:method-call + {:generics (when-not (#{"u8" "i8" "bool"} ty) ["BE"])} + "r" + (str "read_" ty)] + "map" + [[:closure + [["x"]] + [[:method-call + target + "push" + [[:struct-init "Some" [[nil "x"]]]]]]]]]) + +(defn composite-read-push + [target] + [:method-call + {:unwrap true} + target + "read_push" + ["r" "version"]]) + +(defn read-push + [{nm :name, ty :type, ver :version, idx :index}] + (let [target (cond-> [:field-get "self" (or nm idx)] + ver ((comp unwrap as-mut)))] + (if (types ty) + (primitive-read-push target ty) + (composite-read-push target)))) + +(defn read-push-fn + [fields] + [:fn + {:visibility "pub" + :ret ["Result" "()"]} + "read_push" + [["&mut self"] + ["r" "&mut &[u8]"] + ["version" "Version"]] + (->> fields + (nested-version-ifs read-push) + (into [:block]) + (append [:struct-init "Ok" [[nil [:unit]]]]))]) + +(defn mutable-struct + [[nm fields]] + [[:struct nm (mapv mutable-struct-field fields)] + [:impl nm [(with-capacity-fn fields) + (push-none-fn fields) + (read-push-fn fields)]]]) + +(defn normalize-field + [idx field] + (-> field + (update :version #(some-> % + (str/split #"\.") + vec)) + (assoc :index idx))) + +(defn -main [path] + (let [json (-> (read-json path) + (update-vals #(map-indexed normalize-field %))) + decls (mapcat mutable-struct json)] + (println do-not-edit) + (println (slurp (io/resource "preamble/frame/mutable.rs"))) + (println) + (doseq [decl decls] + (println (emit-expr decl) "\n")))) diff --git a/gen/src/peppi_codegen/columnar.clj b/gen/src/peppi_codegen/frame/transpose.clj similarity index 76% rename from gen/src/peppi_codegen/columnar.clj rename to gen/src/peppi_codegen/frame/transpose.clj index fc72a86..85ec2c8 100644 --- a/gen/src/peppi_codegen/columnar.clj +++ b/gen/src/peppi_codegen/frame/transpose.clj @@ -1,4 +1,4 @@ -(ns peppi-codegen.columnar +(ns peppi-codegen.frame.transpose (:require [clojure.java.io :as io] [peppi-codegen.common :refer :all])) @@ -11,7 +11,7 @@ (defn struct-decl [[nm fields]] [:struct - {:derives ["PartialEq", "Debug"]} + {:derives #{"PartialEq", "Debug"}} nm (mapv field fields)]) @@ -19,7 +19,7 @@ (let [json (read-json path) decls (mapv struct-decl json)] (println do-not-edit) - (println (slurp (io/resource "preamble/columnar.rs"))) + (println (slurp (io/resource "preamble/frame/transpose.rs"))) (println) (doseq [decl decls] (println (emit-expr decl) "\n")))) diff --git a/src/lib.rs b/src/lib.rs index 93197f1..aaedd7d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,6 @@ pub(crate) mod ubjson { } pub mod model { - pub mod columnar; pub mod frame; pub mod game; pub mod shift_jis; diff --git a/src/model/frame.rs b/src/model/frame.rs index 132fc5e..ebf858e 100644 --- a/src/model/frame.rs +++ b/src/model/frame.rs @@ -1,27 +1,31 @@ // This file is auto-generated by `gen/scripts/regen`. Do not edit. -#![allow(unused_parens)] #![allow(unused_variables)] -#![allow(dead_code)] + +use std::{ + fmt, + io::{Result, Write}, +}; use arrow2::{ - array::{ListArray, MutablePrimitiveArray, PrimitiveArray, StructArray}, + array::{ListArray, PrimitiveArray, StructArray}, buffer::Buffer, datatypes::{DataType, Field}, - offset::{Offsets, OffsetsBuffer}, + offset::OffsetsBuffer, }; -use byteorder::{ReadBytesExt, WriteBytesExt}; -use std::io::{Result, Write}; +use byteorder::WriteBytesExt; use crate::{ model::{ - columnar, game::{Port, NUM_PORTS}, slippi::Version, }, serde::de::Event, }; +pub mod mutable; +pub mod transpose; + type BE = byteorder::BigEndian; /// Frame indexes start at -123, and reach 0 at "Go!". @@ -33,6 +37,7 @@ pub struct PortOccupancy { pub follower: bool, } +#[derive(Debug)] pub struct Data { pub pre: Pre, pub post: Post, @@ -115,27 +120,8 @@ impl Data { } } -pub struct MutableData { - pub pre: MutablePre, - pub post: MutablePost, -} - -impl MutableData { - pub fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - pre: MutablePre::with_capacity(capacity, version), - post: MutablePost::with_capacity(capacity, version), - } - } - - pub fn push_none(&mut self, version: Version) { - self.pre.push_none(version); - self.post.push_none(version); - } -} - -impl From for Data { - fn from(d: MutableData) -> Self { +impl From for Data { + fn from(d: mutable::Data) -> Self { Self { pre: d.pre.into(), post: d.post.into(), @@ -143,6 +129,7 @@ impl From for Data { } } +#[derive(Debug)] pub struct PortData { pub port: Port, pub leader: Data, @@ -282,27 +269,8 @@ impl PortData { } } -pub struct MutablePortData { - pub port: Port, - pub leader: MutableData, - pub follower: Option, -} - -impl MutablePortData { - pub fn with_capacity(capacity: usize, version: Version, port: PortOccupancy) -> Self { - Self { - port: port.port, - leader: MutableData::with_capacity(capacity, version), - follower: match port.follower { - true => Some(MutableData::with_capacity(capacity, version)), - _ => None, - }, - } - } -} - -impl From for PortData { - fn from(p: MutablePortData) -> Self { +impl From for PortData { + fn from(p: mutable::PortData) -> Self { Self { port: p.port, leader: p.leader.into(), @@ -476,8 +444,8 @@ impl Frame { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::Frame { - columnar::Frame { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::Frame { + transpose::Frame { start: self.start.transpose_one(i, version), end: self.end.transpose_one(i, version), } @@ -508,33 +476,8 @@ impl Frame { } } -pub struct MutableFrame { - pub id: MutablePrimitiveArray, - pub start: MutableStart, - pub end: MutableEnd, - pub port: Vec, - pub item_offset: Offsets, - pub item: MutableItem, -} - -impl MutableFrame { - pub fn with_capacity(capacity: usize, version: Version, ports: &[PortOccupancy]) -> Self { - Self { - id: MutablePrimitiveArray::::with_capacity(capacity), - start: MutableStart::with_capacity(capacity, version), - end: MutableEnd::with_capacity(capacity, version), - port: ports - .iter() - .map(|p| MutablePortData::with_capacity(capacity, version, *p)) - .collect(), - item_offset: Offsets::::with_capacity(capacity), - item: MutableItem::with_capacity(0, version), - } - } -} - -impl From for Frame { - fn from(f: MutableFrame) -> Self { +impl From for Frame { + fn from(f: mutable::Frame) -> Self { Self { id: f.id.into(), start: f.start.into(), @@ -546,562 +489,13 @@ impl From for Frame { } } -pub struct MutablePost { - pub character: MutablePrimitiveArray, - pub state: MutablePrimitiveArray, - pub position: MutablePosition, - pub direction: MutablePrimitiveArray, - pub percent: MutablePrimitiveArray, - pub shield: MutablePrimitiveArray, - pub last_attack_landed: MutablePrimitiveArray, - pub combo_count: MutablePrimitiveArray, - pub last_hit_by: MutablePrimitiveArray, - pub stocks: MutablePrimitiveArray, - pub state_age: Option>, - pub state_flags: Option, - pub misc_as: Option>, - pub airborne: Option>, - pub ground: Option>, - pub jumps: Option>, - pub l_cancel: Option>, - pub hurtbox_state: Option>, - pub velocities: Option, - pub hitlag: Option>, - pub animation_index: Option>, -} - -impl MutablePost { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - character: MutablePrimitiveArray::::with_capacity(capacity), - state: MutablePrimitiveArray::::with_capacity(capacity), - position: MutablePosition::with_capacity(capacity, version), - direction: MutablePrimitiveArray::::with_capacity(capacity), - percent: MutablePrimitiveArray::::with_capacity(capacity), - shield: MutablePrimitiveArray::::with_capacity(capacity), - last_attack_landed: MutablePrimitiveArray::::with_capacity(capacity), - combo_count: MutablePrimitiveArray::::with_capacity(capacity), - last_hit_by: MutablePrimitiveArray::::with_capacity(capacity), - stocks: MutablePrimitiveArray::::with_capacity(capacity), - state_age: version - .gte(0, 2) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - state_flags: version - .gte(2, 0) - .then(|| MutableStateFlags::with_capacity(capacity, version)), - misc_as: version - .gte(2, 0) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - airborne: version - .gte(2, 0) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - ground: version - .gte(2, 0) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - jumps: version - .gte(2, 0) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - l_cancel: version - .gte(2, 0) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - hurtbox_state: version - .gte(2, 1) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - velocities: version - .gte(3, 5) - .then(|| MutableVelocities::with_capacity(capacity, version)), - hitlag: version - .gte(3, 8) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - animation_index: version - .gte(3, 11) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - } - } - - pub fn push_none(&mut self, version: Version) { - self.character.push(None); - self.state.push(None); - self.position.push_none(version); - self.direction.push(None); - self.percent.push(None); - self.shield.push(None); - self.last_attack_landed.push(None); - self.combo_count.push(None); - self.last_hit_by.push(None); - self.stocks.push(None); - if version.gte(0, 2) { - self.state_age.as_mut().unwrap().push(None); - if version.gte(2, 0) { - self.state_flags.as_mut().unwrap().push_none(version); - self.misc_as.as_mut().unwrap().push(None); - self.airborne.as_mut().unwrap().push(None); - self.ground.as_mut().unwrap().push(None); - self.jumps.as_mut().unwrap().push(None); - self.l_cancel.as_mut().unwrap().push(None); - if version.gte(2, 1) { - self.hurtbox_state.as_mut().unwrap().push(None); - if version.gte(3, 5) { - self.velocities.as_mut().unwrap().push_none(version); - if version.gte(3, 8) { - self.hitlag.as_mut().unwrap().push(None); - if version.gte(3, 11) { - self.animation_index.as_mut().unwrap().push(None) - } - } - } - } - } - } - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - r.read_u8().map(|x| self.character.push(Some(x)))?; - r.read_u16::().map(|x| self.state.push(Some(x)))?; - self.position.read_push(r, version)?; - r.read_f32::().map(|x| self.direction.push(Some(x)))?; - r.read_f32::().map(|x| self.percent.push(Some(x)))?; - r.read_f32::().map(|x| self.shield.push(Some(x)))?; - r.read_u8().map(|x| self.last_attack_landed.push(Some(x)))?; - r.read_u8().map(|x| self.combo_count.push(Some(x)))?; - r.read_u8().map(|x| self.last_hit_by.push(Some(x)))?; - r.read_u8().map(|x| self.stocks.push(Some(x)))?; - if version.gte(0, 2) { - r.read_f32::() - .map(|x| self.state_age.as_mut().unwrap().push(Some(x)))?; - if version.gte(2, 0) { - self.state_flags.as_mut().unwrap().read_push(r, version)?; - r.read_f32::() - .map(|x| self.misc_as.as_mut().unwrap().push(Some(x)))?; - r.read_u8() - .map(|x| self.airborne.as_mut().unwrap().push(Some(x)))?; - r.read_u16::() - .map(|x| self.ground.as_mut().unwrap().push(Some(x)))?; - r.read_u8() - .map(|x| self.jumps.as_mut().unwrap().push(Some(x)))?; - r.read_u8() - .map(|x| self.l_cancel.as_mut().unwrap().push(Some(x)))?; - if version.gte(2, 1) { - r.read_u8() - .map(|x| self.hurtbox_state.as_mut().unwrap().push(Some(x)))?; - if version.gte(3, 5) { - self.velocities.as_mut().unwrap().read_push(r, version)?; - if version.gte(3, 8) { - r.read_f32::() - .map(|x| self.hitlag.as_mut().unwrap().push(Some(x)))?; - if version.gte(3, 11) { - r.read_u32::() - .map(|x| self.animation_index.as_mut().unwrap().push(Some(x)))? - } - } - } - } - } - }; - Ok(()) - } -} - -pub struct MutableStart { - pub random_seed: Option>, - pub scene_frame_counter: Option>, -} - -impl MutableStart { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - random_seed: version - .gte(2, 2) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - scene_frame_counter: version - .gte(3, 10) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - } - } - - pub fn push_none(&mut self, version: Version) { - if version.gte(2, 2) { - self.random_seed.as_mut().unwrap().push(None); - if version.gte(3, 10) { - self.scene_frame_counter.as_mut().unwrap().push(None) - } - } - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - if version.gte(2, 2) { - r.read_u32::() - .map(|x| self.random_seed.as_mut().unwrap().push(Some(x)))?; - if version.gte(3, 10) { - r.read_u32::() - .map(|x| self.scene_frame_counter.as_mut().unwrap().push(Some(x)))? - } - }; - Ok(()) - } -} - -pub struct MutableEnd { - pub latest_finalized_frame: Option>, -} - -impl MutableEnd { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - latest_finalized_frame: version - .gte(3, 7) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - } - } - - pub fn push_none(&mut self, version: Version) { - if version.gte(3, 7) { - self.latest_finalized_frame.as_mut().unwrap().push(None) - } - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - if version.gte(3, 7) { - r.read_i32::() - .map(|x| self.latest_finalized_frame.as_mut().unwrap().push(Some(x)))? - }; - Ok(()) - } -} - -pub struct MutableStateFlags( - pub MutablePrimitiveArray, - pub MutablePrimitiveArray, - pub MutablePrimitiveArray, - pub MutablePrimitiveArray, - pub MutablePrimitiveArray, -); - -impl MutableStateFlags { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self( - MutablePrimitiveArray::::with_capacity(capacity), - MutablePrimitiveArray::::with_capacity(capacity), - MutablePrimitiveArray::::with_capacity(capacity), - MutablePrimitiveArray::::with_capacity(capacity), - MutablePrimitiveArray::::with_capacity(capacity), - ) - } - - pub fn push_none(&mut self, version: Version) { - self.0.push(None); - self.1.push(None); - self.2.push(None); - self.3.push(None); - self.4.push(None) - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - r.read_u8().map(|x| self.0.push(Some(x)))?; - r.read_u8().map(|x| self.1.push(Some(x)))?; - r.read_u8().map(|x| self.2.push(Some(x)))?; - r.read_u8().map(|x| self.3.push(Some(x)))?; - r.read_u8().map(|x| self.4.push(Some(x)))?; - Ok(()) - } -} - -pub struct MutablePre { - pub random_seed: MutablePrimitiveArray, - pub state: MutablePrimitiveArray, - pub position: MutablePosition, - pub direction: MutablePrimitiveArray, - pub joystick: MutablePosition, - pub cstick: MutablePosition, - pub triggers: MutablePrimitiveArray, - pub buttons: MutablePrimitiveArray, - pub buttons_physical: MutablePrimitiveArray, - pub triggers_physical: MutableTriggersPhysical, - pub raw_analog_x: Option>, - pub percent: Option>, -} - -impl MutablePre { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - random_seed: MutablePrimitiveArray::::with_capacity(capacity), - state: MutablePrimitiveArray::::with_capacity(capacity), - position: MutablePosition::with_capacity(capacity, version), - direction: MutablePrimitiveArray::::with_capacity(capacity), - joystick: MutablePosition::with_capacity(capacity, version), - cstick: MutablePosition::with_capacity(capacity, version), - triggers: MutablePrimitiveArray::::with_capacity(capacity), - buttons: MutablePrimitiveArray::::with_capacity(capacity), - buttons_physical: MutablePrimitiveArray::::with_capacity(capacity), - triggers_physical: MutableTriggersPhysical::with_capacity(capacity, version), - raw_analog_x: version - .gte(1, 2) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - percent: version - .gte(1, 4) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - } - } - - pub fn push_none(&mut self, version: Version) { - self.random_seed.push(None); - self.state.push(None); - self.position.push_none(version); - self.direction.push(None); - self.joystick.push_none(version); - self.cstick.push_none(version); - self.triggers.push(None); - self.buttons.push(None); - self.buttons_physical.push(None); - self.triggers_physical.push_none(version); - if version.gte(1, 2) { - self.raw_analog_x.as_mut().unwrap().push(None); - if version.gte(1, 4) { - self.percent.as_mut().unwrap().push(None) - } - } - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - r.read_u32::().map(|x| self.random_seed.push(Some(x)))?; - r.read_u16::().map(|x| self.state.push(Some(x)))?; - self.position.read_push(r, version)?; - r.read_f32::().map(|x| self.direction.push(Some(x)))?; - self.joystick.read_push(r, version)?; - self.cstick.read_push(r, version)?; - r.read_f32::().map(|x| self.triggers.push(Some(x)))?; - r.read_u32::().map(|x| self.buttons.push(Some(x)))?; - r.read_u16::() - .map(|x| self.buttons_physical.push(Some(x)))?; - self.triggers_physical.read_push(r, version)?; - if version.gte(1, 2) { - r.read_i8() - .map(|x| self.raw_analog_x.as_mut().unwrap().push(Some(x)))?; - if version.gte(1, 4) { - r.read_f32::() - .map(|x| self.percent.as_mut().unwrap().push(Some(x)))? - } - }; - Ok(()) - } -} - -pub struct MutableItemMisc( - pub MutablePrimitiveArray, - pub MutablePrimitiveArray, - pub MutablePrimitiveArray, - pub MutablePrimitiveArray, -); - -impl MutableItemMisc { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self( - MutablePrimitiveArray::::with_capacity(capacity), - MutablePrimitiveArray::::with_capacity(capacity), - MutablePrimitiveArray::::with_capacity(capacity), - MutablePrimitiveArray::::with_capacity(capacity), - ) - } - - pub fn push_none(&mut self, version: Version) { - self.0.push(None); - self.1.push(None); - self.2.push(None); - self.3.push(None) - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - r.read_u8().map(|x| self.0.push(Some(x)))?; - r.read_u8().map(|x| self.1.push(Some(x)))?; - r.read_u8().map(|x| self.2.push(Some(x)))?; - r.read_u8().map(|x| self.3.push(Some(x)))?; - Ok(()) - } -} - -pub struct MutablePosition { - pub x: MutablePrimitiveArray, - pub y: MutablePrimitiveArray, -} - -impl MutablePosition { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - x: MutablePrimitiveArray::::with_capacity(capacity), - y: MutablePrimitiveArray::::with_capacity(capacity), - } - } - - pub fn push_none(&mut self, version: Version) { - self.x.push(None); - self.y.push(None) - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - r.read_f32::().map(|x| self.x.push(Some(x)))?; - r.read_f32::().map(|x| self.y.push(Some(x)))?; - Ok(()) - } -} - -pub struct MutableVelocities { - pub self_x_air: MutablePrimitiveArray, - pub self_y: MutablePrimitiveArray, - pub knockback_x: MutablePrimitiveArray, - pub knockback_y: MutablePrimitiveArray, - pub self_x_ground: MutablePrimitiveArray, -} - -impl MutableVelocities { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - self_x_air: MutablePrimitiveArray::::with_capacity(capacity), - self_y: MutablePrimitiveArray::::with_capacity(capacity), - knockback_x: MutablePrimitiveArray::::with_capacity(capacity), - knockback_y: MutablePrimitiveArray::::with_capacity(capacity), - self_x_ground: MutablePrimitiveArray::::with_capacity(capacity), - } - } - - pub fn push_none(&mut self, version: Version) { - self.self_x_air.push(None); - self.self_y.push(None); - self.knockback_x.push(None); - self.knockback_y.push(None); - self.self_x_ground.push(None) - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - r.read_f32::().map(|x| self.self_x_air.push(Some(x)))?; - r.read_f32::().map(|x| self.self_y.push(Some(x)))?; - r.read_f32::().map(|x| self.knockback_x.push(Some(x)))?; - r.read_f32::().map(|x| self.knockback_y.push(Some(x)))?; - r.read_f32::() - .map(|x| self.self_x_ground.push(Some(x)))?; - Ok(()) - } -} - -pub struct MutableTriggersPhysical { - pub l: MutablePrimitiveArray, - pub r: MutablePrimitiveArray, -} - -impl MutableTriggersPhysical { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - l: MutablePrimitiveArray::::with_capacity(capacity), - r: MutablePrimitiveArray::::with_capacity(capacity), - } - } - - pub fn push_none(&mut self, version: Version) { - self.l.push(None); - self.r.push(None) - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - r.read_f32::().map(|x| self.l.push(Some(x)))?; - r.read_f32::().map(|x| self.r.push(Some(x)))?; - Ok(()) - } -} - -pub struct MutableVelocity { - pub x: MutablePrimitiveArray, - pub y: MutablePrimitiveArray, -} - -impl MutableVelocity { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - x: MutablePrimitiveArray::::with_capacity(capacity), - y: MutablePrimitiveArray::::with_capacity(capacity), - } - } - - pub fn push_none(&mut self, version: Version) { - self.x.push(None); - self.y.push(None) - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - r.read_f32::().map(|x| self.x.push(Some(x)))?; - r.read_f32::().map(|x| self.y.push(Some(x)))?; - Ok(()) - } -} - -pub struct MutableItem { - pub r#type: MutablePrimitiveArray, - pub state: MutablePrimitiveArray, - pub direction: MutablePrimitiveArray, - pub velocity: MutableVelocity, - pub position: MutablePosition, - pub damage: MutablePrimitiveArray, - pub timer: MutablePrimitiveArray, - pub id: MutablePrimitiveArray, - pub misc: Option, - pub owner: Option>, -} - -impl MutableItem { - fn with_capacity(capacity: usize, version: Version) -> Self { - Self { - r#type: MutablePrimitiveArray::::with_capacity(capacity), - state: MutablePrimitiveArray::::with_capacity(capacity), - direction: MutablePrimitiveArray::::with_capacity(capacity), - velocity: MutableVelocity::with_capacity(capacity, version), - position: MutablePosition::with_capacity(capacity, version), - damage: MutablePrimitiveArray::::with_capacity(capacity), - timer: MutablePrimitiveArray::::with_capacity(capacity), - id: MutablePrimitiveArray::::with_capacity(capacity), - misc: version - .gte(3, 2) - .then(|| MutableItemMisc::with_capacity(capacity, version)), - owner: version - .gte(3, 6) - .then(|| MutablePrimitiveArray::::with_capacity(capacity)), - } - } - - pub fn push_none(&mut self, version: Version) { - self.r#type.push(None); - self.state.push(None); - self.direction.push(None); - self.velocity.push_none(version); - self.position.push_none(version); - self.damage.push(None); - self.timer.push(None); - self.id.push(None); - if version.gte(3, 2) { - self.misc.as_mut().unwrap().push_none(version); - if version.gte(3, 6) { - self.owner.as_mut().unwrap().push(None) - } - } - } - - pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { - r.read_u16::().map(|x| self.r#type.push(Some(x)))?; - r.read_u8().map(|x| self.state.push(Some(x)))?; - r.read_f32::().map(|x| self.direction.push(Some(x)))?; - self.velocity.read_push(r, version)?; - self.position.read_push(r, version)?; - r.read_u16::().map(|x| self.damage.push(Some(x)))?; - r.read_f32::().map(|x| self.timer.push(Some(x)))?; - r.read_u32::().map(|x| self.id.push(Some(x)))?; - if version.gte(3, 2) { - self.misc.as_mut().unwrap().read_push(r, version)?; - if version.gte(3, 6) { - r.read_i8() - .map(|x| self.owner.as_mut().unwrap().push(Some(x)))? - } - }; - Ok(()) +impl fmt::Debug for Frame { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> { + write!(f, "Frame {{ len: {} }}", self.id.len()) } } +#[derive(Debug)] pub struct Post { pub character: PrimitiveArray, pub state: PrimitiveArray, @@ -1382,8 +776,8 @@ impl Post { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::Post { - columnar::Post { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::Post { + transpose::Post { character: self.character.values()[i], state: self.state.values()[i], position: self.position.transpose_one(i, version), @@ -1415,8 +809,8 @@ impl Post { } } -impl From for Post { - fn from(x: MutablePost) -> Self { +impl From for Post { + fn from(x: mutable::Post) -> Self { Self { character: x.character.into(), state: x.state.into(), @@ -1443,6 +837,7 @@ impl From for Post { } } +#[derive(Debug)] pub struct Start { pub random_seed: Option>, pub scene_frame_counter: Option>, @@ -1503,16 +898,16 @@ impl Start { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::Start { - columnar::Start { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::Start { + transpose::Start { random_seed: self.random_seed.as_ref().map(|x| x.values()[i]), scene_frame_counter: self.scene_frame_counter.as_ref().map(|x| x.values()[i]), } } } -impl From for Start { - fn from(x: MutableStart) -> Self { +impl From for Start { + fn from(x: mutable::Start) -> Self { Self { random_seed: x.random_seed.map(|x| x.into()), scene_frame_counter: x.scene_frame_counter.map(|x| x.into()), @@ -1520,6 +915,7 @@ impl From for Start { } } +#[derive(Debug)] pub struct End { pub latest_finalized_frame: Option>, } @@ -1564,21 +960,22 @@ impl End { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::End { - columnar::End { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::End { + transpose::End { latest_finalized_frame: self.latest_finalized_frame.as_ref().map(|x| x.values()[i]), } } } -impl From for End { - fn from(x: MutableEnd) -> Self { +impl From for End { + fn from(x: mutable::End) -> Self { Self { latest_finalized_frame: x.latest_finalized_frame.map(|x| x.into()), } } } +#[derive(Debug)] pub struct StateFlags( pub PrimitiveArray, pub PrimitiveArray, @@ -1652,8 +1049,8 @@ impl StateFlags { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::StateFlags { - columnar::StateFlags( + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::StateFlags { + transpose::StateFlags( self.0.values()[i], self.1.values()[i], self.2.values()[i], @@ -1663,12 +1060,13 @@ impl StateFlags { } } -impl From for StateFlags { - fn from(x: MutableStateFlags) -> Self { +impl From for StateFlags { + fn from(x: mutable::StateFlags) -> Self { Self(x.0.into(), x.1.into(), x.2.into(), x.3.into(), x.4.into()) } } +#[derive(Debug)] pub struct Pre { pub random_seed: PrimitiveArray, pub state: PrimitiveArray, @@ -1835,8 +1233,8 @@ impl Pre { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::Pre { - columnar::Pre { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::Pre { + transpose::Pre { random_seed: self.random_seed.values()[i], state: self.state.values()[i], position: self.position.transpose_one(i, version), @@ -1853,8 +1251,8 @@ impl Pre { } } -impl From for Pre { - fn from(x: MutablePre) -> Self { +impl From for Pre { + fn from(x: mutable::Pre) -> Self { Self { random_seed: x.random_seed.into(), state: x.state.into(), @@ -1872,6 +1270,7 @@ impl From for Pre { } } +#[derive(Debug)] pub struct ItemMisc( pub PrimitiveArray, pub PrimitiveArray, @@ -1936,8 +1335,8 @@ impl ItemMisc { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::ItemMisc { - columnar::ItemMisc( + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::ItemMisc { + transpose::ItemMisc( self.0.values()[i], self.1.values()[i], self.2.values()[i], @@ -1946,12 +1345,13 @@ impl ItemMisc { } } -impl From for ItemMisc { - fn from(x: MutableItemMisc) -> Self { +impl From for ItemMisc { + fn from(x: mutable::ItemMisc) -> Self { Self(x.0.into(), x.1.into(), x.2.into(), x.3.into()) } } +#[derive(Debug)] pub struct Position { pub x: PrimitiveArray, pub y: PrimitiveArray, @@ -1998,16 +1398,16 @@ impl Position { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::Position { - columnar::Position { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::Position { + transpose::Position { x: self.x.values()[i], y: self.y.values()[i], } } } -impl From for Position { - fn from(x: MutablePosition) -> Self { +impl From for Position { + fn from(x: mutable::Position) -> Self { Self { x: x.x.into(), y: x.y.into(), @@ -2015,6 +1415,7 @@ impl From for Position { } } +#[derive(Debug)] pub struct Velocities { pub self_x_air: PrimitiveArray, pub self_y: PrimitiveArray, @@ -2088,8 +1489,8 @@ impl Velocities { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::Velocities { - columnar::Velocities { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::Velocities { + transpose::Velocities { self_x_air: self.self_x_air.values()[i], self_y: self.self_y.values()[i], knockback_x: self.knockback_x.values()[i], @@ -2099,8 +1500,8 @@ impl Velocities { } } -impl From for Velocities { - fn from(x: MutableVelocities) -> Self { +impl From for Velocities { + fn from(x: mutable::Velocities) -> Self { Self { self_x_air: x.self_x_air.into(), self_y: x.self_y.into(), @@ -2111,6 +1512,7 @@ impl From for Velocities { } } +#[derive(Debug)] pub struct TriggersPhysical { pub l: PrimitiveArray, pub r: PrimitiveArray, @@ -2157,16 +1559,16 @@ impl TriggersPhysical { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::TriggersPhysical { - columnar::TriggersPhysical { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::TriggersPhysical { + transpose::TriggersPhysical { l: self.l.values()[i], r: self.r.values()[i], } } } -impl From for TriggersPhysical { - fn from(x: MutableTriggersPhysical) -> Self { +impl From for TriggersPhysical { + fn from(x: mutable::TriggersPhysical) -> Self { Self { l: x.l.into(), r: x.r.into(), @@ -2174,6 +1576,7 @@ impl From for TriggersPhysical { } } +#[derive(Debug)] pub struct Velocity { pub x: PrimitiveArray, pub y: PrimitiveArray, @@ -2220,16 +1623,16 @@ impl Velocity { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::Velocity { - columnar::Velocity { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::Velocity { + transpose::Velocity { x: self.x.values()[i], y: self.y.values()[i], } } } -impl From for Velocity { - fn from(x: MutableVelocity) -> Self { +impl From for Velocity { + fn from(x: mutable::Velocity) -> Self { Self { x: x.x.into(), y: x.y.into(), @@ -2237,6 +1640,7 @@ impl From for Velocity { } } +#[derive(Debug)] pub struct Item { pub r#type: PrimitiveArray, pub state: PrimitiveArray, @@ -2375,8 +1779,8 @@ impl Item { Ok(()) } - pub fn transpose_one(&self, i: usize, version: Version) -> columnar::Item { - columnar::Item { + pub fn transpose_one(&self, i: usize, version: Version) -> transpose::Item { + transpose::Item { r#type: self.r#type.values()[i], state: self.state.values()[i], direction: self.direction.values()[i], @@ -2391,8 +1795,8 @@ impl Item { } } -impl From for Item { - fn from(x: MutableItem) -> Self { +impl From for Item { + fn from(x: mutable::Item) -> Self { Self { r#type: x.r#type.into(), state: x.state.into(), diff --git a/src/model/frame/mutable.rs b/src/model/frame/mutable.rs new file mode 100644 index 0000000..c71f69f --- /dev/null +++ b/src/model/frame/mutable.rs @@ -0,0 +1,633 @@ +// This file is auto-generated by `gen/scripts/regen`. Do not edit. + +#![allow(unused_parens)] +#![allow(unused_variables)] +#![allow(dead_code)] + +use arrow2::{array::MutablePrimitiveArray, offset::Offsets}; + +use byteorder::ReadBytesExt; +use std::io::Result; + +use crate::model::{frame::PortOccupancy, game::Port, slippi::Version}; + +type BE = byteorder::BigEndian; + +pub struct Data { + pub pre: Pre, + pub post: Post, +} + +impl Data { + pub fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + pre: Pre::with_capacity(capacity, version), + post: Post::with_capacity(capacity, version), + } + } + + pub fn push_none(&mut self, version: Version) { + self.pre.push_none(version); + self.post.push_none(version); + } +} + +pub struct PortData { + pub port: Port, + pub leader: Data, + pub follower: Option, +} + +impl PortData { + pub fn with_capacity(capacity: usize, version: Version, port: PortOccupancy) -> Self { + Self { + port: port.port, + leader: Data::with_capacity(capacity, version), + follower: match port.follower { + true => Some(Data::with_capacity(capacity, version)), + _ => None, + }, + } + } +} + +pub struct Frame { + pub id: MutablePrimitiveArray, + pub start: Start, + pub end: End, + pub port: Vec, + pub item_offset: Offsets, + pub item: Item, +} + +impl Frame { + pub fn with_capacity(capacity: usize, version: Version, ports: &[PortOccupancy]) -> Self { + Self { + id: MutablePrimitiveArray::::with_capacity(capacity), + start: Start::with_capacity(capacity, version), + end: End::with_capacity(capacity, version), + port: ports + .iter() + .map(|p| PortData::with_capacity(capacity, version, *p)) + .collect(), + item_offset: Offsets::::with_capacity(capacity), + item: Item::with_capacity(0, version), + } + } +} + +pub struct Post { + pub character: MutablePrimitiveArray, + pub state: MutablePrimitiveArray, + pub position: Position, + pub direction: MutablePrimitiveArray, + pub percent: MutablePrimitiveArray, + pub shield: MutablePrimitiveArray, + pub last_attack_landed: MutablePrimitiveArray, + pub combo_count: MutablePrimitiveArray, + pub last_hit_by: MutablePrimitiveArray, + pub stocks: MutablePrimitiveArray, + pub state_age: Option>, + pub state_flags: Option, + pub misc_as: Option>, + pub airborne: Option>, + pub ground: Option>, + pub jumps: Option>, + pub l_cancel: Option>, + pub hurtbox_state: Option>, + pub velocities: Option, + pub hitlag: Option>, + pub animation_index: Option>, +} + +impl Post { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + character: MutablePrimitiveArray::::with_capacity(capacity), + state: MutablePrimitiveArray::::with_capacity(capacity), + position: Position::with_capacity(capacity, version), + direction: MutablePrimitiveArray::::with_capacity(capacity), + percent: MutablePrimitiveArray::::with_capacity(capacity), + shield: MutablePrimitiveArray::::with_capacity(capacity), + last_attack_landed: MutablePrimitiveArray::::with_capacity(capacity), + combo_count: MutablePrimitiveArray::::with_capacity(capacity), + last_hit_by: MutablePrimitiveArray::::with_capacity(capacity), + stocks: MutablePrimitiveArray::::with_capacity(capacity), + state_age: version + .gte(0, 2) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + state_flags: version + .gte(2, 0) + .then(|| StateFlags::with_capacity(capacity, version)), + misc_as: version + .gte(2, 0) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + airborne: version + .gte(2, 0) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + ground: version + .gte(2, 0) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + jumps: version + .gte(2, 0) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + l_cancel: version + .gte(2, 0) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + hurtbox_state: version + .gte(2, 1) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + velocities: version + .gte(3, 5) + .then(|| Velocities::with_capacity(capacity, version)), + hitlag: version + .gte(3, 8) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + animation_index: version + .gte(3, 11) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + } + } + + pub fn push_none(&mut self, version: Version) { + self.character.push(None); + self.state.push(None); + self.position.push_none(version); + self.direction.push(None); + self.percent.push(None); + self.shield.push(None); + self.last_attack_landed.push(None); + self.combo_count.push(None); + self.last_hit_by.push(None); + self.stocks.push(None); + if version.gte(0, 2) { + self.state_age.as_mut().unwrap().push(None); + if version.gte(2, 0) { + self.state_flags.as_mut().unwrap().push_none(version); + self.misc_as.as_mut().unwrap().push(None); + self.airborne.as_mut().unwrap().push(None); + self.ground.as_mut().unwrap().push(None); + self.jumps.as_mut().unwrap().push(None); + self.l_cancel.as_mut().unwrap().push(None); + if version.gte(2, 1) { + self.hurtbox_state.as_mut().unwrap().push(None); + if version.gte(3, 5) { + self.velocities.as_mut().unwrap().push_none(version); + if version.gte(3, 8) { + self.hitlag.as_mut().unwrap().push(None); + if version.gte(3, 11) { + self.animation_index.as_mut().unwrap().push(None) + } + } + } + } + } + } + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + r.read_u8().map(|x| self.character.push(Some(x)))?; + r.read_u16::().map(|x| self.state.push(Some(x)))?; + self.position.read_push(r, version)?; + r.read_f32::().map(|x| self.direction.push(Some(x)))?; + r.read_f32::().map(|x| self.percent.push(Some(x)))?; + r.read_f32::().map(|x| self.shield.push(Some(x)))?; + r.read_u8().map(|x| self.last_attack_landed.push(Some(x)))?; + r.read_u8().map(|x| self.combo_count.push(Some(x)))?; + r.read_u8().map(|x| self.last_hit_by.push(Some(x)))?; + r.read_u8().map(|x| self.stocks.push(Some(x)))?; + if version.gte(0, 2) { + r.read_f32::() + .map(|x| self.state_age.as_mut().unwrap().push(Some(x)))?; + if version.gte(2, 0) { + self.state_flags.as_mut().unwrap().read_push(r, version)?; + r.read_f32::() + .map(|x| self.misc_as.as_mut().unwrap().push(Some(x)))?; + r.read_u8() + .map(|x| self.airborne.as_mut().unwrap().push(Some(x)))?; + r.read_u16::() + .map(|x| self.ground.as_mut().unwrap().push(Some(x)))?; + r.read_u8() + .map(|x| self.jumps.as_mut().unwrap().push(Some(x)))?; + r.read_u8() + .map(|x| self.l_cancel.as_mut().unwrap().push(Some(x)))?; + if version.gte(2, 1) { + r.read_u8() + .map(|x| self.hurtbox_state.as_mut().unwrap().push(Some(x)))?; + if version.gte(3, 5) { + self.velocities.as_mut().unwrap().read_push(r, version)?; + if version.gte(3, 8) { + r.read_f32::() + .map(|x| self.hitlag.as_mut().unwrap().push(Some(x)))?; + if version.gte(3, 11) { + r.read_u32::() + .map(|x| self.animation_index.as_mut().unwrap().push(Some(x)))? + } + } + } + } + } + }; + Ok(()) + } +} + +pub struct Start { + pub random_seed: Option>, + pub scene_frame_counter: Option>, +} + +impl Start { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + random_seed: version + .gte(2, 2) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + scene_frame_counter: version + .gte(3, 10) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + } + } + + pub fn push_none(&mut self, version: Version) { + if version.gte(2, 2) { + self.random_seed.as_mut().unwrap().push(None); + if version.gte(3, 10) { + self.scene_frame_counter.as_mut().unwrap().push(None) + } + } + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + if version.gte(2, 2) { + r.read_u32::() + .map(|x| self.random_seed.as_mut().unwrap().push(Some(x)))?; + if version.gte(3, 10) { + r.read_u32::() + .map(|x| self.scene_frame_counter.as_mut().unwrap().push(Some(x)))? + } + }; + Ok(()) + } +} + +pub struct End { + pub latest_finalized_frame: Option>, +} + +impl End { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + latest_finalized_frame: version + .gte(3, 7) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + } + } + + pub fn push_none(&mut self, version: Version) { + if version.gte(3, 7) { + self.latest_finalized_frame.as_mut().unwrap().push(None) + } + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + if version.gte(3, 7) { + r.read_i32::() + .map(|x| self.latest_finalized_frame.as_mut().unwrap().push(Some(x)))? + }; + Ok(()) + } +} + +pub struct StateFlags( + pub MutablePrimitiveArray, + pub MutablePrimitiveArray, + pub MutablePrimitiveArray, + pub MutablePrimitiveArray, + pub MutablePrimitiveArray, +); + +impl StateFlags { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self( + MutablePrimitiveArray::::with_capacity(capacity), + MutablePrimitiveArray::::with_capacity(capacity), + MutablePrimitiveArray::::with_capacity(capacity), + MutablePrimitiveArray::::with_capacity(capacity), + MutablePrimitiveArray::::with_capacity(capacity), + ) + } + + pub fn push_none(&mut self, version: Version) { + self.0.push(None); + self.1.push(None); + self.2.push(None); + self.3.push(None); + self.4.push(None) + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + r.read_u8().map(|x| self.0.push(Some(x)))?; + r.read_u8().map(|x| self.1.push(Some(x)))?; + r.read_u8().map(|x| self.2.push(Some(x)))?; + r.read_u8().map(|x| self.3.push(Some(x)))?; + r.read_u8().map(|x| self.4.push(Some(x)))?; + Ok(()) + } +} + +pub struct Pre { + pub random_seed: MutablePrimitiveArray, + pub state: MutablePrimitiveArray, + pub position: Position, + pub direction: MutablePrimitiveArray, + pub joystick: Position, + pub cstick: Position, + pub triggers: MutablePrimitiveArray, + pub buttons: MutablePrimitiveArray, + pub buttons_physical: MutablePrimitiveArray, + pub triggers_physical: TriggersPhysical, + pub raw_analog_x: Option>, + pub percent: Option>, +} + +impl Pre { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + random_seed: MutablePrimitiveArray::::with_capacity(capacity), + state: MutablePrimitiveArray::::with_capacity(capacity), + position: Position::with_capacity(capacity, version), + direction: MutablePrimitiveArray::::with_capacity(capacity), + joystick: Position::with_capacity(capacity, version), + cstick: Position::with_capacity(capacity, version), + triggers: MutablePrimitiveArray::::with_capacity(capacity), + buttons: MutablePrimitiveArray::::with_capacity(capacity), + buttons_physical: MutablePrimitiveArray::::with_capacity(capacity), + triggers_physical: TriggersPhysical::with_capacity(capacity, version), + raw_analog_x: version + .gte(1, 2) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + percent: version + .gte(1, 4) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + } + } + + pub fn push_none(&mut self, version: Version) { + self.random_seed.push(None); + self.state.push(None); + self.position.push_none(version); + self.direction.push(None); + self.joystick.push_none(version); + self.cstick.push_none(version); + self.triggers.push(None); + self.buttons.push(None); + self.buttons_physical.push(None); + self.triggers_physical.push_none(version); + if version.gte(1, 2) { + self.raw_analog_x.as_mut().unwrap().push(None); + if version.gte(1, 4) { + self.percent.as_mut().unwrap().push(None) + } + } + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + r.read_u32::().map(|x| self.random_seed.push(Some(x)))?; + r.read_u16::().map(|x| self.state.push(Some(x)))?; + self.position.read_push(r, version)?; + r.read_f32::().map(|x| self.direction.push(Some(x)))?; + self.joystick.read_push(r, version)?; + self.cstick.read_push(r, version)?; + r.read_f32::().map(|x| self.triggers.push(Some(x)))?; + r.read_u32::().map(|x| self.buttons.push(Some(x)))?; + r.read_u16::() + .map(|x| self.buttons_physical.push(Some(x)))?; + self.triggers_physical.read_push(r, version)?; + if version.gte(1, 2) { + r.read_i8() + .map(|x| self.raw_analog_x.as_mut().unwrap().push(Some(x)))?; + if version.gte(1, 4) { + r.read_f32::() + .map(|x| self.percent.as_mut().unwrap().push(Some(x)))? + } + }; + Ok(()) + } +} + +pub struct ItemMisc( + pub MutablePrimitiveArray, + pub MutablePrimitiveArray, + pub MutablePrimitiveArray, + pub MutablePrimitiveArray, +); + +impl ItemMisc { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self( + MutablePrimitiveArray::::with_capacity(capacity), + MutablePrimitiveArray::::with_capacity(capacity), + MutablePrimitiveArray::::with_capacity(capacity), + MutablePrimitiveArray::::with_capacity(capacity), + ) + } + + pub fn push_none(&mut self, version: Version) { + self.0.push(None); + self.1.push(None); + self.2.push(None); + self.3.push(None) + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + r.read_u8().map(|x| self.0.push(Some(x)))?; + r.read_u8().map(|x| self.1.push(Some(x)))?; + r.read_u8().map(|x| self.2.push(Some(x)))?; + r.read_u8().map(|x| self.3.push(Some(x)))?; + Ok(()) + } +} + +pub struct Position { + pub x: MutablePrimitiveArray, + pub y: MutablePrimitiveArray, +} + +impl Position { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + x: MutablePrimitiveArray::::with_capacity(capacity), + y: MutablePrimitiveArray::::with_capacity(capacity), + } + } + + pub fn push_none(&mut self, version: Version) { + self.x.push(None); + self.y.push(None) + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + r.read_f32::().map(|x| self.x.push(Some(x)))?; + r.read_f32::().map(|x| self.y.push(Some(x)))?; + Ok(()) + } +} + +pub struct Velocities { + pub self_x_air: MutablePrimitiveArray, + pub self_y: MutablePrimitiveArray, + pub knockback_x: MutablePrimitiveArray, + pub knockback_y: MutablePrimitiveArray, + pub self_x_ground: MutablePrimitiveArray, +} + +impl Velocities { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + self_x_air: MutablePrimitiveArray::::with_capacity(capacity), + self_y: MutablePrimitiveArray::::with_capacity(capacity), + knockback_x: MutablePrimitiveArray::::with_capacity(capacity), + knockback_y: MutablePrimitiveArray::::with_capacity(capacity), + self_x_ground: MutablePrimitiveArray::::with_capacity(capacity), + } + } + + pub fn push_none(&mut self, version: Version) { + self.self_x_air.push(None); + self.self_y.push(None); + self.knockback_x.push(None); + self.knockback_y.push(None); + self.self_x_ground.push(None) + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + r.read_f32::().map(|x| self.self_x_air.push(Some(x)))?; + r.read_f32::().map(|x| self.self_y.push(Some(x)))?; + r.read_f32::().map(|x| self.knockback_x.push(Some(x)))?; + r.read_f32::().map(|x| self.knockback_y.push(Some(x)))?; + r.read_f32::() + .map(|x| self.self_x_ground.push(Some(x)))?; + Ok(()) + } +} + +pub struct TriggersPhysical { + pub l: MutablePrimitiveArray, + pub r: MutablePrimitiveArray, +} + +impl TriggersPhysical { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + l: MutablePrimitiveArray::::with_capacity(capacity), + r: MutablePrimitiveArray::::with_capacity(capacity), + } + } + + pub fn push_none(&mut self, version: Version) { + self.l.push(None); + self.r.push(None) + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + r.read_f32::().map(|x| self.l.push(Some(x)))?; + r.read_f32::().map(|x| self.r.push(Some(x)))?; + Ok(()) + } +} + +pub struct Velocity { + pub x: MutablePrimitiveArray, + pub y: MutablePrimitiveArray, +} + +impl Velocity { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + x: MutablePrimitiveArray::::with_capacity(capacity), + y: MutablePrimitiveArray::::with_capacity(capacity), + } + } + + pub fn push_none(&mut self, version: Version) { + self.x.push(None); + self.y.push(None) + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + r.read_f32::().map(|x| self.x.push(Some(x)))?; + r.read_f32::().map(|x| self.y.push(Some(x)))?; + Ok(()) + } +} + +pub struct Item { + pub r#type: MutablePrimitiveArray, + pub state: MutablePrimitiveArray, + pub direction: MutablePrimitiveArray, + pub velocity: Velocity, + pub position: Position, + pub damage: MutablePrimitiveArray, + pub timer: MutablePrimitiveArray, + pub id: MutablePrimitiveArray, + pub misc: Option, + pub owner: Option>, +} + +impl Item { + fn with_capacity(capacity: usize, version: Version) -> Self { + Self { + r#type: MutablePrimitiveArray::::with_capacity(capacity), + state: MutablePrimitiveArray::::with_capacity(capacity), + direction: MutablePrimitiveArray::::with_capacity(capacity), + velocity: Velocity::with_capacity(capacity, version), + position: Position::with_capacity(capacity, version), + damage: MutablePrimitiveArray::::with_capacity(capacity), + timer: MutablePrimitiveArray::::with_capacity(capacity), + id: MutablePrimitiveArray::::with_capacity(capacity), + misc: version + .gte(3, 2) + .then(|| ItemMisc::with_capacity(capacity, version)), + owner: version + .gte(3, 6) + .then(|| MutablePrimitiveArray::::with_capacity(capacity)), + } + } + + pub fn push_none(&mut self, version: Version) { + self.r#type.push(None); + self.state.push(None); + self.direction.push(None); + self.velocity.push_none(version); + self.position.push_none(version); + self.damage.push(None); + self.timer.push(None); + self.id.push(None); + if version.gte(3, 2) { + self.misc.as_mut().unwrap().push_none(version); + if version.gte(3, 6) { + self.owner.as_mut().unwrap().push(None) + } + } + } + + pub fn read_push(&mut self, r: &mut &[u8], version: Version) -> Result<()> { + r.read_u16::().map(|x| self.r#type.push(Some(x)))?; + r.read_u8().map(|x| self.state.push(Some(x)))?; + r.read_f32::().map(|x| self.direction.push(Some(x)))?; + self.velocity.read_push(r, version)?; + self.position.read_push(r, version)?; + r.read_u16::().map(|x| self.damage.push(Some(x)))?; + r.read_f32::().map(|x| self.timer.push(Some(x)))?; + r.read_u32::().map(|x| self.id.push(Some(x)))?; + if version.gte(3, 2) { + self.misc.as_mut().unwrap().read_push(r, version)?; + if version.gte(3, 6) { + r.read_i8() + .map(|x| self.owner.as_mut().unwrap().push(Some(x)))? + } + }; + Ok(()) + } +} diff --git a/src/model/columnar.rs b/src/model/frame/transpose.rs similarity index 85% rename from src/model/columnar.rs rename to src/model/frame/transpose.rs index 9a4dbbb..47fa17f 100644 --- a/src/model/columnar.rs +++ b/src/model/frame/transpose.rs @@ -6,12 +6,12 @@ pub struct Frame { pub end: End, } -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct End { pub latest_finalized_frame: Option, } -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct Item { pub r#type: u16, pub state: u8, @@ -25,16 +25,16 @@ pub struct Item { pub owner: Option, } -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct ItemMisc(pub u8, pub u8, pub u8, pub u8); -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct Position { pub x: f32, pub y: f32, } -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct Post { pub character: u8, pub state: u16, @@ -59,7 +59,7 @@ pub struct Post { pub animation_index: Option, } -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct Pre { pub random_seed: u32, pub state: u16, @@ -75,22 +75,22 @@ pub struct Pre { pub percent: Option, } -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct Start { pub random_seed: Option, pub scene_frame_counter: Option, } -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct StateFlags(pub u8, pub u8, pub u8, pub u8, pub u8); -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct TriggersPhysical { pub l: f32, pub r: f32, } -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct Velocities { pub self_x_air: f32, pub self_y: f32, @@ -99,7 +99,7 @@ pub struct Velocities { pub self_x_ground: f32, } -#[derive(PartialEq, Debug)] +#[derive(Debug, PartialEq)] pub struct Velocity { pub x: f32, pub y: f32, diff --git a/src/model/game.rs b/src/model/game.rs index 5715272..f8b6453 100644 --- a/src/model/game.rs +++ b/src/model/game.rs @@ -23,10 +23,10 @@ pub const MAX_SUPPORTED_VERSION: slippi::Version = slippi::Version(3, 12, 0); pub const NUM_PORTS: u8 = 4; +#[repr(u8)] #[derive( Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, IntoPrimitive, TryFromPrimitive, )] -#[repr(u8)] pub enum Port { P1 = 0, P2 = 1, @@ -55,9 +55,9 @@ impl Default for Port { #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, TryFromPrimitive)] pub enum PlayerType { - HUMAN = 0, - CPU = 1, - DEMO = 2, + Human = 0, + Cpu = 1, + Demo = 2, } #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] @@ -66,11 +66,32 @@ pub struct Team { pub shade: u8, } +#[repr(u32)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, TryFromPrimitive)] +pub enum DashBack { + Ucf = 1, + Arduino = 2, +} + +#[repr(u32)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, TryFromPrimitive)] +pub enum ShieldDrop { + Ucf = 1, + Arduino = 2, +} + +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, TryFromPrimitive)] +pub enum Language { + Japanese = 0, + English = 1, +} + /// Information about the "Universal Controller Fix" mod. #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)] pub struct Ucf { - pub dash_back: u32, - pub shield_drop: u32, + pub dash_back: Option, + pub shield_drop: Option, } /// Netplay name, connect code, and Slippi UID. @@ -136,6 +157,15 @@ pub struct Scene { pub major: u8, } +#[derive(PartialEq, Eq, Clone)] +pub struct Bytes(pub Vec); + +impl Debug for Bytes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + write!(f, "Bytes {{ len: {} }}", self.0.len()) + } +} + /// Information used to initialize the game such as the game mode, settings, characters & stage. #[derive(Clone, Debug, PartialEq, Serialize)] pub struct Start { @@ -166,7 +196,7 @@ pub struct Start { /// mostly-redundant copy of the raw start block, for round-tripping #[serde(skip)] #[doc(hidden)] - pub raw_bytes: Vec, + pub bytes: Bytes, /// (added: v1.5) #[serde(skip_serializing_if = "Option::is_none")] @@ -182,7 +212,7 @@ pub struct Start { /// (added: v3.12) #[serde(skip_serializing_if = "Option::is_none")] - pub language: Option, + pub language: Option, } impl Start { @@ -191,16 +221,26 @@ impl Start { } } +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, TryFromPrimitive)] +pub enum EndMethod { + Unresolved = 0, + Time = 1, + Game = 2, + Resolved = 3, + NoContest = 7, +} + /// Information about the end of the game. #[derive(Clone, Debug, PartialEq, Eq, Serialize)] pub struct End { /// how the game ended - pub method: u8, + pub method: EndMethod, - /// mostly-redundant copy of the raw start block, for round-tripping + /// mostly-redundant copy of the raw end block, for round-tripping #[serde(skip)] #[doc(hidden)] - pub raw_bytes: Vec, + pub bytes: Bytes, /// player who LRAS'd, if any (added: v2.0) #[serde(skip_serializing_if = "Option::is_none")] @@ -236,6 +276,7 @@ pub struct GeckoCodes { pub actual_size: u32, } +#[derive(Debug)] pub struct Game { pub start: Start, pub end: Option, diff --git a/src/serde/de.rs b/src/serde/de.rs index 59cfc5a..07a89b3 100644 --- a/src/serde/de.rs +++ b/src/serde/de.rs @@ -1,19 +1,21 @@ use std::{ collections::HashMap, + error, fs::{self, File}, io::{self, Read, Result, Write}, path::{Path, PathBuf}, }; +use arrow2::array::MutableArray; use byteorder::ReadBytesExt; use log::{debug, info}; -use arrow2::array::MutableArray; type BE = byteorder::BigEndian; use crate::{ model::{ frame, + frame::mutable::Frame as MutableFrame, game::{self, Game, Netplay, Player, PlayerType, Port, NUM_PORTS}, shift_jis::MeleeString, slippi, @@ -41,7 +43,7 @@ pub(crate) enum Event { struct MutableGame { start: game::Start, end: Option, - frames: frame::MutableFrame, + frames: MutableFrame, metadata: Option>, gecko_codes: Option, port_indexes: [usize; 4], @@ -69,6 +71,10 @@ where }) } +fn invalid_data>>(err: E) -> io::Error { + io::Error::new(io::ErrorKind::InvalidData, err) +} + /// Reads the Event Payloads event, which must come first in the raw stream /// and tells us the sizes for all other events to follow. /// Returns the number of bytes read by this function, plus a map of event @@ -145,7 +151,7 @@ fn player( let cpu_level = { let cpu_level = r.read_u8()?; match r#type { - Some(PlayerType::CPU) => Some(cpu_level), + Some(PlayerType::Cpu) => Some(cpu_level), _ => None, } }; @@ -160,8 +166,14 @@ fn player( Some(v1_0) => { let mut r = &v1_0[..]; Some(game::Ucf { - dash_back: r.read_u32::()?, - shield_drop: r.read_u32::()?, + dash_back: match r.read_u32::()? { + 0 => None, + x => Some(game::DashBack::try_from(x).map_err(invalid_data)?), + }, + shield_drop: match r.read_u32::()? { + 0 => None, + x => Some(game::ShieldDrop::try_from(x).map_err(invalid_data)?), + }, }) } _ => None, @@ -180,7 +192,7 @@ fn player( .map(|v3_11| { let first_null = v3_11.iter().position(|&x| x == 0).unwrap_or(28); let result = std::str::from_utf8(&v3_11[0..first_null]); - result.map(String::from).map_err(|_| err!("invalid suid")) + result.map(String::from).map_err(invalid_data) }) .transpose()?; Result::Ok(Netplay { @@ -246,7 +258,7 @@ fn player_bytes_v1_0(r: &mut &[u8]) -> Result<[u8; 8]> { } pub(crate) fn game_start(r: &mut &[u8]) -> Result { - let raw_bytes = r.to_vec(); + let bytes = game::Bytes(r.to_vec()); let slippi = slippi::Slippi { version: slippi::Version(r.read_u8()?, r.read_u8()?, r.read_u8()?), }; @@ -346,7 +358,7 @@ pub(crate) fn game_start(r: &mut &[u8]) -> Result { for n in 0..NUM_PORTS { let nu = n as usize; if let Some(p) = player( - Port::try_from(n).unwrap(), + Port::try_from(n).map_err(invalid_data)?, &players_v0[nu], is_teams, players_v1_0[nu], @@ -359,7 +371,12 @@ pub(crate) fn game_start(r: &mut &[u8]) -> Result { } } - let language = if_more(r, |r| Ok(r.read_u8()?))?; + let language = if_more(r, |r| + Ok( + game::Language::try_from(r.read_u8()?) + .map_err(invalid_data)? + ) + )?; Ok(game::Start { slippi, @@ -374,7 +391,7 @@ pub(crate) fn game_start(r: &mut &[u8]) -> Result { damage_ratio, players, random_seed, - raw_bytes, + bytes, // v1.5 is_pal, // v2.0 @@ -387,12 +404,17 @@ pub(crate) fn game_start(r: &mut &[u8]) -> Result { } pub(crate) fn game_end(r: &mut &[u8]) -> Result { - let raw_bytes = r.to_vec(); + let bytes = game::Bytes(r.to_vec()); Ok(game::End { - method: r.read_u8()?, - raw_bytes: raw_bytes, + method: game::EndMethod::try_from(r.read_u8()?).map_err(invalid_data)?, + bytes: bytes, // v2.0 - lras_initiator: if_more(r, |r| Ok(Port::try_from(r.read_u8()?).ok()))?, + lras_initiator: if_more(r, |r| Ok( + match r.read_u8()? { + 255 => None, + x => Some(Port::try_from(x).map_err(invalid_data)?), + } + ))?, }) } @@ -644,7 +666,7 @@ pub fn deserialize( MutableGame { start: start, end: None, - frames: frame::MutableFrame::with_capacity(1024, version, &ports), + frames: MutableFrame::with_capacity(1024, version, &ports), metadata: None, gecko_codes: None, port_indexes: { diff --git a/src/serde/ser.rs b/src/serde/ser.rs index 718e377..5557682 100644 --- a/src/serde/ser.rs +++ b/src/serde/ser.rs @@ -19,7 +19,7 @@ fn payload_sizes(game: &Game) -> Vec<(u8, u16)> { let ver = start.slippi.version; let mut sizes = Vec::new(); - sizes.push((Event::GameStart as u8, start.raw_bytes.len() as u16)); + sizes.push((Event::GameStart as u8, start.bytes.0.len() as u16)); sizes.push(( Event::FramePre as u8, @@ -103,12 +103,12 @@ fn gecko_codes(w: &mut W, codes: &GeckoCodes) -> Result<()> { fn game_start(w: &mut W, s: &game::Start, ver: Version) -> Result<()> { assert_eq!(ver, s.slippi.version); w.write_u8(Event::GameStart as u8)?; - w.write_all(&s.raw_bytes) + w.write_all(&s.bytes.0) } fn game_end(w: &mut W, e: &game::End, ver: Version) -> Result<()> { w.write_u8(Event::GameEnd as u8)?; - w.write_u8(e.method)?; + w.write_u8(e.method as u8)?; if ver.gte(2, 0) { w.write_u8( e.lras_initiator diff --git a/tests/json.rs b/tests/json.rs index 843e915..e5cc5aa 100644 --- a/tests/json.rs +++ b/tests/json.rs @@ -61,7 +61,7 @@ fn json_start() { { "port":"P1", "character":9, - "type":"HUMAN", + "type":"Human", "stocks":4, "costume":3, "team":null, @@ -72,8 +72,8 @@ fn json_start() { "defense_ratio":1.0, "model_scale":1.0, "ucf":{ - "dash_back":1, - "shield_drop":1 + "dash_back":"Ucf", + "shield_drop":"Ucf" }, "name_tag":"", "netplay":{ @@ -85,7 +85,7 @@ fn json_start() { { "port":"P2", "character":9, - "type":"HUMAN", + "type":"Human", "stocks":4, "costume":0, "team":null, @@ -96,8 +96,8 @@ fn json_start() { "defense_ratio":1.0, "model_scale":1.0, "ucf":{ - "dash_back":1, - "shield_drop":1 + "dash_back":"Ucf", + "shield_drop":"Ucf" }, "name_tag":"", "netplay":{ @@ -114,7 +114,7 @@ fn json_start() { "minor":2, "major":8 }, - "language":1 + "language":"English" }"#, ) .unwrap(); @@ -128,7 +128,7 @@ fn json_end() { let game = game("v3.12"); let expected: serde_json::Value = serde_json::from_str( r#"{ - "method":7, + "method":"NoContest", "lras_initiator":"P2" }"#, ) diff --git a/tests/peppi.rs b/tests/peppi.rs index 5a7be82..413696e 100644 --- a/tests/peppi.rs +++ b/tests/peppi.rs @@ -10,9 +10,9 @@ use serde_json::json; use peppi::{ model::{ - columnar, + frame::transpose, game::{ - End, Game, Netplay, Player, PlayerType, Port, Scene, Start, Ucf, + Bytes, DashBack, End, EndMethod, Game, Language, Netplay, Player, PlayerType, Port, Scene, ShieldDrop, Start, Ucf, }, shift_jis::MeleeString, slippi::{Slippi, Version}, @@ -60,8 +60,8 @@ fn slippi_old_version() { ); assert_eq!(players.len(), 2); - assert_eq!(players[0].character, 2); // External::FOX - assert_eq!(players[1].character, 25); // External::GANONDORF + assert_eq!(players[0].character, 2); // Fox + assert_eq!(players[1].character, 25); // Ganondorf } #[test] @@ -76,12 +76,12 @@ fn basic_game() { "players": { "1": { "characters": { - "1": 5209, // Internal::FOX + "1": 5209, // Fox } }, "0": { "characters": { - "18": 5209 // Internal::MARTH + "18": 5209 // Marth } } }, @@ -107,8 +107,8 @@ fn basic_game() { players: vec![ Player { port: Port::P1, - character: 9, // External::MARTH - r#type: PlayerType::HUMAN, + character: 9, // Marth + r#type: PlayerType::Human, stocks: 4, costume: 3, team: None, @@ -119,16 +119,16 @@ fn basic_game() { defense_ratio: 1.0, model_scale: 1.0, ucf: Some(Ucf { - dash_back: 0, // DashBack::NONE - shield_drop: 0, // ShieldDrop::NONE + dash_back: None, + shield_drop: None, }), name_tag: None, netplay: None, }, Player { port: Port::P2, - character: 2, // External::FOX - r#type: PlayerType::CPU, + character: 2, // Fox + r#type: PlayerType::Cpu, stocks: 4, costume: 0, team: None, @@ -139,8 +139,8 @@ fn basic_game() { defense_ratio: 1.0, model_scale: 1.0, ucf: Some(Ucf { - dash_back: 0, // DashBack::NONE - shield_drop: 0, // ShieldDrop::NONE + dash_back: None, + shield_drop: None, }), name_tag: None, netplay: None, @@ -151,7 +151,7 @@ fn basic_game() { is_frozen_ps: None, scene: None, language: None, - raw_bytes: vec![ + bytes: Bytes(vec![ 1, 0, 0, 0, 50, 1, 134, 76, 195, 0, 0, 0, 0, 0, 0, 255, 255, 110, 0, 8, 0, 0, 1, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 63, 128, 0, 0, 63, 128, 0, 0, 63, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -167,16 +167,16 @@ fn basic_game() { 64, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 128, 0, 0, 63, 128, 0, 0, 63, 128, 0, 0, 226, 176, 35, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - ], + ]), } ); assert_eq!( game.end.unwrap(), End { - method: 3, // EndMethod::RESOLVED + method: EndMethod::Resolved, lras_initiator: None, - raw_bytes: vec![3], + bytes: Bytes(vec![3]), } ); @@ -191,13 +191,13 @@ fn ics() { json!({ "1": { "characters": { - "15": 344 // Internal::JIGGLYPUFF + "15": 344 // Jigglypuff } }, "0": { "characters": { - "11": 344, // Internal::NANA - "10": 344 // Internal::POPO + "11": 344, // Nana + "10": 344 // Popo } } }) @@ -211,15 +211,15 @@ fn ucf() { assert_eq!( game("shield_drop").start.players[0].ucf, Some(Ucf { - dash_back: 0, - shield_drop: 1, // ShieldDrop::UCF + dash_back: None, + shield_drop: Some(ShieldDrop::Ucf), }) ); assert_eq!( game("dash_back").start.players[0].ucf, Some(Ucf { - dash_back: 1, // DashBack::UCF - shield_drop: 0, + dash_back: Some(DashBack::Ucf), + shield_drop: None, }) ); } @@ -231,28 +231,28 @@ fn buttons_lzrs() { button_seq(&game), vec![ Buttons { - logical: 2147483648, // Logical::TRIGGER_ANALOG, - physical: 0, // Physical::NONE, + logical: 2147483648, // Trigger + physical: 0, }, Buttons { - logical: 2147483712, // Logical::TRIGGER_ANALOG | Logical::L, - physical: 64, // Physical::L, + logical: 2147483712, // Trigger | L + physical: 64, // L }, Buttons { - logical: 2147483648, // Logical::TRIGGER_ANALOG, - physical: 0, // Physical::NONE, + logical: 2147483648, // Trigger + physical: 0, }, Buttons { - logical: 2147483680, // Logical::TRIGGER_ANALOG | Logical::R, - physical: 32, // Physical::R, + logical: 2147483680, // Trigger | R + physical: 32, // R }, Buttons { - logical: 2147483920, // Logical::TRIGGER_ANALOG | Logical::A | Logical::Z, - physical: 16, // Physical::Z, + logical: 2147483920, // Trigger | A | Z + physical: 16, // Z }, Buttons { - logical: 4096, // Logical::START, - physical: 4096, // Physical::START, + logical: 4096, // Start + physical: 4096, // Start }, ] ); @@ -265,20 +265,20 @@ fn buttons_abxy() { button_seq(&game), vec![ Buttons { - logical: 256, // Logical::A, - physical: 256, // Physical::A, + logical: 256, // A + physical: 256, // A }, Buttons { - logical: 512, // Logical::B, - physical: 512, // Physical::B, + logical: 512, // B + physical: 512, // B }, Buttons { - logical: 1024, // Logical::X, - physical: 1024, // Physical::X, + logical: 1024, // X + physical: 1024, // X }, Buttons { - logical: 2048, // Logical::Y, - physical: 2048, // Physical::Y, + logical: 2048, // Y + physical: 2048, // Y }, ] ); @@ -291,20 +291,20 @@ fn dpad_udlr() { button_seq(&game), vec![ Buttons { - logical: 8, // Logical::DPAD_UP, - physical: 8, // Physical::DPAD_UP, + logical: 8, // D-pad up + physical: 8, // D-pad up }, Buttons { - logical: 4, // Logical::DPAD_DOWN, - physical: 4, // Physical::DPAD_DOWN, + logical: 4, // D-pad down + physical: 4, // D-pad down }, Buttons { - logical: 1, // Logical::DPAD_LEFT, - physical: 1, // Physical::DPAD_LEFT, + logical: 1, // D-pad left + physical: 1, // D-pad left }, Buttons { - logical: 2, // Logical::DPAD_RIGHT, - physical: 2, // Physical::DPAD_RIGHT, + logical: 2, // D-pad right + physical: 2, // D-pad right }, ] ); @@ -317,20 +317,20 @@ fn cstick_udlr() { button_seq(&game), vec![ Buttons { - logical: 1048576, // Logical::CSTICK_UP, - physical: 0, // Physical::NONE, + logical: 1048576, // C-stick up + physical: 0, }, Buttons { - logical: 2097152, // Logical::CSTICK_DOWN, - physical: 0, // Physical::NONE, + logical: 2097152, // C-stick down + physical: 0, }, Buttons { - logical: 4194304, // Logical::CSTICK_LEFT, - physical: 0, // Physical::NONE, + logical: 4194304, // C-stick left + physical: 0, }, Buttons { - logical: 8388608, // Logical::CSTICK_RIGHT, - physical: 0, // Physical::NONE, + logical: 8388608, // C-stick right + physical: 0, }, ] ); @@ -343,20 +343,20 @@ fn joystick_udlr() { button_seq(&game), vec![ Buttons { - logical: 65536, // Logical::JOYSTICK_UP, - physical: 0, // Physical::NONE, + logical: 65536, // Joystick up + physical: 0, }, Buttons { - logical: 131072, // Logical::JOYSTICK_DOWN, - physical: 0, // Physical::NONE, + logical: 131072, // Joystick down + physical: 0, }, Buttons { - logical: 262144, // Logical::JOYSTICK_LEFT, - physical: 0, // Physical::NONE, + logical: 262144, // Joystick left + physical: 0, }, Buttons { - logical: 524288, // Logical::JOYSTICK_RIGHT, - physical: 0, // Physical::NONE, + logical: 524288, // Joystick right + physical: 0, }, ] ); @@ -436,8 +436,8 @@ fn v3_12() { players: vec![ Player { port: Port::P1, - character: 9, // External::MARTH - r#type: PlayerType::HUMAN, + character: 9, // Marth + r#type: PlayerType::Human, stocks: 4, costume: 3, team: None, @@ -448,8 +448,8 @@ fn v3_12() { defense_ratio: 1.0, model_scale: 1.0, ucf: Some(Ucf { - dash_back: 1, // DashBack::UCF - shield_drop: 1, // ShieldDrop::UCF + dash_back: Some(DashBack::Ucf), + shield_drop: Some(ShieldDrop::Ucf), }), name_tag: Some(MeleeString("".to_string())), netplay: Some(Netplay { @@ -460,8 +460,8 @@ fn v3_12() { }, Player { port: Port::P2, - character: 9, // External::MARTH - r#type: PlayerType::HUMAN, + character: 9, // Marth + r#type: PlayerType::Human, stocks: 4, costume: 0, team: None, @@ -472,8 +472,8 @@ fn v3_12() { defense_ratio: 1.0, model_scale: 1.0, ucf: Some(Ucf { - dash_back: 1, // DashBack::UCF - shield_drop: 1, // ShieldDrop::UCF + dash_back: Some(DashBack::Ucf), + shield_drop: Some(ShieldDrop::Ucf), }), name_tag: Some(MeleeString("".to_string())), netplay: Some(Netplay { @@ -484,7 +484,7 @@ fn v3_12() { } ], random_seed: 39656, - raw_bytes: vec![ + bytes: Bytes(vec![ 3, 12, 0, 0, 50, 1, 142, 76, 195, 0, 0, 0, 0, 0, 0, 255, 255, 110, 0, 3, 0, 0, 1, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 63, 128, 0, 0, 63, 128, 0, 0, 63, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -514,11 +514,11 @@ fn v3_12() { 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 - ], + ]), is_pal: Some(false), is_frozen_ps: Some(false), scene: Some(Scene { minor: 2, major: 8 }), - language: Some(1), // Language::ENGLISH + language: Some(Language::English), } ); } @@ -540,7 +540,7 @@ fn zelda_sheik_transformation() { let game = game("transform"); assert_eq!( game.frames.port[1].leader.pre.state.values()[400], - 355, // State::Zelda(Zelda::TRANSFORM_GROUND) + 355, // Zelda Transform (Ground) ); } @@ -549,55 +549,55 @@ fn items() { let game = game("items"); assert_eq!( game.frames.item.transpose_one(0, game.start.slippi.version), - columnar::Item { + transpose::Item { id: 0, damage: 0, direction: 1.0, - position: columnar::Position { + position: transpose::Position { x: -62.709_606, y: -1.493_274_9 }, state: 0, timer: 140.0, - r#type: 99, // item::Type::PEACH_TURNIP, - velocity: columnar::Velocity { x: 0.0, y: 0.0 }, - misc: Some(columnar::ItemMisc(5, 5, 5, 5)), + r#type: 99, // Peach Turnip + velocity: transpose::Velocity { x: 0.0, y: 0.0 }, + misc: Some(transpose::ItemMisc(5, 5, 5, 5)), owner: Some(0), } ); assert_eq!( game.frames.item.transpose_one(102, game.start.slippi.version), - columnar::Item { + transpose::Item { id: 1, damage: 0, direction: -1.0, - position: columnar::Position { + position: transpose::Position { x: 20.395_56, y: -1.493_274_9 }, state: 0, timer: 140.0, - r#type: 99, // item::Type::PEACH_TURNIP, - velocity: columnar::Velocity { x: 0.0, y: 0.0 }, - misc: Some(columnar::ItemMisc(5, 0, 5, 5)), + r#type: 99, // Peach Turnip + velocity: transpose::Velocity { x: 0.0, y: 0.0 }, + misc: Some(transpose::ItemMisc(5, 0, 5, 5)), owner: Some(0), } ); assert_eq!( game.frames.item.transpose_one(290, game.start.slippi.version), - columnar::Item { + transpose::Item { id: 2, damage: 0, direction: 1.0, - position: columnar::Position { + position: transpose::Position { x: -3.982_539_2, y: -1.493_274_9 }, state: 0, timer: 140.0, - r#type: 99, // item::Type::PEACH_TURNIP, - velocity: columnar::Velocity { x: 0.0, y: 0.0 }, - misc: Some(columnar::ItemMisc(5, 0, 5, 5)), + r#type: 99, // Peach Turnip + velocity: transpose::Velocity { x: 0.0, y: 0.0 }, + misc: Some(transpose::ItemMisc(5, 0, 5, 5)), owner: Some(0), } );