{"record":{"id":"5f2cce70de7ca716","repo":"tonhowtf/omniget","slug":"nao-e-um-jpeg","errorCode":null,"errorMessage":"nao e um JPEG","messagePattern":"nao e um JPEG","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/jpeg_pdf.rs","lineNumber":16,"sourceCode":"//! Escritor mínimo de PDF a partir de JPEGs (uma imagem por página, filtro\n//! DCTDecode, sem recomprimir). É o `img2pdf` dos scripts de SlideShare\n//! (estudo 50) sem dependência nova.\n\nuse anyhow::anyhow;\n\npub struct JpegInfo {\n    pub width: u32,\n    pub height: u32,\n    pub components: u8,\n}\n\n/// Lê largura/altura/canais do marcador SOF do JPEG.\npub fn jpeg_info(data: &[u8]) -> anyhow::Result<JpegInfo> {\n    if data.len() < 4 || data[0] != 0xFF || data[1] != 0xD8 {\n        return Err(anyhow!(\"nao e um JPEG\"));\n    }\n    let mut i = 2usize;\n    while i + 9 < data.len() {\n        if data[i] != 0xFF {\n            i += 1;\n            continue;\n        }\n        let marker = data[i + 1];\n        if marker == 0xFF {\n            i += 1;\n            continue;\n        }\n        // marcadores sem payload\n        if (0xD0..=0xD9).contains(&marker) || marker == 0x01 {\n            i += 2;\n            continue;\n        }\n        let len = u16::from_be_bytes([data[i + 2], data[i + 3]]) as usize;","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/jpeg_pdf.rs#L1-L34","documentation":"jpeg_info parses width/height/channels from a JPEG's SOF marker. It first checks that the data is at least 4 bytes and starts with the JPEG SOI signature FF D8; otherwise it raises \"nao e um JPEG\" (not a JPEG). It is a fast-fail guard so build_pdf never embeds non-JPEG bytes.","triggerScenarios":"Calling jpeg_info with an empty/short buffer, a PNG/WebP/HEIC file, a truncated download that lost the first bytes, or a text/HTML error page saved as .jpg.","commonSituations":"Downloads converted with content-negociation returning WebP/PNG; URL returned an HTML 404 page; file truncated by a failed download; user selected a non-JPEG image for the PDF builder.","solutions":["Check the first bytes (FF D8) or call is_jpeg() before invoking jpeg_info","Re-download or re-obtain the file and verify it is a valid JPEG (file command / magic bytes)","Convert other formats to JPEG first (e.g. with the image crate) if JPEG is required"],"exampleFix":"// before\nlet info = jpeg_info(&bytes)?; // Err: nao e um JPEG\n// after\nif !is_jpeg(&bytes) {\n    let jpg = image::load_from_memory(&bytes)?.to_rgb8(); // convert/validate first\n}\nlet info = jpeg_info(&bytes)?;","handlingStrategy":"type-guard","validationCode":"if bytes.len() < 4 || bytes[0] != 0xFF || bytes[1] != 0xD8 {\n    return Err(\"entrada não é um JPEG válido\");\n}","typeGuard":"fn is_jpeg(data: &[u8]) -> bool {\n    data.len() > 3 && data[0] == 0xFF && data[1] == 0xD8 && data[2] == 0xFF\n}","tryCatchPattern":"match jpeg_info(&bytes) {\n    Err(e) if e.to_string() == \"nao e um JPEG\" => {\n        let jpg = convert_to_jpeg(&bytes)?;\n        jpeg_info(&jpg)\n    }\n    r => r,\n}","preventionTips":["Check magic bytes (FF D8 FF) before parsing any image buffer","Verify downloaded content-type is image/jpeg and retry HTML error responses as downloads","Detect truncation by comparing received bytes to Content-Length"],"tags":["jpeg","image","validation","rust"],"backgroundTag":"invalid-argument-value","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}