gd 0.0.0

Geometry Dash API wrapper written in Rust.
Documentation
use std::io::{Error, Read};

use flate2::{
    bufread::{ZlibDecoder, ZlibEncoder},
    Compress, Compression, Decompress,
};
use miette::Diagnostic;
use thiserror::Error;

#[derive(Debug, Error, Diagnostic)]
#[error("failed to compress")]
#[diagnostic(
    code(gd::crypto::zip::compress),
    help("make sure everything is correct")
)]
pub struct CompressError(#[from] pub Error);

#[derive(Debug, Error, Diagnostic)]
#[error("failed to decompress")]
#[diagnostic(
    code(gd::crypto::zip::decompress),
    help("make sure everything is correct")
)]
pub struct DecompressError(#[from] pub Error);

pub const MAX_WINDOW_BITS: u8 = 15;

pub fn compressor() -> Compress {
    Compress::new_gzip(Compression::best(), MAX_WINDOW_BITS)
}

pub fn decompressor() -> Decompress {
    Decompress::new_gzip(MAX_WINDOW_BITS)
}

pub fn compress<D: AsRef<[u8]>>(data: D) -> Result<Vec<u8>, CompressError> {
    fn compress_inner(data: &[u8]) -> Result<Vec<u8>, CompressError> {
        let mut encoder = ZlibEncoder::new_with_compress(data, compressor());

        let mut compressed = Vec::new();

        encoder
            .read_to_end(&mut compressed)
            .map_err(CompressError)?;

        Ok(compressed)
    }

    compress_inner(data.as_ref())
}

pub fn decompress<D: AsRef<[u8]>>(data: D) -> Result<Vec<u8>, DecompressError> {
    fn decompress_inner(data: &[u8]) -> Result<Vec<u8>, DecompressError> {
        let mut decoder = ZlibDecoder::new_with_decompress(data, decompressor());

        let mut decompressed = Vec::new();

        decoder
            .read_to_end(&mut decompressed)
            .map_err(DecompressError)?;

        Ok(decompressed)
    }

    decompress_inner(data.as_ref())
}