1#[allow(clippy::module_inception)]
2mod recorder;
3pub use recorder::Recorder;
4
5mod replayer;
6pub use replayer::StateWithInputActionsReader;
7
8use std::{
9 borrow::Cow,
10 io::Write,
11 path::{Path, PathBuf},
12};
13
14use serde::{Deserialize, Serialize};
15
16use crate::{p2p::identity::SecretKey as P2pSecretKey, Action, ActionKind, ActionWithMeta, State};
17
18fn initial_state_path<P: AsRef<Path>>(path: P) -> PathBuf {
19 path.as_ref().join("initial_state.postcard")
20}
21
22fn actions_path<P: AsRef<Path>>(path: P, file_index: usize) -> PathBuf {
23 path.as_ref()
24 .join(format!("actions_{}.postcard", file_index))
25}
26
27#[derive(Serialize, Deserialize)]
28pub struct RecordedInitialState<'a> {
29 pub rng_seed: [u8; 32],
30 pub p2p_sec_key: P2pSecretKey,
31 pub state: Cow<'a, State>,
32}
33
34impl RecordedInitialState<'_> {
35 pub fn write_to<W: Write>(&self, writer: &mut W) -> postcard::Result<()> {
36 postcard::to_io(self, writer).and(Ok(()))
37 }
38
39 pub fn decode(encoded: &[u8]) -> postcard::Result<Self> {
40 postcard::from_bytes(encoded)
41 }
42}
43
44#[derive(Serialize, Deserialize, Debug)]
45pub struct RecordedActionWithMeta<'a> {
46 pub kind: ActionKind,
47 pub meta: redux::ActionMeta,
48 pub action: Option<Cow<'a, Action>>,
49}
50
51impl RecordedActionWithMeta<'_> {
52 pub fn encode(&self) -> postcard::Result<Vec<u8>> {
53 postcard::to_stdvec(self)
54 }
55
56 pub fn decode(encoded: &[u8]) -> postcard::Result<Self> {
57 postcard::from_bytes(encoded)
58 }
59
60 pub fn as_action_with_meta(self) -> Result<ActionWithMeta, Self> {
61 if self.action.is_some() {
62 let action = self.action.unwrap().into_owned();
63 Ok(self.meta.with_action(action))
64 } else {
65 Err(self)
66 }
67 }
68}
69
70impl<'a> From<&'a ActionWithMeta> for RecordedActionWithMeta<'a> {
71 fn from(value: &'a ActionWithMeta) -> Self {
72 Self {
73 kind: value.action().kind(),
74 meta: value.meta().clone(),
75 action: Some(Cow::Borrowed(value.action())),
76 }
77 }
78}
79
80impl From<(ActionKind, redux::ActionMeta)> for RecordedActionWithMeta<'static> {
81 fn from((kind, meta): (ActionKind, redux::ActionMeta)) -> Self {
82 Self {
83 kind,
84 meta,
85 action: None,
86 }
87 }
88}