bison_db/lib.rs
1//! # bison-db
2//!
3//! An embedded, document-oriented database for Rust: store, index, and query
4//! schemaless documents entirely in-process, with no server, no network, and no
5//! external services. The whole database is one file — trivial to ship, copy,
6//! and back up — and every write is appended to a checksummed log, so a crash
7//! never leaves a half-written record behind.
8//!
9//! `bison-db` is the first member of the Bison family of embedded databases.
10//!
11//! ## The shape of the API
12//!
13//! Three types carry the everyday workflow:
14//!
15//! - [`Document`] — an ordered set of named fields, the record you store.
16//! - [`Value`] — the content of a field: null, bool, integer, float, string,
17//! bytes, array, or a nested document.
18//! - [`Db`] — the single-file store. Insert a document to get a [`DocId`], then
19//! read, overwrite, or delete it by that id.
20//!
21//! ## Quick start
22//!
23//! ```
24//! # fn main() -> bison_db::Result<()> {
25//! use bison_db::{Db, Document};
26//!
27//! # let path = std::env::temp_dir().join("bison_db_lib_quickstart.bison");
28//! # let _ = std::fs::remove_file(&path);
29//! // Open (or create) a store backed by a single file.
30//! let mut db = Db::open(&path)?;
31//!
32//! // Build a schemaless document and insert it.
33//! let mut song = Document::new();
34//! song.set("title", "Take Five").set("year", 1959_i64).set("live", false);
35//! let id = db.insert(song)?;
36//!
37//! // Read it back by id.
38//! let stored = db.get(id)?.expect("just inserted");
39//! assert_eq!(stored.get("title").and_then(|v| v.as_str()), Some("Take Five"));
40//!
41//! // Overwrite, delete, and make it durable.
42//! db.update(id, { let mut d = Document::new(); d.set("title", "So What"); d })?;
43//! assert!(db.delete(id)?);
44//! db.flush()?;
45//! # let _ = std::fs::remove_file(&path);
46//! # Ok(())
47//! # }
48//! ```
49//!
50//! ## Feature flags
51//!
52//! - `std` *(default)* — enables the file-backed [`Db`]. Without it, the crate
53//! is `no_std` and exposes only the in-memory document model ([`Value`],
54//! [`Document`]).
55//! - `serde` — derives `serde::Serialize`/`Deserialize` for [`Value`] and
56//! [`Document`], so documents move in and out of any serde data format.
57//!
58//! ## Durability and recovery
59//!
60//! Writes are visible to later reads immediately and become durable against
61//! power loss after [`Db::flush`]. On open, the log is replayed and verified;
62//! a record torn by a crash is detected by its length and CRC-32C checksum and
63//! truncated, never silently misread. See [`Db::open`] for the full contract.
64
65#![cfg_attr(not(feature = "std"), no_std)]
66#![cfg_attr(docsrs, feature(doc_cfg))]
67#![deny(missing_docs)]
68#![deny(clippy::unwrap_used)]
69#![deny(clippy::expect_used)]
70#![forbid(unsafe_code)]
71
72extern crate alloc;
73
74mod error;
75mod value;
76
77#[cfg(feature = "serde")]
78mod serde_support;
79
80// The binary codec, secondary indexes, and file store are the persistence
81// layer; they require `std` for filesystem access, so the `no_std` build exposes
82// only the document model.
83#[cfg(feature = "std")]
84mod codec;
85#[cfg(feature = "std")]
86mod index;
87#[cfg(feature = "std")]
88mod store;
89#[cfg(feature = "std")]
90mod sys;
91
92pub use error::{Error, Result};
93pub use value::{Document, Value};
94
95#[cfg(feature = "std")]
96pub use store::{Db, DbOptions, DocId, MAX_RECORD_BYTES, Stats, SyncPolicy};