Skip to content

Conversation

@Muscraft
Copy link
Contributor

I saw #98 and figured I would take a crack at moving away from bincode. I went with postcard as the replacement, as it is essentially a drop-in replacement for bincode given how phonenumber used it. postcard also uses varint encoding by default, which is a nice plus.

The only major difference (from what I can tell) is that the serialized format is different from bincode, but that shouldn't matter.

@codecov
Copy link

codecov bot commented Jan 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.25%. Comparing base (09f8974) to head (593759f).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #99      +/-   ##
==========================================
- Coverage   67.41%   67.25%   -0.16%     
==========================================
  Files          18       18              
  Lines        2145     2138       -7     
==========================================
- Hits         1446     1438       -8     
- Misses        699      700       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@rubdos
Copy link
Member

rubdos commented Jan 13, 2026

Hi! Thanks for filing your merge request. I appreciate you taking a crack at removing the advisory warning!

As you might have seen from my comment on the issue, I am more after a patch like this, without any runtime deserialization at all:

diff --git a/build.rs b/build.rs
index 44840cd..0512c95 100644
--- a/build.rs
+++ b/build.rs
@@ -1,5 +1,6 @@
 use std::env;
 use std::fs::File;
+use std::io::Write;
 use std::io::{BufReader, BufWriter};
 use std::path::Path;
 
@@ -17,15 +18,17 @@ fn main() {
         File::open(pnm_path).expect("could not open metadata file"),
     ))
     .expect("failed to load metadata");
+    let metadata = metadata.as_slice();
+
+    // TODO: remove
+    let metadata = &metadata[..4];
+
     println!("cargo:rerun-if-changed={pnm_path}");
 
     let mut out = BufWriter::new(
-        File::create(Path::new(&env::var("OUT_DIR").unwrap()).join("database.bin"))
+        File::create(Path::new(&env::var("OUT_DIR").unwrap()).join("database.rs"))
             .expect("could not create database file"),
     );
 
-    bincode::options()
-        .with_varint_encoding()
-        .serialize_into(&mut out, &metadata)
-        .expect("failed to serialize database");
+    write!(out, "pub const DATABASE: &[Metadata] = &{:?};", metadata).expect("write database");
 }
diff --git a/src/metadata/database.rs b/src/metadata/database.rs
index 46ae55e..24dca0c 100644
--- a/src/metadata/database.rs
+++ b/src/metadata/database.rs
@@ -15,8 +15,6 @@
 use crate::error;
 use crate::metadata::loader;
 use crate::Metadata;
-use bincode;
-use bincode::Options;
 use fnv::FnvHashMap;
 use once_cell::sync::Lazy;
 use regex_cache::{CachedRegex, CachedRegexBuilder, RegexCache};
@@ -27,18 +25,17 @@ use std::io::{BufReader, Cursor};
 use std::path::Path;
 use std::sync::{Arc, Mutex};
 
-const DATABASE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/database.bin"));
+mod database {
+    use crate::metadata::loader::*;
+    // `database.rs` contains
+    // pub const DATABASE: &[Metadata] = &[ .. ];
+    include!(concat!(env!("OUT_DIR"), "/database.rs"));
+}
+
+use database::DATABASE;
 
 /// The Google provided metadata database, used as default.
-pub static DEFAULT: Lazy<Database> = Lazy::new(|| {
-    Database::from(
-        bincode::options()
-            .with_varint_encoding()
-            .deserialize(DATABASE)
-            .unwrap(),
-    )
-    .unwrap()
-});
+pub static DEFAULT: Lazy<Database> = Lazy::new(|| Database::from(DATABASE.to_vec()).unwrap());
 
 /// Representation of a database of metadata for phone number.
 #[derive(Clone, Debug)]

This has quite some implications regarding borrowing (preferably we'd be on &[Metadata] and borrow everything all the way), and the resulting database.rs file is quite large (1.2MB). So this approach currently generates an awful lot of compile errors, but I think it could still work.

@rubdos
Copy link
Member

rubdos commented Jan 13, 2026

My suggestion requires quite some refactoring though: the loader::Metadata is currently a heap-allocated-only structure, which is reused between the build.rs and the actual runtime. It'd need to be refactored to be either reusable through &'static references and heap allocated structures through some generics (T: AsRef, I suppose), or split out by some other manner.

@rubdos
Copy link
Member

rubdos commented Jan 13, 2026

I spent a bit of time seeing how far it trickles down... Probably this really warrants a complete rewrite of the database loading system as a whole, splitting up the loader into a separate crate for use in the main crate's build.rs, and directly yielding a Database instead of the intermediary [Metadata]. That would also get rid of the "hacky" include! calls in build.rs. That's clearly out of scope for this PR!

Could you have a look at why the rustfmt fails? Then we can pull this in as is :-)

@rubdos rubdos merged commit f1c55d7 into whisperfish:main Jan 13, 2026
7 checks passed
@Muscraft Muscraft deleted the replace-bincode branch January 13, 2026 16:42
@Muscraft
Copy link
Contributor Author

Would you like me to open a PR to update the version so this can be released?

@rubdos
Copy link
Member

rubdos commented Jan 14, 2026

Nah, is fine, I'll do it in a few minutes :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants