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
/// A message code
/// A CoAP code
///
/// For the code's meaning, see the [CoAP Codes IANA subregistry] or the [coap_numbers::code]
/// module that lists them.
///
/// [CoAP Codes IANA subregistry]: https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#codes
/// [coap_numbers::code]: https://docs.rs/coap-numbers/0.1.2/coap_numbers/code/
///
/// All code implementations can be converted to u8 (as they correspond to an 8-bit unsigned
/// integer in the CoAP protocol). The conversion back is fallible to allow strict message
/// implementations to only accept codes supported by the implementation, and/or to limit the
/// values by type state. For example, a strict implementation may distinguish between request and
/// response messages, and only allow the respective code class into their objects (simultaneously
/// creating usable niches in the in-memory representations).
// It'd be convenient to demand TryFrom<u8, Error: core::fmt::Debug>, but RFC 2289 hasn't landed in
// stable yet
pub trait Code: Into<u8> + core::convert::TryFrom<u8> {}

impl Code for u8 {}

/// A CoAP option number
///
/// For its meaning, see the [CoAP Option Numbers IANA subregistry] or the
/// [coap_numbers::option] module that lists them, and provides helpers for decoding their
/// properties.
///
/// [CoAP Option Numbers IANA subregistry]: https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#option-numbers
/// [coap_numbers::option]: https://docs.rs/coap-numbers/0.1.2/coap_numbers/option/
///
/// In analogy to [Code], these are convertible to [u16] and fallibly convertible from there.
pub trait OptionNumber: Into<u16> + core::convert::TryFrom<u16> {}

impl OptionNumber for u16 {}

/// Experimental trait for conversion between option representation, with the goal to later avoid
/// the conversion step via u16 and specialize for T->T conversions.
pub trait FromOtherOption<O: OptionNumber> {
    type Error;

    fn convert_from_other(other: O) -> Result<Self, Self::Error>
    where
        Self: Sized;
}

impl<O: OptionNumber, T: OptionNumber> FromOtherOption<O> for T {
    type Error = <Self as core::convert::TryFrom<u16>>::Error;

    /* default */
    fn convert_from_other(other: O) -> Result<Self, Self::Error>
    where
        Self: Sized,
    {
        let num: u16 = other.into();
        use core::convert::TryInto;
        num.try_into()
    }
}

/*

needs
#![feature(specialization)]
and the above default to be active

impl<T: OptionNumber> FromOtherOption<T> for T
{
//     type Error = <Self as core::convert::TryFrom<u16>>::Error; // lont term I'd like to have `!` here
//
    fn convert_from_other(other: T) -> Result<Self, Self::Error>
    where
        Self: Sized
    {
        Ok(other)
    }
}
*/