1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
//!
//! 
//! 
//!
//! VSDB is a 'Git' in the form of a KV database.
//!
//! Based on the powerful version control function of VSDB, you can easily give your data structure the ability to version management.
//!
//! **Make everything versioned !!**
//!
//! ## Highlights
//!
//! - Support Git-like verison operations, such as:
//!     - Create countless branches and merge them to their parents
//!     - Rolling back a 'branch' to a specified historical 'version'
//!     - Querying the historical value of a key on the specified 'branch'
//! - Most APIs is similar as the coresponding data structures in the standard library
//!     - Use `Vecx` just like `Vec`
//!     - Use `Mapx` just like `HashMap`
//!     - Use `MapxOrd` just like `BTreeMap`
//! - ...
//!
//! ## Examples
//!
//! Suppose you have a great algorithm like this:
//!
//! ```compile_fail
//! struct GreatAlgo {
//!     a: Vec<...>,
//!     b: BTreeMap<...>,
//!     c: u128,
//!     d: HashMap<...>,
//!     e: ...
//! }
//! ```
//!
//! Simply replace the original structure with the corresponding VSDB data structure,
//! and your algorithm get the powerful version control ability at once!
//!
//! ```compile_fail
//! #[dervive(Vs, Default)]
//! struct GreatAlgo {
//!     a: VecxVs<...>,
//!     b: MapxOrdVs<...>,
//!     c: OrphanVs<u128>,
//!     d: MapxVs<...>,
//!     e: ...
//! }
//!
//! let algo = GreatAlgo.default();
//!
//! algo.get_by_branch_version(...);
//! algo.branch_create(...);
//! algo.branch_create_by_base_branch(...);
//! algo.branch_create_by_base_branch_version(...);
//! algo.branch_remove(...);
//! algo.version_pop(...);
//! algo.prune();
//! ```
//!
//! **NOTE !!**
//!
//! the `#[derive(Vs)]` macro can be applied to structures
//! whose internal fields are all types defined in VSDB
//! (primitive types and their collections are also supported),
//! but can not be applied to nesting wrapper among VSDB-types,
//! you should implement the `VsMgmt` trait(or a part of it) manually.
//!
//! This data structure can be handled correctly by `#[derive(Vs)]`:
//!
//! ```no_run
//! use std::collections::{
//!     HashMap, HashSet, BTreeSet, VecDeque, LinkedList
//! };
//! use std::sync::atomic::AtomicU64;
//! use std::marker::PhantomData;
//! use ruc::*;
//! use vsdb::{
//!     BranchName, VersionName, ParentBranchName,
//!     MapxVs, MapxOrdVs, OrphanVs, VsMgmt, Vs,
//!     VecxVs, impl_vs_methods_nope
//! };
//!
//! #[derive(Vs)]
//! struct GoodCase<K, T> {
//!     a: VecxVs<i64>,
//!     b: SubItem0,
//!     c: SubItem1,
//!     d: SubItem2,
//!     e: u8,
//!     f: Vec<i16>,
//!     g: VecDeque<i64>,
//!     h: BTreeSet<u16>,
//!     i: HashMap<K, AtomicU64>,
//!     j: HashSet<i32>,
//!     k: LinkedList<()>,
//!     l: Box<dyn AsRef<bool>>,
//!     m: Box<dyn AsRef<[Vec<u128>]>>,
//!     n: PhantomData<T>,
//! }
//!
//! #[derive(Vs)]
//! struct SubItem0(MapxVs<u8, u8>, VecxVs<u8>);
//!
//! #[derive(Vs)]
//! struct SubItem1 {
//!     a: OrphanVs<i16>,
//!     b: MapxOrdVs<String, u8>
//! }
//!
//! #[derive(Vs)]
//! struct SubItem2 {
//!     a: i8,
//!     b: u128
//! }
//!
//! // // A nope implementation of `VsMgmt` for custom stateless types.
//! // // the `#[derive(Vs)]` on 'SubItem2' is same as this implementation.
//! // impl VsMgmt for SubItem2 {
//! //     impl_vs_methods_nope!();
//! // }
//! ```
//!
//! **But** this one can NOT be handled correctly by `#[derive(Vs)]`:
//!
//! ```no_run
//! use vsdb::{Vs, VecxVs, MapxVs};
//! use ruc::*;
//!
//! // It can be compiled, but the result is wrong !
//! // The versioned methods of the inner 'MapxVs<u8, u8>' will missing,
//! // you should implement the 'VsMgmt' trait(or a part of it) manually.
//! #[derive(Vs)]
//! struct BadCase {
//!     a: VecxVs<MapxVs<u8, u8>>,
//! }
//! ```
//!
//! Some complete examples:
//! - [**Versioned examples**](versioned/index.html)
//! - [**Unversioned examples**](basic/index.html)
//!
//! ## Compilation features
//!
//! - \[**default**] `sled_engine`, use sled as the backend database
//!     - Faster compilation speed
//!     - Support for compiling into a statically linked binary
//! - `rocks_engine`, use rocksdb as the backend database
//!     - Faster running speed
//!     - Can not be compiled into a statically linked binary
//! - \[**default**] `cbor_codec`, use cbor as the codec
//!     - Faster running speed
//! - `bcs_codec`, use bcs as the codec
//!     - Created by the 'Libre' project of Facebook
//!     - Security reinforcement for blockchain scenarios
//!
//! ## Low-level design
//!
//! Based on the underlying one-dimensional linear storage structure (native kv-database, such as sled/rocksdb, etc.), multiple different namespaces are divided, and then abstract each dimension in the multi-dimensional logical structure based on these divided namespaces.
//!
//! In the category of kv-database, namespaces can be expressed as different key ranges, or different key prefix.
//!
//! This is the same as expressing complex data structures in computer memory(the memory itself is just a one-dimensional linear structure).
//!
//! User data will be divided into two dimensions: 'branch' and 'version', the functions of the 'basic' category are stateless, and the functions of the 'versioned' category are stateful. In the internal implementation, each stateful function is implemented based on its corresponding stateless function,
//! all stateful data has two additional identification dimensions ('branch' and 'version'), somewhat like the logic in Git. Stateless functions do not have the feature of 'version' management, but they have higher performance.
#![deny(warnings)]
#![recursion_limit = "512"]
pub mod basic;
mod common;
pub mod merkle;
pub mod versioned;
pub use basic::mapx::Mapx;
pub use basic::mapx_ord::MapxOrd;
pub use basic::vecx::Vecx;
pub use versioned::mapx::MapxVs;
pub use versioned::mapx_ord::MapxOrdVs;
pub use versioned::orphan::OrphanVs;
pub use versioned::vecx::VecxVs;
pub use versioned::VsMgmt;
pub use vsdb_derive::Vs;
pub use merkle::MerkleTree;
pub use common::{
    ende::{KeyEnDe, KeyEnDeOrdered, ValueEnDe},
    vsdb_flush, vsdb_set_base_dir, BranchName, ParentBranchName, VersionName,
};