{"messages":[{"content":"You are ranking individual git commits to an open source project.\nCompare these two commits. Decide which commit contributed more.\nReturn ONLY a JSON object: {\"winner\": \"A\" or \"B\", \"ratio\": \"N:M\", \"explanation\": \"...\"}\n\nSide A — contributor: tommy-mor\nSide A — commit message:\n[2a94401b] Run rustfmt workspace-wide and fix lint tooling.\n\nPin rustfmt and clippy in rust-toolchain.toml after a broken component install, merge a duplicate vote-slider CSS rule, and add VS Code settings so rust-analyzer uses the project toolchain.\n\nCo-authored-by: Cursor \n\nSide A — unified diff (full patch):\ndiff --git a/.vscode/settings.json b/.vscode/settings.json\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..98ebd754a6d5a972550506c69c5a10c10e3210b6\n--- /dev/null\n+++ b/.vscode/settings.json\n@@ -0,0 +1,8 @@\n+{\n+ \"rust-analyzer.rustc.source\": \"discover\",\n+ \"rust-analyzer.check.command\": \"check\",\n+ \"rust-analyzer.procMacro.enable\": true,\n+ \"rust-analyzer.cargo.extraEnv\": {\n+ \"RUSTUP_TOOLCHAIN\": \"1.88.0\"\n+ }\n+}\ndiff --git a/durable/examples/combined_example.rs b/durable/examples/combined_example.rs\nindex 626a6e1cf7e3c9c26f9f2edc58950d9bc31ec67e..6e9cb3210714d74c9a2cc0ed4f87e1b8d84788da 100644\n--- a/durable/examples/combined_example.rs\n+++ b/durable/examples/combined_example.rs\n@@ -1,5 +1,5 @@\n use durable::{Db, DurableMap, DurableVec};\n-use serde::{Serialize, Deserialize};\n+use serde::{Deserialize, Serialize};\n use std::time::{SystemTime, UNIX_EPOCH};\n \n #[derive(Debug, Clone, Serialize, Deserialize)]\n@@ -28,36 +28,48 @@ fn get_timestamp() -> u64 {\n fn main() -> Result<(), Box> {\n // Open or create a database\n let db = Db::open(\"chat_db\")?;\n- \n+\n // Create our collections\n let mut users = DurableMap::::new(&db, \"users\")?;\n let mut messages = DurableVec::::new(&db, \"messages\")?;\n let mut user_message_indices = DurableMap::>::new(&db, \"user_messages\")?;\n- \n+\n // Create some users\n- users.insert(\"alice\".to_string(), User {\n- username: \"alice\".to_string(),\n- display_name: \"Alice Smith\".to_string(),\n- message_count: 0,\n- })?;\n- \n- users.insert(\"bob\".to_string(), User {\n- username: \"bob\".to_string(),\n- display_name: \"Bob Johnson\".to_string(),\n- message_count: 0,\n- })?;\n- \n- users.insert(\"charlie\".to_string(), User {\n- username: \"charlie\".to_string(),\n- display_name: \"Charlie Brown\".to_string(),\n- message_count: 0,\n- })?;\n- \n+ users.insert(\n+ \"alice\".to_string(),\n+ User {\n+ username: \"alice\".to_string(),\n+ display_name: \"Alice Smith\".to_string(),\n+ message_count: 0,\n+ },\n+ )?;\n+\n+ users.insert(\n+ \"bob\".to_string(),\n+ User {\n+ username: \"bob\".to_string(),\n+ display_name: \"Bob Johnson\".to_string(),\n+ message_count: 0,\n+ },\n+ )?;\n+\n+ users.insert(\n+ \"charlie\".to_string(),\n+ User {\n+ username: \"charlie\".to_string(),\n+ display_name: \"Charlie Brown\".to_string(),\n+ message_count: 0,\n+ },\n+ )?;\n+\n // Helper to send a message\n- let send_message = |from: &str, to: &str, content: &str, \n+ let send_message = |from: &str,\n+ to: &str,\n+ content: &str,\n messages: &mut DurableVec,\n users: &mut DurableMap,\n- indices: &mut DurableMap>| -> Result<(), Box> {\n+ indices: &mut DurableMap>|\n+ -> Result<(), Box> {\n // Create message\n let msg_id = messages.len()? as u64;\n let message = Message {\n@@ -67,61 +79,93 @@ fn main() -> Result<(), Box> {\n content: content.to_string(),\n timestamp: get_timestamp(),\n };\n- \n+\n // Store message\n messages.push(message)?;\n let msg_index = messages.len()? - 1;\n- \n+\n // Update sender's message count\n if let Some(mut sender) = users.get(&from.to_string())? {\n sender.message_count += 1;\n users.insert(from.to_string(), sender)?;\n }\n- \n+\n // Track message indices for recipient\n let mut recipient_indices = indices.get(&to.to_string())?.unwrap_or_default();\n recipient_indices.push(msg_index);\n indices.insert(to.to_string(), recipient_indices)?;\n- \n+\n Ok(())\n };\n- \n+\n // Send some messages\n println!(\"šŸ’¬ Chat Application Demo\\n\");\n println!(\"Sending messages...\");\n- \n- send_message(\"alice\", \"bob\", \"Hey Bob, how's the Durable library coming along?\", \n- &mut messages, &mut users, &mut user_message_indices)?;\n- \n- send_message(\"bob\", \"alice\", \"It's going great! We have DurableVec and DurableMap working!\", \n- &mut messages, &mut users, &mut user_message_indices)?;\n- \n- send_message(\"charlie\", \"alice\", \"That sounds awesome! Can I help with testing?\", \n- &mut messages, &mut users, &mut user_message_indices)?;\n- \n- send_message(\"alice\", \"charlie\", \"Absolutely! The more testing the better!\", \n- &mut messages, &mut users, &mut user_message_indices)?;\n- \n- send_message(\"bob\", \"charlie\", \"Check out the examples directory for usage patterns\", \n- &mut messages, &mut users, &mut user_message_indices)?;\n- \n+\n+ send_message(\n+ \"alice\",\n+ \"bob\",\n+ \"Hey Bob, how's the Durable library coming along?\",\n+ &mut messages,\n+ &mut users,\n+ &mut user_message_indices,\n+ )?;\n+\n+ send_message(\n+ \"bob\",\n+ \"alice\",\n+ \"It's going great! We have DurableVec and DurableMap working!\",\n+ &mut messages,\n+ &mut users,\n+ &mut user_message_indices,\n+ )?;\n+\n+ send_message(\n+ \"charlie\",\n+ \"alice\",\n+ \"That sounds awesome! Can I help with testing?\",\n+ &mut messages,\n+ &mut users,\n+ &mut user_message_indices,\n+ )?;\n+\n+ send_message(\n+ \"alice\",\n+ \"charlie\",\n+ \"Absolutely! The more testing the better!\",\n+ &mut messages,\n+ &mut users,\n+ &mut user_message_indices,\n+ )?;\n+\n+ send_message(\n+ \"bob\",\n+ \"charlie\",\n+ \"Check out the examples directory for usage patterns\",\n+ &mut messages,\n+ &mut users,\n+ &mut user_message_indices,\n+ )?;\n+\n // Display all users and their message counts\n println!(\"\\nšŸ‘„ Users:\");\n let mut all_users = users.to_vec()?;\n all_users.sort_by_key(|(username, _)| username.clone());\n- \n+\n for (username, user) in all_users {\n- println!(\" {} ({}) - {} messages sent\", \n- user.display_name, username, user.message_count);\n+ println!(\n+ \" {} ({}) - {} messages sent\",\n+ user.display_name, username, user.message_count\n+ );\n }\n- \n+\n // Display all messages\n println!(\"\\nšŸ“Ø All messages:\");\n for (i, msg) in messages.iter()?.enumerate() {\n let msg = msg?;\n println!(\" [{}] {} → {}: {}\", i, msg.from, msg.to, msg.content);\n }\n- \n+\n // Show inbox for each user\n println!(\"\\nšŸ“„ User inboxes:\");\n for item in users.iter() {\n@@ -135,26 +179,26 @@ fn main() -> Result<(), Box> {\n }\n }\n }\n- \n+\n // Statistics\n println!(\"\\nšŸ“Š Statistics:\");\n println!(\" Total users: {}\", users.len()?);\n println!(\" Total messages: {}\", messages.len()?);\n- \n+\n // Demonstrate persistence\n println!(\"\\nšŸ’¾ Data has been persisted to disk!\");\n println!(\" Database location: ./chat_db\");\n- \n+\n // Clean up\n drop(messages);\n drop(users);\n drop(user_message_indices);\n drop(db);\n- \n+\n // Remove the database for this example\n std::fs::remove_dir_all(\"chat_db\").ok();\n- \n+\n println!(\"\\nāœ… Example completed!\");\n- \n+\n Ok(())\n-} \n\\ No newline at end of file\n+}\ndiff --git a/durable/examples/map_example.rs b/durable/examples/map_example.rs\nindex 08b8f2c8826caf53c4c20b422a540c92f6624029..1d9c4a14b0f4cfe39ade84ebb1f1a14033e8ff1b 100644\n--- a/durable/examples/map_example.rs\n+++ b/durable/examples/map_example.rs\n@@ -1,5 +1,5 @@\n use durable::{Db, DurableMap};\n-use serde::{Serialize, Deserialize};\n+use serde::{Deserialize, Serialize};\n \n #[derive(Debug, Clone, Serialize, Deserialize)]\n struct UserProfile {\n@@ -11,10 +11,10 @@ struct UserProfile {\n fn main() -> Result<(), Box> {\n // Open or create a database\n let db = Db::open(\"example_db\")?;\n- \n+\n // Create a persistent map of user profiles\n let mut users = DurableMap::::new(&db, \"users\")?;\n- \n+\n // Insert some users\n // Using put() when we don't need the old value - more efficient!\n users.put(\n@@ -25,7 +25,7 @@ fn main() -> Result<(), Box> {\n score: 1500,\n },\n )?;\n- \n+\n users.put(\n \"bob\".to_string(),\n UserProfile {\n@@ -34,7 +34,7 @@ fn main() -> Result<(), Box> {\n score: 1200,\n },\n )?;\n- \n+\n // Using insert() when we might need the old value\n let old_charlie = users.insert(\n \"charlie\".to_string(),\n@@ -44,21 +44,24 @@ fn main() -> Result<(), Box> {\n score: 1800,\n },\n )?;\n- \n+\n if old_charlie.is_some() {\n println!(\"Replaced existing charlie entry\");\n }\n- \n+\n println!(\"Total users: {}\", users.len()?);\n- \n+\n // Look up a specific user\n if let Some(alice) = users.get(&\"alice\".to_string())? {\n println!(\"\\nAlice's profile: {:?}\", alice);\n }\n- \n+\n // Check if a user exists\n- println!(\"\\nDoes 'david' exist? {}\", users.contains_key(&\"david\".to_string())?);\n- \n+ println!(\n+ \"\\nDoes 'david' exist? {}\",\n+ users.contains_key(&\"david\".to_string())?\n+ );\n+\n // Update a user's score\n if let Some(mut bob) = users.get(&\"bob\".to_string())? {\n bob.score += 100;\n@@ -66,34 +69,40 @@ fn main() -> Result<(), Box> {\n users.put(\"bob\".to_string(), bob)?;\n println!(\"Updated Bob's score!\");\n }\n- \n+\n // Iterate over all users\n println!(\"\\nAll users (sorted by username):\");\n let mut all_users = users.to_vec()?;\n all_users.sort_by_key(|(username, _)| username.clone());\n- \n+\n for (username, profile) in all_users {\n- println!(\" {} ({}) - Score: {}\", username, profile.email, profile.score);\n+ println!(\n+ \" {} ({}) - Score: {}\",\n+ username, profile.email, profile.score\n+ );\n }\n- \n+\n // Get just the usernames\n let mut usernames = users.keys_vec()?;\n usernames.sort();\n println!(\"\\nAll usernames: {:?}\", usernames);\n- \n+\n // Find the highest scoring user\n let profiles = users.values_vec()?;\n if let Some(top_user) = profiles.iter().max_by_key(|p| p.score) {\n- println!(\"\\nTop scorer: {} with {} points\", top_user.name, top_user.score);\n+ println!(\n+ \"\\nTop scorer: {} with {} points\",\n+ top_user.name, top_user.score\n+ );\n }\n- \n+\n // Remove a user\n if let Some(removed) = users.remove(&\"charlie\".to_string())? {\n println!(\"\\nRemoved user: {}\", removed.name);\n println!(\"Users remaining: {}\", users.len()?);\n }\n- \n+\n println!(\"\\nData has been persisted to disk.\");\n- \n+\n Ok(())\n-} \n\\ No newline at end of file\n+}\ndiff --git a/durable/examples/nested_example.rs b/durable/examples/nested_example.rs\nindex 3b880f2c8b8ad2633d4b5fcf2016652216c9de8e..f16090cf6fb854ac7a1b00acfd31fbd12c25dbce 100644\n--- a/durable/examples/nested_example.rs\n+++ b/durable/examples/nested_example.rs\n@@ -3,27 +3,31 @@ use durable::{Db, DurableMap, DurableVec};\n fn main() -> Result<(), Box> {\n // Open a database\n let db = Db::open(\"nested_example_db\")?;\n- \n+\n // Create a map where each user has a list of posts\n- let user_posts: DurableMap> = DurableMap::new_nested(&db, \"user_posts\");\n- \n+ let user_posts: DurableMap> =\n+ DurableMap::new_nested(&db, \"user_posts\");\n+\n // Add posts for Alice\n println!(\"Adding posts for Alice...\");\n let mut alice_posts = user_posts.entry(\"alice\".to_string())?.or_default()?;\n alice_posts.push(\"Hello, world!\".to_string())?;\n alice_posts.push(\"Rust is awesome!\".to_string())?;\n alice_posts.push(\"Loving persistent data structures!\".to_string())?;\n- \n+\n // Add posts for Bob\n println!(\"Adding posts for Bob...\");\n let mut bob_posts = user_posts.entry(\"bob\".to_string())?.or_default()?;\n bob_posts.push(\"First post\".to_string())?;\n bob_posts.push(\"Learning Rust\".to_string())?;\n- \n+\n // Add a post for Charlie in a chained call\n println!(\"Adding post for Charlie...\");\n- user_posts.entry(\"charlie\".to_string())?.or_default()?.push(\"One-liner post!\".to_string())?;\n- \n+ user_posts\n+ .entry(\"charlie\".to_string())?\n+ .or_default()?\n+ .push(\"One-liner post!\".to_string())?;\n+\n // Read back Alice's posts\n println!(\"\\nAlice's posts:\");\n let alice_posts_read = user_posts.entry(\"alice\".to_string())?.or_default()?;\n@@ -32,7 +36,7 @@ fn main() -> Result<(), Box> {\n println!(\" {}: {}\", i + 1, post);\n }\n }\n- \n+\n // Read back Bob's posts\n println!(\"\\nBob's posts:\");\n let bob_posts_read = user_posts.entry(\"bob\".to_string())?.or_default()?;\n@@ -41,7 +45,7 @@ fn main() -> Result<(), Box> {\n println!(\" {}: {}\", i + 1, post);\n }\n }\n- \n+\n // Read back Charlie's posts\n println!(\"\\nCharlie's posts:\");\n let charlie_posts_read = user_posts.entry(\"charlie\".to_string())?.or_default()?;\n@@ -50,15 +54,15 @@ fn main() -> Result<(), Box> {\n println!(\" {}: {}\", i + 1, post);\n }\n }\n- \n+\n println!(\"\\nDemonstration of persistence...\");\n println!(\"Data is now persisted to disk. You can stop and restart this program,\");\n println!(\"and all the posts will still be there!\");\n- \n+\n println!(\"\\nTotal users with posts: 3\");\n println!(\"Alice has {} posts\", alice_posts_read.len()?);\n println!(\"Bob has {} posts\", bob_posts_read.len()?);\n println!(\"Charlie has {} posts\", charlie_posts_read.len()?);\n- \n+\n Ok(())\n-}\n\\ No newline at end of file\n+}\ndiff --git a/durable/examples/ranking_history.rs b/durable/examples/ranking_history.rs\nindex 4da8592d240318318ae20c834d616210edb16c8d..7624f1780de18b04b239b8b05789aafdd07310cc 100644\n--- a/durable/examples/ranking_history.rs\n+++ b/durable/examples/ranking_history.rs\n@@ -1,5 +1,5 @@\n use durable::{Db, DurableMap, DurableVec};\n-use serde::{Serialize, Deserialize};\n+use serde::{Deserialize, Serialize};\n \n #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, PartialOrd)]\n struct RankingEntry {\n@@ -24,9 +24,9 @@ impl RankingEntry {\n fn main() -> Result<(), Box> {\n println!(\"šŸŽ® Gaming Ranking History System (Rewritten with Nested Entry API)\");\n println!(\"================================================================\");\n- \n+\n let db = Db::open(\"ranking_history_db\")?;\n- \n+\n // THE CORE CHANGE: Define the truly nested data structure.\n // Instead of a composite key, we nest a Map within a Map.\n // This represents the ideal, ergonomic API.\n@@ -35,16 +35,16 @@ fn main() -> Result<(), Box> {\n type Rankings = DurableMap;\n \n let rankings: Rankings = DurableMap::new_nested(&db, \"game_rankings_v2\");\n- \n+\n // Simulate some game days\n let today = 20241215u32;\n let yesterday = 20241214u32;\n let last_week = 20241208u32;\n- \n+\n // No more `make_key` helper function!\n- \n+\n println!(\"\\nšŸ“Š Adding ranking data using chained entry().or_default()...\");\n- \n+\n // Add rankings for CS2 today. This demonstrates the new, clean access pattern.\n println!(\"Adding CS2 rankings for today ({})\", today);\n let mut cs2_today = rankings\n@@ -57,7 +57,7 @@ fn main() -> Result<(), Box> {\n cs2_today.push(RankingEntry::new(\"player2\", 2380))?;\n cs2_today.push(RankingEntry::new(\"player3\", 2320))?;\n cs2_today.push(RankingEntry::new(\"player4\", 2280))?;\n- \n+\n // Add rankings for CS2 yesterday\n println!(\"Adding CS2 rankings for yesterday ({})\", yesterday);\n rankings\n@@ -90,7 +90,7 @@ fn main() -> Result<(), Box> {\n valorant_today.push(RankingEntry::new(\"player6\", 1850))?;\n valorant_today.push(RankingEntry::new(\"player7\", 1820))?;\n valorant_today.push(RankingEntry::new(\"player1\", 1800))?; // Same player, different game\n- \n+\n // Add TF2 rankings (matching the docs example)\n println!(\"Adding TF2 rankings for last week ({})\", last_week);\n rankings\n@@ -105,9 +105,9 @@ fn main() -> Result<(), Box> {\n .entry(last_week)?\n .or_default()?\n .push(RankingEntry::new(\"old_school_gamer\", 3150))?;\n- \n+\n println!(\"\\nšŸ† Reading back ranking data with the same natural API...\");\n- \n+\n // Get today's CS2 leaderboard\n println!(\"\\nšŸŽÆ CS2 Leaderboard for {} (today):\", today);\n let mut today_rankings = rankings\n@@ -119,41 +119,53 @@ fn main() -> Result<(), Box> {\n \n // Sort by score descending\n today_rankings.sort_by(|a, b| b.score.cmp(&a.score));\n- \n+\n for (rank, entry) in today_rankings.iter().enumerate() {\n- println!(\" {}. {} - {} points\", rank + 1, entry.player_id, entry.score);\n+ println!(\n+ \" {}. {} - {} points\",\n+ rank + 1,\n+ entry.player_id,\n+ entry.score\n+ );\n }\n- \n+\n // Show cross-game analysis is still easy\n println!(\"\\nšŸŽ® Multi-game player analysis for player1 on {}:\", today);\n- let cs2_player1_score = today_rankings.iter()\n+ let cs2_player1_score = today_rankings\n+ .iter()\n .find(|e| e.player_id == \"player1\")\n .map(|e| e.score);\n \n- let valorant_player1_score = valorant_today.to_vec()?.iter()\n+ let valorant_player1_score = valorant_today\n+ .to_vec()?\n+ .iter()\n .find(|e| e.player_id == \"player1\")\n .map(|e| e.score);\n \n- if let Some(score) = cs2_player1_score { println!(\" CS2 Score: {}\", score); }\n- if let Some(score) = valorant_player1_score { println!(\" Valorant Score: {}\", score); }\n- \n+ if let Some(score) = cs2_player1_score {\n+ println!(\" CS2 Score: {}\", score);\n+ }\n+ if let Some(score) = valorant_player1_score {\n+ println!(\" Valorant Score: {}\", score);\n+ }\n+\n // Showcase the power of the nested structure for stats\n // For nested collections, we use the keys API instead of iter()\n println!(\"\\nšŸ“Š Dynamic Database Statistics (discovered games):\");\n- \n+\n // Note: For nested collections, we iterate over known keys or use a different approach\n // since the values (nested DurableMaps) cannot be directly deserialized\n let games = vec![\"cs2\", \"valorant\", \"tf2\"]; // In a real app, you might track these separately\n- \n+\n for game in games {\n let game_history = rankings.entry(game.to_string())?.or_default()?;\n let active_days = game_history.len()?;\n- \n+\n if active_days > 0 {\n // For demonstration, let's count entries from known days\n let mut total_entries = 0;\n let days = [today, yesterday, last_week];\n- \n+\n for day in days {\n if let Ok(daily_rankings) = game_history.entry(day) {\n if let Ok(rankings_vec) = daily_rankings.or_default() {\n@@ -161,14 +173,18 @@ fn main() -> Result<(), Box> {\n }\n }\n }\n- \n+\n if total_entries > 0 {\n- println!(\" • {}: {} total entries across {} active day(s)\", \n- game.to_uppercase(), total_entries, active_days);\n+ println!(\n+ \" • {}: {} total entries across {} active day(s)\",\n+ game.to_uppercase(),\n+ total_entries,\n+ active_days\n+ );\n }\n }\n }\n- \n+\n println!(\"\\n✨ Key Benefits of This Rewritten Approach:\");\n println!(\" • No more manual key construction (`format!`) - the core goal is met!\");\n println!(\" • The code's structure now mirrors the mental model: `rankings[game][day]`\");\n@@ -176,4 +192,4 @@ fn main() -> Result<(), Box> {\n println!(\" • Demonstrates the full power of the `DurableCollection` and `entry()` design.\");\n \n Ok(())\n-}\n\\ No newline at end of file\n+}\ndiff --git a/durable/examples/simple_ranking.rs b/durable/examples/simple_ranking.rs\nindex 3cc873c41f3d93c7fa9e6e2dfc80e815f456b1f9..3c35c62674d7199f9b9864192fbbacb6ac0621a1 100644\n--- a/durable/examples/simple_ranking.rs\n+++ b/durable/examples/simple_ranking.rs\n@@ -4,65 +4,68 @@ fn main() -> Result<(), Box> {\n println!(\"šŸ† Simple Game Ranking Example\");\n println!(\"Demonstrating the pattern from docs/motivation.md\");\n println!(\"===============================================\");\n- \n+\n let db = Db::open(\"simple_ranking_db\")?;\n- \n+\n // This is the exact pattern from the docs: Game Mode → List of (Player, Score)\n // For simplicity, we're showing one day's data per game mode\n- let rankings: DurableMap> = DurableMap::new_nested(&db, \"rankings\");\n- \n+ let rankings: DurableMap> =\n+ DurableMap::new_nested(&db, \"rankings\");\n+\n println!(\"\\nšŸ“Š Adding TF2 rankings (from the docs example)...\");\n- \n+\n // This is the exact code pattern shown in docs/motivation.md\n let mut tf2_rankings = rankings.entry(\"tf2\".to_string())?.or_default()?;\n tf2_rankings.push((\"player1\".to_string(), 1500))?;\n tf2_rankings.push((\"player2\".to_string(), 1400))?;\n tf2_rankings.push((\"player3\".to_string(), 1300))?;\n- \n+\n println!(\"āœ… Added TF2 rankings using the docs pattern!\");\n- \n+\n // Add some other games for comparison\n println!(\"\\nšŸ“Š Adding CS2 rankings...\");\n let mut cs2_rankings = rankings.entry(\"cs2\".to_string())?.or_default()?;\n cs2_rankings.push((\"pro_player\".to_string(), 2500))?;\n cs2_rankings.push((\"skilled_gamer\".to_string(), 2200))?;\n- \n+\n println!(\"āœ… Added CS2 rankings!\");\n- \n+\n // Now read back the data\n println!(\"\\nšŸ† Current TF2 Leaderboard:\");\n let tf2_data = rankings.entry(\"tf2\".to_string())?.or_default()?;\n- \n+\n // Convert to vec and sort for display\n let mut tf2_leaderboard = tf2_data.to_vec()?;\n tf2_leaderboard.sort_by(|a, b| b.1.cmp(&a.1)); // Sort by score descending\n- \n+\n for (rank, (player, score)) in tf2_leaderboard.iter().enumerate() {\n println!(\" {}. {} - {} points\", rank + 1, player, score);\n }\n- \n+\n println!(\"\\nšŸ† Current CS2 Leaderboard:\");\n let cs2_data = rankings.entry(\"cs2\".to_string())?.or_default()?;\n- \n+\n let mut cs2_leaderboard = cs2_data.to_vec()?;\n cs2_leaderboard.sort_by(|a, b| b.1.cmp(&a.1));\n- \n+\n for (rank, (player, score)) in cs2_leaderboard.iter().enumerate() {\n println!(\" {}. {} - {} points\", rank + 1, player, score);\n }\n- \n+\n println!(\"\\nšŸ“ˆ Database Statistics:\");\n println!(\" TF2 has {} players\", tf2_data.len()?);\n println!(\" CS2 has {} players\", cs2_data.len()?);\n- \n+\n println!(\"\\n✨ This demonstrates the exact pattern from docs/motivation.md:\");\n println!(\" rankings.entry(game_mode)?.or_default()?.push((player, score))?;\");\n println!(\" \");\n println!(\" Compare this to the manual key construction required with raw KV stores:\");\n- println!(\" let key = format!(\\\"leaderboard:{{}}:{{}}:player:{{}}\\\", game_mode, day, player_id);\");\n+ println!(\n+ \" let key = format!(\\\"leaderboard:{{}}:{{}}:player:{{}}\\\", game_mode, day, player_id);\"\n+ );\n println!(\" db.insert(key.as_bytes(), score.to_le_bytes())?;\");\n println!(\" \");\n println!(\" Durable provides the ergonomic, type-safe abstraction over RocksDB!\");\n- \n+\n Ok(())\n-}\n\\ No newline at end of file\n+}\ndiff --git a/durable/examples/streaming_demo.rs b/durable/examples/streaming_demo.rs\nindex 3a74a5318675f94f89aaf01562a5b28f8a1b664a..437a37e3f820a45ad738df68ef1928d20846a028 100644\n--- a/durable/examples/streaming_demo.rs\n+++ b/durable/examples/streaming_demo.rs\n@@ -2,44 +2,44 @@ use durable::{Db, DurableMap, DurableVec};\n \n fn main() -> Result<(), Box> {\n let db = Db::open(\"streaming_demo_db\")?;\n- \n+\n // Create collections with a moderate amount of data\n let mut map = DurableMap::::new(&db, \"large_map\")?;\n let mut vec = DurableVec::::new(&db, \"large_vec\")?;\n- \n+\n println!(\"šŸš€ Streaming Iterator Demo\\n\");\n- \n+\n // Add 1000 entries to demonstrate streaming\n println!(\"Adding 1000 entries to map and vec...\");\n for i in 0..1000 {\n map.insert(i, format!(\"Value {}\", i))?;\n vec.push(format!(\"Item {}\", i))?;\n }\n- \n+\n println!(\"\\nšŸ“Š Collection sizes:\");\n println!(\" Map entries: {}\", map.len()?);\n println!(\" Vec elements: {}\", vec.len()?);\n- \n+\n // Demonstrate streaming iteration - memory efficient\n println!(\"\\n✨ Streaming iteration (memory efficient):\");\n- \n+\n // Count items without loading into memory\n let map_count = map.iter().count();\n- println!(\" Counted {} map entries without loading into memory\", map_count);\n- \n+ println!(\n+ \" Counted {} map entries without loading into memory\",\n+ map_count\n+ );\n+\n // Find specific items efficiently\n let target = 500;\n- let found = map.iter()\n- .find(|item| {\n- item.as_ref()\n- .map(|(k, _)| *k == target)\n- .unwrap_or(false)\n- });\n- \n+ let found = map\n+ .iter()\n+ .find(|item| item.as_ref().map(|(k, _)| *k == target).unwrap_or(false));\n+\n if let Some(Ok((k, v))) = found {\n println!(\" Found key {} with value '{}' via streaming\", k, v);\n }\n- \n+\n // Process only what we need\n println!(\"\\nšŸŽÆ Processing first 10 items only:\");\n for (i, item) in vec.iter()?.take(10).enumerate() {\n@@ -48,34 +48,31 @@ fn main() -> Result<(), Box> {\n Err(e) => println!(\" [{}] Error: {:?}\", i, e),\n }\n }\n- \n+\n // Filter and process without loading all data\n println!(\"\\nšŸ” Filtering even keys without loading all data:\");\n- let even_count = map.keys()\n- .filter(|item| {\n- item.as_ref()\n- .map(|k| k % 2 == 0)\n- .unwrap_or(false)\n- })\n+ let even_count = map\n+ .keys()\n+ .filter(|item| item.as_ref().map(|k| k % 2 == 0).unwrap_or(false))\n .count();\n println!(\" Found {} even keys\", even_count);\n- \n+\n // Compare with loading everything into memory\n println!(\"\\nāš ļø Loading all data into memory (less efficient for large collections):\");\n let all_values = map.values_vec()?;\n println!(\" Loaded {} values into a Vec\", all_values.len());\n- \n+\n println!(\"\\nāœ… Streaming iterators provide:\");\n println!(\" • Constant memory usage regardless of collection size\");\n println!(\" • Ability to process data larger than RAM\");\n println!(\" • Early termination when finding specific items\");\n println!(\" • Efficient filtering and transformation\");\n- \n+\n // Clean up\n drop(map);\n drop(vec);\n drop(db);\n std::fs::remove_dir_all(\"streaming_demo_db\").ok();\n- \n+\n Ok(())\n-} \n\\ No newline at end of file\n+}\ndiff --git a/durable/examples/vec_example.rs b/durable/examples/vec_example.rs\nindex 07d394b5f3964ea1942a645c2f008e9e3c37d6d8..7576bdb0c14fc57a5cc52a9a93fd9bf59ffa03af 100644\n--- a/durable/examples/vec_example.rs\n+++ b/durable/examples/vec_example.rs\n@@ -1,5 +1,5 @@\n use durable::{Db, DurableVec};\n-use serde::{Serialize, Deserialize};\n+use serde::{Deserialize, Serialize};\n \n #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]\n struct Task {\n@@ -11,56 +11,57 @@ struct Task {\n fn main() -> Result<(), Box> {\n // Open or create a database\n let db = Db::open(\"example_db\")?;\n- \n+\n // Create a persistent vector of tasks\n let mut tasks = DurableVec::::new(&db, \"tasks\")?;\n- \n+\n // Add some tasks\n tasks.push(Task {\n id: 1,\n title: \"Build Durable library\".to_string(),\n completed: true,\n })?;\n- \n+\n tasks.push(Task {\n id: 2,\n title: \"Write comprehensive tests\".to_string(),\n completed: true,\n })?;\n- \n+\n tasks.push(Task {\n id: 3,\n title: \"Create documentation\".to_string(),\n completed: false,\n })?;\n- \n+\n println!(\"Total tasks: {}\", tasks.len()?);\n- \n+\n // Iterate through all tasks\n println!(\"\\nAll tasks:\");\n for (i, task) in tasks.iter()?.enumerate() {\n let task = task?;\n- println!(\" [{}] {} - {}\", \n- i, \n- task.title, \n+ println!(\n+ \" [{}] {} - {}\",\n+ i,\n+ task.title,\n if task.completed { \"āœ“\" } else { \"ā—‹\" }\n );\n }\n- \n+\n // Get a specific task\n if let Some(task) = tasks.get(1)? {\n println!(\"\\nTask at index 1: {:?}\", task);\n }\n- \n+\n // Mark the last task as completed\n if let Some(mut last_task) = tasks.pop()? {\n println!(\"\\nCompleting task: {}\", last_task.title);\n last_task.completed = true;\n tasks.push(last_task)?;\n }\n- \n+\n // The data persists even after the program exits!\n println!(\"\\nData has been persisted to disk.\");\n- \n+\n Ok(())\n-} \n\\ No newline at end of file\n+}\ndiff --git a/durable/src/lib.rs b/durable/src/lib.rs\nindex 8c46d49e27750832f19368e8f4e4a6f58ef287bc..7bfdbf20287f8e48322a99e9f935c7f4b63c4639 100644\n--- a/durable/src/lib.rs\n+++ b/durable/src/lib.rs\n@@ -1,30 +1,30 @@\n //! Durable - RocksDB-backed persistent data structures for Rust\n \n+use rocksdb::{Options, WriteBatch, DB as RocksDB};\n use std::path::Path;\n use std::sync::Arc;\n-use rocksdb::{DB as RocksDB, Options, WriteBatch};\n use thiserror::Error;\n \n-pub mod vec;\n pub mod map;\n-pub use vec::DurableVec;\n+pub mod vec;\n pub use map::DurableMap;\n+pub use vec::DurableVec;\n \n /// Error types for Durable operations\n #[derive(Error, Debug)]\n pub enum DurableError {\n #[error(\"RocksDB error: {0}\")]\n RocksDB(#[from] rocksdb::Error),\n- \n+\n #[error(\"Serialization error: {0}\")]\n Serialization(#[from] bincode::Error),\n- \n+\n #[error(\"Key not found\")]\n KeyNotFound,\n- \n+\n #[error(\"Collection not found: {0}\")]\n CollectionNotFound(String),\n- \n+\n #[error(\"Data corruption: {0}\")]\n Corruption(String),\n }\n@@ -35,7 +35,7 @@ pub type Result = std::result::Result;\n pub trait DurableCollection {\n /// Creates a new instance of the collection from a database handle\n /// and a pre-determined, unique key prefix.\n- /// \n+ ///\n /// This is the key method that allows `DurableMap` to instantiate\n /// a nested collection handle.\n fn from_prefix(db: Db, prefix: Vec) -> Self;\n@@ -53,13 +53,13 @@ impl Db {\n let mut opts = Options::default();\n opts.create_if_missing(true);\n opts.create_missing_column_families(true);\n- \n+\n let db = RocksDB::open(&opts, path)?;\n- Ok(Db { \n+ Ok(Db {\n inner: Arc::new(db),\n })\n }\n- \n+\n /// Create a new write batch for atomic operations\n pub fn batch(&self) -> Batch {\n Batch {\n@@ -67,41 +67,44 @@ impl Db {\n inner: WriteBatch::default(),\n }\n }\n- \n+\n /// Get the underlying RocksDB handle (for advanced usage)\n pub(crate) fn rocks(&self) -> &RocksDB {\n &self.inner\n }\n- \n+\n /// Get a new unique collection ID for nested collections\n pub fn new_collection_id(&self) -> Result {\n let key = b\"__global_meta:next_collection_id\";\n- \n+\n // Get current value\n let current_bytes = self.rocks().get(key)?;\n let current_id = match current_bytes {\n Some(bytes) => {\n if bytes.len() != 8 {\n- return Err(DurableError::Corruption(\"Invalid collection ID bytes size\".into()));\n+ return Err(DurableError::Corruption(\n+ \"Invalid collection ID bytes size\".into(),\n+ ));\n }\n- let id_bytes: [u8; 8] = bytes[..8].try_into()\n+ let id_bytes: [u8; 8] = bytes[..8]\n+ .try_into()\n .map_err(|_| DurableError::Corruption(\"Invalid collection ID bytes\".into()))?;\n u64::from_le_bytes(id_bytes)\n }\n None => 0,\n };\n- \n+\n let next_id = current_id + 1;\n- \n+\n // Try to atomically update - use compare-and-swap semantics\n let mut batch = WriteBatch::default();\n batch.put(key, &next_id.to_le_bytes());\n- \n+\n // For now, just write it directly. In a real implementation,\n // we'd want proper compare-and-swap to handle concurrent access\n self.rocks().write(batch)?;\n self.rocks().flush_wal(true)?;\n- \n+\n Ok(current_id)\n }\n }\n@@ -129,5 +132,4 @@ impl Batch {\n self.db.rocks().flush_wal(true)?;\n Ok(())\n }\n- \n }\ndiff --git a/durable/src/map.rs b/durable/src/map.rs\nindex d3cc39bfede02f66532e4055299acdbffb8f6280..f7fdf224f52e791ec1204668ece9413035b4bfce 100644\n--- a/durable/src/map.rs\n+++ b/durable/src/map.rs\n@@ -1,6 +1,6 @@\n-use crate::{Batch, Db, Result, DurableError, DurableCollection};\n-use rocksdb::{IteratorMode, WriteBatch, Direction};\n-use serde::{Serialize, Deserialize};\n+use crate::{Batch, Db, DurableCollection, DurableError, Result};\n+use rocksdb::{Direction, IteratorMode, WriteBatch};\n+use serde::{Deserialize, Serialize};\n use std::marker::PhantomData;\n \n /// A persistent map backed by RocksDB\n@@ -10,78 +10,78 @@ pub struct DurableMap {\n _phantom: PhantomData<(K, V)>,\n }\n \n-impl DurableMap \n-where \n+impl DurableMap\n+where\n K: Serialize + for<'de> Deserialize<'de>,\n V: Serialize + for<'de> Deserialize<'de>,\n {\n /// Create a new DurableMap with the given name\n pub fn new(db: &Db, name: &str) -> Result {\n let prefix = format!(\"map:{}\", name).into_bytes();\n- \n+\n Ok(DurableMap {\n db: db.clone(),\n prefix,\n _phantom: PhantomData,\n })\n }\n- \n+\n /// Insert a key-value pair into the map\n pub fn insert(&mut self, key: K, value: V) -> Result> {\n let key_bytes = bincode::serialize(&key)?;\n let value_bytes = bincode::serialize(&value)?;\n- \n+\n // Get the old value if it exists\n let old_value = self.get(&key)?;\n- \n+\n let mut batch = WriteBatch::default();\n- \n+\n // Write the new value\n let db_key = self.entry_key(&key_bytes);\n batch.put(&db_key, &value_bytes);\n- \n+\n // Update length if this is a new key\n if old_value.is_none() {\n let new_len = self.len()? + 1;\n let len_key = self.meta_key(\"len\");\n batch.put(&len_key, &(new_len as u64).to_le_bytes());\n }\n- \n+\n // Commit atomically\n self.db.rocks().write(batch)?;\n self.db.rocks().flush_wal(true)?;\n- \n+\n Ok(old_value)\n }\n- \n+\n /// Put a key-value pair into the map without returning the old value\n- /// \n+ ///\n /// This is more efficient than `insert` when you don't need the old value,\n /// as it only checks for key existence without deserializing the value.\n pub fn put(&mut self, key: K, value: V) -> Result<()> {\n let key_bytes = bincode::serialize(&key)?;\n let value_bytes = bincode::serialize(&value)?;\n let db_key = self.entry_key(&key_bytes);\n- \n+\n let mut batch = WriteBatch::default();\n- \n+\n // Check if this is a new key (without deserializing the value)\n let is_new = self.db.rocks().get_pinned(&db_key)?.is_none();\n- \n+\n // Write the new value\n batch.put(&db_key, &value_bytes);\n- \n+\n // Update length if this is a new key\n if is_new {\n let new_len = self.len()? + 1;\n let len_key = self.meta_key(\"len\");\n batch.put(&len_key, &(new_len as u64).to_le_bytes());\n }\n- \n+\n // Commit atomically\n self.db.rocks().write(batch)?;\n self.db.rocks().flush_wal(true)?;\n- \n+\n Ok(())\n }\n \n@@ -105,12 +105,12 @@ where\n \n Ok(())\n }\n- \n+\n /// Get a value by key\n pub fn get(&self, key: &K) -> Result> {\n let key_bytes = bincode::serialize(key)?;\n let db_key = self.entry_key(&key_bytes);\n- \n+\n match self.db.rocks().get(&db_key)? {\n Some(bytes) => {\n let value = bincode::deserialize(&bytes)?;\n@@ -119,20 +119,20 @@ where\n None => Ok(None),\n }\n }\n- \n+\n /// Check if a key exists in the map\n pub fn contains_key(&self, key: &K) -> Result {\n let key_bytes = bincode::serialize(key)?;\n let db_key = self.entry_key(&key_bytes);\n- \n+\n Ok(self.db.rocks().get(&db_key)?.is_some())\n }\n- \n+\n /// Remove a key-value pair from the map\n pub fn remove(&mut self, key: &K) -> Result> {\n let key_bytes = bincode::serialize(key)?;\n let db_key = self.entry_key(&key_bytes);\n- \n+\n // Get the old value\n let old_value = match self.db.rocks().get(&db_key)? {\n Some(bytes) => {\n@@ -141,36 +141,37 @@ where\n }\n None => None,\n };\n- \n+\n // Delete the key if it existed and update length\n if old_value.is_some() {\n let mut batch = WriteBatch::default();\n- \n+\n // Delete the entry\n batch.delete(&db_key);\n- \n+\n // Update length\n let new_len = self.len()? - 1;\n let len_key = self.meta_key(\"len\");\n batch.put(&len_key, &(new_len as u64).to_le_bytes());\n- \n+\n // Commit atomically\n self.db.rocks().write(batch)?;\n self.db.rocks().flush_wal(true)?;\n }\n- \n+\n Ok(old_value)\n }\n- \n \n- \n /// Clear all entries from the map\n pub fn clear(&mut self) -> Result<()> {\n let prefix = self.entry_prefix();\n let mut batch = WriteBatch::default();\n- \n+\n // Collect all keys to delete\n- let iter = self.db.rocks().iterator(IteratorMode::From(&prefix, Direction::Forward));\n+ let iter = self\n+ .db\n+ .rocks()\n+ .iterator(IteratorMode::From(&prefix, Direction::Forward));\n for item in iter {\n let (key, _) = item?;\n if !key.starts_with(&prefix) {\n@@ -178,32 +179,35 @@ where\n }\n batch.delete(&key);\n }\n- \n+\n // Reset length to 0\n let len_key = self.meta_key(\"len\");\n batch.delete(&len_key);\n- \n+\n // Commit atomically\n self.db.rocks().write(batch)?;\n self.db.rocks().flush_wal(true)?;\n- \n+\n Ok(())\n }\n- \n+\n /// Iterate over all key-value pairs using a streaming iterator\n pub fn iter(&self) -> MapIterator<'_, K, V> {\n let prefix = self.entry_prefix();\n- let iter = self.db.rocks().iterator(IteratorMode::From(&prefix, Direction::Forward));\n- \n+ let iter = self\n+ .db\n+ .rocks()\n+ .iterator(IteratorMode::From(&prefix, Direction::Forward));\n+\n MapIterator {\n inner: iter,\n prefix,\n _phantom: PhantomData,\n }\n }\n- \n+\n /// Load all key-value pairs into a Vec\n- /// \n+ ///\n /// Note: This loads the entire collection into memory. For large collections,\n /// prefer using `iter()` which streams elements.\n pub fn to_vec(&self) -> Result> {\n@@ -213,21 +217,24 @@ where\n }\n Ok(result)\n }\n- \n+\n /// Iterate over all keys using a streaming iterator\n pub fn keys(&self) -> KeyIterator<'_, K, V> {\n let prefix = self.entry_prefix();\n- let iter = self.db.rocks().iterator(IteratorMode::From(&prefix, Direction::Forward));\n- \n+ let iter = self\n+ .db\n+ .rocks()\n+ .iterator(IteratorMode::From(&prefix, Direction::Forward));\n+\n KeyIterator {\n inner: iter,\n prefix,\n _phantom: PhantomData,\n }\n }\n- \n+\n /// Load all keys into a Vec\n- /// \n+ ///\n /// Note: This loads all keys into memory. For large collections,\n /// prefer using `keys()` which streams elements.\n pub fn keys_vec(&self) -> Result> {\n@@ -237,21 +244,24 @@ where\n }\n Ok(result)\n }\n- \n+\n /// Iterate over all values using a streaming iterator\n pub fn values(&self) -> ValueIterator<'_, K, V> {\n let prefix = self.entry_prefix();\n- let iter = self.db.rocks().iterator(IteratorMode::From(&prefix, Direction::Forward));\n- \n+ let iter = self\n+ .db\n+ .rocks()\n+ .iterator(IteratorMode::From(&prefix, Direction::Forward));\n+\n ValueIterator {\n inner: iter,\n prefix,\n _phantom: PhantomData,\n }\n }\n- \n+\n /// Load all values into a Vec\n- /// \n+ ///\n /// Note: This loads all values into memory. For large collections,\n /// prefer using `values()` which streams elements.\n pub fn values_vec(&self) -> Result> {\n@@ -261,54 +271,52 @@ where\n }\n Ok(result)\n }\n- \n+\n /// Insert multiple key-value pairs in a single batch\n pub fn extend(&mut self, iter: I) -> Result<()>\n where\n- I: IntoIterator\n+ I: IntoIterator,\n {\n let mut batch = WriteBatch::default();\n let current_len = self.len()?;\n let mut new_entries = 0;\n- \n+\n for (key, value) in iter {\n let key_bytes = bincode::serialize(&key)?;\n let value_bytes = bincode::serialize(&value)?;\n let db_key = self.entry_key(&key_bytes);\n- \n+\n // Check if this is a new key\n if !self.contains_key(&key)? {\n new_entries += 1;\n }\n- \n+\n batch.put(&db_key, &value_bytes);\n }\n- \n+\n // Update length if we added new entries\n if new_entries > 0 {\n let new_len = current_len + new_entries;\n let len_key = self.meta_key(\"len\");\n batch.put(&len_key, &(new_len as u64).to_le_bytes());\n }\n- \n+\n // Commit atomically\n self.db.rocks().write(batch)?;\n self.db.rocks().flush_wal(true)?;\n- \n+\n Ok(())\n }\n- \n \n- \n // Helper methods\n- \n+\n fn entry_key(&self, key_bytes: &[u8]) -> Vec {\n let mut db_key = self.prefix.clone();\n db_key.extend_from_slice(b\":entry:\");\n db_key.extend_from_slice(key_bytes);\n db_key\n }\n- \n+\n fn entry_prefix(&self) -> Vec {\n let mut prefix = self.prefix.clone();\n prefix.extend_from_slice(b\":entry:\");\n@@ -321,14 +329,14 @@ impl DurableMap {\n /// Create a new DurableMap for nested collections (no serialization constraints)\n pub fn new_nested(db: &Db, name: &str) -> Self {\n let prefix = format!(\"map:{}\", name).into_bytes();\n- \n+\n DurableMap {\n db: db.clone(),\n prefix,\n _phantom: PhantomData,\n }\n }\n- \n+\n /// Create a new DurableMap from a prefix (used for nested collections)\n pub fn from_prefix(db: Db, prefix: Vec) -> Self {\n Self {\n@@ -337,7 +345,7 @@ impl DurableMap {\n _phantom: PhantomData,\n }\n }\n- \n+\n /// Get the number of entries in the map (unconstrained version for nested collections)\n pub fn len(&self) -> Result {\n let key = self.meta_key(\"len\");\n@@ -346,14 +354,15 @@ impl DurableMap {\n if bytes.len() != 8 {\n return Err(DurableError::Corruption(\"Invalid length bytes size\".into()));\n }\n- let len_bytes: [u8; 8] = bytes[..8].try_into()\n+ let len_bytes: [u8; 8] = bytes[..8]\n+ .try_into()\n .map_err(|_| DurableError::Corruption(\"Invalid length bytes\".into()))?;\n Ok(u64::from_le_bytes(len_bytes) as usize)\n }\n None => Ok(0),\n }\n }\n- \n+\n /// Check if the map is empty (unconstrained version for nested collections)\n pub fn is_empty(&self) -> Result {\n Ok(self.len()? == 0)\n@@ -366,7 +375,7 @@ impl DurableMap {\n db_key.extend_from_slice(key_bytes);\n db_key\n }\n- \n+\n fn meta_key(&self, meta_type: &str) -> Vec {\n let mut key = self.prefix.clone();\n key.extend_from_slice(b\":__meta:\");\n@@ -411,7 +420,7 @@ pub struct OccupiedEntry<'a, K, V> {\n value_marker: Vec, // The bytes read from RocksDB, e.g., [0x02, ...]\n }\n \n-impl<'a, K, V> OccupiedEntry<'a, K, V> \n+impl<'a, K, V> OccupiedEntry<'a, K, V>\n where\n V: DurableCollection,\n {\n@@ -421,8 +430,9 @@ where\n if self.value_marker.len() != 9 || self.value_marker[0] != 0x02 {\n return Err(DurableError::Corruption(\"Invalid collection marker\".into()));\n }\n- \n- let col_id_bytes: [u8; 8] = self.value_marker[1..9].try_into()\n+\n+ let col_id_bytes: [u8; 8] = self.value_marker[1..9]\n+ .try_into()\n .map_err(|_| DurableError::Corruption(\"Invalid collection ID\".into()))?;\n let col_id = u64::from_le_bytes(col_id_bytes);\n \n@@ -433,7 +443,7 @@ where\n // 3. Create the collection handle using the trait method\n Ok(V::from_prefix(self.map.db.clone(), child_prefix))\n }\n- \n+\n /// Gets a handle to the existing nested collection (same as get but consumes self)\n pub fn or_default(self) -> Result {\n self.get()\n@@ -446,7 +456,7 @@ pub struct VacantEntry<'a, K, V> {\n key: K, // The original key from the user\n }\n \n-impl<'a, K, V> VacantEntry<'a, K, V> \n+impl<'a, K, V> VacantEntry<'a, K, V>\n where\n K: Serialize,\n V: DurableCollection,\n@@ -518,7 +528,7 @@ where\n V: for<'de> Deserialize<'de>,\n {\n type Item = Result<(K, V)>;\n- \n+\n fn next(&mut self) -> Option {\n match self.inner.next() {\n Some(Ok((db_key, value_bytes))) => {\n@@ -526,13 +536,16 @@ where\n if !db_key.starts_with(&self.prefix) {\n return None;\n }\n- \n+\n // Extract the key part (skip prefix)\n let key_start = self.prefix.len();\n let key_bytes = &db_key[key_start..];\n- \n+\n // Deserialize key and value\n- match (bincode::deserialize(key_bytes), bincode::deserialize(&value_bytes)) {\n+ match (\n+ bincode::deserialize(key_bytes),\n+ bincode::deserialize(&value_bytes),\n+ ) {\n (Ok(key), Ok(value)) => Some(Ok((key, value))),\n (Err(e), _) | (_, Err(e)) => Some(Err(e.into())),\n }\n@@ -555,7 +568,7 @@ where\n K: for<'de> Deserialize<'de>,\n {\n type Item = Result;\n- \n+\n fn next(&mut self) -> Option {\n match self.inner.next() {\n Some(Ok((db_key, _))) => {\n@@ -563,11 +576,11 @@ where\n if !db_key.starts_with(&self.prefix) {\n return None;\n }\n- \n+\n // Extract the key part (skip prefix)\n let key_start = self.prefix.len();\n let key_bytes = &db_key[key_start..];\n- \n+\n // Deserialize key\n match bincode::deserialize(key_bytes) {\n Ok(key) => Some(Ok(key)),\n@@ -592,7 +605,7 @@ where\n V: for<'de> Deserialize<'de>,\n {\n type Item = Result;\n- \n+\n fn next(&mut self) -> Option {\n match self.inner.next() {\n Some(Ok((db_key, value_bytes))) => {\n@@ -600,7 +613,7 @@ where\n if !db_key.starts_with(&self.prefix) {\n return None;\n }\n- \n+\n // Deserialize value\n match bincode::deserialize(&value_bytes) {\n Ok(value) => Some(Ok(value)),\n@@ -616,214 +629,232 @@ where\n #[cfg(test)]\n mod tests {\n use super::*;\n- use tempfile::TempDir;\n use std::collections::HashMap;\n- \n+ use tempfile::TempDir;\n+\n fn setup_test_db() -> (TempDir, Db) {\n let temp_dir = TempDir::new().unwrap();\n let db = Db::open(temp_dir.path()).unwrap();\n (temp_dir, db)\n }\n- \n+\n #[test]\n fn test_insert_and_get() {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"test_map\").unwrap();\n- \n+\n // Insert some values\n assert_eq!(map.insert(\"one\".to_string(), 1).unwrap(), None);\n assert_eq!(map.insert(\"two\".to_string(), 2).unwrap(), None);\n assert_eq!(map.insert(\"three\".to_string(), 3).unwrap(), None);\n- \n+\n // Get values\n assert_eq!(map.get(&\"one\".to_string()).unwrap(), Some(1));\n assert_eq!(map.get(&\"two\".to_string()).unwrap(), Some(2));\n assert_eq!(map.get(&\"three\".to_string()).unwrap(), Some(3));\n assert_eq!(map.get(&\"four\".to_string()).unwrap(), None);\n- \n+\n // Update existing value\n assert_eq!(map.insert(\"two\".to_string(), 22).unwrap(), Some(2));\n assert_eq!(map.get(&\"two\".to_string()).unwrap(), Some(22));\n }\n- \n+\n #[test]\n fn test_remove() {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"remove_map\").unwrap();\n- \n+\n // Insert and remove\n map.insert(\"key\".to_string(), \"value\".to_string()).unwrap();\n- assert_eq!(map.remove(&\"key\".to_string()).unwrap(), Some(\"value\".to_string()));\n+ assert_eq!(\n+ map.remove(&\"key\".to_string()).unwrap(),\n+ Some(\"value\".to_string())\n+ );\n assert_eq!(map.remove(&\"key\".to_string()).unwrap(), None);\n assert_eq!(map.get(&\"key\".to_string()).unwrap(), None);\n }\n- \n+\n #[test]\n fn test_contains_key() {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"contains_map\").unwrap();\n- \n+\n map.insert(42, \"answer\".to_string()).unwrap();\n- \n+\n assert!(map.contains_key(&42).unwrap());\n assert!(!map.contains_key(&43).unwrap());\n }\n- \n+\n #[test]\n fn test_len_and_clear() {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"len_map\").unwrap();\n- \n+\n // Empty map\n assert_eq!(map.len().unwrap(), 0);\n assert!(map.is_empty().unwrap());\n- \n+\n // Add items\n for i in 0..10 {\n map.insert(i, i * 2).unwrap();\n }\n assert_eq!(map.len().unwrap(), 10);\n assert!(!map.is_empty().unwrap());\n- \n+\n // Clear\n map.clear().unwrap();\n assert_eq!(map.len().unwrap(), 0);\n assert!(map.is_empty().unwrap());\n }\n- \n+\n #[test]\n fn test_persistence() {\n let (temp_dir, db) = setup_test_db();\n- \n+\n // Create and populate map\n {\n let mut map = DurableMap::>::new(&db, \"persist_map\").unwrap();\n- map.insert(\"binary\".to_string(), vec![1, 2, 3, 4, 5]).unwrap();\n+ map.insert(\"binary\".to_string(), vec![1, 2, 3, 4, 5])\n+ .unwrap();\n map.insert(\"data\".to_string(), vec![10, 20, 30]).unwrap();\n }\n- \n+\n // Drop the database\n drop(db);\n- \n+\n // Reopen and verify data persists\n {\n let db = Db::open(temp_dir.path()).unwrap();\n let map = DurableMap::>::new(&db, \"persist_map\").unwrap();\n- \n- assert_eq!(map.get(&\"binary\".to_string()).unwrap(), Some(vec![1, 2, 3, 4, 5]));\n- assert_eq!(map.get(&\"data\".to_string()).unwrap(), Some(vec![10, 20, 30]));\n+\n+ assert_eq!(\n+ map.get(&\"binary\".to_string()).unwrap(),\n+ Some(vec![1, 2, 3, 4, 5])\n+ );\n+ assert_eq!(\n+ map.get(&\"data\".to_string()).unwrap(),\n+ Some(vec![10, 20, 30])\n+ );\n assert_eq!(map.len().unwrap(), 2);\n }\n }\n- \n+\n #[test]\n fn test_iteration() {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"iter_map\").unwrap();\n- \n+\n // Insert data\n let data = vec![\n (\"apple\".to_string(), 1),\n (\"banana\".to_string(), 2),\n (\"cherry\".to_string(), 3),\n ];\n- \n+\n for (k, v) in &data {\n map.insert(k.clone(), *v).unwrap();\n }\n- \n+\n // Test iter()\n let mut items = map.to_vec().unwrap();\n items.sort_by_key(|(k, _)| k.clone());\n assert_eq!(items, data);\n- \n+\n // Test keys()\n let mut keys = map.keys_vec().unwrap();\n keys.sort();\n assert_eq!(keys, vec![\"apple\", \"banana\", \"cherry\"]);\n- \n+\n // Test values()\n let mut values = map.values_vec().unwrap();\n values.sort();\n assert_eq!(values, vec![1, 2, 3]);\n }\n- \n+\n #[test]\n fn test_extend() {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"extend_map\").unwrap();\n- \n+\n // Extend from iterator\n let data: HashMap = vec![\n (1, \"one\".to_string()),\n (2, \"two\".to_string()),\n (3, \"three\".to_string()),\n- ].into_iter().collect();\n- \n+ ]\n+ .into_iter()\n+ .collect();\n+\n map.extend(data.clone()).unwrap();\n- \n+\n // Verify all items were inserted\n for (k, v) in data {\n assert_eq!(map.get(&k).unwrap(), Some(v));\n }\n assert_eq!(map.len().unwrap(), 3);\n }\n- \n+\n #[test]\n fn test_complex_keys() {\n- use serde::{Serialize, Deserialize};\n- \n+ use serde::{Deserialize, Serialize};\n+\n #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]\n struct ComplexKey {\n id: u64,\n name: String,\n }\n- \n+\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"complex_map\").unwrap();\n- \n- let key1 = ComplexKey { id: 1, name: \"first\".to_string() };\n- let key2 = ComplexKey { id: 2, name: \"second\".to_string() };\n- \n+\n+ let key1 = ComplexKey {\n+ id: 1,\n+ name: \"first\".to_string(),\n+ };\n+ let key2 = ComplexKey {\n+ id: 2,\n+ name: \"second\".to_string(),\n+ };\n+\n map.insert(key1.clone(), \"value1\".to_string()).unwrap();\n map.insert(key2.clone(), \"value2\".to_string()).unwrap();\n- \n+\n assert_eq!(map.get(&key1).unwrap(), Some(\"value1\".to_string()));\n assert_eq!(map.get(&key2).unwrap(), Some(\"value2\".to_string()));\n }\n- \n+\n #[test]\n fn test_multiple_maps_same_db() {\n let (_temp, db) = setup_test_db();\n- \n+\n let mut map1 = DurableMap::::new(&db, \"map1\").unwrap();\n let mut map2 = DurableMap::::new(&db, \"map2\").unwrap();\n- \n+\n // Insert different data\n map1.insert(\"shared_key\".to_string(), 100).unwrap();\n map2.insert(\"shared_key\".to_string(), 200).unwrap();\n- \n+\n // Verify isolation\n assert_eq!(map1.get(&\"shared_key\".to_string()).unwrap(), Some(100));\n assert_eq!(map2.get(&\"shared_key\".to_string()).unwrap(), Some(200));\n }\n- \n+\n #[test]\n fn test_streaming_iterators() {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"stream_map\").unwrap();\n- \n+\n // Insert test data\n let data = vec![\n (\"alice\".to_string(), 100),\n (\"bob\".to_string(), 200),\n (\"charlie\".to_string(), 300),\n ];\n- \n+\n for (k, v) in &data {\n map.insert(k.clone(), *v).unwrap();\n }\n- \n+\n // Test streaming iteration\n let mut collected = Vec::new();\n for item in map.iter() {\n@@ -832,7 +863,7 @@ mod tests {\n }\n collected.sort_by_key(|(k, _)| k.clone());\n assert_eq!(collected, data);\n- \n+\n // Test keys iterator\n let mut keys = Vec::new();\n for key in map.keys() {\n@@ -840,7 +871,7 @@ mod tests {\n }\n keys.sort();\n assert_eq!(keys, vec![\"alice\", \"bob\", \"charlie\"]);\n- \n+\n // Test values iterator\n let mut values = Vec::new();\n for value in map.values() {\n@@ -848,48 +879,51 @@ mod tests {\n }\n values.sort();\n assert_eq!(values, vec![100, 200, 300]);\n- \n+\n // Test that iterators properly handle prefix boundaries\n let mut map2 = DurableMap::::new(&db, \"stream_map2\").unwrap();\n map2.insert(\"dave\".to_string(), 400).unwrap();\n- \n+\n // Each iterator should only see its own data\n let collected1: Vec<_> = map.iter().map(Result::unwrap).collect();\n let collected2: Vec<_> = map2.iter().map(Result::unwrap).collect();\n- \n+\n assert_eq!(collected1.len(), 3);\n assert_eq!(collected2.len(), 1);\n assert_eq!(collected2[0], (\"dave\".to_string(), 400));\n }\n- \n+\n #[test]\n fn test_metadata_length_tracking() {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"length_map\").unwrap();\n- \n+\n // Empty map\n assert_eq!(map.len().unwrap(), 0);\n assert!(map.is_empty().unwrap());\n- \n+\n // Insert operations should update length\n- map.insert(\"key1\".to_string(), \"value1\".to_string()).unwrap();\n+ map.insert(\"key1\".to_string(), \"value1\".to_string())\n+ .unwrap();\n assert_eq!(map.len().unwrap(), 1);\n- \n- map.insert(\"key2\".to_string(), \"value2\".to_string()).unwrap();\n+\n+ map.insert(\"key2\".to_string(), \"value2\".to_string())\n+ .unwrap();\n assert_eq!(map.len().unwrap(), 2);\n- \n+\n // Updating existing key should not change length\n- map.insert(\"key1\".to_string(), \"new_value1\".to_string()).unwrap();\n+ map.insert(\"key1\".to_string(), \"new_value1\".to_string())\n+ .unwrap();\n assert_eq!(map.len().unwrap(), 2);\n- \n+\n // Remove operations should update length\n map.remove(&\"key1\".to_string()).unwrap();\n assert_eq!(map.len().unwrap(), 1);\n- \n+\n // Removing non-existent key should not change length\n map.remove(&\"non_existent\".to_string()).unwrap();\n assert_eq!(map.len().unwrap(), 1);\n- \n+\n // Extend should update length correctly\n let data = vec![\n (\"key3\".to_string(), \"value3\".to_string()),\n@@ -898,7 +932,7 @@ mod tests {\n ];\n map.extend(data).unwrap();\n assert_eq!(map.len().unwrap(), 4); // key2 + 3 new keys\n- \n+\n // Extend with existing keys should only count new ones\n let mixed_data = vec![\n (\"key2\".to_string(), \"updated_value2\".to_string()), // existing\n@@ -906,39 +940,39 @@ mod tests {\n ];\n map.extend(mixed_data).unwrap();\n assert_eq!(map.len().unwrap(), 5); // only key6 was new\n- \n+\n // Clear should reset length to 0\n map.clear().unwrap();\n assert_eq!(map.len().unwrap(), 0);\n assert!(map.is_empty().unwrap());\n }\n- \n+\n #[test]\n fn test_put_method() {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"put_map\").unwrap();\n- \n+\n // Put new entries\n map.put(\"a\".to_string(), 1).unwrap();\n map.put(\"b\".to_string(), 2).unwrap();\n map.put(\"c\".to_string(), 3).unwrap();\n- \n+\n // Verify entries exist and length is correct\n assert_eq!(map.get(&\"a\".to_string()).unwrap(), Some(1));\n assert_eq!(map.get(&\"b\".to_string()).unwrap(), Some(2));\n assert_eq!(map.get(&\"c\".to_string()).unwrap(), Some(3));\n assert_eq!(map.len().unwrap(), 3);\n- \n+\n // Update existing entry with put\n map.put(\"b\".to_string(), 20).unwrap();\n assert_eq!(map.get(&\"b\".to_string()).unwrap(), Some(20));\n assert_eq!(map.len().unwrap(), 3); // Length should not change\n- \n+\n // Compare put vs insert performance characteristics\n // put() doesn't return old value but is more efficient\n map.put(\"d\".to_string(), 4).unwrap();\n assert_eq!(map.len().unwrap(), 4);\n- \n+\n // insert() returns old value\n let old = map.insert(\"d\".to_string(), 40).unwrap();\n assert_eq!(old, Some(4));\n@@ -950,145 +984,186 @@ mod tests {\n mod proptests {\n use super::*;\n use proptest::prelude::*;\n- use tempfile::TempDir;\n use std::collections::HashMap;\n- \n+ use tempfile::TempDir;\n+\n fn setup_test_db() -> (TempDir, Db) {\n let temp_dir = TempDir::new().unwrap();\n let db = Db::open(temp_dir.path()).unwrap();\n (temp_dir, db)\n }\n- \n+\n proptest! {\n #[test]\n fn prop_insert_get_consistency(data: HashMap) {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"prop_map\").unwrap();\n- \n+\n // Insert all pairs\n for (k, v) in &data {\n map.insert(k.clone(), *v).unwrap();\n }\n- \n+\n // Verify all can be retrieved\n for (k, v) in &data {\n prop_assert_eq!(map.get(k).unwrap(), Some(*v));\n }\n- \n+\n // Verify length\n prop_assert_eq!(map.len().unwrap(), data.len());\n }\n- \n+\n #[test]\n fn prop_remove_consistency(data: HashMap) {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"remove_map\").unwrap();\n- \n+\n // Insert all\n map.extend(data.clone()).unwrap();\n- \n+\n // Remove all and verify\n for (k, v) in data {\n prop_assert_eq!(map.remove(&k).unwrap(), Some(v));\n prop_assert_eq!(map.remove(&k).unwrap(), None);\n prop_assert!(!map.contains_key(&k).unwrap());\n }\n- \n+\n prop_assert!(map.is_empty().unwrap());\n }\n- \n+\n #[test]\n fn prop_clear_makes_empty(data: HashMap) {\n let (_temp, db) = setup_test_db();\n let mut map = DurableMap::::new(&db, \"clear_map\").unwrap();\n- \n+\n map.extend(data).unwrap();\n map.clear().unwrap();\n- \n+\n prop_assert_eq!(map.len().unwrap(), 0);\n prop_assert!(map.is_empty().unwrap());\n prop_assert_eq!(map.to_vec().unwrap(), vec![]);\n }\n }\n- \n+\n #[test]\n fn test_nested_collections() {\n use crate::DurableVec;\n- \n+\n let (_temp, db) = setup_test_db();\n- \n+\n // Create a map where values are DurableVec\n- let users_posts: DurableMap> = DurableMap::new_nested(&db, \"user_posts\");\n- \n+ let users_posts: DurableMap> =\n+ DurableMap::new_nested(&db, \"user_posts\");\n+\n // Test creating nested collections through the entry API\n- let mut alice_posts = users_posts.entry(\"alice\".to_string()).unwrap().or_default().unwrap();\n+ let mut alice_posts = users_posts\n+ .entry(\"alice\".to_string())\n+ .unwrap()\n+ .or_default()\n+ .unwrap();\n alice_posts.push(101).unwrap();\n alice_posts.push(102).unwrap();\n alice_posts.push(103).unwrap();\n- \n+\n // Test accessing the same collection again\n- let alice_posts_again = users_posts.entry(\"alice\".to_string()).unwrap().or_default().unwrap();\n+ let alice_posts_again = users_posts\n+ .entry(\"alice\".to_string())\n+ .unwrap()\n+ .or_default()\n+ .unwrap();\n assert_eq!(alice_posts_again.len().unwrap(), 3);\n assert_eq!(alice_posts_again.get(0).unwrap(), Some(101));\n assert_eq!(alice_posts_again.get(1).unwrap(), Some(102));\n assert_eq!(alice_posts_again.get(2).unwrap(), Some(103));\n- \n+\n // Test creating a different nested collection\n- let mut bob_posts = users_posts.entry(\"bob\".to_string()).unwrap().or_default().unwrap();\n+ let mut bob_posts = users_posts\n+ .entry(\"bob\".to_string())\n+ .unwrap()\n+ .or_default()\n+ .unwrap();\n bob_posts.push(201).unwrap();\n bob_posts.push(202).unwrap();\n- \n+\n // Verify isolation between nested collections\n assert_eq!(alice_posts_again.len().unwrap(), 3);\n assert_eq!(bob_posts.len().unwrap(), 2);\n- \n+\n // Test chained calls\n- users_posts.entry(\"charlie\".to_string()).unwrap().or_default().unwrap().push(301).unwrap();\n- let charlie_posts = users_posts.entry(\"charlie\".to_string()).unwrap().or_default().unwrap();\n+ users_posts\n+ .entry(\"charlie\".to_string())\n+ .unwrap()\n+ .or_default()\n+ .unwrap()\n+ .push(301)\n+ .unwrap();\n+ let charlie_posts = users_posts\n+ .entry(\"charlie\".to_string())\n+ .unwrap()\n+ .or_default()\n+ .unwrap();\n assert_eq!(charlie_posts.len().unwrap(), 1);\n assert_eq!(charlie_posts.get(0).unwrap(), Some(301));\n }\n- \n- // Note: Nested DurableMap-in-DurableMap requires implementing Serialize/Deserialize \n+\n+ // Note: Nested DurableMap-in-DurableMap requires implementing Serialize/Deserialize\n // for DurableMap, which is not straightforward since it contains database handles.\n // For now, let's focus on the more common case of Map-to-Vec nesting.\n- \n+\n // Deep nesting with Map -> Map -> Vec also requires DurableMap serialization\n // Let's skip this for now and focus on the fundamental Map -> Vec case\n- \n+\n #[test]\n fn test_nested_collection_persistence() {\n use crate::DurableVec;\n- \n+\n let (temp_dir, db) = setup_test_db();\n- \n+\n // Create nested structure and populate it\n {\n- let users_data: DurableMap> = DurableMap::new_nested(&db, \"users\");\n- let mut user1_data = users_data.entry(\"user1\".to_string()).unwrap().or_default().unwrap();\n+ let users_data: DurableMap> =\n+ DurableMap::new_nested(&db, \"users\");\n+ let mut user1_data = users_data\n+ .entry(\"user1\".to_string())\n+ .unwrap()\n+ .or_default()\n+ .unwrap();\n user1_data.push(\"data1\".to_string()).unwrap();\n user1_data.push(\"data2\".to_string()).unwrap();\n- \n- let mut user2_data = users_data.entry(\"user2\".to_string()).unwrap().or_default().unwrap();\n+\n+ let mut user2_data = users_data\n+ .entry(\"user2\".to_string())\n+ .unwrap()\n+ .or_default()\n+ .unwrap();\n user2_data.push(\"other_data\".to_string()).unwrap();\n }\n- \n+\n // Drop the database\n drop(db);\n- \n+\n // Reopen and verify persistence\n {\n let db = Db::open(temp_dir.path()).unwrap();\n- let users_data: DurableMap> = DurableMap::new_nested(&db, \"users\");\n- \n- let user1_data = users_data.entry(\"user1\".to_string()).unwrap().or_default().unwrap();\n+ let users_data: DurableMap> =\n+ DurableMap::new_nested(&db, \"users\");\n+\n+ let user1_data = users_data\n+ .entry(\"user1\".to_string())\n+ .unwrap()\n+ .or_default()\n+ .unwrap();\n assert_eq!(user1_data.len().unwrap(), 2);\n assert_eq!(user1_data.get(0).unwrap(), Some(\"data1\".to_string()));\n assert_eq!(user1_data.get(1).unwrap(), Some(\"data2\".to_string()));\n- \n- let user2_data = users_data.entry(\"user2\".to_string()).unwrap().or_default().unwrap();\n+\n+ let user2_data = users_data\n+ .entry(\"user2\".to_string())\n+ .unwrap()\n+ .or_default()\n+ .unwrap();\n assert_eq!(user2_data.len().unwrap(), 1);\n assert_eq!(user2_data.get(0).unwrap(), Some(\"other_data\".to_string()));\n }\n }\n-} \n\\ No newline at end of file\n+}\ndiff --git a/durable/src/vec.rs b/durable/src/vec.rs\nindex 28d08fd0786df241aaf9c01b279708e547e4c034..bb6a690e5f491687b4446dc4dc612f14eb50c031 100644\n--- a/durable/src/vec.rs\n+++ b/durable/src/vec.rs\n@@ -1,6 +1,6 @@\n-use crate::{Db, Result, DurableError, DurableCollection};\n+use crate::{Db, DurableCollection, DurableError, Result};\n use rocksdb::WriteBatch;\n-use serde::{Serialize, Deserialize};\n+use serde::{Deserialize, Serialize};\n use std::marker::PhantomData;\n \n /// A persistent vector backed by RocksDB\n@@ -10,21 +10,21 @@ pub struct DurableVec {\n _phantom: PhantomData,\n }\n \n-impl DurableVec \n-where \n- T: Serialize + for<'de> Deserialize<'de>\n+impl DurableVec\n+where\n+ T: Serialize + for<'de> Deserialize<'de>,\n {\n /// Create a new DurableVec with the given name\n pub fn new(db: &Db, name: &str) -> Result {\n let prefix = format!(\"vec:{}\", name).into_bytes();\n- \n+\n Ok(DurableVec {\n db: db.clone(),\n prefix,\n _phantom: PhantomData,\n })\n }\n- \n+\n /// Create a new DurableVec from a prefix (used for nested collections)\n pub fn from_prefix(db: Db, prefix: Vec) -> Self {\n Self {\n@@ -33,7 +33,7 @@ where\n _phantom: PhantomData,\n }\n }\n- \n+\n /// Get the length of the vector\n pub fn len(&self) -> Result {\n let key = self.meta_key(\"len\");\n@@ -42,180 +42,185 @@ where\n if bytes.len() != 8 {\n return Err(DurableError::Corruption(\"Invalid length bytes size\".into()));\n }\n- let len_bytes: [u8; 8] = bytes[..8].try_into()\n+ let len_bytes: [u8; 8] = bytes[..8]\n+ .try_into()\n .map_err(|_| DurableError::Corruption(\"Invalid length bytes\".into()))?;\n Ok(u64::from_le_bytes(len_bytes) as usize)\n }\n None => Ok(0),\n }\n }\n- \n+\n /// Check if the vector is empty\n pub fn is_empty(&self) -> Result {\n Ok(self.len()? == 0)\n }\n- \n+\n /// Push an element to the end of the vector\n pub fn push(&mut self, value: T) -> Result<()> {\n let len = self.len()?;\n let mut batch = WriteBatch::default();\n- \n+\n // Serialize the value\n let value_bytes = bincode::serialize(&value)?;\n- \n+\n // Write the element\n let elem_key = self.element_key(len);\n batch.put(&elem_key, &value_bytes);\n- \n+\n // Update the length\n let new_len = (len + 1) as u64;\n let len_key = self.meta_key(\"len\");\n batch.put(&len_key, &new_len.to_le_bytes());\n- \n+\n // Commit atomically\n self.db.rocks().write(batch)?;\n self.db.rocks().flush_wal(true)?;\n- \n+\n Ok(())\n }\n- \n+\n /// Get an element at the given index\n pub fn get(&self, index: usize) -> Result> {\n let len = self.len()?;\n if index >= len {\n return Ok(None);\n }\n- \n+\n let key = self.element_key(index);\n match self.db.rocks().get(&key)? {\n Some(bytes) => {\n let value = bincode::deserialize(&bytes)?;\n Ok(Some(value))\n }\n- None => Err(DurableError::Corruption(\n- format!(\"Element at index {} not found but index < len\", index)\n- )),\n+ None => Err(DurableError::Corruption(format!(\n+ \"Element at index {} not found but index < len\",\n+ index\n+ ))),\n }\n }\n- \n+\n /// Clear all elements from the vector\n pub fn clear(&mut self) -> Result<()> {\n let len = self.len()?;\n let mut batch = WriteBatch::default();\n- \n+\n // Delete all elements\n for i in 0..len {\n let key = self.element_key(i);\n batch.delete(&key);\n }\n- \n+\n // Delete the length meta key\n let len_key = self.meta_key(\"len\");\n batch.delete(&len_key);\n- \n+\n // Commit atomically\n self.db.rocks().write(batch)?;\n self.db.rocks().flush_wal(true)?;\n- \n+\n Ok(())\n }\n- \n+\n /// Create a streaming iterator over the vector\n pub fn iter(&self) -> Result> + '_> {\n let prefix = self.element_prefix();\n- let iter = self.db.rocks().iterator(rocksdb::IteratorMode::From(&prefix, rocksdb::Direction::Forward));\n- \n+ let iter = self.db.rocks().iterator(rocksdb::IteratorMode::From(\n+ &prefix,\n+ rocksdb::Direction::Forward,\n+ ));\n+\n Ok(VecIterator {\n inner: iter,\n prefix,\n _phantom: PhantomData,\n })\n }\n- \n+\n /// Convert the entire vector to a Vec in memory\n- /// \n+ ///\n /// Note: This loads the entire collection into memory. For large collections,\n /// prefer using `iter()` which streams elements.\n pub fn to_vec(&self) -> Result> {\n let len = self.len()?;\n let mut result = Vec::with_capacity(len);\n- \n+\n for item in self.iter()? {\n result.push(item?);\n }\n- \n+\n Ok(result)\n }\n- \n+\n /// Push multiple elements in a single batch\n pub fn extend(&mut self, iter: I) -> Result<()>\n where\n- I: IntoIterator\n+ I: IntoIterator,\n {\n let mut batch = WriteBatch::default();\n let mut len = self.len()?;\n- \n+\n for value in iter {\n let value_bytes = bincode::serialize(&value)?;\n let elem_key = self.element_key(len);\n batch.put(&elem_key, &value_bytes);\n len += 1;\n }\n- \n+\n // Update length\n let len_key = self.meta_key(\"len\");\n batch.put(&len_key, &(len as u64).to_le_bytes());\n- \n+\n // Commit atomically\n self.db.rocks().write(batch)?;\n self.db.rocks().flush_wal(true)?;\n- \n+\n Ok(())\n }\n- \n+\n /// Remove and return the last element\n pub fn pop(&mut self) -> Result> {\n let len = self.len()?;\n if len == 0 {\n return Ok(None);\n }\n- \n+\n let last_idx = len - 1;\n let value = self.get(last_idx)?;\n- \n+\n let mut batch = WriteBatch::default();\n- \n+\n // Delete the last element\n let elem_key = self.element_key(last_idx);\n batch.delete(&elem_key);\n- \n+\n // Update length\n let len_key = self.meta_key(\"len\");\n batch.put(&len_key, &(last_idx as u64).to_le_bytes());\n- \n+\n // Commit atomically\n self.db.rocks().write(batch)?;\n self.db.rocks().flush_wal(true)?;\n- \n+\n Ok(value)\n }\n- \n+\n // Helper methods\n- \n+\n fn element_key(&self, index: usize) -> Vec {\n let mut key = self.prefix.clone();\n key.push(b':');\n key.extend_from_slice(&(index as u64).to_be_bytes());\n key\n }\n- \n+\n fn meta_key(&self, meta_type: &str) -> Vec {\n let mut key = self.prefix.clone();\n key.extend_from_slice(b\":__meta:\");\n key.extend_from_slice(meta_type.as_bytes());\n key\n }\n- \n+\n fn element_prefix(&self) -> Vec {\n let mut prefix = self.prefix.clone();\n prefix.push(b':');\n@@ -224,9 +229,9 @@ where\n }\n \n // Implement the DurableCollection trait for DurableVec\n-impl DurableCollection for DurableVec \n+impl DurableCollection for DurableVec\n where\n- T: Serialize + for<'de> Deserialize<'de>\n+ T: Serialize + for<'de> Deserialize<'de>,\n {\n fn from_prefix(db: Db, prefix: Vec) -> Self {\n DurableVec::from_prefix(db, prefix)\n@@ -242,10 +247,10 @@ pub struct VecIterator<'a, T> {\n \n impl<'a, T> Iterator for VecIterator<'a, T>\n where\n- T: for<'de> Deserialize<'de>\n+ T: for<'de> Deserialize<'de>,\n {\n type Item = Result;\n- \n+\n fn next(&mut self) -> Option {\n loop {\n match self.inner.next() {\n@@ -254,14 +259,14 @@ where\n if !key.starts_with(&self.prefix) {\n return None;\n }\n- \n+\n // Check if this is a meta key (skip it)\n // The key pattern is: prefix:element_index or prefix:__meta:type\n // We want to skip any key that contains \"__meta:\"\n if key.windows(7).any(|w| w == b\"__meta:\") {\n continue; // Skip this key and try the next one\n }\n- \n+\n // Deserialize the value\n match bincode::deserialize(&value) {\n Ok(item) => return Some(Ok(item)),\n@@ -279,37 +284,37 @@ where\n mod tests {\n use super::*;\n use tempfile::TempDir;\n- \n+\n fn setup_test_db() -> (TempDir, Db) {\n let temp_dir = TempDir::new().unwrap();\n let db = Db::open(temp_dir.path()).unwrap();\n (temp_dir, db)\n }\n- \n+\n #[test]\n fn test_push_and_get() {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"test_vec\").unwrap();\n- \n+\n // Push some values\n vec.push(\"first\".to_string()).unwrap();\n vec.push(\"second\".to_string()).unwrap();\n vec.push(\"third\".to_string()).unwrap();\n- \n+\n // Check length\n assert_eq!(vec.len().unwrap(), 3);\n- \n+\n // Get values\n assert_eq!(vec.get(0).unwrap(), Some(\"first\".to_string()));\n assert_eq!(vec.get(1).unwrap(), Some(\"second\".to_string()));\n assert_eq!(vec.get(2).unwrap(), Some(\"third\".to_string()));\n assert_eq!(vec.get(3).unwrap(), None);\n }\n- \n+\n #[test]\n fn test_persistence() {\n let (temp_dir, db) = setup_test_db();\n- \n+\n // Create and populate vector\n {\n let mut vec = DurableVec::::new(&db, \"persist_vec\").unwrap();\n@@ -317,55 +322,55 @@ mod tests {\n vec.push(100).unwrap();\n vec.push(-7).unwrap();\n }\n- \n+\n // Drop the database\n drop(db);\n- \n+\n // Reopen and verify data persists\n {\n let db = Db::open(temp_dir.path()).unwrap();\n let vec = DurableVec::::new(&db, \"persist_vec\").unwrap();\n- \n+\n assert_eq!(vec.len().unwrap(), 3);\n assert_eq!(vec.get(0).unwrap(), Some(42));\n assert_eq!(vec.get(1).unwrap(), Some(100));\n assert_eq!(vec.get(2).unwrap(), Some(-7));\n }\n }\n- \n+\n #[test]\n fn test_clear() {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"clear_vec\").unwrap();\n- \n+\n // Add some elements\n vec.extend(vec![1, 2, 3, 4, 5]).unwrap();\n assert_eq!(vec.len().unwrap(), 5);\n- \n+\n // Clear\n vec.clear().unwrap();\n assert_eq!(vec.len().unwrap(), 0);\n assert!(vec.is_empty().unwrap());\n- \n+\n // Should be able to push again\n vec.push(42).unwrap();\n assert_eq!(vec.len().unwrap(), 1);\n assert_eq!(vec.get(0).unwrap(), Some(42));\n }\n- \n+\n #[test]\n fn test_pop() {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"pop_vec\").unwrap();\n- \n+\n // Empty pop\n assert_eq!(vec.pop().unwrap(), None);\n- \n+\n // Push and pop\n vec.push(\"a\".to_string()).unwrap();\n vec.push(\"b\".to_string()).unwrap();\n vec.push(\"c\".to_string()).unwrap();\n- \n+\n assert_eq!(vec.pop().unwrap(), Some(\"c\".to_string()));\n assert_eq!(vec.len().unwrap(), 2);\n assert_eq!(vec.pop().unwrap(), Some(\"b\".to_string()));\n@@ -374,68 +379,70 @@ mod tests {\n assert_eq!(vec.len().unwrap(), 0);\n assert_eq!(vec.pop().unwrap(), None);\n }\n- \n+\n #[test]\n fn test_iteration() {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"iter_vec\").unwrap();\n- \n+\n // Add elements\n let values = vec![10, 20, 30, 40, 50];\n vec.extend(values.clone()).unwrap();\n- \n+\n // Iterate and collect\n let collected = vec.to_vec().unwrap();\n- \n+\n assert_eq!(collected, values);\n }\n- \n+\n #[test]\n fn test_extend() {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"extend_vec\").unwrap();\n- \n+\n // Extend with iterator\n- vec.extend(vec![\"a\", \"b\", \"c\"].into_iter().map(String::from)).unwrap();\n+ vec.extend(vec![\"a\", \"b\", \"c\"].into_iter().map(String::from))\n+ .unwrap();\n assert_eq!(vec.len().unwrap(), 3);\n- \n+\n // Extend again\n- vec.extend(vec![\"d\", \"e\"].into_iter().map(String::from)).unwrap();\n+ vec.extend(vec![\"d\", \"e\"].into_iter().map(String::from))\n+ .unwrap();\n assert_eq!(vec.len().unwrap(), 5);\n- \n+\n // Verify all elements\n let all = vec.to_vec().unwrap();\n assert_eq!(all, vec![\"a\", \"b\", \"c\", \"d\", \"e\"]);\n }\n- \n+\n #[test]\n fn test_large_dataset() {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"large_vec\").unwrap();\n- \n+\n // Push many elements\n let count = 1000;\n for i in 0..count {\n vec.push(i).unwrap();\n }\n- \n+\n assert_eq!(vec.len().unwrap(), count as usize);\n- \n+\n // Verify some random accesses\n assert_eq!(vec.get(0).unwrap(), Some(0));\n assert_eq!(vec.get(500).unwrap(), Some(500));\n assert_eq!(vec.get(999).unwrap(), Some(999));\n assert_eq!(vec.get(1000).unwrap(), None);\n- \n+\n // Verify iteration count\n let all_values = vec.to_vec().unwrap();\n assert_eq!(all_values.len(), count as usize);\n }\n- \n- #[test] \n+\n+ #[test]\n fn test_complex_types() {\n- use serde::{Serialize, Deserialize};\n- \n+ use serde::{Deserialize, Serialize};\n+\n #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]\n struct User {\n id: u64,\n@@ -443,36 +450,36 @@ mod tests {\n email: String,\n active: bool,\n }\n- \n+\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"users\").unwrap();\n- \n+\n let user1 = User {\n id: 1,\n name: \"Alice\".to_string(),\n email: \"alice@example.com\".to_string(),\n active: true,\n };\n- \n+\n let user2 = User {\n id: 2,\n name: \"Bob\".to_string(),\n email: \"bob@example.com\".to_string(),\n active: false,\n };\n- \n+\n vec.push(user1.clone()).unwrap();\n vec.push(user2.clone()).unwrap();\n- \n+\n assert_eq!(vec.get(0).unwrap(), Some(user1));\n assert_eq!(vec.get(1).unwrap(), Some(user2));\n }\n- \n+\n #[test]\n fn test_empty_vec_operations() {\n let (_temp, db) = setup_test_db();\n let vec = DurableVec::::new(&db, \"empty_vec\").unwrap();\n- \n+\n // Test operations on empty vec\n assert_eq!(vec.len().unwrap(), 0);\n assert!(vec.is_empty().unwrap());\n@@ -480,93 +487,93 @@ mod tests {\n assert_eq!(vec.get(100).unwrap(), None);\n assert_eq!(vec.to_vec().unwrap(), Vec::::new());\n }\n- \n+\n #[test]\n fn test_multiple_vecs_same_db() {\n let (_temp, db) = setup_test_db();\n- \n+\n // Create multiple vectors with different names\n let mut vec1 = DurableVec::::new(&db, \"vec1\").unwrap();\n let mut vec2 = DurableVec::::new(&db, \"vec2\").unwrap();\n- \n+\n // Push different data to each\n vec1.push(\"vec1_data\".to_string()).unwrap();\n vec2.push(\"vec2_data\".to_string()).unwrap();\n- \n+\n // Verify they don't interfere\n assert_eq!(vec1.get(0).unwrap(), Some(\"vec1_data\".to_string()));\n assert_eq!(vec2.get(0).unwrap(), Some(\"vec2_data\".to_string()));\n assert_eq!(vec1.len().unwrap(), 1);\n assert_eq!(vec2.len().unwrap(), 1);\n }\n- \n+\n #[test]\n fn test_batch_atomicity() {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"batch_vec\").unwrap();\n- \n+\n // Add initial data\n vec.push(1).unwrap();\n vec.push(2).unwrap();\n vec.push(3).unwrap();\n- \n+\n // Verify initial state\n assert_eq!(vec.len().unwrap(), 3);\n- \n+\n // Clear should be atomic - either all elements deleted or none\n vec.clear().unwrap();\n assert_eq!(vec.len().unwrap(), 0);\n- \n+\n // Extend should be atomic - either all elements added or none\n vec.extend(vec![10, 20, 30, 40, 50]).unwrap();\n assert_eq!(vec.len().unwrap(), 5);\n let all = vec.to_vec().unwrap();\n assert_eq!(all, vec![10, 20, 30, 40, 50]);\n }\n- \n+\n #[test]\n fn test_unicode_strings() {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"unicode_vec\").unwrap();\n- \n+\n let test_strings = vec![\n \"Hello, äø–ē•Œ!\".to_string(),\n \"šŸ¦€ Rust šŸš€\".to_string(),\n \"ƑoƱo\".to_string(),\n \"šŸ“ā€ā˜ ļø Pirates\".to_string(),\n ];\n- \n+\n vec.extend(test_strings.clone()).unwrap();\n- \n+\n let retrieved = vec.to_vec().unwrap();\n assert_eq!(retrieved, test_strings);\n }\n- \n+\n #[test]\n fn test_streaming_iterator() {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"stream_vec\").unwrap();\n- \n+\n // Add test data\n let values = vec![1, 2, 3, 4, 5];\n vec.extend(values.clone()).unwrap();\n- \n+\n // Test streaming iteration\n let mut collected = Vec::new();\n for item in vec.iter().unwrap() {\n collected.push(item.unwrap());\n }\n- \n+\n assert_eq!(collected, values);\n- \n+\n // Test that iterator properly handles prefix boundaries\n let mut vec2 = DurableVec::::new(&db, \"stream_vec2\").unwrap();\n vec2.extend(vec![10, 20, 30]).unwrap();\n- \n+\n // Each iterator should only see its own data\n let collected1: Vec<_> = vec.iter().unwrap().collect::>>().unwrap();\n let collected2: Vec<_> = vec2.iter().unwrap().collect::>>().unwrap();\n- \n+\n assert_eq!(collected1, values);\n assert_eq!(collected2, vec![10, 20, 30]);\n }\n@@ -577,82 +584,82 @@ mod proptests {\n use super::*;\n use proptest::prelude::*;\n use tempfile::TempDir;\n- \n+\n fn setup_test_db() -> (TempDir, Db) {\n let temp_dir = TempDir::new().unwrap();\n let db = Db::open(temp_dir.path()).unwrap();\n (temp_dir, db)\n }\n- \n+\n proptest! {\n #[test]\n fn prop_push_get_consistency(values: Vec) {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"prop_vec\").unwrap();\n- \n+\n // Push all values\n for value in &values {\n vec.push(*value).unwrap();\n }\n- \n+\n // Verify length\n prop_assert_eq!(vec.len().unwrap(), values.len());\n- \n+\n // Verify all values can be retrieved correctly\n for (i, expected) in values.iter().enumerate() {\n prop_assert_eq!(vec.get(i).unwrap(), Some(*expected));\n }\n }\n- \n+\n #[test]\n fn prop_extend_iter_roundtrip(values: Vec) {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"extend_vec\").unwrap();\n- \n+\n // Extend with all values\n vec.extend(values.clone()).unwrap();\n- \n+\n // Get back via iteration\n let retrieved = vec.to_vec().unwrap();\n- \n+\n prop_assert_eq!(retrieved, values);\n }\n- \n+\n #[test]\n fn prop_pop_removes_last(mut values: Vec) {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"pop_vec\").unwrap();\n- \n+\n // Add all values\n vec.extend(values.clone()).unwrap();\n- \n+\n // Pop values and verify\n while let Some(expected) = values.pop() {\n let popped = vec.pop().unwrap();\n prop_assert_eq!(popped, Some(expected));\n prop_assert_eq!(vec.len().unwrap(), values.len());\n }\n- \n+\n // Vector should be empty\n prop_assert!(vec.is_empty().unwrap());\n prop_assert_eq!(vec.pop().unwrap(), None);\n }\n- \n+\n #[test]\n fn prop_clear_makes_empty(values: Vec) {\n let (_temp, db) = setup_test_db();\n let mut vec = DurableVec::::new(&db, \"clear_vec\").unwrap();\n- \n+\n // Add values\n vec.extend(values).unwrap();\n- \n+\n // Clear\n vec.clear().unwrap();\n- \n+\n // Should be empty\n prop_assert_eq!(vec.len().unwrap(), 0);\n prop_assert!(vec.is_empty().unwrap());\n prop_assert_eq!(vec.get(0).unwrap(), None);\n }\n }\n-} \n\\ No newline at end of file\n+}\ndiff --git a/rust-toolchain.toml b/rust-toolchain.toml\nindex e88baf106b9e6550446ae1cd13dbba561193e062..7855e6d557c0d29ac368603b23807b7f6e2379bd 100644\n--- a/rust-toolchain.toml\n+++ b/rust-toolchain.toml\n@@ -1,2 +1,3 @@\n [toolchain]\n channel = \"1.88.0\"\n+components = [\"rustfmt\", \"clippy\"]\ndiff --git a/server/src/events.rs b/server/src/events.rs\nindex b21cb4d6ff3fe2a217f6abca3b17dd639bf4e839..1a1525e265b56cc1c4bbab4ae6d496ce5ea42e33 100644\n--- a/server/src/events.rs\n+++ b/server/src/events.rs\n@@ -20,9 +20,5 @@ pub enum Event {\n /// Register a node path in the fractal tree (no external fetch).\n NodeEnsured { id: String },\n /// Full upstream API payload for a node (domain-specific view derived at replay/render time).\n- EntityImported {\n- id: String,\n- ts: i64,\n- payload: Value,\n- },\n+ EntityImported { id: String, ts: i64, payload: Value },\n }\ndiff --git a/server/src/html/vote.rs b/server/src/html/vote.rs\nindex 30dab303b9d1e763a5b9261dffff13a778e3e4e3..8cf2b0d4d8bd58cc51cc27c9046fa7f7728a7017 100644\n--- a/server/src/html/vote.rs\n+++ b/server/src/html/vote.rs\n@@ -31,10 +31,7 @@ pub struct VoteQuery {\n }\n \n pub fn vote_href(parent: &ItemId) -> String {\n- format!(\n- \"/vote?parent={}\",\n- urlencoding::encode(parent.as_str())\n- )\n+ format!(\"/vote?parent={}\", urlencoding::encode(parent.as_str()))\n }\n \n fn vote_compare_href(parent: &ItemId, left: &ItemId, right: &ItemId) -> String {\n@@ -114,7 +111,12 @@ fn slider_value_from_ratios(r_left: i32, r_right: i32) -> i32 {\n ((r / sum) * 100.0).round().clamp(0.0, 100.0) as i32\n }\n \n-fn vote_edge_history(tree: &GlobalTree, group: &GroupState, left: &ItemId, right: &ItemId) -> Markup {\n+fn vote_edge_history(\n+ tree: &GlobalTree,\n+ group: &GroupState,\n+ left: &ItemId,\n+ right: &ItemId,\n+) -> Markup {\n let mut votes = edge_votes(group, left, right);\n votes.sort_by(|a, b| b.ts.cmp(&a.ts));\n let legend_left = child_title(tree, left);\n@@ -154,7 +156,6 @@ fn vote_edge_history(tree: &GlobalTree, group: &GroupState, left: &ItemId, right\n }\n }\n \n-\n fn vote_hud_form(\n parent: &ItemId,\n left: &ItemId,\n@@ -200,7 +201,12 @@ fn vote_compare_actions(parent: &ItemId, next: Option<&(ItemId, ItemId)>) -> Mar\n }\n }\n \n-fn vote_ranking_sidebar(tree: &GlobalTree, parent: &ItemId, left: &ItemId, right: &ItemId) -> Markup {\n+fn vote_ranking_sidebar(\n+ tree: &GlobalTree,\n+ parent: &ItemId,\n+ left: &ItemId,\n+ right: &ItemId,\n+) -> Markup {\n let empty = NodeState::default();\n let node = tree.get(parent).unwrap_or(&empty);\n let highlighted: HashSet = [left.clone(), right.clone()].into_iter().collect();\n@@ -222,11 +228,7 @@ pub(crate) fn vote_recorded_morph(\n ) -> JsBuilder {\n let pool = children_of(tree, parent);\n let empty = NodeState::default();\n- let group = tree\n- .get(parent)\n- .unwrap_or(&empty)\n- .local_ranking\n- .clone();\n+ let group = tree.get(parent).unwrap_or(&empty).local_ranking.clone();\n let edge_history = vote_edge_history(tree, &group, left, right);\n let next_pair = suggest_next(&group, left, right, &pool);\n let actions = vote_compare_actions(parent, next_pair.as_ref());\n@@ -249,8 +251,12 @@ fn vote_compare_item_card(tree: &GlobalTree, item: &ItemId, side_class: &str) ->\n }\n }\n \n-\n-fn suggest_next(group: &GroupState, left: &ItemId, right: &ItemId, pool: &[ItemId]) -> Option<(ItemId, ItemId)> {\n+fn suggest_next(\n+ group: &GroupState,\n+ left: &ItemId,\n+ right: &ItemId,\n+ pool: &[ItemId],\n+) -> Option<(ItemId, ItemId)> {\n suggest_next_pair_in_pool(group, pool, Some((left, right)))\n }\n \n@@ -262,22 +268,20 @@ pub async fn vote_page(\n let left_param = q.left.as_deref().map(parse_item_param);\n let right_param = q.right.as_deref().map(parse_item_param);\n \n- let tree = state.scope_tree(&parent).unwrap_or_else(|_| GlobalTree::new());\n+ let tree = state\n+ .scope_tree(&parent)\n+ .unwrap_or_else(|_| GlobalTree::new());\n let empty = NodeState::default();\n let parent_node = tree.get(&parent).unwrap_or(&empty);\n \n- let (left, right) = match resolve_pair(\n- &tree,\n- &parent,\n- left_param.as_ref(),\n- right_param.as_ref(),\n- ) {\n- Ok(p) => p,\n- Err(e) => {\n- let (msg, status) = e.status_message();\n- return (status, msg).into_response();\n- }\n- };\n+ let (left, right) =\n+ match resolve_pair(&tree, &parent, left_param.as_ref(), right_param.as_ref()) {\n+ Ok(p) => p,\n+ Err(e) => {\n+ let (msg, status) = e.status_message();\n+ return (status, msg).into_response();\n+ }\n+ };\n \n let pool = children_of(&tree, &parent);\n let group = &parent_node.local_ranking;\n@@ -326,15 +330,7 @@ pub async fn vote_page(\n state.views.increment(path.clone());\n let views = state.views.get_views(&path);\n \n- Html(\n- layout(\n- &title,\n- body,\n- views,\n- )\n- .into_string(),\n- )\n- .into_response()\n+ Html(layout(&title, body, views).into_string()).into_response()\n }\n \n #[cfg(test)]\ndiff --git a/server/src/pair.rs b/server/src/pair.rs\nindex 606ffa51038a57ffacf335aa48bdb1185f8483fb..54b5d2417e9dba04ed8df422156e274c2b2f76b2 100644\n--- a/server/src/pair.rs\n+++ b/server/src/pair.rs\n@@ -89,10 +89,7 @@ fn pair_priority(\n }\n \n /// All unordered pairs from `pool`, optionally skipping `exclude`.\n-fn candidate_pairs(\n- pool: &[ItemId],\n- exclude: Option<(&ItemId, &ItemId)>,\n-) -> Vec<(ItemId, ItemId)> {\n+fn candidate_pairs(pool: &[ItemId], exclude: Option<(&ItemId, &ItemId)>) -> Vec<(ItemId, ItemId)> {\n let mut out = Vec::new();\n for i in 0..pool.len() {\n for j in (i + 1)..pool.len() {\n@@ -228,10 +225,7 @@ impl PairError {\n \"provide both left and right, or neither\",\n axum::http::StatusCode::BAD_REQUEST,\n ),\n- Self::NoPair => (\n- \"no pair available\",\n- axum::http::StatusCode::BAD_REQUEST,\n- ),\n+ Self::NoPair => (\"no pair available\", axum::http::StatusCode::BAD_REQUEST),\n }\n }\n }\n@@ -292,16 +286,20 @@ mod tests {\n \"reddit.com/r/rust/d\",\n ],\n );\n- let ab = VoteData::from_recorded(1, \"reddit.com/r/rust/a\", \"reddit.com/r/rust/b\", 2, 1).unwrap();\n- let cd = VoteData::from_recorded(2, \"reddit.com/r/rust/c\", \"reddit.com/r/rust/d\", 2, 1).unwrap();\n+ let ab =\n+ VoteData::from_recorded(1, \"reddit.com/r/rust/a\", \"reddit.com/r/rust/b\", 2, 1).unwrap();\n+ let cd =\n+ VoteData::from_recorded(2, \"reddit.com/r/rust/c\", \"reddit.com/r/rust/d\", 2, 1).unwrap();\n tree.apply_vote(&parent, ab);\n tree.apply_vote(&parent, cd);\n let group = tree.get(&parent).unwrap().local_ranking.clone();\n let pool = children_of(&tree, &parent);\n let pair = suggest_next_pair_in_pool(&group, &pool, None).unwrap();\n let chosen = pair_set(&pair);\n- let from_ab = chosen.contains(\"reddit.com/r/rust/a\") || chosen.contains(\"reddit.com/r/rust/b\");\n- let from_cd = chosen.contains(\"reddit.com/r/rust/c\") || chosen.contains(\"reddit.com/r/rust/d\");\n+ let from_ab =\n+ chosen.contains(\"reddit.com/r/rust/a\") || chosen.contains(\"reddit.com/r/rust/b\");\n+ let from_cd =\n+ chosen.contains(\"reddit.com/r/rust/c\") || chosen.contains(\"reddit.com/r/rust/d\");\n assert!(from_ab && from_cd, \"expected bridge pair, got {:?}\", chosen);\n }\n \n@@ -316,7 +314,8 @@ mod tests {\n \"reddit.com/r/rust/c\",\n ],\n );\n- let ab = VoteData::from_recorded(1, \"reddit.com/r/rust/a\", \"reddit.com/r/rust/b\", 2, 1).unwrap();\n+ let ab =\n+ VoteData::from_recorded(1, \"reddit.com/r/rust/a\", \"reddit.com/r/rust/b\", 2, 1).unwrap();\n tree.apply_vote(&parent, ab);\n let group = tree.get(&parent).unwrap().local_ranking.clone();\n let pool = children_of(&tree, &parent);\ndiff --git a/server/src/parser.rs b/server/src/parser.rs\nindex 51aa0e0f982546aab68bd5e1ca0cb726e88b3f50..9df2dcc9313f7fe250ce3b6aa167f6ec5d57951f 100644\n--- a/server/src/parser.rs\n+++ b/server/src/parser.rs\n@@ -43,10 +43,7 @@ mod tests {\n \"https://old.reddit.com/r/AmItheAsshole/comments/1trnvdl/aita_for_cancelling/\",\n )\n .unwrap();\n- assert_eq!(\n- id.as_str(),\n- \"reddit.com/r/amitheasshole/comments/1trnvdl\"\n- );\n+ assert_eq!(id.as_str(), \"reddit.com/r/amitheasshole/comments/1trnvdl\");\n }\n \n #[test]\ndiff --git a/server/src/path_types.rs b/server/src/path_types.rs\nindex a0d1a028b8bd3c5d1c714dea3ec597d1ac39e1bc..fafd924452f6fd85e7a5b27ed2653a19581e6e56 100644\n--- a/server/src/path_types.rs\n+++ b/server/src/path_types.rs\n@@ -114,11 +114,7 @@ impl ItemId {\n if self.as_str().contains(\"://\") {\n return self.as_str().to_string();\n }\n- if self\n- .segments()\n- .first()\n- .is_some_and(|s| s.contains('.'))\n- {\n+ if self.segments().first().is_some_and(|s| s.contains('.')) {\n format!(\"https://{}\", self.as_str())\n } else {\n self.as_str().to_string()\n@@ -146,8 +142,7 @@ impl ItemId {\n }\n \n pub fn from_browse_uri(path: &str) -> Option {\n- path.strip_prefix(\"/~/\")\n- .map(ItemId::from_browse_tail)\n+ path.strip_prefix(\"/~/\").map(ItemId::from_browse_tail)\n }\n \n fn canonicalize(raw: &str) -> Option {\n@@ -273,10 +268,7 @@ mod tests {\n \"https://old.reddit.com/r/AmItheAsshole/comments/1trnvdl/aita_for_cancelling/\",\n )\n .unwrap();\n- assert_eq!(\n- id.as_str(),\n- \"reddit.com/r/amitheasshole/comments/1trnvdl\"\n- );\n+ assert_eq!(id.as_str(), \"reddit.com/r/amitheasshole/comments/1trnvdl\");\n }\n \n #[test]\n@@ -296,10 +288,7 @@ mod tests {\n #[test]\n fn parent_of_post_is_subreddit() {\n let id = ItemId::parse(\"reddit.com/r/aww/comments/1trnvdl\").unwrap();\n- assert_eq!(\n- id.parent().unwrap().as_str(),\n- \"reddit.com/r/aww\"\n- );\n+ assert_eq!(id.parent().unwrap().as_str(), \"reddit.com/r/aww\");\n }\n \n #[test]\n@@ -342,7 +331,8 @@ mod tests {\n \n #[test]\n fn from_storage_strips_post_title_slug() {\n- let id = ItemId::from_storage(\"reddit.com/r/rust/comments/aaa/announcing_rust_199\").unwrap();\n+ let id =\n+ ItemId::from_storage(\"reddit.com/r/rust/comments/aaa/announcing_rust_199\").unwrap();\n assert_eq!(id.as_str(), \"reddit.com/r/rust/comments/aaa\");\n }\n \ndiff --git a/server/src/ranking.rs b/server/src/ranking.rs\nindex 93cb4c9f5887a1e598cdc9d648751055f618adcc..a83f7be120d9420db042479222ca9efc230b6da9 100644\n--- a/server/src/ranking.rs\n+++ b/server/src/ranking.rs\n@@ -68,12 +68,8 @@ pub fn connected_components_from_voted_pairs(\n /// there is no score cache.\n pub fn ranked_items(group: &GroupState) -> Vec {\n let n = group.idx_to_item.len();\n- let scores = compute_scores_from_edges(\n- n,\n- group.edges.iter().map(|(&k, &w)| (k, w)),\n- MAX_ITERS,\n- TOL,\n- );\n+ let scores =\n+ compute_scores_from_edges(n, group.edges.iter().map(|(&k, &w)| (k, w)), MAX_ITERS, TOL);\n \n let mut items: Vec = group\n .idx_to_item\n@@ -85,7 +81,11 @@ pub fn ranked_items(group: &GroupState) -> Vec {\n })\n .collect();\n \n- items.sort_by(|a, b| b.score.partial_cmp(&a.score).unwrap_or(std::cmp::Ordering::Equal));\n+ items.sort_by(|a, b| {\n+ b.score\n+ .partial_cmp(&a.score)\n+ .unwrap_or(std::cmp::Ordering::Equal)\n+ });\n items\n }\n \n@@ -216,7 +216,12 @@ pub fn compute_scores_from_edges(\n /// Rank-centrality within a subset of items (an induced subgraph), using the group's aggregated edges.\n ///\n /// `idxs` are indices into `group.idx_to_item`. The returned items use the original item names.\n-pub fn ranked_items_subset(group: &GroupState, idxs: &[usize], max_iters: usize, tol: f64) -> Vec {\n+pub fn ranked_items_subset(\n+ group: &GroupState,\n+ idxs: &[usize],\n+ max_iters: usize,\n+ tol: f64,\n+) -> Vec {\n if idxs.is_empty() {\n return vec![];\n }\n@@ -241,11 +246,18 @@ pub fn ranked_items_subset(group: &GroupState, idxs: &[usize], max_iters: usize,\n .enumerate()\n .filter_map(|(j, &orig)| {\n let item = group.idx_to_item.get(orig)?.clone();\n- Some(RankedItem { item, score: *scores.get(j).unwrap_or(&0.0) })\n+ Some(RankedItem {\n+ item,\n+ score: *scores.get(j).unwrap_or(&0.0),\n+ })\n })\n .collect();\n \n- items.sort_by(|a, b| b.score.partial_cmp(&a.score).unwrap_or(std::cmp::Ordering::Equal));\n+ items.sort_by(|a, b| {\n+ b.score\n+ .partial_cmp(&a.score)\n+ .unwrap_or(std::cmp::Ordering::Equal)\n+ });\n items\n }\n \n@@ -417,8 +429,10 @@ mod tests {\n g.apply_vote(vote(1, \"a\", \"b\", 3, 1)); // a > b\n g.apply_vote(vote(2, \"c\", \"d\", 1, 4)); // d > c\n \n- let (comps, _) =\n- connected_components_from_voted_pairs(g.idx_to_item.len(), g.voted_pairs.iter().copied());\n+ let (comps, _) = connected_components_from_voted_pairs(\n+ g.idx_to_item.len(),\n+ g.voted_pairs.iter().copied(),\n+ );\n assert_eq!(comps.len(), 2);\n \n // Rank each component and ensure winner is first within that component.\ndiff --git a/server/src/ui_action.rs b/server/src/ui_action.rs\nindex 237411a689fb10ad1b7022ea66aee1969c7507ec..227ab3f6e8e9cce1532454450773f65daa24bfe7 100644\n--- a/server/src/ui_action.rs\n+++ b/server/src/ui_action.rs\n@@ -36,9 +36,7 @@ pub enum HtmlUiAction {\n vote_compare: bool,\n },\n /// Parse pasted Reddit URL/path; redirect to subreddit ranking on success.\n- ParseQuery {\n- query: String,\n- },\n+ ParseQuery { query: String },\n /// Import entity data; `POST /ui` responds with `text/event-stream` whose\n /// events carry JS snippets to `eval` (Idiomorph morphs), not JSON.\n FetchEntity {\ndiff --git a/server/src/views.rs b/server/src/views.rs\nindex a3712e779d4b34bca2c021a2451721c4055222c2..35c2089f4c10911318dbac3d3537d04308723f4f 100644\n--- a/server/src/views.rs\n+++ b/server/src/views.rs\n@@ -140,7 +140,10 @@ async fn flush_worker_loop(\n }\n }\n \n-fn flush_dirty(memory: &MemStateLock, inner: &Arc>) -> Result<(), ViewStoreError> {\n+fn flush_dirty(\n+ memory: &MemStateLock,\n+ inner: &Arc>,\n+) -> Result<(), ViewStoreError> {\n let snapshot: Vec<(String, u64)> = {\n let mut mem = memory.lock().map_err(|_| ViewStoreError::Poisoned)?;\n if mem.dirty.is_empty() {\n@@ -160,9 +163,7 @@ fn flush_dirty(memory: &MemStateLock, inner: &Arc>) -> Res\n let inner = inner.lock().map_err(|_| ViewStoreError::Poisoned)?;\n let mut batch = inner.db.batch();\n for (path, count) in &snapshot {\n- inner\n- .counts\n- .put_in_batch(&mut batch, path, count)?;\n+ inner.counts.put_in_batch(&mut batch, path, count)?;\n }\n batch.commit()?;\n Ok(())\ndiff --git a/server/static/sorter.css b/server/static/sorter.css\nindex bdd3d931365703705be08537a07f3ccaf975d3ea..e66a1e6c1acc473c8ff1ddb1e16e75a82d33741c 100644\n--- a/server/static/sorter.css\n+++ b/server/static/sorter.css\n@@ -468,9 +468,6 @@ h1 {\n margin: 0;\n background: transparent;\n cursor: pointer;\n-}\n-\n-.vote-hud-slider input[type=\"range\"] {\n --vote-track-muted: color-mix(in oklch, var(--muted) 55%, var(--bg));\n }\n \n\n\nSide B — contributor: tommy-mor\nSide B — commit message:\n[2b970f92] delete random test that was a warning\n\nSide B — unified diff (full patch):\ndiff --git a/server/src/dsl.rs b/server/src/dsl.rs\nindex af6d3b52621e65288f75f757d54e5abeaa7501e8..c32ff6ccc13ff38ae7712af441bd8d9e8568cc3b 100644\n--- a/server/src/dsl.rs\n+++ b/server/src/dsl.rs\n@@ -671,17 +671,6 @@ mod tests {\n assert!(err_msg.contains(\"missing vote explanation\"), \"error: {}\", err_msg);\n }\n \n- fn parse_full_keeps_quoted_thread_title_statement_as_prose() {\n- let input = \"\\\"This is a title\\\" { This is the body of the post }\\n\";\n- let doc = parse_full(input).unwrap();\n- assert_eq!(\n- doc.statements,\n- vec![Stmt::Prose {\n- text: \"\\\"This is a title\\\" { This is the body of the post }\\n\".trim_end_matches('\\n').to_string()\n- }]\n- );\n- }\n-\n #[test]\n fn parse_full_keeps_regular_quoted_prose() {\n let input = \"She said \\\"hello\\\" and left.\";\n","role":"user"}],"model":"openai/gpt-5.2-chat"}