vncrs 0.1.6

A pure Rust VNC server library for Windows
Documentation
use super::Encoder;
use crate::error::Result;
use flate2::{Compress, Compression, FlushCompress};

pub struct ZlibCompressor {
    compress: Compress,
}

impl ZlibCompressor {
    pub fn new() -> Self {
        Self {
            compress: Compress::new(Compression::fast(), true),
        }
    }
}

impl Encoder for ZlibCompressor {
    fn encoding_id(&self) -> i32 {
        6
    }

    fn encode_rect(
        &mut self,
        pixels: &[u8],
        stride: usize,
        x: u16,
        y: u16,
        w: u16,
        h: u16,
        swap_rb: bool,
    ) -> Result<Vec<u8>> {
        let row_bytes = w as usize * 4;
        let mut raw = Vec::with_capacity(row_bytes * h as usize);

        for row in y..y + h {
            let start = row as usize * stride + x as usize * 4;
            let end = start + row_bytes;
            raw.extend_from_slice(&pixels[start..end]);
        }

        if swap_rb {
            for pixel in raw.chunks_exact_mut(4) {
                pixel.swap(0, 2);
            }
        }

        let before = self.compress.total_out();
        let mut compressed = Vec::with_capacity(raw.len());
        self.compress
            .compress_vec(&raw, &mut compressed, FlushCompress::Sync)
            .map_err(|e| crate::error::VncError::Encoding(e.to_string()))?;
        let compressed_len = (self.compress.total_out() - before) as usize;
        compressed.truncate(compressed_len);

        let mut result = Vec::with_capacity(4 + compressed.len());
        result.extend_from_slice(&(compressed.len() as u32).to_be_bytes());
        result.extend_from_slice(&compressed);

        Ok(result)
    }
}