use std::{fmt, str::FromStr};
use crate::deploy::outcomes::actions::error::DeployError;
use crate::utils::Dec;
fn bounded(text: &str, most: Dec) -> Option<Dec> {
let text = text.trim();
if text.starts_with(['+', '-']) {
return None;
}
let value = Dec::parse(text).ok()?;
(!value.is_negative() && value <= most).then_some(value)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct FeeScale(Dec);
impl FeeScale {
pub const ZERO: FeeScale = FeeScale(Dec::ZERO);
pub const ONE: FeeScale = FeeScale(Dec::ONE);
#[must_use]
pub const fn value(self) -> Dec {
self.0
}
#[must_use]
pub fn to_wire(self) -> String {
self.0.to_wire()
}
}
impl FromStr for FeeScale {
type Err = DeployError;
fn from_str(text: &str) -> Result<Self, Self::Err> {
bounded(text, Dec::from_int(10)).map(FeeScale).ok_or_else(|| DeployError::FeeScale(text.trim().to_owned()))
}
}
impl fmt::Display for FeeScale {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Fraction(Dec);
impl Fraction {
pub const ZERO: Fraction = Fraction(Dec::ZERO);
pub const ONE: Fraction = Fraction(Dec::ONE);
#[must_use]
pub const fn value(self) -> Dec {
self.0
}
#[must_use]
pub fn to_wire(self) -> String {
self.0.to_wire()
}
#[must_use]
pub fn is_whole(self) -> bool {
self == Fraction::ZERO || self == Fraction::ONE
}
}
impl FromStr for Fraction {
type Err = DeployError;
fn from_str(text: &str) -> Result<Self, Self::Err> {
bounded(text, Dec::ONE).map(Fraction).ok_or_else(|| DeployError::Fraction(text.trim().to_owned()))
}
}
impl fmt::Display for Fraction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[cfg(test)]
#[path = "tests/bounded.rs"]
mod tests;