use std::io;
pub(crate) const V3_MAGIC: [u8; 4] = [0x52, 0x47, 0x46, 0x03];
pub(crate) const V4_MAGIC: [u8; 4] = [0x52, 0x47, 0x46, 0x04];
pub(crate) const V5_MAGIC: [u8; 4] = [0x52, 0x47, 0x46, 0x05];
pub(crate) const V6_MAGIC: [u8; 4] = [0x52, 0x47, 0x46, 0x06];
pub(crate) const CURRENT_CONTAINER_VERSION: u8 = V6_MAGIC[3];
pub(crate) const V3_HARD_BREAK_MSG: &str = "kglite .kgl file format v3 is not supported by this \
binary. It predates the current RGF v5/Postcard container; the Value enum gained \
structured Node / Relationship / Path / List / Map variants, which changes \
the serialised property representation. Rebuild your graph from its \
original source (CSV, DataFrame, dataset loader) and save again, \
or downgrade kglite to the 0.9.x line if you need to read this \
file. If you no longer have the original source but can still run \
the old binary, open the file there and export a portable, \
format-stable copy with g.export_csv('backup/'), then rebuild here \
with kglite.from_blueprint('backup/blueprint.json').";
pub(crate) fn newer_portable_format_error(version: u8) -> io::Error {
io::Error::other(format!(
"File uses .kgl container version {version}, but this library only supports up to version {}. Please upgrade kglite.",
V6_MAGIC[3]
))
}
pub(crate) fn unrecognized_magic_error(prefix: &[u8], origin: &str) -> io::Error {
if prefix.len() >= 3 && prefix[..3] == V6_MAGIC[..3] {
return io::Error::other(format!(
"Unrecognized .kgl container version {} in {origin}. This file was saved with an \
older version of kglite. Please rebuild the graph with the current version and \
save again. If you no longer have the original source but can still run the old \
binary, open the file there and export a portable copy with g.export_csv('backup/'), \
then rebuild here with kglite.from_blueprint('backup/blueprint.json').",
prefix.get(3).copied().unwrap_or(0)
));
}
io::Error::other(format!(
"{origin} is not a kglite graph: it does not start with the .kgl container magic \
\"RGF\" (first bytes: {}). Check the path — a disk-mode graph is a directory, not a \
file inside it, and every .kgl kglite has ever written begins with RGF.",
describe_header_bytes(prefix)
))
}
fn describe_header_bytes(prefix: &[u8]) -> String {
let hex: Vec<String> = prefix.iter().map(|b| format!("{b:02x}")).collect();
let hex = hex.join(" ");
if prefix.iter().all(|b| b.is_ascii_graphic() || *b == b' ') {
format!("{hex} = \"{}\"", String::from_utf8_lossy(prefix))
} else {
hex
}
}