psibase 0.23.0

Library and command-line tool for interacting with psibase networks
Documentation
use std::str::FromStr;

use fracpack::{FracInputStream, Pack, ToSchema, Unpack};
use serde::{Deserialize, Serialize};

use crate::services::tokens::TokensError;
use async_graphql::scalar;

#[derive(PartialEq, Debug, Copy, Clone, Pack, ToSchema, Serialize)]
#[fracpack(fracpack_mod = "fracpack")]
pub struct Precision(u8);

impl Precision {
    pub fn new(value: u8) -> Result<Self, TokensError> {
        if value <= 8 {
            Ok(Self(value))
        } else {
            Err(TokensError::PrecisionOverflow)
        }
    }

    pub fn value(&self) -> u8 {
        self.0
    }
}

impl std::fmt::Display for Precision {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl TryFrom<u8> for Precision {
    type Error = TokensError;

    fn try_from(value: u8) -> Result<Self, Self::Error> {
        Self::new(value)
    }
}

impl FromStr for Precision {
    type Err = TokensError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::new(s.parse::<u8>().map_err(|_| TokensError::InvalidNumber)?)
    }
}

impl<'a> Unpack<'a> for Precision {
    const FIXED_SIZE: u32 = 1;

    const VARIABLE_SIZE: bool = false;

    fn unpack(src: &mut FracInputStream<'a>) -> fracpack::Result<Self> {
        u8::unpack(src)?
            .try_into()
            .map_err(|_| fracpack::Error::BadScalar)
    }

    fn verify(src: &mut FracInputStream) -> fracpack::Result<()> {
        Self::unpack(src)?;
        Ok(())
    }
}

impl<'de> Deserialize<'de> for Precision {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let number: u8 = Deserialize::deserialize(deserializer)?;
        Precision::new(number).map_err(|e| serde::de::Error::custom(e.to_string()))
    }
}

scalar!(Precision);