/// Contains traits for the wire encoding of frames
pub mod wire;
/// Contains the implementation of FrameWritable
pub mod write;
/// Contains the implementation of FrameReadable
pub mod read;
/// Contains functions useful for encoding and decoding wire lengths
pub mod length;
/// Contains functions for frame masking
pub mod mask;
/// Contains the AsFrame and FromFrame traits and their implementations for Message
pub mod frame_ops;

#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Frame {
    /// Is this a continuation packet?
    pub fin: bool, // 1 bit
    /// Reserved bit 1
    pub rsv1: bool, // 1 bit
    /// Reserved bit 2
    pub rsv2: bool, // 1 bit
    /// Reserved bit 3
    pub rsv3: bool, // 1 bit
    /// Message opcode
    pub opcode: Opcode, // 4 bits
    // -- byte boundary --
    /// Is this message masked?
    pub mask: bool, // 1 bit
    /// How long is the payload
    pub payload_len: u64, // 7 bits, or 7 + 16 bits, or 7 + 64 bits
    // -- byte boundary --
    /// If masked, what is the masking key?
    pub masking_key: Option<[u8; 4]>, // 4 bytes
    // -- byte boundary --
    /// Payload
    pub payload_data: Vec<u8>
}

#[derive(Clone, PartialEq, Eq, Debug)]
#[repr(u8)]
pub enum Opcode {
    /// This message is a continuation of a previous packet
    Continuation = 0x0,
    /// This message is a text packet
    Text = 0x1,
    /// This message is a binary packet
    Binary = 0x2,
    /// This message is a connection close packet
    ConnectionClose = 0x8,
    /// This message is a ping
    Ping = 0x9,
    /// This message is a pong
    Pong = 0xa
}

pub trait AsBit {
    /// Converts the type into a single-bit representation, using the LSB (rightmost) bit.
    fn as_bit(&self) -> u8;
}
impl AsBit for bool {
    fn as_bit(&self) -> u8 {
        if *self { 1u8 } else { 0u8 }
    }
}

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Message {
    /// A UTF-8 text message
    Text(String),
    /// An arbitrary binary message
    Binary(Vec<u8>),
    /// A ping message with arbitrary contents
    Ping(Vec<u8>),
    /// A pong message with arbitrary contents
    Pong(Vec<u8>)
}