openrgb 0.1.2

OpenRGB SDK client
Documentation
use std::mem::size_of;

use async_trait::async_trait;

use crate::data::{OpenRGBReadable, OpenRGBWritable};
use crate::OpenRGBError;
use crate::OpenRGBError::ProtocolError;
use crate::protocol::{OpenRGBReadableStream, OpenRGBWritableStream};

#[async_trait]
impl OpenRGBWritable for () {
    fn size(&self, _protocol: u32) -> usize {
        0
    }

    async fn write(self, _stream: &mut impl OpenRGBWritableStream, _protocol: u32) -> Result<(), OpenRGBError> {
        Ok(())
    }
}

#[async_trait]
impl OpenRGBReadable for () {
    async fn read(_stream: &mut impl OpenRGBReadableStream, _protocol: u32) -> Result<Self, OpenRGBError> {
        Ok(())
    }
}

#[async_trait]
impl OpenRGBWritable for u8 {
    fn size(&self, _protocol: u32) -> usize {
        size_of::<u8>()
    }

    async fn write(self, stream: &mut impl OpenRGBWritableStream, _protocol: u32) -> Result<(), OpenRGBError> {
        stream.write_u8(self).await.map_err(Into::into)
    }
}

#[async_trait]
impl OpenRGBReadable for u8 {
    async fn read(stream: &mut impl OpenRGBReadableStream, _protocol: u32) -> Result<Self, OpenRGBError> {
        stream.read_u8().await.map_err(Into::into)
    }
}

#[async_trait]
impl OpenRGBWritable for u16 {
    fn size(&self, _protocol: u32) -> usize {
        size_of::<u16>()
    }

    async fn write(self, stream: &mut impl OpenRGBWritableStream, _protocol: u32) -> Result<(), OpenRGBError> {
        stream.write_u16_le(self).await.map_err(Into::into)
    }
}

#[async_trait]
impl OpenRGBReadable for u16 {
    async fn read(stream: &mut impl OpenRGBReadableStream, _protocol: u32) -> Result<Self, OpenRGBError> {
        stream.read_u16_le().await.map_err(Into::into)
    }
}

#[async_trait]
impl OpenRGBWritable for u32 {
    fn size(&self, _protocol: u32) -> usize {
        size_of::<u32>()
    }

    async fn write(self, stream: &mut impl OpenRGBWritableStream, _protocol: u32) -> Result<(), OpenRGBError> {
        stream.write_u32_le(self).await.map_err(Into::into)
    }
}

#[async_trait]
impl OpenRGBReadable for u32 {
    async fn read(stream: &mut impl OpenRGBReadableStream, _protocol: u32) -> Result<Self, OpenRGBError> {
        stream.read_u32_le().await.map_err(Into::into)
    }
}

#[async_trait]
impl OpenRGBWritable for i32 {
    fn size(&self, _protocol: u32) -> usize {
        size_of::<i32>()
    }

    async fn write(self, stream: &mut impl OpenRGBWritableStream, _protocol: u32) -> Result<(), OpenRGBError> {
        stream.write_i32_le(self).await.map_err(Into::into)
    }
}

#[async_trait]
impl OpenRGBReadable for i32 {
    async fn read(stream: &mut impl OpenRGBReadableStream, _protocol: u32) -> Result<Self, OpenRGBError> {
        stream.read_i32_le().await.map_err(Into::into)
    }
}

#[async_trait]
impl OpenRGBWritable for usize {
    fn size(&self, _protocol: u32) -> usize {
        size_of::<u32>()
    }

    async fn write(self, stream: &mut impl OpenRGBWritableStream, protocol: u32) -> Result<(), OpenRGBError> {
        stream.write_value(
            u32::try_from(self)
                .map_err(|e| ProtocolError(format!("Data size is too large to encode: {} ({})", self, e)))?,
            protocol,
        ).await
    }
}

#[async_trait]
impl OpenRGBReadable for usize {
    async fn read(stream: &mut impl OpenRGBReadableStream, protocol: u32) -> Result<Self, OpenRGBError> {
        stream.read_value::<u32>(protocol).await.map(|s| s as Self)
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error;

    use tokio_test::io::Builder;

    use crate::{DEFAULT_PROTOCOL};
    use crate::protocol::{OpenRGBReadableStream, OpenRGBWritableStream};
    use crate::tests::setup;

    #[tokio::test]
    async fn test_read_void_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new().build();

        assert_eq!(stream.read_value::<()>(DEFAULT_PROTOCOL).await?, ());

        Ok(())
    }

    #[tokio::test]
    async fn test_write_void_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new().build();

        stream.write_value((), DEFAULT_PROTOCOL).await?;

        Ok(())
    }

    #[tokio::test]
    async fn test_read_u8_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new()
            .read(&[37_u8])
            .build();

        assert_eq!(stream.read_value::<u8>(DEFAULT_PROTOCOL).await?, 37);

        Ok(())
    }

    #[tokio::test]
    async fn test_write_u8_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new()
            .write(&[37_u8])
            .build();

        stream.write_value(37_u8, DEFAULT_PROTOCOL).await?;

        Ok(())
    }

    #[tokio::test]
    async fn test_read_u16_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new()
            .read(&37_u16.to_le_bytes())
            .build();

        assert_eq!(stream.read_value::<u16>(DEFAULT_PROTOCOL).await?, 37);

        Ok(())
    }

    #[tokio::test]
    async fn test_write_u16_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new()
            .write(&37_u16.to_le_bytes())
            .build();

        stream.write_value(37_u16, DEFAULT_PROTOCOL).await?;

        Ok(())
    }

    #[tokio::test]
    async fn test_read_u32_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new()
            .read(&185851_u32.to_le_bytes())
            .build();

        assert_eq!(stream.read_value::<u32>(DEFAULT_PROTOCOL).await?, 185851);

        Ok(())
    }

    #[tokio::test]
    async fn test_write_u32_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new()
            .write(&185851_u32.to_le_bytes())
            .build();

        stream.write_value(185851_u32, DEFAULT_PROTOCOL).await?;

        Ok(())
    }

    #[tokio::test]
    async fn test_read_i32_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new()
            .read(&(-185851_i32).to_le_bytes())
            .build();

        assert_eq!(stream.read_value::<i32>(DEFAULT_PROTOCOL).await?, -185851_i32);

        Ok(())
    }

    #[tokio::test]
    async fn test_write_i32_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new()
            .write(&(-185851_i32).to_le_bytes())
            .build();

        stream.write_value(-185851_i32, DEFAULT_PROTOCOL).await?;

        Ok(())
    }

    #[tokio::test]
    async fn test_read_usize_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new()
            .read(&185851_u32.to_le_bytes())
            .build();

        assert_eq!(stream.read_value::<usize>(DEFAULT_PROTOCOL).await?, 185851_usize);

        Ok(())
    }

    #[tokio::test]
    async fn test_write_usize_001() -> Result<(), Box<dyn Error>> {
        setup()?;

        let mut stream = Builder::new()
            .write(&185851_u32.to_le_bytes())
            .build();

        stream.write_value(185851_usize, DEFAULT_PROTOCOL).await?;

        Ok(())
    }
}