/// 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).
pub trait Code: Into<u8> + core::convert::TryFrom<u8> {
    /// Error of the `.new()` method; ideally, this is also the TryFrom::Error (which can not
    /// be restricted without [Associated type
    /// bounds](https://github.com/rust-lang/rust/issues/52662) being stabilized).
    ///
    /// Once that is available, the built-in new method will be deprecated and eventually
    /// removed -- a change that will be trivial on code using it provided that this error is
    /// indeed the error of TryFrom.
    ///
    /// The error, when rendered, should represent a 5.00 style error, because what went wrong was
    /// that the server CoAP library can not represent the response code intended by the handler.
    type Error: core::fmt::Debug + crate::error::RenderableOnMinimal;

    /// This constructor is a more concrete variant of the TryFrom function whose error code is
    /// practically usable (see [Self::Error])
    fn new(code: u8) -> Result<Self, <Self as Code>::Error>;
}

impl Code for u8 {
    type Error = core::convert::Infallible;

    fn new(code: u8) -> Result<Self, core::convert::Infallible> {
        Ok(code)
    }
}

/// 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> {
    /// Error of the `.new()` method; ideally, this is also the TryFrom::Error (which can not
    /// be restricted without [Associated type
    /// bounds](https://github.com/rust-lang/rust/issues/52662) being stabilized).
    ///
    /// Once that is available, the built-in new method will be deprecated and eventually
    /// removed -- a change that will be trivial on code using it provided that this error is
    /// indeed the error of TryFrom.
    ///
    /// The error, when rendered, should represent a 5.00 style error, because what went wrong was
    /// that the server handler attempted to use a CoAP option which the server could not
    /// represent.
    type Error: core::fmt::Debug + crate::error::RenderableOnMinimal;

    /// This constructor is a more concrete variant of the TryFrom function whose error code is
    /// practically usable (see [Self::Error])
    fn new(option: u16) -> Result<Self, <Self as OptionNumber>::Error>;
}

impl OptionNumber for u16 {
    type Error = core::convert::Infallible;

    fn new(option: u16) -> Result<Self, core::convert::Infallible> {
        Ok(option)
    }
}
