Skip to main content

munin_msbuild/
header.rs

1// Copyright (c) Michael Grier
2
3//! Binlog header reader and GZip decompression setup.
4//!
5//! A `.binlog` file is a GZip-compressed stream whose decompressed content
6//! begins with the format version and minimum reader version (two little-endian
7//! `i32` values), followed by serialized build event records.
8
9use std::io::{BufReader, Read};
10
11use flate2::read::GzDecoder;
12
13use crate::{error::MuninError, primitives::read_i32_le};
14
15/// The minimum binlog format version we support. Version 18 introduced
16/// forward-compatible reading with per-record length prefixes.
17pub const MIN_SUPPORTED_VERSION: i32 = 18;
18
19/// The maximum binlog format version we have full support for.
20pub const MAX_KNOWN_VERSION: i32 = 25;
21
22/// Parsed binlog file header.
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct BinlogHeader {
25    /// The file format version written by the BinaryLogger.
26    pub file_format_version: i32,
27
28    /// The minimum reader version needed to interpret this file.
29    pub min_reader_version: i32,
30}
31
32/// Open a binlog stream: decompress, read the header, and return a reader
33/// positioned at the start of the record stream.
34///
35/// The caller provides any `Read` — typically a `File` or `Cursor<Vec<u8>>`.
36/// The returned reader decompresses on the fly; all subsequent reads
37/// produce decompressed record bytes.
38///
39/// The `.binlog` format is entirely GZip-compressed; the version header is
40/// the first 8 bytes of the decompressed stream.
41pub fn open_binlog<R: Read>(
42    reader: R,
43) -> Result<(BinlogHeader, BufReader<GzDecoder<R>>), MuninError> {
44    let gz = GzDecoder::new(reader);
45    let mut buffered = BufReader::with_capacity(32768, gz);
46
47    let file_format_version = read_i32_le(&mut buffered)?;
48
49    if file_format_version < MIN_SUPPORTED_VERSION {
50        return Err(MuninError::UnsupportedVersion {
51            file_version: file_format_version,
52            min_reader_version: 0,
53        });
54    }
55
56    // Version 18+ writes a second i32: the minimum reader version.
57    let min_reader_version = read_i32_le(&mut buffered)?;
58
59    let header = BinlogHeader {
60        file_format_version,
61        min_reader_version,
62    };
63
64    Ok((header, buffered))
65}
66
67#[cfg(test)]
68mod tests;