/// Wraps a [bit field](https://en.wikipedia.org/wiki/Bit_field) used in [Message](crate::v4::Message).
///
/// The two bytes that this field occupies were unused in [RFC-951](https://datatracker.ietf.org/doc/html/rfc951#section-3), and later [defined](https://datatracker.ietf.org/doc/html/rfc1542#section-2.2) then [clarified](https://datatracker.ietf.org/doc/html/rfc1542#section-3.1) in RFC-1542.
///
/// The leftmost bit is defined as the Broadcast flag. The remaining bits are reserved for future use, and must be set to zero by clients and ignored by servers and relay agents.
#[derive(Debug, PartialEq)]
pub struct Flags {
    /// Used to work around some clients that cannot accept IP unicast datagrams before the TCP/IP software is configured.
    pub broadcast: bool,
}

impl Flags {
    const EMPTY: [u8; 2] = [0, 0];
    const BROADCAST: [u8; 2] = [128, 0];

    /// As long as the flags field is only used for
    /// broadcasts then this method can be used as a faster way
    /// to serialize the broadcast value to bytes.
    ///
    /// Otherwise, you'll want to use the existing From impl.
    ///
    /// As of 2025 I do not see any RFC that updates RFC-2131 with
    /// new flags.
    #[inline]
    pub const fn temporary_to_bytes(&self) -> [u8; 2] {
        if self.broadcast {
            Self::BROADCAST
        } else {
            Self::EMPTY
        }
    }
}

impl From<&Flags> for [u8; 2] {
    fn from(flags: &Flags) -> Self {
        let mut bytes: u16 = 0b00000000_00000000;

        if flags.broadcast {
            bytes |= 0b10000000_00000000
        }

        bytes.to_be_bytes()
    }
}

/// Converts the only byte currently used by the flags field.
/// For use with `UndecodedMessage`'s `slice_flags_temporary`.
///
/// Warning: If more bit flags are added via RFC then this may
/// need to change or be removed.
impl From<u8> for Flags {
    fn from(byte: u8) -> Self {
        let broadcast = byte & 0b10000000 == 0b10000000;
        Flags { broadcast }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn broadcast_const_is_correct() {
        let decimal: u16 = 0b10000000_00000000;
        assert_eq!(Flags::BROADCAST, decimal.to_be_bytes());
    }
}
