weiss_core/db/
serialization.rs1use std::fs;
2use std::path::Path;
3
4use anyhow::{Context, Result};
5
6use super::store::CardDb;
7
8const WSDB_MAGIC: &[u8; 4] = b"WSDB";
9const MAX_WSDB_BYTES: u64 = 128 * 1024 * 1024;
10pub const WSDB_SCHEMA_VERSION: u32 = 2;
12
13impl CardDb {
14 pub fn load<P: AsRef<Path>>(path: P) -> Result<Self> {
16 let path = path.as_ref();
17 let metadata =
18 fs::metadata(path).with_context(|| format!("Failed to stat card db {path:?}"))?;
19 if metadata.len() > MAX_WSDB_BYTES {
20 anyhow::bail!(
21 "Card db file {path:?} is {} bytes, exceeding maximum {MAX_WSDB_BYTES} bytes",
22 metadata.len()
23 );
24 }
25 let bytes = fs::read(path).with_context(|| format!("Failed to read card db {path:?}"))?;
26 Self::from_wsdb_bytes(&bytes)
27 }
28
29 pub fn from_wsdb_bytes(bytes: &[u8]) -> Result<Self> {
31 if bytes.len() as u64 > MAX_WSDB_BYTES {
32 anyhow::bail!(
33 "Card db byte buffer is {} bytes, exceeding maximum {MAX_WSDB_BYTES} bytes",
34 bytes.len()
35 );
36 }
37 if bytes.len() < 8 {
38 anyhow::bail!("Card db file too small");
39 }
40 if &bytes[0..4] != WSDB_MAGIC {
41 anyhow::bail!("Card db magic mismatch; expected WSDB header");
42 }
43 let version = u32::from_le_bytes(
44 bytes[4..8]
45 .try_into()
46 .map_err(|_| anyhow::anyhow!("Card db header missing version bytes"))?,
47 );
48 if version != WSDB_SCHEMA_VERSION {
49 anyhow::bail!(
50 "Unsupported card db schema version {version}, expected {WSDB_SCHEMA_VERSION}. \
51 This build only loads WSDB v2 files; regenerate the card DB with the current \
52 parser-v2 rule-pack pipeline."
53 );
54 }
55 let payload = &bytes[8..];
56 Self::from_postcard_payload(payload)
57 }
58
59 pub fn from_postcard_payload(payload: &[u8]) -> Result<Self> {
61 let mut db: CardDb =
62 postcard::from_bytes(payload).context("Failed to decode card db payload")?;
63 db.build_index()?;
64 Ok(db)
65 }
66
67 pub fn schema_version() -> u32 {
69 WSDB_SCHEMA_VERSION
70 }
71
72 pub fn to_bytes_with_header(&self) -> Result<Vec<u8>> {
74 let payload = postcard::to_stdvec(self)?;
75 let mut out = Vec::with_capacity(8 + payload.len());
76 out.extend_from_slice(WSDB_MAGIC);
77 out.extend_from_slice(&WSDB_SCHEMA_VERSION.to_le_bytes());
78 out.extend_from_slice(&payload);
79 Ok(out)
80 }
81}