use std::io::Write;
const MMDB_MARKER: &[u8] = b"\xab\xcd\xefMaxMind.com";
const ARCHIVE_DIRECTORY: &str = "GeoLite2-City_20241231";
pub(crate) fn mmdb_body(payload: &[u8]) -> Vec<u8> {
let mut body = payload.to_vec();
body.extend_from_slice(MMDB_MARKER);
body.extend_from_slice(b"binary metadata section");
body
}
pub(crate) fn sha256_hex(body: &[u8]) -> String {
use sha2::Digest;
use std::fmt::Write as _;
sha2::Sha256::digest(body)
.iter()
.fold(String::new(), |mut hex, byte| {
let _ = write!(hex, "{byte:02x}");
hex
})
}
pub(crate) fn gzip(payload: &[u8]) -> Vec<u8> {
let mut encoder = flate2::write::GzEncoder::new(Vec::new(), flate2::Compression::fast());
encoder.write_all(payload).unwrap();
encoder.finish().unwrap()
}
pub(crate) fn tar_gz(member: &str, payload: &[u8]) -> Vec<u8> {
let path = format!("{ARCHIVE_DIRECTORY}/{member}");
tar_gz_of(&[(path.as_str(), tar::EntryType::Regular, payload)])
}
pub(crate) fn tar_gz_of(entries: &[(&str, tar::EntryType, &[u8])]) -> Vec<u8> {
let mut builder = tar::Builder::new(flate2::write::GzEncoder::new(
Vec::new(),
flate2::Compression::fast(),
));
for (path, kind, payload) in entries {
let mut header = tar::Header::new_gnu();
header.set_size(payload.len() as u64);
header.set_mode(0o644);
header.set_entry_type(*kind);
header.set_cksum();
builder.append_data(&mut header, path, *payload).unwrap();
}
let mut encoder = builder.into_inner().unwrap();
encoder.flush().unwrap();
encoder.finish().unwrap()
}