use super::CountryCode;
use crate::{len::PAYOUT_BLOCK, std::fmt, Error, Result};
mod list;
pub use list::*;
pub type PayoutBlock = [u8; PAYOUT_BLOCK];
#[repr(u8)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub enum PayoutOption {
TestPayoutAmount = 0x19,
#[default]
PayoutAmount = 0x58,
}
impl From<PayoutOption> for u8 {
fn from(val: PayoutOption) -> Self {
val as u8
}
}
impl From<&PayoutOption> for u8 {
fn from(val: &PayoutOption) -> Self {
(*val).into()
}
}
impl From<u8> for PayoutOption {
fn from(val: u8) -> Self {
match val {
0x19 => Self::TestPayoutAmount,
0x58 => Self::PayoutAmount,
_ => Self::PayoutAmount,
}
}
}
impl From<&PayoutOption> for &'static str {
fn from(val: &PayoutOption) -> Self {
match val {
PayoutOption::TestPayoutAmount => "TestPayoutAmount",
PayoutOption::PayoutAmount => "PayoutAmount",
}
}
}
impl From<PayoutOption> for &'static str {
fn from(val: PayoutOption) -> Self {
(&val).into()
}
}
impl fmt::Display for PayoutOption {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, r#""{}""#, <&str>::from(self))
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct PayoutDenomination {
number: u16,
value: u32,
currency: CountryCode,
}
impl PayoutDenomination {
pub const fn new() -> Self {
Self {
number: 0,
value: 0,
currency: CountryCode::new(),
}
}
pub const fn create(number: u16, value: u32, currency: CountryCode) -> Self {
Self {
number,
value,
currency,
}
}
pub const fn number(&self) -> u16 {
self.number
}
pub fn set_number(&mut self, val: u16) {
self.number = val;
}
pub fn with_number(mut self, val: u16) -> Self {
self.set_number(val);
self
}
pub const fn value(&self) -> u32 {
self.value
}
pub fn set_value(&mut self, val: u32) {
self.value = val;
}
pub fn with_value(mut self, val: u32) -> Self {
self.set_value(val);
self
}
pub const fn currency(&self) -> CountryCode {
self.currency
}
pub fn set_currency(&mut self, val: CountryCode) {
self.currency = val;
}
pub fn with_currency(mut self, val: CountryCode) -> Self {
self.set_currency(val);
self
}
pub fn to_buffer(&self, buf: &mut [u8]) -> Result<()> {
let buf_len = buf.len();
if buf_len < PAYOUT_BLOCK {
Err(Error::InvalidLength((buf_len, PAYOUT_BLOCK)))
} else {
buf[..2].copy_from_slice(self.number().to_le_bytes().as_ref());
buf[2..6].copy_from_slice(self.value().to_le_bytes().as_ref());
buf[6..PAYOUT_BLOCK].copy_from_slice(<&str>::from(self.currency()).as_bytes());
Ok(())
}
}
pub fn from_buffer(buf: &[u8]) -> Result<Self> {
let len = buf.len();
if len < PAYOUT_BLOCK {
Err(Error::InvalidLength((len, PAYOUT_BLOCK)))
} else {
let number = u16::from_le_bytes(buf[..2].try_into().unwrap_or([0; 2]));
let value = u32::from_le_bytes(buf[2..6].try_into().unwrap_or([0; 4]));
let currency = CountryCode::from(&buf[6..PAYOUT_BLOCK]);
Ok(Self::create(number, value, currency))
}
}
}
impl From<PayoutDenomination> for PayoutBlock {
fn from(val: PayoutDenomination) -> Self {
let mut res = [0u8; PAYOUT_BLOCK];
val.to_buffer(res.as_mut()).ok();
res
}
}
impl From<&PayoutBlock> for PayoutDenomination {
fn from(val: &PayoutBlock) -> Self {
Self::from_buffer(val.as_ref()).unwrap_or(Self::new())
}
}
impl TryFrom<&[u8]> for PayoutDenomination {
type Error = Error;
fn try_from(val: &[u8]) -> Result<Self> {
Self::from_buffer(val)
}
}
impl fmt::Display for PayoutDenomination {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{{")?;
write!(f, r#""number":{},"#, self.number())?;
write!(f, r#""value":{},"#, self.value())?;
write!(f, r#""currency":{}"#, self.currency())?;
write!(f, "}}")
}
}