async_maelstrom/
lib.rs

1//! A Rust library that allows distributed applications to work with
2//! [Maelstrom](https://github.com/jepsen-io/maelstrom).
3//!
4//! [Maelstrom](https://github.com/jepsen-io/maelstrom) is a workbench for learning and testing
5//! distributed applications.
6//! It drives [workloads](https://github.com/jepsen-io/maelstrom/blob/main/doc/workloads.md) to
7//! application nodes, and uses [Jepsen](https://github.com/jepsen-io/jepsen) to verify safety
8//! properties.
9//!
10//! The library provides
11//! - a `Msg` implementation for creating and parsing workload and node-to-node message according to the
12//!   [Maelstrom message protocol](https://github.com/jepsen-io/maelstrom/blob/main/doc/protocol.md#messages)
13//! - a `Process` trait for implementing application node processes
14//! - a `Runtime` for driving processes and communicating with the
15//!   [Maelstrom network](https://github.com/jepsen-io/maelstrom/blob/main/doc/protocol.md#nodes-and-networks)
16//!
17//! See the [echo.rs](https://github.com/bnjmnt/async-maelstrom/blob/main/examples/echo.rs) for a
18//! simple  library usage example.
19use std::fmt::{Debug, Display, Formatter};
20use std::{error, io};
21
22use async_std::channel::{RecvError, SendError};
23use serde::de::DeserializeOwned;
24use serde::Serialize;
25use serde_json::Value;
26
27use crate::msg::Msg;
28use crate::Error::{Deserialize, Shutdown, IO};
29
30pub mod msg;
31pub mod process;
32pub mod runtime;
33
34/// Maelstrom [node address](https://github.com/jepsen-io/maelstrom/blob/main/doc/protocol.md#messages)
35pub type Id = String;
36
37/// Maelstrom [error code](https://github.com/jepsen-io/maelstrom/blob/main/doc/protocol.md#errors)
38pub type ErrorCode = u64;
39
40/// Errors the library may return to the application
41#[derive(Debug)]
42pub enum Error {
43    /// A message could not be deserialized
44    Deserialize(serde_json::Error),
45    /// Initialization of a [process::Process] failed
46    Initialization(Box<dyn error::Error>),
47    /// An IO operation failed
48    IO(io::Error),
49    /// The expected deserialized message type does not match the serialized data
50    MessageType,
51    /// A message could not be serialized
52    Serialize(serde_json::Error),
53    /// The runtime has shutdown before the process completed
54    Shutdown,
55    /// Testing only
56    TestIO,
57    /// A process received a message that was unexpected for the current state or protocol
58    UnexpectedMsg { expected: &'static str },
59}
60
61unsafe impl Send for Error {}
62
63impl From<io::Error> for Error {
64    fn from(e: io::Error) -> Self {
65        IO(e)
66    }
67}
68impl From<serde_json::Error> for Error {
69    fn from(e: serde_json::Error) -> Self {
70        Deserialize(e)
71    }
72}
73
74impl From<RecvError> for Error {
75    fn from(_: RecvError) -> Self {
76        Shutdown
77    }
78}
79
80impl<W, A> From<SendError<Msg<W, A>>> for Error
81where
82    W: DeserializeOwned + Serialize,
83    A: DeserializeOwned + Serialize,
84{
85    fn from(_: SendError<Msg<W, A>>) -> Self {
86        Shutdown
87    }
88}
89
90impl Display for Error {
91    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
92        write!(f, "{:?}", self)
93    }
94}
95
96impl error::Error for Error {}
97
98/// Results for library functions that may fail
99pub type Result<T> = std::result::Result<T, Error>;
100
101/// Status for library functions that may fail
102pub type Status = std::result::Result<(), Error>;
103
104/// Maelstrom [Lin-kv workload key](https://github.com/jepsen-io/maelstrom/blob/main/doc/workloads.md#workload-lin-kv)
105pub type Key = Value;
106
107/// Maelstrom [Lin-kv workload value](https://github.com/jepsen-io/maelstrom/blob/main/doc/workloads.md#workload-lin-kv)
108pub type Val = Value;