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
120
121
122
123
#[cfg(feature = "nightly")]
use super::UnwrapBitsExample;
use crate::conv::UnsafeFrom;
pub use core::num::TryFromIntError;

/// Wrapper around [`NonZeroU8`](core::num::NonZeroU8) to implement conversion traits on a foreign
/// type.
#[derive(Clone, Copy, Debug)]
pub struct NonZeroU8(core::num::NonZeroU8);

impl From<NonZeroU8> for u8 {
    fn from(other: NonZeroU8) -> Self {
        other.0.into()
    }
}

impl TryFrom<u8> for NonZeroU8 {
    type Error = TryFromIntError;

    fn try_from(other: u8) -> Result<Self, Self::Error> {
        Ok(NonZeroU8(other.try_into()?))
    }
}

impl UnsafeFrom<u8> for NonZeroU8 {
    unsafe fn unsafe_from(other: u8) -> Self {
        NonZeroU8(core::num::NonZeroU8::new_unchecked(other))
    }
}

/// Wrapper around [`u16`] to implement conversion traits on a foreign type.
#[derive(Clone, Copy, Debug)]
pub struct U16(pub u16);

impl UnsafeFrom<U16> for u8 {
    unsafe fn unsafe_from(other: U16) -> Self {
        other.0 as u8
    }
}

impl TryFrom<U16> for u8 {
    type Error = TryFromIntError;

    fn try_from(other: U16) -> Result<Self, Self::Error> {
        other.0.try_into()
    }
}

/// Wrapper around [`u8`] with infallible conversions both ways.
#[derive(Clone, Copy, Debug)]
pub struct U8WithParity {
    pub raw: u8,
    pub has_even_set_bits: bool,
}

impl From<u8> for U8WithParity {
    fn from(other: u8) -> Self {
        U8WithParity {
            raw: other,
            has_even_set_bits: other.count_ones() & 1 == 0,
        }
    }
}

impl From<U8WithParity> for u8 {
    fn from(other: U8WithParity) -> Self {
        other.raw
    }
}

/// Wrapper around [`u8`] with fallible and unsafe conversion options both ways.
#[derive(Clone, Copy, Debug)]
pub struct SpuriouslyFailingU8(u8);

impl TryFrom<u8> for SpuriouslyFailingU8 {
    type Error = ();

    fn try_from(other: u8) -> Result<Self, Self::Error> {
        // Doesn't actually fail, but in real-world code this function could fail depending on
        // external factors
        Ok(SpuriouslyFailingU8(other))
    }
}

impl UnsafeFrom<u8> for SpuriouslyFailingU8 {
    unsafe fn unsafe_from(other: u8) -> Self {
        SpuriouslyFailingU8(other)
    }
}

impl TryFrom<SpuriouslyFailingU8> for u8 {
    type Error = ();

    fn try_from(other: SpuriouslyFailingU8) -> Result<Self, Self::Error> {
        // Same as above
        Ok(other.0)
    }
}

impl UnsafeFrom<SpuriouslyFailingU8> for u8 {
    unsafe fn unsafe_from(other: SpuriouslyFailingU8) -> Self {
        other.0
    }
}

#[cfg(feature = "nightly")]
impl TryFrom<u8> for UnwrapBitsExample {
    type Error = ();

    fn try_from(other: u8) -> Result<Self, Self::Error> {
        match NonZeroU8::try_from(other) {
            Ok(v) => Ok(UnwrapBitsExample(v)),
            Err(_) => Err(()),
        }
    }
}

#[cfg(feature = "nightly")]
impl From<UnwrapBitsExample> for u8 {
    fn from(other: UnwrapBitsExample) -> Self {
        other.0.into()
    }
}