cloudflare-soos 2.3.1

Helper tool for Cloudflare's enhanced HTTP/2 and HTTP/3 prioritization, which makes progressive images load faster. Supports JPEG, GIF, and PNG.
Documentation
use std::convert::TryInto;

use crate::error::{Error, Result};
use crate::Scans;

pub fn scans(input_file: &[u8]) -> Result<Scans> {
    let file_size = input_file.len();
    if file_size < 48 {
        return Err(Error::Format("PNG too small"));
    }
    // PNG header has a fixed layout, so it doesn't need parsing
    let interlace = input_file[28];
    let idat_start = find_idat_start(input_file).unwrap_or(38);
    Ok(Scans {
        metadata_end: Some(37),
        frame_render_start: Some(idat_start),
        // Offsets for interlaced images are a guess. Avoids inflating IDATs.
        first_scan_end: if interlace != 0 { Some(idat_start + (file_size - idat_start) / 4) } else { None },
        good_scan_end: if interlace != 0 { Some(idat_start + (file_size - idat_start) / 2) } else { None },
        file_size,
    })
}

fn find_idat_start(input_file: &[u8]) -> Option<usize> {
    let mut pos = 8;
    loop {
        let chunk = input_file.get(pos..pos + 12)?;
        pos += 12;
        if &chunk[4..8] == b"IDAT" {
            return Some(pos);
        }
        let len = u32::from_be_bytes(chunk[..4].try_into().unwrap());
        pos += len as usize;
    }
}