use super::*;

/// An inbound message, that must be handled by the callback set on a [`StreamCandidate`].
///
/// It simply wraps a [`Payload`] (which it notably [`Deref`]s to) such that additional metadata
/// about an inbound message can be provided without breaking changes in the future.
pub struct Inbound(pub(crate) datastreams_ffi::Inbound);

impl Inbound {
    /// The payload of the inbound message.
    ///
    /// You may also access it though the [`Deref`] and [`DerefMut`] implementations.
    pub fn payload(&self) -> &Payload {
        &self.0.payload
    }
}

impl core::ops::Deref for Inbound {
    type Target = Payload;
    fn deref(&self) -> &Self::Target {
        &self.0.payload
    }
}

impl core::ops::DerefMut for Inbound {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0.payload
    }
}

impl From<Inbound> for Payload {
    fn from(value: Inbound) -> Self {
        value.0.payload
    }
}

impl core::fmt::Debug for Inbound {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("Inbound")
            .field("payload", self.payload())
            .finish()
    }
}

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

    #[test]
    fn test_inbound() {
        let payload = Bytes::from_static(b"hello");
        let inbound = Inbound(datastreams_ffi::Inbound {
            payload: payload.clone(),
        });
        assert_eq!(&*inbound, &payload);
        assert_eq!(inbound.payload(), &payload);
        assert_eq!(Payload::from(inbound), payload);
    }
}
