use crate::{errors, packer::Packer};
use bytes::Bytes;
use serde::{Deserialize, Serialize};
#[derive(
Deserialize,
Serialize,
std::clone::Clone,
std::cmp::Eq,
std::cmp::Ord,
std::cmp::PartialEq,
std::cmp::PartialOrd,
std::fmt::Debug,
std::hash::Hash,
)]
pub enum Status {
Processing,
Rejected,
Accepted,
Unknown(String),
}
impl Default for Status {
fn default() -> Self {
Status::Unknown("default".to_owned())
}
}
impl std::convert::From<&str> for Status {
fn from(s: &str) -> Self {
match s {
"Processing" => Status::Processing,
"Rejected" => Status::Rejected,
"Accepted" => Status::Accepted,
other => Status::Unknown(other.to_owned()),
}
}
}
impl std::str::FromStr for Status {
type Err = std::convert::Infallible;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
Ok(Status::from(s))
}
}
impl std::fmt::Display for Status {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl Status {
pub fn as_str(&self) -> &str {
match self {
Status::Processing => "Processing",
Status::Rejected => "Rejected",
Status::Accepted => "Accepted",
Status::Unknown(s) => s.as_ref(),
}
}
pub fn values() -> &'static [&'static str] {
&["Processing", "Rejected", "Accepted"]
}
pub fn decided(&self) -> bool {
matches!(self, Status::Rejected | Status::Accepted)
}
pub fn fetched(&self) -> bool {
match self {
Status::Processing => true,
_ => self.decided(),
}
}
pub fn bytes(&self) -> errors::Result<Bytes> {
let iota = match self {
Status::Processing => 1_u32,
Status::Rejected => 2_u32,
Status::Accepted => 3_u32,
Status::Unknown(_) => 0_u32,
};
let packer = Packer::new(4, 4);
packer.pack_u32(iota)?;
Ok(packer.take_bytes())
}
pub fn to_u32(&self) -> u32 {
match self {
Status::Processing => 1,
Status::Rejected => 2,
Status::Accepted => 3,
Status::Unknown(_) => 0,
}
}
pub fn to_i32(&self) -> i32 {
match self {
Status::Processing => 1,
Status::Rejected => 2,
Status::Accepted => 3,
Status::Unknown(_) => 0,
}
}
pub fn u32_from_slice(bytes: &[u8]) -> u32 {
assert!(bytes.len() <= 4);
let d: [u8; 4] = bytes.try_into().unwrap();
u32::from_ne_bytes(d)
}
}
impl AsRef<str> for Status {
fn as_ref(&self) -> &str {
self.as_str()
}
}
#[test]
fn test_bytes() {
let sb = Status::Processing.bytes().unwrap().to_vec();
assert!(cmp_manager::eq_vectors(&sb, &[0x00, 0x00, 0x00, 0x01]));
let sb = Status::Rejected.bytes().unwrap().to_vec();
assert!(cmp_manager::eq_vectors(&sb, &[0x00, 0x00, 0x00, 0x02]));
let sb = Status::Accepted.bytes().unwrap().to_vec();
assert!(cmp_manager::eq_vectors(&sb, &[0x00, 0x00, 0x00, 0x03]));
let sb = Status::Unknown("()".to_string()).bytes().unwrap().to_vec();
assert!(cmp_manager::eq_vectors(&sb, &[0x00, 0x00, 0x00, 0x00]));
}
#[test]
fn test_to_u32() {
assert_eq!(Status::Unknown("hello".to_string()).to_u32(), 0);
assert_eq!(Status::Processing.to_u32(), 1);
assert_eq!(Status::Rejected.to_u32(), 2);
assert_eq!(Status::Accepted.to_u32(), 3);
}