bee-ternary 1.0.0

Ergonomic ternary manipulation utilities
Documentation
// Copyright 2020-2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use core::{fmt, marker::PhantomData};

use serde::{
    de::{Error, SeqAccess, Unexpected, Visitor},
    ser::SerializeSeq,
    Deserialize, Deserializer, Serialize, Serializer,
};

use crate::{Btrit, RawEncoding, RawEncodingBuf, TritBuf, Trits, Utrit};

// Serialisation

impl Serialize for Btrit {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_i8((*self).into())
    }
}

impl Serialize for Utrit {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_i8((*self).into())
    }
}

impl<'a, T: RawEncoding> Serialize for &'a Trits<T>
where
    T::Trit: Serialize,
    T: serde::Serialize,
{
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut seq = serializer.serialize_seq(Some(self.len()))?;
        for trit in self.iter() {
            seq.serialize_element(&trit)?;
        }
        seq.end()
    }
}

impl<T: RawEncodingBuf> Serialize for TritBuf<T>
where
    <T::Slice as RawEncoding>::Trit: Serialize,
{
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut seq = serializer.serialize_seq(Some(self.len()))?;
        for trit in self.iter() {
            seq.serialize_element(&trit)?;
        }
        seq.end()
    }
}

// Deserialisation

struct BtritVisitor;

impl<'de> Visitor<'de> for BtritVisitor {
    type Value = Btrit;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("a value between -1 and 1 inclusive")
    }

    fn visit_u64<E: Error>(self, trit: u64) -> Result<Self::Value, E> {
        i8::try_from(trit)
            .map_err(|_| ())
            .and_then(|trit| Btrit::try_from(trit).map_err(|_| ()))
            .map_err(|_| E::invalid_value(Unexpected::Unsigned(trit), &self))
    }

    fn visit_i64<E: Error>(self, trit: i64) -> Result<Self::Value, E> {
        i8::try_from(trit)
            .map_err(|_| ())
            .and_then(|trit| Btrit::try_from(trit).map_err(|_| ()))
            .map_err(|_| E::invalid_value(Unexpected::Signed(trit), &self))
    }

    fn visit_u8<E: Error>(self, trit: u8) -> Result<Self::Value, E> {
        i8::try_from(trit)
            .map_err(|_| ())
            .and_then(|trit| Btrit::try_from(trit).map_err(|_| ()))
            .map_err(|_| E::invalid_value(Unexpected::Unsigned(trit as u64), &self))
    }

    fn visit_i8<E: Error>(self, trit: i8) -> Result<Self::Value, E> {
        Btrit::try_from(trit).map_err(|_| E::invalid_value(Unexpected::Signed(trit as i64), &self))
    }
}

impl<'de> Deserialize<'de> for Btrit {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_i8(BtritVisitor)
    }
}

struct UtritVisitor;

impl<'de> Visitor<'de> for UtritVisitor {
    type Value = Utrit;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("a value between 0 and 2 inclusive")
    }

    fn visit_u64<E: Error>(self, trit: u64) -> Result<Self::Value, E> {
        u8::try_from(trit)
            .map_err(|_| ())
            .and_then(|trit| Utrit::try_from(trit).map_err(|_| ()))
            .map_err(|_| E::invalid_value(Unexpected::Unsigned(trit), &self))
    }

    fn visit_i64<E: Error>(self, trit: i64) -> Result<Self::Value, E> {
        i8::try_from(trit)
            .map_err(|_| ())
            .and_then(|trit| Utrit::try_from(trit).map_err(|_| ()))
            .map_err(|_| E::invalid_value(Unexpected::Signed(trit), &self))
    }

    fn visit_u8<E: Error>(self, trit: u8) -> Result<Self::Value, E> {
        Ok(trit)
            .and_then(|trit| Utrit::try_from(trit).map_err(|_| ()))
            .map_err(|_| E::invalid_value(Unexpected::Unsigned(trit as u64), &self))
    }

    fn visit_i8<E: Error>(self, trit: i8) -> Result<Self::Value, E> {
        Utrit::try_from(trit).map_err(|_| E::invalid_value(Unexpected::Signed(trit as i64), &self))
    }
}

impl<'de> Deserialize<'de> for Utrit {
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_i8(UtritVisitor)
    }
}

struct TritBufVisitor<T>(PhantomData<T>);

impl<'de, T: RawEncodingBuf> Visitor<'de> for TritBufVisitor<T>
where
    <T::Slice as RawEncoding>::Trit: Deserialize<'de>,
{
    type Value = TritBuf<T>;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("a sequence of trits")
    }

    fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
        let mut buf = TritBuf::with_capacity(seq.size_hint().unwrap_or(0));

        while let Some(trit) = seq.next_element()? {
            buf.push(trit);
        }

        Ok(buf)
    }
}

impl<'de, T: RawEncodingBuf> Deserialize<'de> for TritBuf<T>
where
    <T::Slice as RawEncoding>::Trit: Deserialize<'de>,
{
    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_seq(TritBufVisitor::<T>(PhantomData))
    }
}