1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::WireItem;
use std::convert::TryFrom;
use std::io::{Read, Write};

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, TryFromPrimitive)]
#[repr(u16)]
pub enum Flag {
    Reward = 0,
    CommitOutputs = 1,
}
impl Flag {
    pub const fn flag(&self) -> u16 {
        1 << *self as u16
    }
    pub const fn in_bitvec(&self, bitvec: u16) -> bool {
        bitvec & self.flag() != 0
    }
    pub const fn all() -> [Flag; 2] {
        use Flag::*;
        [Reward, CommitOutputs]
    }
}
impl std::fmt::Display for Flag {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Flag{:?}", self)
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Type(pub u16);
impl Type {
    pub const fn has(&self, f: Flag) -> bool {
        f.in_bitvec(self.0)
    }
    pub const fn is(&self, t: KnownType) -> bool {
        self.0 == t as u16
    }
    pub fn has_unknown_flags(&self) -> bool {
        std::iter::successors(Some(15), |i| if *i > 0 { Some(i - 1) } else { None })
            .filter(|i: &u16| Flag::try_from(*i).is_err())
            .map(|i| 1 << i)
            .filter(|i| self.0 & i == 0)
            .next()
            .is_some()
    }
}
impl<T> From<T> for Type
where
    u16: From<T>,
{
    fn from(t: T) -> Self {
        Type(u16::from(t))
    }
}
impl std::iter::FromIterator<Flag> for Type {
    fn from_iter<I: IntoIterator<Item = Flag>>(iter: I) -> Self {
        Type(iter.into_iter().fold(0_u16, |acc, x| acc & x.flag()))
    }
}
impl WireItem for Type {
    fn encode<W: Write>(&self, w: &mut W) -> std::io::Result<usize> {
        self.0.encode(w)
    }

    fn decode<R: Read>(r: &mut R) -> std::io::Result<Self> {
        u16::decode(r).map(Type)
    }
}
impl std::fmt::Display for Type {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.has_unknown_flags() {
            write!(f, "{:016b}", self.0)?;
        }
        write!(f, "[")?;
        let mut first = true;
        for flag in Flag::all().iter() {
            if !first {
                write!(f, "|")?;
            } else {
                first = false;
            }
            if self.has(*flag) {
                write!(f, "{}", flag)?;
            } else {
                write!(f, "No-{}", flag)?;
            }
        }
        write!(f, "]")?;
        Ok(())
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, TryFromPrimitive)]
#[repr(u16)]
pub enum KnownType {
    TypeAltruistCommit = Flag::CommitOutputs.flag(),
    TypeRewardCommit = Flag::CommitOutputs.flag() | Flag::Reward.flag(),
}
impl From<KnownType> for u16 {
    fn from(t: KnownType) -> Self {
        t as u16
    }
}
impl WireItem for KnownType {
    fn encode<W: Write>(&self, w: &mut W) -> std::io::Result<usize> {
        (*self as u16).encode(w)
    }

    fn decode<R: Read>(r: &mut R) -> std::io::Result<Self> {
        KnownType::try_from(u16::decode(r)?).map_err(|_| std::io::ErrorKind::InvalidData.into())
    }
}
impl TryFrom<Type> for KnownType {
    type Error = Type;

    fn try_from(t: Type) -> Result<Self, Type> {
        KnownType::try_from(t.0).map_err(Type)
    }
}