obf2png 0.2.0

A library to parse, encode, decode, manipulate PNG chunks
Documentation
use std::{fs, path::Path, str::FromStr};

use crate::{errors::Result, Chunk, ChunkType, Error, Png};

/// Append a chunk containing the desired bytes at the end of a PNG file and saves the result
///
/// Args :
/// input_file, output_file : PathBuf to input/output file
/// chunk_type: UTF-8 String of max length of 4. Technically limited to [u8; 4]
/// bytes_tu_hide : slice of the bytes to hide
pub fn encode<T: AsRef<Path>>(
    input_file: T,
    output_file: T,
    chunk_type: String,
    bytes_to_hide: &[u8],
) -> Result<()> {
    let file_bytes = fs::read(input_file)?;
    let mut png = Png::try_from(file_bytes.as_slice())?;

    let chunk_type = ChunkType::from_str(&chunk_type)?;
    let new_chunk = Chunk::new(chunk_type, bytes_to_hide.to_vec());

    png.append_chunk(new_chunk);

    fs::write(output_file, png.as_bytes())?;
    Ok(())
}

/// Searches for a bytes hidden in a PNG file based on the chunk type and return it if one is found
///
/// Args :
/// file: PathBuf to input file
/// chunk_type: UTF-8 String of max length of 4. Technically limited to [u8; 4]
pub fn decode<T: AsRef<Path>>(file: T, chunk_type: String) -> Result<Vec<u8>> {
    let file_bytes = fs::read(file)?;
    let png = Png::try_from(file_bytes.as_slice())?;

    let chunk = match png.chunk_by_type(&chunk_type) {
        Some(chunk) => chunk,
        None => {
            return Err(Error::from("No chunk found for specified chunk type"));
        }
    };

    let hidden_bytes = chunk.data().to_vec();

    // println!("Hidden message:'{hidden_string}'");
    Ok(hidden_bytes)
}

/// Removes the first chunk from a PNG file based on the chunk type and saves the result
///
/// Args :
/// file: PathBuf to input file
/// chunk_type: UTF-8 String of max length of 4. Technically limited to [u8; 4]
pub fn remove<T: AsRef<Path>>(file: T, chunk_type: String) -> Result<()> {
    let file_bytes = fs::read(file)?;
    let mut png = Png::try_from(file_bytes.as_slice())?;

    let _chunk = png.remove_first_chunk(chunk_type.as_str())?;
    // println!("Removed chunk : {chunk}");

    fs::write("img/removed_chunk.png", png.as_bytes())?;
    Ok(())
}

/// Prints all of the chunks in a PNG file
///
/// Args :
/// file: PathBuf to input file
pub fn print_chunks<T: AsRef<Path>>(file: T) -> Result<()> {
    let file_bytes = fs::read(file)?;
    let png = Png::try_from(file_bytes.as_slice())?;

    println!("PNG file content : {png}");
    Ok(())
}