This commit is contained in:
Michael Zhang 2024-06-27 16:24:48 -05:00
commit 2b4aeab092
11 changed files with 1056 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/target

618
Cargo.lock generated Normal file
View file

@ -0,0 +1,618 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "bindgen"
version = "0.60.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6"
dependencies = [
"bitflags 1.3.2",
"cexpr",
"clang-sys",
"clap",
"env_logger",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"which",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "cc"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d"
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "3.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
dependencies = [
"atty",
"bitflags 1.3.2",
"clap_lex",
"indexmap",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "contracts"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1d1429e3bd78171c65aa010eabcdf8f863ba3254728dbfb0ad4b1545beac15c"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "env_logger"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys",
]
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "interval-tree"
version = "0.1.0"
dependencies = [
"contracts",
"itertools",
"sqlite-loadable",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libloading"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d"
dependencies = [
"cfg-if",
"windows-targets",
]
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"minimal-lexical",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "os_str_bytes"
version = "6.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.6.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "serde"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.68",
]
[[package]]
name = "serde_json"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "sqlite-loadable"
version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a916b7bb8738eef189dea88731b619b80bf3f62b3acf05138fa43fbf8621cc94"
dependencies = [
"bitflags 1.3.2",
"serde",
"serde_json",
"sqlite-loadable-macros",
"sqlite3ext-sys",
]
[[package]]
name = "sqlite-loadable-macros"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98bc75a8d6fd24f6a2cfea34f28758780fa17279d3051eec926efa381971e48"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "sqlite3ext-sys"
version = "0.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3afdc2b3dc08f16d6eecf8aa07d19975a268603ab1cca67d3f9b4172c507cf16"
dependencies = [
"bindgen",
"cc",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [
"windows-sys",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

12
Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "interval-tree"
version = "0.1.0"
edition = "2021"
[lib]
crate-type=["cdylib"]
[dependencies]
contracts = { version = "0.6.3", features = ["mirai_assertions"] }
itertools = "0.13.0"
sqlite-loadable = "0.0.5"

1
rustfmt.toml Normal file
View file

@ -0,0 +1 @@
tab_spaces = 2

160
src/lib.rs Normal file
View file

@ -0,0 +1,160 @@
#[macro_use]
extern crate contracts;
// #[macro_use]
// pub mod util;
// pub mod rbtree;
// pub mod rbtree_mem;
// pub mod rbtree_sqlite;
use std::os::raw::{c_char, c_int, c_uint};
use std::ptr::{null, null_mut};
use itertools::Itertools;
use sqlite_loadable::define_virtual_table_writeable;
use sqlite_loadable::prelude::{
register_entrypoint, sqlite3, sqlite3_api_routines, sqlite3_context, sqlite3_value, sqlite3_vtab,
sqlite3_vtab_cursor, sqlite_entrypoint,
};
use sqlite_loadable::table::{
IndexInfo, UpdateOperation, VTab, VTabArguments, VTabCursor, VTabWriteable,
};
use sqlite_loadable::{api, BestIndexError, Result as SqResult};
#[sqlite_entrypoint]
pub fn sqlite3_intervaltree_init(db: *mut sqlite3) -> SqResult<()> {
define_virtual_table_writeable::<IntervalTreeTable>(db, "interval_tree", Some(()))?;
// define_virtual_table_writeable_with_transactions::<IntervalTreeTable>(
// db,
// "interval_tree",
// Some(()),
// )?;
Ok(())
}
#[repr(C)]
struct IntervalTreeTable {
base: sqlite3_vtab,
}
impl IntervalTreeTable {
fn init(
db: *mut sqlite3,
aux: Option<&<IntervalTreeTable as VTab>::Aux>,
args: VTabArguments,
is_create: bool,
) -> SqResult<(String, Self)> {
println!("SHIET {aux:?} {:?}", args.arguments);
let table = Self {
base: sqlite3_vtab {
pModule: null(),
nRef: 0,
zErrMsg: null_mut(),
},
};
let create_sql = if is_create {
format!(
"
CREATE TABLE {orig}_values ({});
CREATE TABLE {orig}_rbtree (
rowid INTEGER PRIMARY KEY AUTOINCREMENT,
parent INTEGER,
left_child INTEGER,
right_child INTEGER
);
",
args
.arguments
.into_iter()
.map(|arg| format!("{arg}"))
.join(", "),
orig = args.table_name,
)
} else {
String::new()
};
println!("SQL: {}", create_sql);
Ok((create_sql, table))
}
}
impl<'a> VTab<'a> for IntervalTreeTable {
type Aux = ();
type Cursor = IntervalTreeTableCursor;
fn create(
db: *mut sqlite3,
aux: Option<&Self::Aux>,
args: VTabArguments,
) -> SqResult<(String, Self)> {
Self::init(db, aux, args, true)
}
fn connect(
db: *mut sqlite3,
aux: Option<&Self::Aux>,
args: VTabArguments,
) -> SqResult<(String, Self)> {
Self::init(db, aux, args, false)
}
fn best_index(&self, info: IndexInfo) -> Result<(), BestIndexError> {
todo!()
}
fn open(&'a mut self) -> SqResult<Self::Cursor> {
Ok(IntervalTreeTableCursor::new())
}
}
impl<'a> VTabWriteable<'a> for IntervalTreeTable {
fn update(&'a mut self, operation: UpdateOperation, p_rowid: *mut i64) -> SqResult<()> {
println!("Operation: {:?}", operation);
println!("Rowid: {}", unsafe { *p_rowid });
todo!()
}
}
#[repr(C)]
struct IntervalTreeTableCursor {
base: sqlite3_vtab_cursor,
}
impl IntervalTreeTableCursor {
pub fn new() -> Self {
IntervalTreeTableCursor {
base: sqlite3_vtab_cursor { pVtab: null_mut() },
}
}
}
impl VTabCursor for IntervalTreeTableCursor {
fn filter(
&mut self,
idx_num: c_int,
idx_str: Option<&str>,
values: &[*mut sqlite3_value],
) -> SqResult<()> {
todo!()
}
fn next(&mut self) -> SqResult<()> {
todo!()
}
fn eof(&self) -> bool {
todo!()
}
fn column(&self, ctx: *mut sqlite3_context, i: c_int) -> SqResult<()> {
todo!()
}
fn rowid(&self) -> SqResult<i64> {
todo!()
}
}

153
src/rbtree.rs Normal file
View file

@ -0,0 +1,153 @@
pub trait Bool {
fn mk_true() -> Self;
fn mk_false() -> Self;
fn if_then_else<T>(&self, a: T, b: T) -> T;
fn value(&self) -> bool;
}
pub trait Color<Bool> {
fn is_red(&self) -> Bool;
fn is_black(&self) -> Bool;
}
#[contract_trait]
pub trait Tree: Sized {
type Bool: Bool;
type NodeId: Clone;
type NodeIter: NodeIter<Self::NodeId>;
type Color: Color<Self::Bool>;
#[ensures(self.property2().value())]
#[ensures(self.property3().value())]
#[ensures(self.property4().value())]
#[ensures(self.property5().value())]
fn root(&self) -> Option<Self::NodeId>;
fn node_color(&self, id: &Self::NodeId) -> Self::Color;
fn node_parent(&self, id: &Self::NodeId) -> Option<Self::NodeId>;
fn node_get_left(&self, id: &Self::NodeId) -> Option<Self::NodeId>;
fn node_get_right(&self, id: &Self::NodeId) -> Option<Self::NodeId>;
fn node_set_left(&mut self, id: &Self::NodeId, child: Option<Self::NodeId>);
fn node_set_right(&mut self, id: &Self::NodeId, child: Option<Self::NodeId>);
#[inline]
fn node_is_leaf(&self, id: &Self::NodeId) -> bool {
self.node_get_left(id).is_none() && self.node_get_right(id).is_none()
}
#[inline]
fn node_is_red(&self, id: &Self::NodeId) -> Self::Bool {
self.node_color(id).is_red()
}
#[inline]
fn node_is_black(&self, id: &Self::NodeId) -> Self::Bool {
self.node_color(id).is_black()
}
#[inline]
fn node_path_length(&self, id: Self::NodeId) -> usize {
let mut ctr = 0;
let mut curr = id;
while let Some(parent) = self.node_parent(&curr) {
ctr += 1;
curr = parent;
}
ctr
}
// #[inline]
// fn node_iter<'a>(&'a self) -> NodeIter<'a, Self> {
// let mut queue = VecDeque::new();
// if let Some(root) = self.root() {
// queue.push_back(root);
// }
// NodeIter { tree: self, queue }
// }
/// Property 2: The root is black
fn property2(&self) -> Self::Bool {
self
.root()
.map(|root| self.node_is_black(&root))
.unwrap_or(true)
}
/// Property 3: Every leaf is black
fn property3(&self) -> Self::Bool {
self
.node_iter()
.filter(|node| self.node_is_leaf(node))
.all(|node| self.node_is_black(&node))
}
/// Property 4: If a node is red, then both its children are black
fn property4(&self) -> Self::Bool {
self
.node_iter()
.filter(|node| self.node_is_red(node))
.all(|node| {
self
.node_get_left(&node)
.map(|node| self.node_is_black(&node))
.unwrap_or(true)
&& self
.node_get_right(&node)
.map(|node| self.node_is_black(&node))
.unwrap_or(true)
})
}
/// Property 5: all paths take the same number of black nodes
fn property5(&self) -> Self::Bool {
let mut iter = self
.node_iter()
.filter(|node| self.node_is_leaf(node))
.map(|node| self.node_path_length(node));
let first = match iter.next() {
Some(n) => n,
None => return true,
};
iter.all(|m| m == first)
}
}
pub trait NodeIter<NodeId> {
fn next(&mut self) -> Option<NodeId>;
}
// pub struct NodeIter<'a, T: Tree + Sized> {
// tree: &'a T,
// queue: VecDeque<T::NodeId>,
// }
// impl<'a, T: Tree + Sized> Iterator for NodeIter<'a, T> {
// type Item = T::NodeId;
// #[inline]
// fn next(&mut self) -> Option<Self::Item> {
// let node = match self.queue.pop_front() {
// Some(n) => n,
// None => return None,
// };
// if let Some(left) = self.tree.node_get_left(&node) {
// self.queue.push_back(left);
// }
// if let Some(right) = self.tree.node_get_right(&node) {
// self.queue.push_back(right);
// }
// Some(node)
// }
// }

80
src/rbtree_mem.rs Normal file
View file

@ -0,0 +1,80 @@
use crate::rbtree::{self, Tree};
pub struct RbTreeMem<T> {
root: Option<usize>,
nodes: Vec<RbNodeMem<T>>,
}
struct RbNodeMem<T> {
parent: Option<usize>,
left_child: Option<usize>,
right_child: Option<usize>,
color: Color,
data: T,
}
impl<T> RbTreeMem<T> {
pub fn node_data(&self, id: &usize) -> &T {
&self.nodes[*id].data
}
}
#[contract_trait]
impl<T> Tree for RbTreeMem<T> {
type NodeId = usize;
fn root(&self) -> Option<usize> {
self.root
}
fn node_color(&self, id: &usize) -> Color {
self.nodes[*id].color
}
fn node_parent(&self, id: &usize) -> Option<usize> {
self.nodes[*id].parent
}
fn node_get_left(&self, id: &usize) -> Option<usize> {
self.nodes[*id].left_child
}
fn node_get_right(&self, id: &usize) -> Option<usize> {
self.nodes[*id].right_child
}
fn node_set_left(&mut self, id: &usize, child: Option<usize>) {
self.nodes[*id].left_child = child;
}
fn node_set_right(&mut self, id: &usize, child: Option<usize>) {
self.nodes[*id].right_child = child;
}
}
#[cfg(test)]
mod tests {
#[test]
fn test() {}
}
pub enum Color {
Red,
Black,
}
impl<B: rbtree::Bool> rbtree::Color<B> for Color {
fn is_red(&self) -> B {
match self {
Color::Red => B::mk_true(),
Color::Black => B::mk_false(),
}
}
fn is_black(&self) -> B {
match self {
Color::Red => B::mk_false(),
Color::Black => B::mk_true(),
}
}
}

1
src/rbtree_sqlite.rs Normal file
View file

@ -0,0 +1 @@
pub struct RbTreeSqlite {}

15
src/util.rs Normal file
View file

@ -0,0 +1,15 @@
macro_rules! debug_checked_precondition {
($condition:expr, $($arg:tt)*) => ( debug_assert!($condition, $($arg)*); );
}
macro_rules! debug_checked_postcondition {
($condition:expr, $($arg:tt)*) => ( debug_assert!($condition, $($arg)*); );
}
macro_rules! checked_precondition {
($condition:expr, $($arg:tt)*) => ( assert!($condition, $($arg)*); );
}
macro_rules! checked_postcondition {
($condition:expr, $($arg:tt)*) => ( assert!($condition, $($arg)*); );
}

5
test.sh Executable file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env bash
cargo build -q
sqlite3 ':memory:' '.read test.sql'

9
test.sql Normal file
View file

@ -0,0 +1,9 @@
.header on
.load target/debug/libinterval_tree
CREATE VIRTUAL TABLE helloge USING interval_tree(id, start, end);
INSERT INTO helloge (start, end) VALUES (10, 20);
SELECT * FROM helloge_rbtree;