kudu 0.1.0

Library for interacting with Antelope blockchains
Documentation
use std::str::FromStr;

use snafu::ResultExt;

use crate::{
    JsonValue,
    convert::{ConversionError, HexDecodeSnafu, IncompatibleVariantTypesSnafu},
};

type Result<T, E = ConversionError> = std::result::Result<T, E>;

pub use float128_impl::Float128;

#[cfg(not(feature = "float128"))]
mod float128_impl {
    use super::*;

    #[derive(Copy, Clone, Debug, PartialEq, Default)]
    pub struct Float128([u8;16]);

    impl Float128 {
        pub fn from_variant(v: &JsonValue) -> Result<Self> {
            variant_to_f128(v)
        }

        pub fn to_hex(&self) -> String {
            hex::encode(self.0)
        }

        pub fn to_bin_repr(&self) -> &[u8; 16] {
            &self.0
        }

        pub fn from_bin_repr(bin: &[u8; 16]) -> Self {
            Float128(*bin)
        }
    }

    pub fn variant_to_f128(v: &JsonValue) -> Result<Float128> {
        if let Some(x) = v.as_f64()      { Ok(x.into()) }
        else if let Some(s) = v.as_str() {
            let mut result = Float128::default();
            hex::decode_to_slice(s, &mut result.0).context(HexDecodeSnafu { repr: s })?;
            Ok(result)
        }
        else {
            IncompatibleVariantTypesSnafu { typename: "f128", value: v.clone() }.fail()
        }
    }

    impl From<f64> for Float128 {
        fn from(_value: f64) -> Self {
            unimplemented!("no native f128 support");
        }
    }

    impl FromStr for Float128 {
        type Err = ConversionError;

        fn from_str(_s: &str) -> Result<Self, Self::Err> {
            unimplemented!("no native f128 support");
        }
    }
}


#[cfg(feature = "float128")]
mod float128_impl {
    use super::*;

    use bytemuck::{cast_ref, pod_read_unaligned};

    use crate::convert::str_to_float;

    #[derive(Copy, Clone, Debug, PartialEq, Default)]
    pub struct Float128(f128);

    impl Float128 {
        pub fn from_variant(v: &JsonValue) -> Result<Self> {
            variant_to_f128(v).map(Float128)
        }

        pub fn to_hex(&self) -> String {
            hex::encode(self.0.to_ne_bytes())
        }

        pub fn to_bin_repr(&self) -> &[u8; 16] {
            cast_ref::<f128, [u8; 16]>(&self.0)
        }

        pub fn from_bin_repr(bin: &[u8; 16]) -> Self {
            Float128(pod_read_unaligned(bin))
        }
    }

    pub fn variant_to_f128(v: &JsonValue) -> Result<f128> {
        if let Some(x) = v.as_f64()      { Ok(x.into()) }
        else if let Some(s) = v.as_str() {
            let mut result = [0_u8; 16];
            hex::decode_to_slice(s, &mut result).context(HexDecodeSnafu { repr: s })?;
            Ok(f128::from_le_bytes(result))
        }
        else {
            IncompatibleVariantTypesSnafu { typename: "f128", value: v.clone() }.fail()
        }
    }

    impl From<f64> for Float128 {
        fn from(value: f64) -> Self {
            Float128(f128::from(value))
        }
    }

    impl FromStr for Float128 {
        type Err = ConversionError;

        fn from_str(s: &str) -> Result<Self, Self::Err> {
            str_to_float::<f64>(s).map(|x| x.into())
        }
    }

}