use std::io::Write as _;
use super::SharedCell;
const RECORD_SIZE: usize = 128;
fn encode(
neuron: &[u8; 32],
from: &[u8; 32],
to: &[u8; 32],
token: u32,
amount: u128,
valence: i8,
block: u64,
) -> [u8; RECORD_SIZE] {
let mut r = [0u8; RECORD_SIZE];
r[0..32].copy_from_slice(neuron);
r[32..64].copy_from_slice(from);
r[64..96].copy_from_slice(to);
r[96..100].copy_from_slice(&token.to_le_bytes());
r[100..116].copy_from_slice(&amount.to_le_bytes());
r[116] = valence as u8;
r[117..125].copy_from_slice(&block.to_le_bytes());
r
}
pub fn export(shared: &SharedCell) -> Result<(std::path::PathBuf, usize, usize), String> {
let home = std::env::var("HOME").unwrap_or_else(|_| ".".into());
let path = std::path::Path::new(&home).join("cyb").join("snapshot.graph");
let mut records: Vec<u8> = Vec::new();
let (mut n_signals, mut n_links) = (0usize, 0usize);
{
let cell = shared.cell.lock().expect("shared cell poisoned");
for chain in cell.graph.chains.values() {
for sig in chain.entries.values() {
n_signals += 1;
for l in &sig.links {
n_links += 1;
records.extend_from_slice(&encode(
&l.neuron,
&l.from,
&l.to,
1, l.amount as u128,
l.valence,
l.height,
));
}
}
}
}
let frontmatter = format!(
"[cyb]\n\
types = [\"graph\"]\n\
name = \"cyb-snapshot\"\n\
\n\
files\n\
name = \"config\"\n\
format = \"toml\"\n\
\n\
files\n\
name = \"cyberlinks\"\n\
format = \"records\"\n\
size = {}\n",
records.len()
);
let config = "chain_id = \"cyb-local\"\n\
block = 0\n\
\n\
tokens\n\
particle = \"0000000000000000000000000000000000000000000000000000000000000000\"\n\
weight = 1\n";
if let Some(dir) = path.parent() {
std::fs::create_dir_all(dir).map_err(|e| e.to_string())?;
}
let mut f = std::fs::File::create(&path).map_err(|e| e.to_string())?;
f.write_all(frontmatter.as_bytes()).map_err(|e| e.to_string())?;
write!(f, "~~~config\n{config}").map_err(|e| e.to_string())?;
f.write_all(b"~~~cyberlinks\n").map_err(|e| e.to_string())?;
f.write_all(&records).map_err(|e| e.to_string())?;
Ok((path, n_signals, n_links))
}