Skip to main content

cdb64/
lib.rs

1//! # cdb64
2//!
3//! `cdb64` is a Rust implementation of D. J. Bernstein's cdb (constant database) format,
4//! specifically designed to handle large database files efficiently using 64-bit hash values and offsets.
5//!
6//! This library provides `CdbWriter` for creating cdb files and `Cdb` for reading existing cdb files.
7//! It also includes `CdbIterator` for iterating over all key-value pairs within a database.
8//!
9//! ## Features
10//!
11//! - CDB file creation (`CdbWriter`)
12//! - CDB file reading and key lookups (`Cdb`)
13//! - Database iteration (`CdbIterator`)
14//! - Support for custom hash functions (defaults to CDB hash)
15//!
16//! ## Usage Examples
17//!
18//! ### Creating and Reading a CDB File
19//!
20//! ```rust
21//! use cdb64::{CdbWriter, Cdb, Error, CdbHash};
22//! use tempfile::NamedTempFile;
23//! use std::fs::File;
24//!
25//! fn main() -> Result<(), Error> {
26//!     let temp_file = NamedTempFile::new().expect("Failed to create temp file");
27//!     let path = temp_file.path();
28//!
29//!     // Create a CDB file
30//!     let mut writer = CdbWriter::<File, CdbHash>::create(path)?;
31//!     writer.put(b"hello", b"world")?;
32//!     writer.put(b"rust", b"is awesome")?;
33//!     writer.finalize()?; // After finalize, writer can still be used (but put is blocked by is_finalized)
34//!
35//!     // Open the CDB file
36//!     let cdb = Cdb::<File, CdbHash>::open(path)?;
37//!
38//!     // Retrieve a value by key
39//!     if let Some(value) = cdb.get(b"hello")? {
40//!         println!("Found value: {}", String::from_utf8_lossy(&value));
41//!     }
42//!
43//!     // Search for a non-existent key
44//!     assert!(cdb.get(b"nonexistent")?.is_none());
45//!
46//!     Ok(())
47//! }
48//! ```
49//!
50//! ### Using the Iterator
51//!
52//! ```rust
53//! use cdb64::{CdbWriter, Cdb, CdbIterator, Error, CdbHash};
54//! use tempfile::NamedTempFile;
55//! use std::collections::HashMap;
56//! use std::fs::File;
57//!
58//! fn main() -> Result<(), Error> {
59//!     let temp_file = NamedTempFile::new().expect("Failed to create temp file");
60//!     let path = temp_file.path();
61//!
62//!     let mut data = HashMap::new();
63//!     data.insert(b"key1".to_vec(), b"value1".to_vec());
64//!     data.insert(b"key2".to_vec(), b"value2".to_vec());
65//!
66//!     let mut writer = CdbWriter::<File, CdbHash>::create(path)?;
67//!     for (k, v) in &data {
68//!         writer.put(k, v)?;
69//!     }
70//!     writer.finalize()?;
71//!
72//!     let cdb: Cdb<_, CdbHash> = Cdb::open(path)?;
73//!     let iter = cdb.iter();
74//!
75//!     let mut retrieved_count = 0;
76//!     for result in iter {
77//!         let (key, value) = result?;
78//!         println!("Key: {}, Value: {}",
79//!             String::from_utf8_lossy(&key),
80//!             String::from_utf8_lossy(&value)
81//!         );
82//!         assert_eq!(data.get(&key).unwrap(), &value);
83//!         retrieved_count += 1;
84//!     }
85//!     assert_eq!(retrieved_count, data.len());
86//!
87//!     Ok(())
88//! }
89//! ```
90
91mod cdb;
92mod hash;
93mod iterator;
94mod util;
95mod writer;
96
97// re-exports
98pub use cdb::Cdb;
99pub use hash::CdbHash;
100pub use iterator::CdbIterator;
101pub use util::ReaderAt;
102pub use writer::CdbWriter;
103
104/// Errors that can occur when working with CDB databases.
105#[derive(Debug, thiserror::Error)]
106pub enum Error {
107    /// An I/O error occurred during file operations.
108    ///
109    /// This can happen during:
110    /// - File opening, reading, or writing
111    /// - Memory mapping (when mmap feature is enabled)
112    /// - Data serialization or deserialization
113    #[error("I/O error: {0}")]
114    Io(#[from] std::io::Error),
115
116    /// Indicates an attempt to operate on a writer that has already been finalized.
117    ///
118    /// Once `CdbWriter::finalize()` is called, no further `put()` operations are allowed.
119    /// This error is returned if you try to call `put()` after finalization.
120    ///
121    /// # Example
122    ///
123    /// ```
124    /// use cdb64::{CdbWriter, CdbHash, Error};
125    /// use std::io::Cursor;
126    ///
127    /// let mut writer = CdbWriter::<_, CdbHash>::new(Cursor::new(Vec::new())).unwrap();
128    /// writer.finalize().unwrap();
129    ///
130    /// // This will fail with WriterFinalized error
131    /// match writer.put(b"key", b"value") {
132    ///     Err(Error::WriterFinalized) => println!("Expected error!"),
133    ///     _ => panic!("Should have failed"),
134    /// }
135    /// ```
136    #[error("Attempted to operate on a finalized writer")]
137    WriterFinalized,
138
139    /// Indicates an attempt to use a writer that has not been finalized yet when finalization is required.
140    ///
141    /// This error is returned by `CdbWriter::into_inner()` if `finalize()` has not been called.
142    /// You must call `finalize()` to complete the database structure before consuming the writer.
143    ///
144    /// # Example
145    ///
146    /// ```
147    /// use cdb64::{CdbWriter, CdbHash, Error};
148    /// use std::io::Cursor;
149    ///
150    /// let mut writer = CdbWriter::<_, CdbHash>::new(Cursor::new(Vec::new())).unwrap();
151    /// writer.put(b"key", b"value").unwrap();
152    ///
153    /// // This will fail with WriterNotFinalized error
154    /// match writer.into_inner() {
155    ///     Err(Error::WriterNotFinalized) => println!("Expected error!"),
156    ///     _ => panic!("Should have failed"),
157    /// }
158    /// ```
159    #[error("Writer has not been finalized yet")]
160    WriterNotFinalized,
161}