this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Initial implementation of GigaBrain graph database

- Core graph data structures with nodes and relationships
- Memory-based storage engine with persistence interface
- Cypher query lexer and parser with AST
- Query planner and executor framework
- Indexing system with label and property indexes
- Transaction manager with ACID support
- Distributed sharding capability
- B-tree and WAL storage components

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

Cameron Pfiffer dd10f26a

+4422
+2119
Cargo.lock
··· 1 + # This file is automatically @generated by Cargo. 2 + # It is not intended for manual editing. 3 + version = 4 4 + 5 + [[package]] 6 + name = "addr2line" 7 + version = "0.24.2" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 10 + dependencies = [ 11 + "gimli", 12 + ] 13 + 14 + [[package]] 15 + name = "adler2" 16 + version = "2.0.1" 17 + source = "registry+https://github.com/rust-lang/crates.io-index" 18 + checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" 19 + 20 + [[package]] 21 + name = "ahash" 22 + version = "0.8.12" 23 + source = "registry+https://github.com/rust-lang/crates.io-index" 24 + checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" 25 + dependencies = [ 26 + "cfg-if", 27 + "getrandom 0.3.3", 28 + "once_cell", 29 + "version_check", 30 + "zerocopy", 31 + ] 32 + 33 + [[package]] 34 + name = "aho-corasick" 35 + version = "1.1.3" 36 + source = "registry+https://github.com/rust-lang/crates.io-index" 37 + checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 38 + dependencies = [ 39 + "memchr", 40 + ] 41 + 42 + [[package]] 43 + name = "allocator-api2" 44 + version = "0.2.21" 45 + source = "registry+https://github.com/rust-lang/crates.io-index" 46 + checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" 47 + 48 + [[package]] 49 + name = "anes" 50 + version = "0.1.6" 51 + source = "registry+https://github.com/rust-lang/crates.io-index" 52 + checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" 53 + 54 + [[package]] 55 + name = "anstyle" 56 + version = "1.0.11" 57 + source = "registry+https://github.com/rust-lang/crates.io-index" 58 + checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" 59 + 60 + [[package]] 61 + name = "anyhow" 62 + version = "1.0.98" 63 + source = "registry+https://github.com/rust-lang/crates.io-index" 64 + checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 65 + 66 + [[package]] 67 + name = "async-stream" 68 + version = "0.3.6" 69 + source = "registry+https://github.com/rust-lang/crates.io-index" 70 + checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" 71 + dependencies = [ 72 + "async-stream-impl", 73 + "futures-core", 74 + "pin-project-lite", 75 + ] 76 + 77 + [[package]] 78 + name = "async-stream-impl" 79 + version = "0.3.6" 80 + source = "registry+https://github.com/rust-lang/crates.io-index" 81 + checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" 82 + dependencies = [ 83 + "proc-macro2", 84 + "quote", 85 + "syn", 86 + ] 87 + 88 + [[package]] 89 + name = "async-trait" 90 + version = "0.1.88" 91 + source = "registry+https://github.com/rust-lang/crates.io-index" 92 + checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" 93 + dependencies = [ 94 + "proc-macro2", 95 + "quote", 96 + "syn", 97 + ] 98 + 99 + [[package]] 100 + name = "atomic-waker" 101 + version = "1.1.2" 102 + source = "registry+https://github.com/rust-lang/crates.io-index" 103 + checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 104 + 105 + [[package]] 106 + name = "autocfg" 107 + version = "1.5.0" 108 + source = "registry+https://github.com/rust-lang/crates.io-index" 109 + checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 110 + 111 + [[package]] 112 + name = "axum" 113 + version = "0.7.9" 114 + source = "registry+https://github.com/rust-lang/crates.io-index" 115 + checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" 116 + dependencies = [ 117 + "async-trait", 118 + "axum-core", 119 + "bytes", 120 + "futures-util", 121 + "http", 122 + "http-body", 123 + "http-body-util", 124 + "itoa", 125 + "matchit", 126 + "memchr", 127 + "mime", 128 + "percent-encoding", 129 + "pin-project-lite", 130 + "rustversion", 131 + "serde", 132 + "sync_wrapper", 133 + "tower 0.5.2", 134 + "tower-layer", 135 + "tower-service", 136 + ] 137 + 138 + [[package]] 139 + name = "axum-core" 140 + version = "0.4.5" 141 + source = "registry+https://github.com/rust-lang/crates.io-index" 142 + checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" 143 + dependencies = [ 144 + "async-trait", 145 + "bytes", 146 + "futures-util", 147 + "http", 148 + "http-body", 149 + "http-body-util", 150 + "mime", 151 + "pin-project-lite", 152 + "rustversion", 153 + "sync_wrapper", 154 + "tower-layer", 155 + "tower-service", 156 + ] 157 + 158 + [[package]] 159 + name = "backtrace" 160 + version = "0.3.75" 161 + source = "registry+https://github.com/rust-lang/crates.io-index" 162 + checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" 163 + dependencies = [ 164 + "addr2line", 165 + "cfg-if", 166 + "libc", 167 + "miniz_oxide", 168 + "object", 169 + "rustc-demangle", 170 + "windows-targets 0.52.6", 171 + ] 172 + 173 + [[package]] 174 + name = "base64" 175 + version = "0.22.1" 176 + source = "registry+https://github.com/rust-lang/crates.io-index" 177 + checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 178 + 179 + [[package]] 180 + name = "bincode" 181 + version = "1.3.3" 182 + source = "registry+https://github.com/rust-lang/crates.io-index" 183 + checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" 184 + dependencies = [ 185 + "serde", 186 + ] 187 + 188 + [[package]] 189 + name = "bit-set" 190 + version = "0.8.0" 191 + source = "registry+https://github.com/rust-lang/crates.io-index" 192 + checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" 193 + dependencies = [ 194 + "bit-vec", 195 + ] 196 + 197 + [[package]] 198 + name = "bit-vec" 199 + version = "0.8.0" 200 + source = "registry+https://github.com/rust-lang/crates.io-index" 201 + checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" 202 + 203 + [[package]] 204 + name = "bitflags" 205 + version = "2.9.1" 206 + source = "registry+https://github.com/rust-lang/crates.io-index" 207 + checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 208 + 209 + [[package]] 210 + name = "bumpalo" 211 + version = "3.19.0" 212 + source = "registry+https://github.com/rust-lang/crates.io-index" 213 + checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" 214 + 215 + [[package]] 216 + name = "bytemuck" 217 + version = "1.23.1" 218 + source = "registry+https://github.com/rust-lang/crates.io-index" 219 + checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" 220 + 221 + [[package]] 222 + name = "byteorder" 223 + version = "1.5.0" 224 + source = "registry+https://github.com/rust-lang/crates.io-index" 225 + checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 226 + 227 + [[package]] 228 + name = "bytes" 229 + version = "1.10.1" 230 + source = "registry+https://github.com/rust-lang/crates.io-index" 231 + checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 232 + 233 + [[package]] 234 + name = "cast" 235 + version = "0.3.0" 236 + source = "registry+https://github.com/rust-lang/crates.io-index" 237 + checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" 238 + 239 + [[package]] 240 + name = "cfg-if" 241 + version = "1.0.1" 242 + source = "registry+https://github.com/rust-lang/crates.io-index" 243 + checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" 244 + 245 + [[package]] 246 + name = "ciborium" 247 + version = "0.2.2" 248 + source = "registry+https://github.com/rust-lang/crates.io-index" 249 + checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" 250 + dependencies = [ 251 + "ciborium-io", 252 + "ciborium-ll", 253 + "serde", 254 + ] 255 + 256 + [[package]] 257 + name = "ciborium-io" 258 + version = "0.2.2" 259 + source = "registry+https://github.com/rust-lang/crates.io-index" 260 + checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" 261 + 262 + [[package]] 263 + name = "ciborium-ll" 264 + version = "0.2.2" 265 + source = "registry+https://github.com/rust-lang/crates.io-index" 266 + checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 267 + dependencies = [ 268 + "ciborium-io", 269 + "half", 270 + ] 271 + 272 + [[package]] 273 + name = "clap" 274 + version = "4.5.40" 275 + source = "registry+https://github.com/rust-lang/crates.io-index" 276 + checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" 277 + dependencies = [ 278 + "clap_builder", 279 + ] 280 + 281 + [[package]] 282 + name = "clap_builder" 283 + version = "4.5.40" 284 + source = "registry+https://github.com/rust-lang/crates.io-index" 285 + checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" 286 + dependencies = [ 287 + "anstyle", 288 + "clap_lex", 289 + ] 290 + 291 + [[package]] 292 + name = "clap_lex" 293 + version = "0.7.5" 294 + source = "registry+https://github.com/rust-lang/crates.io-index" 295 + checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" 296 + 297 + [[package]] 298 + name = "criterion" 299 + version = "0.5.1" 300 + source = "registry+https://github.com/rust-lang/crates.io-index" 301 + checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" 302 + dependencies = [ 303 + "anes", 304 + "cast", 305 + "ciborium", 306 + "clap", 307 + "criterion-plot", 308 + "is-terminal", 309 + "itertools 0.10.5", 310 + "num-traits", 311 + "once_cell", 312 + "oorandom", 313 + "plotters", 314 + "rayon", 315 + "regex", 316 + "serde", 317 + "serde_derive", 318 + "serde_json", 319 + "tinytemplate", 320 + "walkdir", 321 + ] 322 + 323 + [[package]] 324 + name = "criterion-plot" 325 + version = "0.5.0" 326 + source = "registry+https://github.com/rust-lang/crates.io-index" 327 + checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" 328 + dependencies = [ 329 + "cast", 330 + "itertools 0.10.5", 331 + ] 332 + 333 + [[package]] 334 + name = "crossbeam" 335 + version = "0.8.4" 336 + source = "registry+https://github.com/rust-lang/crates.io-index" 337 + checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" 338 + dependencies = [ 339 + "crossbeam-channel", 340 + "crossbeam-deque", 341 + "crossbeam-epoch", 342 + "crossbeam-queue", 343 + "crossbeam-utils", 344 + ] 345 + 346 + [[package]] 347 + name = "crossbeam-channel" 348 + version = "0.5.15" 349 + source = "registry+https://github.com/rust-lang/crates.io-index" 350 + checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" 351 + dependencies = [ 352 + "crossbeam-utils", 353 + ] 354 + 355 + [[package]] 356 + name = "crossbeam-deque" 357 + version = "0.8.6" 358 + source = "registry+https://github.com/rust-lang/crates.io-index" 359 + checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 360 + dependencies = [ 361 + "crossbeam-epoch", 362 + "crossbeam-utils", 363 + ] 364 + 365 + [[package]] 366 + name = "crossbeam-epoch" 367 + version = "0.9.18" 368 + source = "registry+https://github.com/rust-lang/crates.io-index" 369 + checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 370 + dependencies = [ 371 + "crossbeam-utils", 372 + ] 373 + 374 + [[package]] 375 + name = "crossbeam-queue" 376 + version = "0.3.12" 377 + source = "registry+https://github.com/rust-lang/crates.io-index" 378 + checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" 379 + dependencies = [ 380 + "crossbeam-utils", 381 + ] 382 + 383 + [[package]] 384 + name = "crossbeam-utils" 385 + version = "0.8.21" 386 + source = "registry+https://github.com/rust-lang/crates.io-index" 387 + checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 388 + 389 + [[package]] 390 + name = "crunchy" 391 + version = "0.2.4" 392 + source = "registry+https://github.com/rust-lang/crates.io-index" 393 + checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" 394 + 395 + [[package]] 396 + name = "dashmap" 397 + version = "6.1.0" 398 + source = "registry+https://github.com/rust-lang/crates.io-index" 399 + checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" 400 + dependencies = [ 401 + "cfg-if", 402 + "crossbeam-utils", 403 + "hashbrown 0.14.5", 404 + "lock_api", 405 + "once_cell", 406 + "parking_lot_core", 407 + ] 408 + 409 + [[package]] 410 + name = "either" 411 + version = "1.15.0" 412 + source = "registry+https://github.com/rust-lang/crates.io-index" 413 + checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 414 + 415 + [[package]] 416 + name = "equivalent" 417 + version = "1.0.2" 418 + source = "registry+https://github.com/rust-lang/crates.io-index" 419 + checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 420 + 421 + [[package]] 422 + name = "errno" 423 + version = "0.3.13" 424 + source = "registry+https://github.com/rust-lang/crates.io-index" 425 + checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" 426 + dependencies = [ 427 + "libc", 428 + "windows-sys 0.60.2", 429 + ] 430 + 431 + [[package]] 432 + name = "fastrand" 433 + version = "2.3.0" 434 + source = "registry+https://github.com/rust-lang/crates.io-index" 435 + checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" 436 + 437 + [[package]] 438 + name = "fixedbitset" 439 + version = "0.4.2" 440 + source = "registry+https://github.com/rust-lang/crates.io-index" 441 + checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" 442 + 443 + [[package]] 444 + name = "fixedbitset" 445 + version = "0.5.7" 446 + source = "registry+https://github.com/rust-lang/crates.io-index" 447 + checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" 448 + 449 + [[package]] 450 + name = "fnv" 451 + version = "1.0.7" 452 + source = "registry+https://github.com/rust-lang/crates.io-index" 453 + checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 454 + 455 + [[package]] 456 + name = "foldhash" 457 + version = "0.1.5" 458 + source = "registry+https://github.com/rust-lang/crates.io-index" 459 + checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 460 + 461 + [[package]] 462 + name = "futures-channel" 463 + version = "0.3.31" 464 + source = "registry+https://github.com/rust-lang/crates.io-index" 465 + checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 466 + dependencies = [ 467 + "futures-core", 468 + ] 469 + 470 + [[package]] 471 + name = "futures-core" 472 + version = "0.3.31" 473 + source = "registry+https://github.com/rust-lang/crates.io-index" 474 + checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 475 + 476 + [[package]] 477 + name = "futures-sink" 478 + version = "0.3.31" 479 + source = "registry+https://github.com/rust-lang/crates.io-index" 480 + checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 481 + 482 + [[package]] 483 + name = "futures-task" 484 + version = "0.3.31" 485 + source = "registry+https://github.com/rust-lang/crates.io-index" 486 + checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 487 + 488 + [[package]] 489 + name = "futures-util" 490 + version = "0.3.31" 491 + source = "registry+https://github.com/rust-lang/crates.io-index" 492 + checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 493 + dependencies = [ 494 + "futures-core", 495 + "futures-task", 496 + "pin-project-lite", 497 + "pin-utils", 498 + ] 499 + 500 + [[package]] 501 + name = "getrandom" 502 + version = "0.2.16" 503 + source = "registry+https://github.com/rust-lang/crates.io-index" 504 + checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 505 + dependencies = [ 506 + "cfg-if", 507 + "libc", 508 + "wasi 0.11.1+wasi-snapshot-preview1", 509 + ] 510 + 511 + [[package]] 512 + name = "getrandom" 513 + version = "0.3.3" 514 + source = "registry+https://github.com/rust-lang/crates.io-index" 515 + checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 516 + dependencies = [ 517 + "cfg-if", 518 + "libc", 519 + "r-efi", 520 + "wasi 0.14.2+wasi-0.2.4", 521 + ] 522 + 523 + [[package]] 524 + name = "gigabrain" 525 + version = "0.1.0" 526 + dependencies = [ 527 + "ahash", 528 + "async-trait", 529 + "bincode", 530 + "bytes", 531 + "criterion", 532 + "crossbeam", 533 + "dashmap", 534 + "lru", 535 + "memmap2", 536 + "nom", 537 + "num_cpus", 538 + "parking_lot", 539 + "petgraph 0.6.5", 540 + "proptest", 541 + "prost", 542 + "rayon", 543 + "roaring", 544 + "serde", 545 + "tempfile", 546 + "thiserror", 547 + "tokio", 548 + "tonic", 549 + "tonic-build", 550 + "tower 0.5.2", 551 + "tracing", 552 + "tracing-subscriber", 553 + "uuid", 554 + ] 555 + 556 + [[package]] 557 + name = "gimli" 558 + version = "0.31.1" 559 + source = "registry+https://github.com/rust-lang/crates.io-index" 560 + checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 561 + 562 + [[package]] 563 + name = "h2" 564 + version = "0.4.10" 565 + source = "registry+https://github.com/rust-lang/crates.io-index" 566 + checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" 567 + dependencies = [ 568 + "atomic-waker", 569 + "bytes", 570 + "fnv", 571 + "futures-core", 572 + "futures-sink", 573 + "http", 574 + "indexmap 2.9.0", 575 + "slab", 576 + "tokio", 577 + "tokio-util", 578 + "tracing", 579 + ] 580 + 581 + [[package]] 582 + name = "half" 583 + version = "2.6.0" 584 + source = "registry+https://github.com/rust-lang/crates.io-index" 585 + checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" 586 + dependencies = [ 587 + "cfg-if", 588 + "crunchy", 589 + ] 590 + 591 + [[package]] 592 + name = "hashbrown" 593 + version = "0.12.3" 594 + source = "registry+https://github.com/rust-lang/crates.io-index" 595 + checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 596 + 597 + [[package]] 598 + name = "hashbrown" 599 + version = "0.14.5" 600 + source = "registry+https://github.com/rust-lang/crates.io-index" 601 + checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 602 + 603 + [[package]] 604 + name = "hashbrown" 605 + version = "0.15.4" 606 + source = "registry+https://github.com/rust-lang/crates.io-index" 607 + checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" 608 + dependencies = [ 609 + "allocator-api2", 610 + "equivalent", 611 + "foldhash", 612 + ] 613 + 614 + [[package]] 615 + name = "heck" 616 + version = "0.5.0" 617 + source = "registry+https://github.com/rust-lang/crates.io-index" 618 + checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 619 + 620 + [[package]] 621 + name = "hermit-abi" 622 + version = "0.5.2" 623 + source = "registry+https://github.com/rust-lang/crates.io-index" 624 + checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" 625 + 626 + [[package]] 627 + name = "http" 628 + version = "1.3.1" 629 + source = "registry+https://github.com/rust-lang/crates.io-index" 630 + checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 631 + dependencies = [ 632 + "bytes", 633 + "fnv", 634 + "itoa", 635 + ] 636 + 637 + [[package]] 638 + name = "http-body" 639 + version = "1.0.1" 640 + source = "registry+https://github.com/rust-lang/crates.io-index" 641 + checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 642 + dependencies = [ 643 + "bytes", 644 + "http", 645 + ] 646 + 647 + [[package]] 648 + name = "http-body-util" 649 + version = "0.1.3" 650 + source = "registry+https://github.com/rust-lang/crates.io-index" 651 + checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 652 + dependencies = [ 653 + "bytes", 654 + "futures-core", 655 + "http", 656 + "http-body", 657 + "pin-project-lite", 658 + ] 659 + 660 + [[package]] 661 + name = "httparse" 662 + version = "1.10.1" 663 + source = "registry+https://github.com/rust-lang/crates.io-index" 664 + checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 665 + 666 + [[package]] 667 + name = "httpdate" 668 + version = "1.0.3" 669 + source = "registry+https://github.com/rust-lang/crates.io-index" 670 + checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 671 + 672 + [[package]] 673 + name = "hyper" 674 + version = "1.6.0" 675 + source = "registry+https://github.com/rust-lang/crates.io-index" 676 + checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" 677 + dependencies = [ 678 + "bytes", 679 + "futures-channel", 680 + "futures-util", 681 + "h2", 682 + "http", 683 + "http-body", 684 + "httparse", 685 + "httpdate", 686 + "itoa", 687 + "pin-project-lite", 688 + "smallvec", 689 + "tokio", 690 + "want", 691 + ] 692 + 693 + [[package]] 694 + name = "hyper-timeout" 695 + version = "0.5.2" 696 + source = "registry+https://github.com/rust-lang/crates.io-index" 697 + checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" 698 + dependencies = [ 699 + "hyper", 700 + "hyper-util", 701 + "pin-project-lite", 702 + "tokio", 703 + "tower-service", 704 + ] 705 + 706 + [[package]] 707 + name = "hyper-util" 708 + version = "0.1.14" 709 + source = "registry+https://github.com/rust-lang/crates.io-index" 710 + checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" 711 + dependencies = [ 712 + "bytes", 713 + "futures-channel", 714 + "futures-core", 715 + "futures-util", 716 + "http", 717 + "http-body", 718 + "hyper", 719 + "libc", 720 + "pin-project-lite", 721 + "socket2", 722 + "tokio", 723 + "tower-service", 724 + "tracing", 725 + ] 726 + 727 + [[package]] 728 + name = "indexmap" 729 + version = "1.9.3" 730 + source = "registry+https://github.com/rust-lang/crates.io-index" 731 + checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 732 + dependencies = [ 733 + "autocfg", 734 + "hashbrown 0.12.3", 735 + ] 736 + 737 + [[package]] 738 + name = "indexmap" 739 + version = "2.9.0" 740 + source = "registry+https://github.com/rust-lang/crates.io-index" 741 + checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" 742 + dependencies = [ 743 + "equivalent", 744 + "hashbrown 0.15.4", 745 + ] 746 + 747 + [[package]] 748 + name = "is-terminal" 749 + version = "0.4.16" 750 + source = "registry+https://github.com/rust-lang/crates.io-index" 751 + checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" 752 + dependencies = [ 753 + "hermit-abi", 754 + "libc", 755 + "windows-sys 0.59.0", 756 + ] 757 + 758 + [[package]] 759 + name = "itertools" 760 + version = "0.10.5" 761 + source = "registry+https://github.com/rust-lang/crates.io-index" 762 + checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 763 + dependencies = [ 764 + "either", 765 + ] 766 + 767 + [[package]] 768 + name = "itertools" 769 + version = "0.14.0" 770 + source = "registry+https://github.com/rust-lang/crates.io-index" 771 + checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" 772 + dependencies = [ 773 + "either", 774 + ] 775 + 776 + [[package]] 777 + name = "itoa" 778 + version = "1.0.15" 779 + source = "registry+https://github.com/rust-lang/crates.io-index" 780 + checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 781 + 782 + [[package]] 783 + name = "js-sys" 784 + version = "0.3.77" 785 + source = "registry+https://github.com/rust-lang/crates.io-index" 786 + checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 787 + dependencies = [ 788 + "once_cell", 789 + "wasm-bindgen", 790 + ] 791 + 792 + [[package]] 793 + name = "lazy_static" 794 + version = "1.5.0" 795 + source = "registry+https://github.com/rust-lang/crates.io-index" 796 + checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 797 + 798 + [[package]] 799 + name = "libc" 800 + version = "0.2.174" 801 + source = "registry+https://github.com/rust-lang/crates.io-index" 802 + checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" 803 + 804 + [[package]] 805 + name = "linux-raw-sys" 806 + version = "0.9.4" 807 + source = "registry+https://github.com/rust-lang/crates.io-index" 808 + checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" 809 + 810 + [[package]] 811 + name = "lock_api" 812 + version = "0.4.13" 813 + source = "registry+https://github.com/rust-lang/crates.io-index" 814 + checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" 815 + dependencies = [ 816 + "autocfg", 817 + "scopeguard", 818 + ] 819 + 820 + [[package]] 821 + name = "log" 822 + version = "0.4.27" 823 + source = "registry+https://github.com/rust-lang/crates.io-index" 824 + checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 825 + 826 + [[package]] 827 + name = "lru" 828 + version = "0.12.5" 829 + source = "registry+https://github.com/rust-lang/crates.io-index" 830 + checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" 831 + dependencies = [ 832 + "hashbrown 0.15.4", 833 + ] 834 + 835 + [[package]] 836 + name = "matchers" 837 + version = "0.1.0" 838 + source = "registry+https://github.com/rust-lang/crates.io-index" 839 + checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 840 + dependencies = [ 841 + "regex-automata 0.1.10", 842 + ] 843 + 844 + [[package]] 845 + name = "matchit" 846 + version = "0.7.3" 847 + source = "registry+https://github.com/rust-lang/crates.io-index" 848 + checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" 849 + 850 + [[package]] 851 + name = "memchr" 852 + version = "2.7.5" 853 + source = "registry+https://github.com/rust-lang/crates.io-index" 854 + checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" 855 + 856 + [[package]] 857 + name = "memmap2" 858 + version = "0.9.5" 859 + source = "registry+https://github.com/rust-lang/crates.io-index" 860 + checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" 861 + dependencies = [ 862 + "libc", 863 + ] 864 + 865 + [[package]] 866 + name = "mime" 867 + version = "0.3.17" 868 + source = "registry+https://github.com/rust-lang/crates.io-index" 869 + checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 870 + 871 + [[package]] 872 + name = "minimal-lexical" 873 + version = "0.2.1" 874 + source = "registry+https://github.com/rust-lang/crates.io-index" 875 + checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 876 + 877 + [[package]] 878 + name = "miniz_oxide" 879 + version = "0.8.9" 880 + source = "registry+https://github.com/rust-lang/crates.io-index" 881 + checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" 882 + dependencies = [ 883 + "adler2", 884 + ] 885 + 886 + [[package]] 887 + name = "mio" 888 + version = "1.0.4" 889 + source = "registry+https://github.com/rust-lang/crates.io-index" 890 + checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" 891 + dependencies = [ 892 + "libc", 893 + "wasi 0.11.1+wasi-snapshot-preview1", 894 + "windows-sys 0.59.0", 895 + ] 896 + 897 + [[package]] 898 + name = "multimap" 899 + version = "0.10.1" 900 + source = "registry+https://github.com/rust-lang/crates.io-index" 901 + checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" 902 + 903 + [[package]] 904 + name = "nom" 905 + version = "7.1.3" 906 + source = "registry+https://github.com/rust-lang/crates.io-index" 907 + checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 908 + dependencies = [ 909 + "memchr", 910 + "minimal-lexical", 911 + ] 912 + 913 + [[package]] 914 + name = "nu-ansi-term" 915 + version = "0.46.0" 916 + source = "registry+https://github.com/rust-lang/crates.io-index" 917 + checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 918 + dependencies = [ 919 + "overload", 920 + "winapi", 921 + ] 922 + 923 + [[package]] 924 + name = "num-traits" 925 + version = "0.2.19" 926 + source = "registry+https://github.com/rust-lang/crates.io-index" 927 + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 928 + dependencies = [ 929 + "autocfg", 930 + ] 931 + 932 + [[package]] 933 + name = "num_cpus" 934 + version = "1.17.0" 935 + source = "registry+https://github.com/rust-lang/crates.io-index" 936 + checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" 937 + dependencies = [ 938 + "hermit-abi", 939 + "libc", 940 + ] 941 + 942 + [[package]] 943 + name = "object" 944 + version = "0.36.7" 945 + source = "registry+https://github.com/rust-lang/crates.io-index" 946 + checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" 947 + dependencies = [ 948 + "memchr", 949 + ] 950 + 951 + [[package]] 952 + name = "once_cell" 953 + version = "1.21.3" 954 + source = "registry+https://github.com/rust-lang/crates.io-index" 955 + checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 956 + 957 + [[package]] 958 + name = "oorandom" 959 + version = "11.1.5" 960 + source = "registry+https://github.com/rust-lang/crates.io-index" 961 + checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" 962 + 963 + [[package]] 964 + name = "overload" 965 + version = "0.1.1" 966 + source = "registry+https://github.com/rust-lang/crates.io-index" 967 + checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 968 + 969 + [[package]] 970 + name = "parking_lot" 971 + version = "0.12.4" 972 + source = "registry+https://github.com/rust-lang/crates.io-index" 973 + checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" 974 + dependencies = [ 975 + "lock_api", 976 + "parking_lot_core", 977 + ] 978 + 979 + [[package]] 980 + name = "parking_lot_core" 981 + version = "0.9.11" 982 + source = "registry+https://github.com/rust-lang/crates.io-index" 983 + checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" 984 + dependencies = [ 985 + "cfg-if", 986 + "libc", 987 + "redox_syscall", 988 + "smallvec", 989 + "windows-targets 0.52.6", 990 + ] 991 + 992 + [[package]] 993 + name = "percent-encoding" 994 + version = "2.3.1" 995 + source = "registry+https://github.com/rust-lang/crates.io-index" 996 + checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 997 + 998 + [[package]] 999 + name = "petgraph" 1000 + version = "0.6.5" 1001 + source = "registry+https://github.com/rust-lang/crates.io-index" 1002 + checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" 1003 + dependencies = [ 1004 + "fixedbitset 0.4.2", 1005 + "indexmap 2.9.0", 1006 + ] 1007 + 1008 + [[package]] 1009 + name = "petgraph" 1010 + version = "0.7.1" 1011 + source = "registry+https://github.com/rust-lang/crates.io-index" 1012 + checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" 1013 + dependencies = [ 1014 + "fixedbitset 0.5.7", 1015 + "indexmap 2.9.0", 1016 + ] 1017 + 1018 + [[package]] 1019 + name = "pin-project" 1020 + version = "1.1.10" 1021 + source = "registry+https://github.com/rust-lang/crates.io-index" 1022 + checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" 1023 + dependencies = [ 1024 + "pin-project-internal", 1025 + ] 1026 + 1027 + [[package]] 1028 + name = "pin-project-internal" 1029 + version = "1.1.10" 1030 + source = "registry+https://github.com/rust-lang/crates.io-index" 1031 + checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" 1032 + dependencies = [ 1033 + "proc-macro2", 1034 + "quote", 1035 + "syn", 1036 + ] 1037 + 1038 + [[package]] 1039 + name = "pin-project-lite" 1040 + version = "0.2.16" 1041 + source = "registry+https://github.com/rust-lang/crates.io-index" 1042 + checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 1043 + 1044 + [[package]] 1045 + name = "pin-utils" 1046 + version = "0.1.0" 1047 + source = "registry+https://github.com/rust-lang/crates.io-index" 1048 + checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1049 + 1050 + [[package]] 1051 + name = "plotters" 1052 + version = "0.3.7" 1053 + source = "registry+https://github.com/rust-lang/crates.io-index" 1054 + checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" 1055 + dependencies = [ 1056 + "num-traits", 1057 + "plotters-backend", 1058 + "plotters-svg", 1059 + "wasm-bindgen", 1060 + "web-sys", 1061 + ] 1062 + 1063 + [[package]] 1064 + name = "plotters-backend" 1065 + version = "0.3.7" 1066 + source = "registry+https://github.com/rust-lang/crates.io-index" 1067 + checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" 1068 + 1069 + [[package]] 1070 + name = "plotters-svg" 1071 + version = "0.3.7" 1072 + source = "registry+https://github.com/rust-lang/crates.io-index" 1073 + checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" 1074 + dependencies = [ 1075 + "plotters-backend", 1076 + ] 1077 + 1078 + [[package]] 1079 + name = "ppv-lite86" 1080 + version = "0.2.21" 1081 + source = "registry+https://github.com/rust-lang/crates.io-index" 1082 + checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 1083 + dependencies = [ 1084 + "zerocopy", 1085 + ] 1086 + 1087 + [[package]] 1088 + name = "prettyplease" 1089 + version = "0.2.35" 1090 + source = "registry+https://github.com/rust-lang/crates.io-index" 1091 + checksum = "061c1221631e079b26479d25bbf2275bfe5917ae8419cd7e34f13bfc2aa7539a" 1092 + dependencies = [ 1093 + "proc-macro2", 1094 + "syn", 1095 + ] 1096 + 1097 + [[package]] 1098 + name = "proc-macro2" 1099 + version = "1.0.95" 1100 + source = "registry+https://github.com/rust-lang/crates.io-index" 1101 + checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 1102 + dependencies = [ 1103 + "unicode-ident", 1104 + ] 1105 + 1106 + [[package]] 1107 + name = "proptest" 1108 + version = "1.7.0" 1109 + source = "registry+https://github.com/rust-lang/crates.io-index" 1110 + checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" 1111 + dependencies = [ 1112 + "bit-set", 1113 + "bit-vec", 1114 + "bitflags", 1115 + "lazy_static", 1116 + "num-traits", 1117 + "rand 0.9.1", 1118 + "rand_chacha 0.9.0", 1119 + "rand_xorshift", 1120 + "regex-syntax 0.8.5", 1121 + "rusty-fork", 1122 + "tempfile", 1123 + "unarray", 1124 + ] 1125 + 1126 + [[package]] 1127 + name = "prost" 1128 + version = "0.13.5" 1129 + source = "registry+https://github.com/rust-lang/crates.io-index" 1130 + checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" 1131 + dependencies = [ 1132 + "bytes", 1133 + "prost-derive", 1134 + ] 1135 + 1136 + [[package]] 1137 + name = "prost-build" 1138 + version = "0.13.5" 1139 + source = "registry+https://github.com/rust-lang/crates.io-index" 1140 + checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" 1141 + dependencies = [ 1142 + "heck", 1143 + "itertools 0.14.0", 1144 + "log", 1145 + "multimap", 1146 + "once_cell", 1147 + "petgraph 0.7.1", 1148 + "prettyplease", 1149 + "prost", 1150 + "prost-types", 1151 + "regex", 1152 + "syn", 1153 + "tempfile", 1154 + ] 1155 + 1156 + [[package]] 1157 + name = "prost-derive" 1158 + version = "0.13.5" 1159 + source = "registry+https://github.com/rust-lang/crates.io-index" 1160 + checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" 1161 + dependencies = [ 1162 + "anyhow", 1163 + "itertools 0.14.0", 1164 + "proc-macro2", 1165 + "quote", 1166 + "syn", 1167 + ] 1168 + 1169 + [[package]] 1170 + name = "prost-types" 1171 + version = "0.13.5" 1172 + source = "registry+https://github.com/rust-lang/crates.io-index" 1173 + checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" 1174 + dependencies = [ 1175 + "prost", 1176 + ] 1177 + 1178 + [[package]] 1179 + name = "quick-error" 1180 + version = "1.2.3" 1181 + source = "registry+https://github.com/rust-lang/crates.io-index" 1182 + checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 1183 + 1184 + [[package]] 1185 + name = "quote" 1186 + version = "1.0.40" 1187 + source = "registry+https://github.com/rust-lang/crates.io-index" 1188 + checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 1189 + dependencies = [ 1190 + "proc-macro2", 1191 + ] 1192 + 1193 + [[package]] 1194 + name = "r-efi" 1195 + version = "5.3.0" 1196 + source = "registry+https://github.com/rust-lang/crates.io-index" 1197 + checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 1198 + 1199 + [[package]] 1200 + name = "rand" 1201 + version = "0.8.5" 1202 + source = "registry+https://github.com/rust-lang/crates.io-index" 1203 + checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1204 + dependencies = [ 1205 + "libc", 1206 + "rand_chacha 0.3.1", 1207 + "rand_core 0.6.4", 1208 + ] 1209 + 1210 + [[package]] 1211 + name = "rand" 1212 + version = "0.9.1" 1213 + source = "registry+https://github.com/rust-lang/crates.io-index" 1214 + checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" 1215 + dependencies = [ 1216 + "rand_chacha 0.9.0", 1217 + "rand_core 0.9.3", 1218 + ] 1219 + 1220 + [[package]] 1221 + name = "rand_chacha" 1222 + version = "0.3.1" 1223 + source = "registry+https://github.com/rust-lang/crates.io-index" 1224 + checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1225 + dependencies = [ 1226 + "ppv-lite86", 1227 + "rand_core 0.6.4", 1228 + ] 1229 + 1230 + [[package]] 1231 + name = "rand_chacha" 1232 + version = "0.9.0" 1233 + source = "registry+https://github.com/rust-lang/crates.io-index" 1234 + checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 1235 + dependencies = [ 1236 + "ppv-lite86", 1237 + "rand_core 0.9.3", 1238 + ] 1239 + 1240 + [[package]] 1241 + name = "rand_core" 1242 + version = "0.6.4" 1243 + source = "registry+https://github.com/rust-lang/crates.io-index" 1244 + checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1245 + dependencies = [ 1246 + "getrandom 0.2.16", 1247 + ] 1248 + 1249 + [[package]] 1250 + name = "rand_core" 1251 + version = "0.9.3" 1252 + source = "registry+https://github.com/rust-lang/crates.io-index" 1253 + checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 1254 + dependencies = [ 1255 + "getrandom 0.3.3", 1256 + ] 1257 + 1258 + [[package]] 1259 + name = "rand_xorshift" 1260 + version = "0.4.0" 1261 + source = "registry+https://github.com/rust-lang/crates.io-index" 1262 + checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" 1263 + dependencies = [ 1264 + "rand_core 0.9.3", 1265 + ] 1266 + 1267 + [[package]] 1268 + name = "rayon" 1269 + version = "1.10.0" 1270 + source = "registry+https://github.com/rust-lang/crates.io-index" 1271 + checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 1272 + dependencies = [ 1273 + "either", 1274 + "rayon-core", 1275 + ] 1276 + 1277 + [[package]] 1278 + name = "rayon-core" 1279 + version = "1.12.1" 1280 + source = "registry+https://github.com/rust-lang/crates.io-index" 1281 + checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 1282 + dependencies = [ 1283 + "crossbeam-deque", 1284 + "crossbeam-utils", 1285 + ] 1286 + 1287 + [[package]] 1288 + name = "redox_syscall" 1289 + version = "0.5.13" 1290 + source = "registry+https://github.com/rust-lang/crates.io-index" 1291 + checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" 1292 + dependencies = [ 1293 + "bitflags", 1294 + ] 1295 + 1296 + [[package]] 1297 + name = "regex" 1298 + version = "1.11.1" 1299 + source = "registry+https://github.com/rust-lang/crates.io-index" 1300 + checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 1301 + dependencies = [ 1302 + "aho-corasick", 1303 + "memchr", 1304 + "regex-automata 0.4.9", 1305 + "regex-syntax 0.8.5", 1306 + ] 1307 + 1308 + [[package]] 1309 + name = "regex-automata" 1310 + version = "0.1.10" 1311 + source = "registry+https://github.com/rust-lang/crates.io-index" 1312 + checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 1313 + dependencies = [ 1314 + "regex-syntax 0.6.29", 1315 + ] 1316 + 1317 + [[package]] 1318 + name = "regex-automata" 1319 + version = "0.4.9" 1320 + source = "registry+https://github.com/rust-lang/crates.io-index" 1321 + checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 1322 + dependencies = [ 1323 + "aho-corasick", 1324 + "memchr", 1325 + "regex-syntax 0.8.5", 1326 + ] 1327 + 1328 + [[package]] 1329 + name = "regex-syntax" 1330 + version = "0.6.29" 1331 + source = "registry+https://github.com/rust-lang/crates.io-index" 1332 + checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 1333 + 1334 + [[package]] 1335 + name = "regex-syntax" 1336 + version = "0.8.5" 1337 + source = "registry+https://github.com/rust-lang/crates.io-index" 1338 + checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 1339 + 1340 + [[package]] 1341 + name = "roaring" 1342 + version = "0.10.12" 1343 + source = "registry+https://github.com/rust-lang/crates.io-index" 1344 + checksum = "19e8d2cfa184d94d0726d650a9f4a1be7f9b76ac9fdb954219878dc00c1c1e7b" 1345 + dependencies = [ 1346 + "bytemuck", 1347 + "byteorder", 1348 + ] 1349 + 1350 + [[package]] 1351 + name = "rustc-demangle" 1352 + version = "0.1.25" 1353 + source = "registry+https://github.com/rust-lang/crates.io-index" 1354 + checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" 1355 + 1356 + [[package]] 1357 + name = "rustix" 1358 + version = "1.0.7" 1359 + source = "registry+https://github.com/rust-lang/crates.io-index" 1360 + checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" 1361 + dependencies = [ 1362 + "bitflags", 1363 + "errno", 1364 + "libc", 1365 + "linux-raw-sys", 1366 + "windows-sys 0.59.0", 1367 + ] 1368 + 1369 + [[package]] 1370 + name = "rustversion" 1371 + version = "1.0.21" 1372 + source = "registry+https://github.com/rust-lang/crates.io-index" 1373 + checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" 1374 + 1375 + [[package]] 1376 + name = "rusty-fork" 1377 + version = "0.3.0" 1378 + source = "registry+https://github.com/rust-lang/crates.io-index" 1379 + checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" 1380 + dependencies = [ 1381 + "fnv", 1382 + "quick-error", 1383 + "tempfile", 1384 + "wait-timeout", 1385 + ] 1386 + 1387 + [[package]] 1388 + name = "ryu" 1389 + version = "1.0.20" 1390 + source = "registry+https://github.com/rust-lang/crates.io-index" 1391 + checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 1392 + 1393 + [[package]] 1394 + name = "same-file" 1395 + version = "1.0.6" 1396 + source = "registry+https://github.com/rust-lang/crates.io-index" 1397 + checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1398 + dependencies = [ 1399 + "winapi-util", 1400 + ] 1401 + 1402 + [[package]] 1403 + name = "scopeguard" 1404 + version = "1.2.0" 1405 + source = "registry+https://github.com/rust-lang/crates.io-index" 1406 + checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1407 + 1408 + [[package]] 1409 + name = "serde" 1410 + version = "1.0.219" 1411 + source = "registry+https://github.com/rust-lang/crates.io-index" 1412 + checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 1413 + dependencies = [ 1414 + "serde_derive", 1415 + ] 1416 + 1417 + [[package]] 1418 + name = "serde_derive" 1419 + version = "1.0.219" 1420 + source = "registry+https://github.com/rust-lang/crates.io-index" 1421 + checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 1422 + dependencies = [ 1423 + "proc-macro2", 1424 + "quote", 1425 + "syn", 1426 + ] 1427 + 1428 + [[package]] 1429 + name = "serde_json" 1430 + version = "1.0.140" 1431 + source = "registry+https://github.com/rust-lang/crates.io-index" 1432 + checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 1433 + dependencies = [ 1434 + "itoa", 1435 + "memchr", 1436 + "ryu", 1437 + "serde", 1438 + ] 1439 + 1440 + [[package]] 1441 + name = "sharded-slab" 1442 + version = "0.1.7" 1443 + source = "registry+https://github.com/rust-lang/crates.io-index" 1444 + checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 1445 + dependencies = [ 1446 + "lazy_static", 1447 + ] 1448 + 1449 + [[package]] 1450 + name = "signal-hook-registry" 1451 + version = "1.4.5" 1452 + source = "registry+https://github.com/rust-lang/crates.io-index" 1453 + checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" 1454 + dependencies = [ 1455 + "libc", 1456 + ] 1457 + 1458 + [[package]] 1459 + name = "slab" 1460 + version = "0.4.10" 1461 + source = "registry+https://github.com/rust-lang/crates.io-index" 1462 + checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" 1463 + 1464 + [[package]] 1465 + name = "smallvec" 1466 + version = "1.15.1" 1467 + source = "registry+https://github.com/rust-lang/crates.io-index" 1468 + checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 1469 + 1470 + [[package]] 1471 + name = "socket2" 1472 + version = "0.5.10" 1473 + source = "registry+https://github.com/rust-lang/crates.io-index" 1474 + checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" 1475 + dependencies = [ 1476 + "libc", 1477 + "windows-sys 0.52.0", 1478 + ] 1479 + 1480 + [[package]] 1481 + name = "syn" 1482 + version = "2.0.104" 1483 + source = "registry+https://github.com/rust-lang/crates.io-index" 1484 + checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" 1485 + dependencies = [ 1486 + "proc-macro2", 1487 + "quote", 1488 + "unicode-ident", 1489 + ] 1490 + 1491 + [[package]] 1492 + name = "sync_wrapper" 1493 + version = "1.0.2" 1494 + source = "registry+https://github.com/rust-lang/crates.io-index" 1495 + checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 1496 + 1497 + [[package]] 1498 + name = "tempfile" 1499 + version = "3.20.0" 1500 + source = "registry+https://github.com/rust-lang/crates.io-index" 1501 + checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" 1502 + dependencies = [ 1503 + "fastrand", 1504 + "getrandom 0.3.3", 1505 + "once_cell", 1506 + "rustix", 1507 + "windows-sys 0.59.0", 1508 + ] 1509 + 1510 + [[package]] 1511 + name = "thiserror" 1512 + version = "1.0.69" 1513 + source = "registry+https://github.com/rust-lang/crates.io-index" 1514 + checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1515 + dependencies = [ 1516 + "thiserror-impl", 1517 + ] 1518 + 1519 + [[package]] 1520 + name = "thiserror-impl" 1521 + version = "1.0.69" 1522 + source = "registry+https://github.com/rust-lang/crates.io-index" 1523 + checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 1524 + dependencies = [ 1525 + "proc-macro2", 1526 + "quote", 1527 + "syn", 1528 + ] 1529 + 1530 + [[package]] 1531 + name = "thread_local" 1532 + version = "1.1.9" 1533 + source = "registry+https://github.com/rust-lang/crates.io-index" 1534 + checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" 1535 + dependencies = [ 1536 + "cfg-if", 1537 + ] 1538 + 1539 + [[package]] 1540 + name = "tinytemplate" 1541 + version = "1.2.1" 1542 + source = "registry+https://github.com/rust-lang/crates.io-index" 1543 + checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" 1544 + dependencies = [ 1545 + "serde", 1546 + "serde_json", 1547 + ] 1548 + 1549 + [[package]] 1550 + name = "tokio" 1551 + version = "1.45.1" 1552 + source = "registry+https://github.com/rust-lang/crates.io-index" 1553 + checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" 1554 + dependencies = [ 1555 + "backtrace", 1556 + "bytes", 1557 + "libc", 1558 + "mio", 1559 + "parking_lot", 1560 + "pin-project-lite", 1561 + "signal-hook-registry", 1562 + "socket2", 1563 + "tokio-macros", 1564 + "windows-sys 0.52.0", 1565 + ] 1566 + 1567 + [[package]] 1568 + name = "tokio-macros" 1569 + version = "2.5.0" 1570 + source = "registry+https://github.com/rust-lang/crates.io-index" 1571 + checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" 1572 + dependencies = [ 1573 + "proc-macro2", 1574 + "quote", 1575 + "syn", 1576 + ] 1577 + 1578 + [[package]] 1579 + name = "tokio-stream" 1580 + version = "0.1.17" 1581 + source = "registry+https://github.com/rust-lang/crates.io-index" 1582 + checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" 1583 + dependencies = [ 1584 + "futures-core", 1585 + "pin-project-lite", 1586 + "tokio", 1587 + ] 1588 + 1589 + [[package]] 1590 + name = "tokio-util" 1591 + version = "0.7.15" 1592 + source = "registry+https://github.com/rust-lang/crates.io-index" 1593 + checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" 1594 + dependencies = [ 1595 + "bytes", 1596 + "futures-core", 1597 + "futures-sink", 1598 + "pin-project-lite", 1599 + "tokio", 1600 + ] 1601 + 1602 + [[package]] 1603 + name = "tonic" 1604 + version = "0.12.3" 1605 + source = "registry+https://github.com/rust-lang/crates.io-index" 1606 + checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" 1607 + dependencies = [ 1608 + "async-stream", 1609 + "async-trait", 1610 + "axum", 1611 + "base64", 1612 + "bytes", 1613 + "h2", 1614 + "http", 1615 + "http-body", 1616 + "http-body-util", 1617 + "hyper", 1618 + "hyper-timeout", 1619 + "hyper-util", 1620 + "percent-encoding", 1621 + "pin-project", 1622 + "prost", 1623 + "socket2", 1624 + "tokio", 1625 + "tokio-stream", 1626 + "tower 0.4.13", 1627 + "tower-layer", 1628 + "tower-service", 1629 + "tracing", 1630 + ] 1631 + 1632 + [[package]] 1633 + name = "tonic-build" 1634 + version = "0.12.3" 1635 + source = "registry+https://github.com/rust-lang/crates.io-index" 1636 + checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" 1637 + dependencies = [ 1638 + "prettyplease", 1639 + "proc-macro2", 1640 + "prost-build", 1641 + "prost-types", 1642 + "quote", 1643 + "syn", 1644 + ] 1645 + 1646 + [[package]] 1647 + name = "tower" 1648 + version = "0.4.13" 1649 + source = "registry+https://github.com/rust-lang/crates.io-index" 1650 + checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" 1651 + dependencies = [ 1652 + "futures-core", 1653 + "futures-util", 1654 + "indexmap 1.9.3", 1655 + "pin-project", 1656 + "pin-project-lite", 1657 + "rand 0.8.5", 1658 + "slab", 1659 + "tokio", 1660 + "tokio-util", 1661 + "tower-layer", 1662 + "tower-service", 1663 + "tracing", 1664 + ] 1665 + 1666 + [[package]] 1667 + name = "tower" 1668 + version = "0.5.2" 1669 + source = "registry+https://github.com/rust-lang/crates.io-index" 1670 + checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" 1671 + dependencies = [ 1672 + "futures-core", 1673 + "futures-util", 1674 + "pin-project-lite", 1675 + "sync_wrapper", 1676 + "tower-layer", 1677 + "tower-service", 1678 + ] 1679 + 1680 + [[package]] 1681 + name = "tower-layer" 1682 + version = "0.3.3" 1683 + source = "registry+https://github.com/rust-lang/crates.io-index" 1684 + checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 1685 + 1686 + [[package]] 1687 + name = "tower-service" 1688 + version = "0.3.3" 1689 + source = "registry+https://github.com/rust-lang/crates.io-index" 1690 + checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1691 + 1692 + [[package]] 1693 + name = "tracing" 1694 + version = "0.1.41" 1695 + source = "registry+https://github.com/rust-lang/crates.io-index" 1696 + checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" 1697 + dependencies = [ 1698 + "pin-project-lite", 1699 + "tracing-attributes", 1700 + "tracing-core", 1701 + ] 1702 + 1703 + [[package]] 1704 + name = "tracing-attributes" 1705 + version = "0.1.30" 1706 + source = "registry+https://github.com/rust-lang/crates.io-index" 1707 + checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" 1708 + dependencies = [ 1709 + "proc-macro2", 1710 + "quote", 1711 + "syn", 1712 + ] 1713 + 1714 + [[package]] 1715 + name = "tracing-core" 1716 + version = "0.1.34" 1717 + source = "registry+https://github.com/rust-lang/crates.io-index" 1718 + checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" 1719 + dependencies = [ 1720 + "once_cell", 1721 + "valuable", 1722 + ] 1723 + 1724 + [[package]] 1725 + name = "tracing-log" 1726 + version = "0.2.0" 1727 + source = "registry+https://github.com/rust-lang/crates.io-index" 1728 + checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 1729 + dependencies = [ 1730 + "log", 1731 + "once_cell", 1732 + "tracing-core", 1733 + ] 1734 + 1735 + [[package]] 1736 + name = "tracing-subscriber" 1737 + version = "0.3.19" 1738 + source = "registry+https://github.com/rust-lang/crates.io-index" 1739 + checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" 1740 + dependencies = [ 1741 + "matchers", 1742 + "nu-ansi-term", 1743 + "once_cell", 1744 + "regex", 1745 + "sharded-slab", 1746 + "smallvec", 1747 + "thread_local", 1748 + "tracing", 1749 + "tracing-core", 1750 + "tracing-log", 1751 + ] 1752 + 1753 + [[package]] 1754 + name = "try-lock" 1755 + version = "0.2.5" 1756 + source = "registry+https://github.com/rust-lang/crates.io-index" 1757 + checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1758 + 1759 + [[package]] 1760 + name = "unarray" 1761 + version = "0.1.4" 1762 + source = "registry+https://github.com/rust-lang/crates.io-index" 1763 + checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" 1764 + 1765 + [[package]] 1766 + name = "unicode-ident" 1767 + version = "1.0.18" 1768 + source = "registry+https://github.com/rust-lang/crates.io-index" 1769 + checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 1770 + 1771 + [[package]] 1772 + name = "uuid" 1773 + version = "1.17.0" 1774 + source = "registry+https://github.com/rust-lang/crates.io-index" 1775 + checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" 1776 + dependencies = [ 1777 + "getrandom 0.3.3", 1778 + "js-sys", 1779 + "serde", 1780 + "wasm-bindgen", 1781 + ] 1782 + 1783 + [[package]] 1784 + name = "valuable" 1785 + version = "0.1.1" 1786 + source = "registry+https://github.com/rust-lang/crates.io-index" 1787 + checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" 1788 + 1789 + [[package]] 1790 + name = "version_check" 1791 + version = "0.9.5" 1792 + source = "registry+https://github.com/rust-lang/crates.io-index" 1793 + checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 1794 + 1795 + [[package]] 1796 + name = "wait-timeout" 1797 + version = "0.2.1" 1798 + source = "registry+https://github.com/rust-lang/crates.io-index" 1799 + checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" 1800 + dependencies = [ 1801 + "libc", 1802 + ] 1803 + 1804 + [[package]] 1805 + name = "walkdir" 1806 + version = "2.5.0" 1807 + source = "registry+https://github.com/rust-lang/crates.io-index" 1808 + checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 1809 + dependencies = [ 1810 + "same-file", 1811 + "winapi-util", 1812 + ] 1813 + 1814 + [[package]] 1815 + name = "want" 1816 + version = "0.3.1" 1817 + source = "registry+https://github.com/rust-lang/crates.io-index" 1818 + checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1819 + dependencies = [ 1820 + "try-lock", 1821 + ] 1822 + 1823 + [[package]] 1824 + name = "wasi" 1825 + version = "0.11.1+wasi-snapshot-preview1" 1826 + source = "registry+https://github.com/rust-lang/crates.io-index" 1827 + checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 1828 + 1829 + [[package]] 1830 + name = "wasi" 1831 + version = "0.14.2+wasi-0.2.4" 1832 + source = "registry+https://github.com/rust-lang/crates.io-index" 1833 + checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 1834 + dependencies = [ 1835 + "wit-bindgen-rt", 1836 + ] 1837 + 1838 + [[package]] 1839 + name = "wasm-bindgen" 1840 + version = "0.2.100" 1841 + source = "registry+https://github.com/rust-lang/crates.io-index" 1842 + checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 1843 + dependencies = [ 1844 + "cfg-if", 1845 + "once_cell", 1846 + "rustversion", 1847 + "wasm-bindgen-macro", 1848 + ] 1849 + 1850 + [[package]] 1851 + name = "wasm-bindgen-backend" 1852 + version = "0.2.100" 1853 + source = "registry+https://github.com/rust-lang/crates.io-index" 1854 + checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 1855 + dependencies = [ 1856 + "bumpalo", 1857 + "log", 1858 + "proc-macro2", 1859 + "quote", 1860 + "syn", 1861 + "wasm-bindgen-shared", 1862 + ] 1863 + 1864 + [[package]] 1865 + name = "wasm-bindgen-macro" 1866 + version = "0.2.100" 1867 + source = "registry+https://github.com/rust-lang/crates.io-index" 1868 + checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 1869 + dependencies = [ 1870 + "quote", 1871 + "wasm-bindgen-macro-support", 1872 + ] 1873 + 1874 + [[package]] 1875 + name = "wasm-bindgen-macro-support" 1876 + version = "0.2.100" 1877 + source = "registry+https://github.com/rust-lang/crates.io-index" 1878 + checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 1879 + dependencies = [ 1880 + "proc-macro2", 1881 + "quote", 1882 + "syn", 1883 + "wasm-bindgen-backend", 1884 + "wasm-bindgen-shared", 1885 + ] 1886 + 1887 + [[package]] 1888 + name = "wasm-bindgen-shared" 1889 + version = "0.2.100" 1890 + source = "registry+https://github.com/rust-lang/crates.io-index" 1891 + checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 1892 + dependencies = [ 1893 + "unicode-ident", 1894 + ] 1895 + 1896 + [[package]] 1897 + name = "web-sys" 1898 + version = "0.3.77" 1899 + source = "registry+https://github.com/rust-lang/crates.io-index" 1900 + checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" 1901 + dependencies = [ 1902 + "js-sys", 1903 + "wasm-bindgen", 1904 + ] 1905 + 1906 + [[package]] 1907 + name = "winapi" 1908 + version = "0.3.9" 1909 + source = "registry+https://github.com/rust-lang/crates.io-index" 1910 + checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1911 + dependencies = [ 1912 + "winapi-i686-pc-windows-gnu", 1913 + "winapi-x86_64-pc-windows-gnu", 1914 + ] 1915 + 1916 + [[package]] 1917 + name = "winapi-i686-pc-windows-gnu" 1918 + version = "0.4.0" 1919 + source = "registry+https://github.com/rust-lang/crates.io-index" 1920 + checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1921 + 1922 + [[package]] 1923 + name = "winapi-util" 1924 + version = "0.1.9" 1925 + source = "registry+https://github.com/rust-lang/crates.io-index" 1926 + checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 1927 + dependencies = [ 1928 + "windows-sys 0.59.0", 1929 + ] 1930 + 1931 + [[package]] 1932 + name = "winapi-x86_64-pc-windows-gnu" 1933 + version = "0.4.0" 1934 + source = "registry+https://github.com/rust-lang/crates.io-index" 1935 + checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1936 + 1937 + [[package]] 1938 + name = "windows-sys" 1939 + version = "0.52.0" 1940 + source = "registry+https://github.com/rust-lang/crates.io-index" 1941 + checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1942 + dependencies = [ 1943 + "windows-targets 0.52.6", 1944 + ] 1945 + 1946 + [[package]] 1947 + name = "windows-sys" 1948 + version = "0.59.0" 1949 + source = "registry+https://github.com/rust-lang/crates.io-index" 1950 + checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1951 + dependencies = [ 1952 + "windows-targets 0.52.6", 1953 + ] 1954 + 1955 + [[package]] 1956 + name = "windows-sys" 1957 + version = "0.60.2" 1958 + source = "registry+https://github.com/rust-lang/crates.io-index" 1959 + checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 1960 + dependencies = [ 1961 + "windows-targets 0.53.2", 1962 + ] 1963 + 1964 + [[package]] 1965 + name = "windows-targets" 1966 + version = "0.52.6" 1967 + source = "registry+https://github.com/rust-lang/crates.io-index" 1968 + checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1969 + dependencies = [ 1970 + "windows_aarch64_gnullvm 0.52.6", 1971 + "windows_aarch64_msvc 0.52.6", 1972 + "windows_i686_gnu 0.52.6", 1973 + "windows_i686_gnullvm 0.52.6", 1974 + "windows_i686_msvc 0.52.6", 1975 + "windows_x86_64_gnu 0.52.6", 1976 + "windows_x86_64_gnullvm 0.52.6", 1977 + "windows_x86_64_msvc 0.52.6", 1978 + ] 1979 + 1980 + [[package]] 1981 + name = "windows-targets" 1982 + version = "0.53.2" 1983 + source = "registry+https://github.com/rust-lang/crates.io-index" 1984 + checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" 1985 + dependencies = [ 1986 + "windows_aarch64_gnullvm 0.53.0", 1987 + "windows_aarch64_msvc 0.53.0", 1988 + "windows_i686_gnu 0.53.0", 1989 + "windows_i686_gnullvm 0.53.0", 1990 + "windows_i686_msvc 0.53.0", 1991 + "windows_x86_64_gnu 0.53.0", 1992 + "windows_x86_64_gnullvm 0.53.0", 1993 + "windows_x86_64_msvc 0.53.0", 1994 + ] 1995 + 1996 + [[package]] 1997 + name = "windows_aarch64_gnullvm" 1998 + version = "0.52.6" 1999 + source = "registry+https://github.com/rust-lang/crates.io-index" 2000 + checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 2001 + 2002 + [[package]] 2003 + name = "windows_aarch64_gnullvm" 2004 + version = "0.53.0" 2005 + source = "registry+https://github.com/rust-lang/crates.io-index" 2006 + checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 2007 + 2008 + [[package]] 2009 + name = "windows_aarch64_msvc" 2010 + version = "0.52.6" 2011 + source = "registry+https://github.com/rust-lang/crates.io-index" 2012 + checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 2013 + 2014 + [[package]] 2015 + name = "windows_aarch64_msvc" 2016 + version = "0.53.0" 2017 + source = "registry+https://github.com/rust-lang/crates.io-index" 2018 + checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 2019 + 2020 + [[package]] 2021 + name = "windows_i686_gnu" 2022 + version = "0.52.6" 2023 + source = "registry+https://github.com/rust-lang/crates.io-index" 2024 + checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 2025 + 2026 + [[package]] 2027 + name = "windows_i686_gnu" 2028 + version = "0.53.0" 2029 + source = "registry+https://github.com/rust-lang/crates.io-index" 2030 + checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 2031 + 2032 + [[package]] 2033 + name = "windows_i686_gnullvm" 2034 + version = "0.52.6" 2035 + source = "registry+https://github.com/rust-lang/crates.io-index" 2036 + checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 2037 + 2038 + [[package]] 2039 + name = "windows_i686_gnullvm" 2040 + version = "0.53.0" 2041 + source = "registry+https://github.com/rust-lang/crates.io-index" 2042 + checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 2043 + 2044 + [[package]] 2045 + name = "windows_i686_msvc" 2046 + version = "0.52.6" 2047 + source = "registry+https://github.com/rust-lang/crates.io-index" 2048 + checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 2049 + 2050 + [[package]] 2051 + name = "windows_i686_msvc" 2052 + version = "0.53.0" 2053 + source = "registry+https://github.com/rust-lang/crates.io-index" 2054 + checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 2055 + 2056 + [[package]] 2057 + name = "windows_x86_64_gnu" 2058 + version = "0.52.6" 2059 + source = "registry+https://github.com/rust-lang/crates.io-index" 2060 + checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 2061 + 2062 + [[package]] 2063 + name = "windows_x86_64_gnu" 2064 + version = "0.53.0" 2065 + source = "registry+https://github.com/rust-lang/crates.io-index" 2066 + checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 2067 + 2068 + [[package]] 2069 + name = "windows_x86_64_gnullvm" 2070 + version = "0.52.6" 2071 + source = "registry+https://github.com/rust-lang/crates.io-index" 2072 + checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 2073 + 2074 + [[package]] 2075 + name = "windows_x86_64_gnullvm" 2076 + version = "0.53.0" 2077 + source = "registry+https://github.com/rust-lang/crates.io-index" 2078 + checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 2079 + 2080 + [[package]] 2081 + name = "windows_x86_64_msvc" 2082 + version = "0.52.6" 2083 + source = "registry+https://github.com/rust-lang/crates.io-index" 2084 + checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 2085 + 2086 + [[package]] 2087 + name = "windows_x86_64_msvc" 2088 + version = "0.53.0" 2089 + source = "registry+https://github.com/rust-lang/crates.io-index" 2090 + checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 2091 + 2092 + [[package]] 2093 + name = "wit-bindgen-rt" 2094 + version = "0.39.0" 2095 + source = "registry+https://github.com/rust-lang/crates.io-index" 2096 + checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 2097 + dependencies = [ 2098 + "bitflags", 2099 + ] 2100 + 2101 + [[package]] 2102 + name = "zerocopy" 2103 + version = "0.8.26" 2104 + source = "registry+https://github.com/rust-lang/crates.io-index" 2105 + checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" 2106 + dependencies = [ 2107 + "zerocopy-derive", 2108 + ] 2109 + 2110 + [[package]] 2111 + name = "zerocopy-derive" 2112 + version = "0.8.26" 2113 + source = "registry+https://github.com/rust-lang/crates.io-index" 2114 + checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" 2115 + dependencies = [ 2116 + "proc-macro2", 2117 + "quote", 2118 + "syn", 2119 + ]
+43
Cargo.toml
··· 1 + [package] 2 + name = "gigabrain" 3 + version = "0.1.0" 4 + edition = "2021" 5 + 6 + [dependencies] 7 + tokio = { version = "1.40", features = ["full"] } 8 + bytes = "1.5" 9 + serde = { version = "1.0", features = ["derive"] } 10 + bincode = "1.3" 11 + memmap2 = "0.9" 12 + dashmap = "6.0" 13 + parking_lot = "0.12" 14 + thiserror = "1.0" 15 + tracing = "0.1" 16 + tracing-subscriber = { version = "0.3", features = ["env-filter"] } 17 + uuid = { version = "1.10", features = ["v4", "serde"] } 18 + ahash = "0.8" 19 + roaring = "0.10" 20 + nom = "7.1" 21 + petgraph = "0.6" 22 + rayon = "1.10" 23 + crossbeam = "0.8" 24 + lru = "0.12" 25 + async-trait = "0.1" 26 + tonic = "0.12" 27 + prost = "0.13" 28 + tower = "0.5" 29 + num_cpus = "1.16" 30 + 31 + [build-dependencies] 32 + tonic-build = "0.12" 33 + 34 + [dev-dependencies] 35 + criterion = { version = "0.5", features = ["html_reports"] } 36 + proptest = "1.4" 37 + tempfile = "3.10" 38 + 39 + [profile.release] 40 + lto = true 41 + codegen-units = 1 42 + opt-level = 3 43 +
+3
build.rs
··· 1 + fn main() -> Result<(), Box<dyn std::error::Error>> { 2 + Ok(()) 3 + }
+153
src/core/graph.rs
··· 1 + use dashmap::DashMap; 2 + use std::sync::Arc; 3 + use parking_lot::RwLock; 4 + use crate::{ 5 + NodeId, RelationshipId, Node, Relationship, 6 + Result, GigabrainError 7 + }; 8 + use crate::core::{relationship::Direction, GraphSchema}; 9 + 10 + pub struct Graph { 11 + nodes: Arc<DashMap<NodeId, Node>>, 12 + relationships: Arc<DashMap<RelationshipId, Relationship>>, 13 + node_relationships: Arc<DashMap<NodeId, Vec<RelationshipId>>>, 14 + schema: Arc<RwLock<GraphSchema>>, 15 + 16 + next_node_id: Arc<RwLock<u64>>, 17 + next_relationship_id: Arc<RwLock<u64>>, 18 + } 19 + 20 + impl Graph { 21 + pub fn new() -> Self { 22 + Self { 23 + nodes: Arc::new(DashMap::new()), 24 + relationships: Arc::new(DashMap::new()), 25 + node_relationships: Arc::new(DashMap::new()), 26 + schema: Arc::new(RwLock::new(GraphSchema::new())), 27 + next_node_id: Arc::new(RwLock::new(0)), 28 + next_relationship_id: Arc::new(RwLock::new(0)), 29 + } 30 + } 31 + 32 + pub fn create_node(&self) -> NodeId { 33 + let mut id_gen = self.next_node_id.write(); 34 + let id = NodeId(*id_gen); 35 + *id_gen += 1; 36 + drop(id_gen); 37 + 38 + let node = Node::new(id); 39 + self.nodes.insert(id, node); 40 + self.node_relationships.insert(id, Vec::new()); 41 + id 42 + } 43 + 44 + pub fn create_relationship( 45 + &self, 46 + start: NodeId, 47 + end: NodeId, 48 + rel_type: u32, 49 + ) -> Result<RelationshipId> { 50 + if !self.nodes.contains_key(&start) { 51 + return Err(GigabrainError::NodeNotFound(start)); 52 + } 53 + if !self.nodes.contains_key(&end) { 54 + return Err(GigabrainError::NodeNotFound(end)); 55 + } 56 + 57 + let mut id_gen = self.next_relationship_id.write(); 58 + let id = RelationshipId(*id_gen); 59 + *id_gen += 1; 60 + drop(id_gen); 61 + 62 + let relationship = Relationship::new(id, start, end, rel_type); 63 + self.relationships.insert(id, relationship); 64 + 65 + self.node_relationships.entry(start).and_modify(|rels| rels.push(id)); 66 + if start != end { 67 + self.node_relationships.entry(end).and_modify(|rels| rels.push(id)); 68 + } 69 + 70 + Ok(id) 71 + } 72 + 73 + pub fn get_node(&self, id: NodeId) -> Option<Node> { 74 + self.nodes.get(&id).map(|node| node.clone()) 75 + } 76 + 77 + pub fn get_relationship(&self, id: RelationshipId) -> Option<Relationship> { 78 + self.relationships.get(&id).map(|rel| rel.clone()) 79 + } 80 + 81 + pub fn get_node_relationships( 82 + &self, 83 + node_id: NodeId, 84 + direction: Direction, 85 + rel_types: Option<&[u32]>, 86 + ) -> Vec<Relationship> { 87 + let rel_ids = match self.node_relationships.get(&node_id) { 88 + Some(ids) => ids.clone(), 89 + None => return Vec::new(), 90 + }; 91 + 92 + rel_ids 93 + .into_iter() 94 + .filter_map(|rel_id| { 95 + self.relationships.get(&rel_id).and_then(|rel| { 96 + let matches_direction = match direction { 97 + Direction::Outgoing => rel.start_node == node_id, 98 + Direction::Incoming => rel.end_node == node_id, 99 + Direction::Both => true, 100 + }; 101 + 102 + let matches_type = rel_types 103 + .map(|types| types.contains(&rel.rel_type)) 104 + .unwrap_or(true); 105 + 106 + if matches_direction && matches_type { 107 + Some(rel.clone()) 108 + } else { 109 + None 110 + } 111 + }) 112 + }) 113 + .collect() 114 + } 115 + 116 + pub fn delete_node(&self, id: NodeId) -> Result<()> { 117 + if let Some((_, rel_ids)) = self.node_relationships.remove(&id) { 118 + for rel_id in rel_ids { 119 + self.delete_relationship(rel_id)?; 120 + } 121 + } 122 + 123 + self.nodes 124 + .remove(&id) 125 + .ok_or(GigabrainError::NodeNotFound(id))?; 126 + 127 + Ok(()) 128 + } 129 + 130 + pub fn delete_relationship(&self, id: RelationshipId) -> Result<()> { 131 + let rel = self 132 + .relationships 133 + .remove(&id) 134 + .ok_or(GigabrainError::RelationshipNotFound(id))? 135 + .1; 136 + 137 + self.node_relationships.entry(rel.start_node).and_modify(|rels| { 138 + rels.retain(|&r| r != id); 139 + }); 140 + 141 + if rel.start_node != rel.end_node { 142 + self.node_relationships.entry(rel.end_node).and_modify(|rels| { 143 + rels.retain(|&r| r != id); 144 + }); 145 + } 146 + 147 + Ok(()) 148 + } 149 + 150 + pub fn schema(&self) -> &Arc<RwLock<GraphSchema>> { 151 + &self.schema 152 + } 153 + }
+70
src/core/mod.rs
··· 1 + use serde::{Deserialize, Serialize}; 2 + use std::collections::HashMap; 3 + use crate::{NodeId, RelationshipId, LabelId, PropertyKeyId, Result}; 4 + 5 + pub mod graph; 6 + pub mod node; 7 + pub mod relationship; 8 + pub mod property; 9 + 10 + pub use graph::Graph; 11 + pub use node::Node; 12 + pub use relationship::Relationship; 13 + pub use property::{Property, PropertyValue}; 14 + 15 + #[derive(Debug, Clone, Serialize, Deserialize)] 16 + pub struct GraphSchema { 17 + pub labels: HashMap<String, LabelId>, 18 + pub property_keys: HashMap<String, PropertyKeyId>, 19 + pub relationship_types: HashMap<String, u32>, 20 + 21 + next_label_id: LabelId, 22 + next_property_key_id: PropertyKeyId, 23 + next_relationship_type_id: u32, 24 + } 25 + 26 + impl GraphSchema { 27 + pub fn new() -> Self { 28 + Self { 29 + labels: HashMap::new(), 30 + property_keys: HashMap::new(), 31 + relationship_types: HashMap::new(), 32 + next_label_id: LabelId(0), 33 + next_property_key_id: PropertyKeyId(0), 34 + next_relationship_type_id: 0, 35 + } 36 + } 37 + 38 + pub fn get_or_create_label(&mut self, label: &str) -> LabelId { 39 + if let Some(&id) = self.labels.get(label) { 40 + return id; 41 + } 42 + 43 + let id = self.next_label_id; 44 + self.labels.insert(label.to_string(), id); 45 + self.next_label_id = LabelId(self.next_label_id.0 + 1); 46 + id 47 + } 48 + 49 + pub fn get_or_create_property_key(&mut self, key: &str) -> PropertyKeyId { 50 + if let Some(&id) = self.property_keys.get(key) { 51 + return id; 52 + } 53 + 54 + let id = self.next_property_key_id; 55 + self.property_keys.insert(key.to_string(), id); 56 + self.next_property_key_id = PropertyKeyId(self.next_property_key_id.0 + 1); 57 + id 58 + } 59 + 60 + pub fn get_or_create_relationship_type(&mut self, rel_type: &str) -> u32 { 61 + if let Some(&id) = self.relationship_types.get(rel_type) { 62 + return id; 63 + } 64 + 65 + let id = self.next_relationship_type_id; 66 + self.relationship_types.insert(rel_type.to_string(), id); 67 + self.next_relationship_type_id += 1; 68 + id 69 + } 70 + }
+44
src/core/node.rs
··· 1 + use serde::{Deserialize, Serialize}; 2 + use crate::{NodeId, LabelId}; 3 + use crate::core::property::PropertyMap; 4 + 5 + #[derive(Debug, Clone, Serialize, Deserialize)] 6 + pub struct Node { 7 + pub id: NodeId, 8 + pub labels: Vec<LabelId>, 9 + pub properties: PropertyMap, 10 + } 11 + 12 + impl Node { 13 + pub fn new(id: NodeId) -> Self { 14 + Self { 15 + id, 16 + labels: Vec::new(), 17 + properties: PropertyMap::new(), 18 + } 19 + } 20 + 21 + pub fn with_labels(mut self, labels: Vec<LabelId>) -> Self { 22 + self.labels = labels; 23 + self 24 + } 25 + 26 + pub fn with_properties(mut self, properties: PropertyMap) -> Self { 27 + self.properties = properties; 28 + self 29 + } 30 + 31 + pub fn add_label(&mut self, label: LabelId) { 32 + if !self.labels.contains(&label) { 33 + self.labels.push(label); 34 + } 35 + } 36 + 37 + pub fn remove_label(&mut self, label: LabelId) { 38 + self.labels.retain(|&l| l != label); 39 + } 40 + 41 + pub fn has_label(&self, label: LabelId) -> bool { 42 + self.labels.contains(&label) 43 + } 44 + }
+79
src/core/property.rs
··· 1 + use serde::{Deserialize, Serialize}; 2 + use std::collections::HashMap; 3 + use crate::PropertyKeyId; 4 + 5 + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] 6 + pub enum PropertyValue { 7 + Null, 8 + Boolean(bool), 9 + Integer(i64), 10 + Float(f64), 11 + String(String), 12 + List(Vec<PropertyValue>), 13 + Map(HashMap<String, PropertyValue>), 14 + } 15 + 16 + impl Eq for PropertyValue {} 17 + 18 + impl std::hash::Hash for PropertyValue { 19 + fn hash<H: std::hash::Hasher>(&self, state: &mut H) { 20 + match self { 21 + PropertyValue::Null => 0.hash(state), 22 + PropertyValue::Boolean(b) => { 23 + 1.hash(state); 24 + b.hash(state); 25 + } 26 + PropertyValue::Integer(i) => { 27 + 2.hash(state); 28 + i.hash(state); 29 + } 30 + PropertyValue::Float(f) => { 31 + 3.hash(state); 32 + f.to_bits().hash(state); 33 + } 34 + PropertyValue::String(s) => { 35 + 4.hash(state); 36 + s.hash(state); 37 + } 38 + PropertyValue::List(l) => { 39 + 5.hash(state); 40 + l.hash(state); 41 + } 42 + PropertyValue::Map(m) => { 43 + 6.hash(state); 44 + // Sort keys for deterministic hashing 45 + let mut sorted: Vec<_> = m.iter().collect(); 46 + sorted.sort_by_key(|(k, _)| *k); 47 + sorted.hash(state); 48 + } 49 + } 50 + } 51 + } 52 + 53 + impl PropertyValue { 54 + pub fn type_name(&self) -> &'static str { 55 + match self { 56 + PropertyValue::Null => "null", 57 + PropertyValue::Boolean(_) => "boolean", 58 + PropertyValue::Integer(_) => "integer", 59 + PropertyValue::Float(_) => "float", 60 + PropertyValue::String(_) => "string", 61 + PropertyValue::List(_) => "list", 62 + PropertyValue::Map(_) => "map", 63 + } 64 + } 65 + } 66 + 67 + #[derive(Debug, Clone, Serialize, Deserialize)] 68 + pub struct Property { 69 + pub key_id: PropertyKeyId, 70 + pub value: PropertyValue, 71 + } 72 + 73 + impl Property { 74 + pub fn new(key_id: PropertyKeyId, value: PropertyValue) -> Self { 75 + Self { key_id, value } 76 + } 77 + } 78 + 79 + pub type PropertyMap = HashMap<PropertyKeyId, PropertyValue>;
+65
src/core/relationship.rs
··· 1 + use serde::{Deserialize, Serialize}; 2 + use crate::{NodeId, RelationshipId}; 3 + use crate::core::property::PropertyMap; 4 + 5 + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] 6 + pub enum Direction { 7 + Outgoing, 8 + Incoming, 9 + Both, 10 + } 11 + 12 + #[derive(Debug, Clone, Serialize, Deserialize)] 13 + pub struct Relationship { 14 + pub id: RelationshipId, 15 + pub start_node: NodeId, 16 + pub end_node: NodeId, 17 + pub rel_type: u32, 18 + pub properties: PropertyMap, 19 + } 20 + 21 + impl Relationship { 22 + pub fn new( 23 + id: RelationshipId, 24 + start_node: NodeId, 25 + end_node: NodeId, 26 + rel_type: u32, 27 + ) -> Self { 28 + Self { 29 + id, 30 + start_node, 31 + end_node, 32 + rel_type, 33 + properties: PropertyMap::new(), 34 + } 35 + } 36 + 37 + pub fn with_properties(mut self, properties: PropertyMap) -> Self { 38 + self.properties = properties; 39 + self 40 + } 41 + 42 + pub fn other_node(&self, node_id: NodeId) -> Option<NodeId> { 43 + if self.start_node == node_id { 44 + Some(self.end_node) 45 + } else if self.end_node == node_id { 46 + Some(self.start_node) 47 + } else { 48 + None 49 + } 50 + } 51 + 52 + pub fn connects(&self, node_id: NodeId) -> bool { 53 + self.start_node == node_id || self.end_node == node_id 54 + } 55 + 56 + pub fn direction_from(&self, node_id: NodeId) -> Option<Direction> { 57 + if self.start_node == node_id { 58 + Some(Direction::Outgoing) 59 + } else if self.end_node == node_id { 60 + Some(Direction::Incoming) 61 + } else { 62 + None 63 + } 64 + } 65 + }
+193
src/cypher/ast.rs
··· 1 + use serde::{Serialize, Deserialize}; 2 + use std::collections::HashMap; 3 + use crate::core::PropertyValue; 4 + 5 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 6 + pub enum CypherQuery { 7 + Match(MatchClause), 8 + Create(CreateClause), 9 + Merge(MergeClause), 10 + Delete(DeleteClause), 11 + Set(SetClause), 12 + Remove(RemoveClause), 13 + Return(ReturnClause), 14 + With(WithClause), 15 + Union(Box<CypherQuery>, Box<CypherQuery>), 16 + Compound(Vec<CypherQuery>), 17 + } 18 + 19 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 20 + pub struct MatchClause { 21 + pub pattern: Pattern, 22 + pub where_clause: Option<Expression>, 23 + pub optional: bool, 24 + } 25 + 26 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 27 + pub struct CreateClause { 28 + pub pattern: Pattern, 29 + } 30 + 31 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 32 + pub struct MergeClause { 33 + pub pattern: Pattern, 34 + pub on_create: Option<Vec<SetItem>>, 35 + pub on_match: Option<Vec<SetItem>>, 36 + } 37 + 38 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 39 + pub struct DeleteClause { 40 + pub expressions: Vec<Expression>, 41 + pub detach: bool, 42 + } 43 + 44 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 45 + pub struct SetClause { 46 + pub items: Vec<SetItem>, 47 + } 48 + 49 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 50 + pub struct SetItem { 51 + pub property: PropertyExpression, 52 + pub expression: Expression, 53 + } 54 + 55 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 56 + pub struct RemoveClause { 57 + pub items: Vec<RemoveItem>, 58 + } 59 + 60 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 61 + pub enum RemoveItem { 62 + Property(PropertyExpression), 63 + Label(String, String), 64 + } 65 + 66 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 67 + pub struct ReturnClause { 68 + pub distinct: bool, 69 + pub items: Vec<ReturnItem>, 70 + pub order_by: Option<Vec<OrderByItem>>, 71 + pub skip: Option<Expression>, 72 + pub limit: Option<Expression>, 73 + } 74 + 75 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 76 + pub struct ReturnItem { 77 + pub expression: Expression, 78 + pub alias: Option<String>, 79 + } 80 + 81 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 82 + pub struct OrderByItem { 83 + pub expression: Expression, 84 + pub ascending: bool, 85 + } 86 + 87 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 88 + pub struct WithClause { 89 + pub distinct: bool, 90 + pub items: Vec<ReturnItem>, 91 + pub order_by: Option<Vec<OrderByItem>>, 92 + pub skip: Option<Expression>, 93 + pub limit: Option<Expression>, 94 + pub where_clause: Option<Expression>, 95 + } 96 + 97 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 98 + pub struct Pattern { 99 + pub elements: Vec<PatternElement>, 100 + } 101 + 102 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 103 + pub enum PatternElement { 104 + Node(NodePattern), 105 + Relationship(RelationshipPattern), 106 + Path(PathPattern), 107 + } 108 + 109 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 110 + pub struct NodePattern { 111 + pub variable: Option<String>, 112 + pub labels: Vec<String>, 113 + pub properties: Option<HashMap<String, Expression>>, 114 + } 115 + 116 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 117 + pub struct RelationshipPattern { 118 + pub variable: Option<String>, 119 + pub types: Vec<String>, 120 + pub properties: Option<HashMap<String, Expression>>, 121 + pub direction: RelationshipDirection, 122 + pub length: Option<RelationshipLength>, 123 + } 124 + 125 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 126 + pub enum RelationshipDirection { 127 + Outgoing, 128 + Incoming, 129 + Both, 130 + } 131 + 132 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 133 + pub struct RelationshipLength { 134 + pub min: Option<u32>, 135 + pub max: Option<u32>, 136 + } 137 + 138 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 139 + pub struct PathPattern { 140 + pub variable: Option<String>, 141 + pub elements: Vec<PatternElement>, 142 + } 143 + 144 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 145 + pub enum Expression { 146 + Variable(String), 147 + Property(PropertyExpression), 148 + Literal(PropertyValue), 149 + List(Vec<Expression>), 150 + Map(HashMap<String, Expression>), 151 + 152 + Add(Box<Expression>, Box<Expression>), 153 + Subtract(Box<Expression>, Box<Expression>), 154 + Multiply(Box<Expression>, Box<Expression>), 155 + Divide(Box<Expression>, Box<Expression>), 156 + Modulo(Box<Expression>, Box<Expression>), 157 + Power(Box<Expression>, Box<Expression>), 158 + 159 + Equal(Box<Expression>, Box<Expression>), 160 + NotEqual(Box<Expression>, Box<Expression>), 161 + LessThan(Box<Expression>, Box<Expression>), 162 + LessThanOrEqual(Box<Expression>, Box<Expression>), 163 + GreaterThan(Box<Expression>, Box<Expression>), 164 + GreaterThanOrEqual(Box<Expression>, Box<Expression>), 165 + 166 + And(Box<Expression>, Box<Expression>), 167 + Or(Box<Expression>, Box<Expression>), 168 + Not(Box<Expression>), 169 + 170 + In(Box<Expression>, Box<Expression>), 171 + IsNull(Box<Expression>), 172 + IsNotNull(Box<Expression>), 173 + 174 + Case(Vec<CaseWhen>, Option<Box<Expression>>), 175 + 176 + FunctionCall(String, Vec<Expression>), 177 + 178 + Parameter(String), 179 + 180 + PatternExpression(Pattern), 181 + } 182 + 183 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 184 + pub struct PropertyExpression { 185 + pub expression: Box<Expression>, 186 + pub property: String, 187 + } 188 + 189 + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] 190 + pub struct CaseWhen { 191 + pub condition: Expression, 192 + pub result: Expression, 193 + }
+59
src/cypher/executor.rs
··· 1 + use crate::cypher::planner::QueryPlan; 2 + use crate::core::Graph; 3 + use crate::{Result, GigabrainError}; 4 + use std::sync::Arc; 5 + 6 + pub struct QueryExecutor { 7 + graph: Arc<Graph>, 8 + } 9 + 10 + impl QueryExecutor { 11 + pub fn new(graph: Arc<Graph>) -> Self { 12 + Self { graph } 13 + } 14 + 15 + pub async fn execute(&self, plan: QueryPlan) -> Result<QueryResult> { 16 + match plan { 17 + QueryPlan::Scan(scan_plan) => self.execute_scan(scan_plan).await, 18 + QueryPlan::Create(create_plan) => self.execute_create(create_plan).await, 19 + _ => Err(GigabrainError::Query("Execution not implemented for this plan type".to_string())), 20 + } 21 + } 22 + 23 + async fn execute_scan(&self, _scan_plan: crate::cypher::planner::ScanPlan) -> Result<QueryResult> { 24 + Ok(QueryResult { 25 + rows: Vec::new(), 26 + columns: Vec::new(), 27 + }) 28 + } 29 + 30 + async fn execute_create(&self, _create_plan: crate::cypher::planner::CreatePlan) -> Result<QueryResult> { 31 + Ok(QueryResult { 32 + rows: Vec::new(), 33 + columns: Vec::new(), 34 + }) 35 + } 36 + } 37 + 38 + #[derive(Debug)] 39 + pub struct QueryResult { 40 + pub rows: Vec<Row>, 41 + pub columns: Vec<String>, 42 + } 43 + 44 + #[derive(Debug)] 45 + pub struct Row { 46 + pub values: Vec<Value>, 47 + } 48 + 49 + #[derive(Debug)] 50 + pub enum Value { 51 + Null, 52 + Node(crate::NodeId), 53 + Relationship(crate::RelationshipId), 54 + Integer(i64), 55 + Float(f64), 56 + String(String), 57 + Boolean(bool), 58 + List(Vec<Value>), 59 + }
+245
src/cypher/lexer.rs
··· 1 + use nom::{ 2 + IResult, 3 + branch::alt, 4 + bytes::complete::{tag, is_not}, 5 + character::complete::{char, digit1, multispace0, alpha1, alphanumeric1}, 6 + combinator::{map, recognize, opt, value}, 7 + multi::many0, 8 + sequence::{preceded, tuple, delimited}, 9 + }; 10 + 11 + #[derive(Debug, Clone, PartialEq)] 12 + pub enum Token { 13 + Match, 14 + Optional, 15 + Create, 16 + Merge, 17 + Delete, 18 + Detach, 19 + Set, 20 + Remove, 21 + Return, 22 + Distinct, 23 + With, 24 + Where, 25 + And, 26 + Or, 27 + Not, 28 + In, 29 + Is, 30 + Null, 31 + True, 32 + False, 33 + Case, 34 + When, 35 + Then, 36 + Else, 37 + End, 38 + As, 39 + By, 40 + Order, 41 + Asc, 42 + Desc, 43 + Skip, 44 + Limit, 45 + Union, 46 + All, 47 + 48 + LeftParen, 49 + RightParen, 50 + LeftBracket, 51 + RightBracket, 52 + LeftBrace, 53 + RightBrace, 54 + 55 + Comma, 56 + Dot, 57 + Colon, 58 + Semicolon, 59 + 60 + Plus, 61 + Minus, 62 + Star, 63 + Slash, 64 + Percent, 65 + Caret, 66 + 67 + Equal, 68 + NotEqual, 69 + LessThan, 70 + LessThanOrEqual, 71 + GreaterThan, 72 + GreaterThanOrEqual, 73 + 74 + Arrow, 75 + LeftArrow, 76 + 77 + Identifier(String), 78 + Integer(i64), 79 + Float(f64), 80 + String(String), 81 + Parameter(String), 82 + } 83 + 84 + pub fn lex(input: &str) -> IResult<&str, Vec<Token>> { 85 + many0(preceded(multispace0, token))(input) 86 + } 87 + 88 + fn token(input: &str) -> IResult<&str, Token> { 89 + alt(( 90 + keyword, 91 + operator, 92 + delimiter, 93 + parameter, 94 + number, 95 + string_literal, 96 + identifier, 97 + ))(input) 98 + } 99 + 100 + fn keyword(input: &str) -> IResult<&str, Token> { 101 + if input.is_empty() { 102 + return Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Eof))); 103 + } 104 + 105 + let keywords = &[ 106 + ("MATCH", Token::Match), 107 + ("OPTIONAL", Token::Optional), 108 + ("CREATE", Token::Create), 109 + ("MERGE", Token::Merge), 110 + ("DELETE", Token::Delete), 111 + ("DETACH", Token::Detach), 112 + ("SET", Token::Set), 113 + ("REMOVE", Token::Remove), 114 + ("RETURN", Token::Return), 115 + ("DISTINCT", Token::Distinct), 116 + ("WITH", Token::With), 117 + ("WHERE", Token::Where), 118 + ("AND", Token::And), 119 + ("ORDER", Token::Order), 120 + ("OR", Token::Or), 121 + ("NOT", Token::Not), 122 + ("IN", Token::In), 123 + ("IS", Token::Is), 124 + ("NULL", Token::Null), 125 + ("TRUE", Token::True), 126 + ("FALSE", Token::False), 127 + ("CASE", Token::Case), 128 + ("WHEN", Token::When), 129 + ("THEN", Token::Then), 130 + ("ELSE", Token::Else), 131 + ("END", Token::End), 132 + ("AS", Token::As), 133 + ("BY", Token::By), 134 + ("ASC", Token::Asc), 135 + ("DESC", Token::Desc), 136 + ("SKIP", Token::Skip), 137 + ("LIMIT", Token::Limit), 138 + ("UNION", Token::Union), 139 + ("ALL", Token::All), 140 + ]; 141 + 142 + for (keyword_str, token) in keywords { 143 + if input.len() >= keyword_str.len() { 144 + let (head, tail) = input.split_at(keyword_str.len()); 145 + if head.to_uppercase() == *keyword_str { 146 + if tail.is_empty() || !tail.chars().next().unwrap().is_alphanumeric() { 147 + return Ok((tail, token.clone())); 148 + } 149 + } 150 + } 151 + } 152 + 153 + Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Tag))) 154 + } 155 + 156 + fn operator(input: &str) -> IResult<&str, Token> { 157 + alt(( 158 + value(Token::Arrow, tag("->")), 159 + value(Token::LeftArrow, tag("<-")), 160 + value(Token::NotEqual, tag("<>")), 161 + value(Token::LessThanOrEqual, tag("<=")), 162 + value(Token::GreaterThanOrEqual, tag(">=")), 163 + value(Token::Plus, char('+')), 164 + value(Token::Minus, char('-')), 165 + value(Token::Star, char('*')), 166 + value(Token::Slash, char('/')), 167 + value(Token::Percent, char('%')), 168 + value(Token::Caret, char('^')), 169 + value(Token::Equal, char('=')), 170 + value(Token::LessThan, char('<')), 171 + value(Token::GreaterThan, char('>')), 172 + ))(input) 173 + } 174 + 175 + fn delimiter(input: &str) -> IResult<&str, Token> { 176 + alt(( 177 + value(Token::LeftParen, char('(')), 178 + value(Token::RightParen, char(')')), 179 + value(Token::LeftBracket, char('[')), 180 + value(Token::RightBracket, char(']')), 181 + value(Token::LeftBrace, char('{')), 182 + value(Token::RightBrace, char('}')), 183 + value(Token::Comma, char(',')), 184 + value(Token::Dot, char('.')), 185 + value(Token::Colon, char(':')), 186 + value(Token::Semicolon, char(';')), 187 + ))(input) 188 + } 189 + 190 + fn identifier(input: &str) -> IResult<&str, Token> { 191 + map( 192 + recognize(tuple(( 193 + alt((alpha1, tag("_"))), 194 + many0(alt((alphanumeric1, tag("_")))), 195 + ))), 196 + |s: &str| Token::Identifier(s.to_string()), 197 + )(input) 198 + } 199 + 200 + fn parameter(input: &str) -> IResult<&str, Token> { 201 + map( 202 + preceded( 203 + char('$'), 204 + recognize(tuple(( 205 + alt((alpha1, tag("_"))), 206 + many0(alt((alphanumeric1, tag("_")))), 207 + ))), 208 + ), 209 + |s: &str| Token::Parameter(s.to_string()), 210 + )(input) 211 + } 212 + 213 + fn number(input: &str) -> IResult<&str, Token> { 214 + alt(( 215 + map( 216 + recognize(tuple(( 217 + opt(char('-')), 218 + digit1, 219 + char('.'), 220 + digit1, 221 + ))), 222 + |s: &str| Token::Float(s.parse().unwrap()), 223 + ), 224 + map( 225 + recognize(tuple(( 226 + opt(char('-')), 227 + digit1, 228 + ))), 229 + |s: &str| Token::Integer(s.parse().unwrap()), 230 + ), 231 + ))(input) 232 + } 233 + 234 + fn string_literal(input: &str) -> IResult<&str, Token> { 235 + alt(( 236 + map( 237 + delimited(char('\''), is_not("'"), char('\'')), 238 + |s: &str| Token::String(s.to_string()), 239 + ), 240 + map( 241 + delimited(char('"'), is_not("\""), char('"')), 242 + |s: &str| Token::String(s.to_string()), 243 + ), 244 + ))(input) 245 + }
+10
src/cypher/mod.rs
··· 1 + pub mod ast; 2 + pub mod parser; 3 + pub mod lexer; 4 + pub mod planner; 5 + pub mod executor; 6 + 7 + pub use ast::{CypherQuery, Expression, Pattern}; 8 + pub use parser::parse_cypher; 9 + pub use planner::QueryPlan; 10 + pub use executor::QueryExecutor;
+358
src/cypher/parser.rs
··· 1 + use nom::{ 2 + IResult, 3 + branch::alt, 4 + combinator::{map, opt, value}, 5 + multi::{many0, many1, separated_list0, separated_list1}, 6 + sequence::{preceded, terminated, tuple, delimited, pair}, 7 + }; 8 + use std::collections::HashMap; 9 + use crate::core::PropertyValue; 10 + use crate::cypher::ast::*; 11 + use crate::cypher::lexer::{Token, lex}; 12 + 13 + pub fn parse_cypher(input: &str) -> Result<CypherQuery, String> { 14 + let (_, tokens) = lex(input).map_err(|e| format!("Lexing error: {:?}", e))?; 15 + let (remaining, query) = cypher_query(&tokens).map_err(|e| format!("Parse error: {:?}", e))?; 16 + 17 + if !remaining.is_empty() { 18 + return Err(format!("Unexpected tokens after query: {:?}", remaining)); 19 + } 20 + 21 + Ok(query) 22 + } 23 + 24 + type Tokens<'a> = &'a [Token]; 25 + 26 + fn cypher_query(input: Tokens) -> IResult<Tokens, CypherQuery> { 27 + alt(( 28 + map(match_clause, CypherQuery::Match), 29 + map(create_clause, CypherQuery::Create), 30 + map(return_clause, CypherQuery::Return), 31 + map( 32 + separated_list1( 33 + |i| expect_token(i, &Token::Semicolon), 34 + alt(( 35 + map(match_clause, CypherQuery::Match), 36 + map(create_clause, CypherQuery::Create), 37 + map(return_clause, CypherQuery::Return), 38 + )) 39 + ), 40 + CypherQuery::Compound 41 + ), 42 + ))(input) 43 + } 44 + 45 + fn match_clause(input: Tokens) -> IResult<Tokens, MatchClause> { 46 + map( 47 + tuple(( 48 + opt(|i| expect_token(i, &Token::Optional)), 49 + |i| expect_token(i, &Token::Match), 50 + pattern, 51 + opt(where_clause), 52 + )), 53 + |(optional, _, pattern, where_clause)| MatchClause { 54 + pattern, 55 + where_clause, 56 + optional: optional.is_some(), 57 + }, 58 + )(input) 59 + } 60 + 61 + fn create_clause(input: Tokens) -> IResult<Tokens, CreateClause> { 62 + map( 63 + preceded( 64 + |i| expect_token(i, &Token::Create), 65 + pattern, 66 + ), 67 + |pattern| CreateClause { pattern }, 68 + )(input) 69 + } 70 + 71 + fn return_clause(input: Tokens) -> IResult<Tokens, ReturnClause> { 72 + map( 73 + tuple(( 74 + |i| expect_token(i, &Token::Return), 75 + opt(|i| expect_token(i, &Token::Distinct)), 76 + separated_list1(|i| expect_token(i, &Token::Comma), return_item), 77 + opt(order_by), 78 + opt(preceded(|i| expect_token(i, &Token::Skip), expression)), 79 + opt(preceded(|i| expect_token(i, &Token::Limit), expression)), 80 + )), 81 + |(_, distinct, items, order_by, skip, limit)| ReturnClause { 82 + distinct: distinct.is_some(), 83 + items, 84 + order_by, 85 + skip, 86 + limit, 87 + }, 88 + )(input) 89 + } 90 + 91 + fn return_item(input: Tokens) -> IResult<Tokens, ReturnItem> { 92 + map( 93 + tuple(( 94 + expression, 95 + opt(preceded(|i| expect_token(i, &Token::As), identifier)), 96 + )), 97 + |(expression, alias)| ReturnItem { expression, alias }, 98 + )(input) 99 + } 100 + 101 + fn order_by(input: Tokens) -> IResult<Tokens, Vec<OrderByItem>> { 102 + preceded( 103 + tuple(( 104 + |i| expect_token(i, &Token::Order), 105 + |i| expect_token(i, &Token::By), 106 + )), 107 + separated_list1(|i| expect_token(i, &Token::Comma), order_by_item), 108 + )(input) 109 + } 110 + 111 + fn order_by_item(input: Tokens) -> IResult<Tokens, OrderByItem> { 112 + map( 113 + tuple(( 114 + expression, 115 + opt(alt(( 116 + value(true, |i| expect_token(i, &Token::Asc)), 117 + value(false, |i| expect_token(i, &Token::Desc)), 118 + ))), 119 + )), 120 + |(expression, ascending)| OrderByItem { 121 + expression, 122 + ascending: ascending.unwrap_or(true), 123 + }, 124 + )(input) 125 + } 126 + 127 + fn where_clause(input: Tokens) -> IResult<Tokens, Expression> { 128 + preceded( 129 + |i| expect_token(i, &Token::Where), 130 + expression, 131 + )(input) 132 + } 133 + 134 + fn pattern(input: Tokens) -> IResult<Tokens, Pattern> { 135 + map( 136 + separated_list1(|i| expect_token(i, &Token::Comma), pattern_part), 137 + |parts| Pattern { 138 + elements: parts.into_iter().flatten().collect(), 139 + }, 140 + )(input) 141 + } 142 + 143 + fn pattern_part(input: Tokens) -> IResult<Tokens, Vec<PatternElement>> { 144 + many1(pattern_element)(input) 145 + } 146 + 147 + fn pattern_element(input: Tokens) -> IResult<Tokens, PatternElement> { 148 + alt(( 149 + map(node_pattern, PatternElement::Node), 150 + map(relationship_pattern, PatternElement::Relationship), 151 + ))(input) 152 + } 153 + 154 + fn node_pattern(input: Tokens) -> IResult<Tokens, NodePattern> { 155 + delimited( 156 + |i| expect_token(i, &Token::LeftParen), 157 + map( 158 + tuple(( 159 + opt(identifier), 160 + many0(preceded(|i| expect_token(i, &Token::Colon), identifier)), 161 + opt(properties_map), 162 + )), 163 + |(variable, labels, properties)| NodePattern { 164 + variable, 165 + labels, 166 + properties, 167 + }, 168 + ), 169 + |i| expect_token(i, &Token::RightParen), 170 + )(input) 171 + } 172 + 173 + fn relationship_pattern(input: Tokens) -> IResult<Tokens, RelationshipPattern> { 174 + alt(( 175 + map( 176 + tuple(( 177 + |i| expect_token(i, &Token::Minus), 178 + delimited( 179 + |i| expect_token(i, &Token::LeftBracket), 180 + relationship_detail, 181 + |i| expect_token(i, &Token::RightBracket), 182 + ), 183 + |i| expect_token(i, &Token::Arrow), 184 + )), 185 + |(_, detail, _)| RelationshipPattern { 186 + direction: RelationshipDirection::Outgoing, 187 + ..detail 188 + }, 189 + ), 190 + map( 191 + tuple(( 192 + |i| expect_token(i, &Token::LeftArrow), 193 + delimited( 194 + |i| expect_token(i, &Token::LeftBracket), 195 + relationship_detail, 196 + |i| expect_token(i, &Token::RightBracket), 197 + ), 198 + |i| expect_token(i, &Token::Minus), 199 + )), 200 + |(_, detail, _)| RelationshipPattern { 201 + direction: RelationshipDirection::Incoming, 202 + ..detail 203 + }, 204 + ), 205 + ))(input) 206 + } 207 + 208 + fn relationship_detail(input: Tokens) -> IResult<Tokens, RelationshipPattern> { 209 + map( 210 + tuple(( 211 + opt(identifier), 212 + many0(preceded(|i| expect_token(i, &Token::Colon), identifier)), 213 + opt(properties_map), 214 + )), 215 + |(variable, types, properties)| RelationshipPattern { 216 + variable, 217 + types, 218 + properties, 219 + direction: RelationshipDirection::Both, 220 + length: None, 221 + }, 222 + )(input) 223 + } 224 + 225 + fn properties_map(input: Tokens) -> IResult<Tokens, HashMap<String, Expression>> { 226 + delimited( 227 + |i| expect_token(i, &Token::LeftBrace), 228 + map( 229 + separated_list0( 230 + |i| expect_token(i, &Token::Comma), 231 + tuple(( 232 + identifier, 233 + |i| expect_token(i, &Token::Colon), 234 + expression, 235 + )), 236 + ), 237 + |items| items.into_iter().map(|(k, _, v)| (k, v)).collect(), 238 + ), 239 + |i| expect_token(i, &Token::RightBrace), 240 + )(input) 241 + } 242 + 243 + fn expression(input: Tokens) -> IResult<Tokens, Expression> { 244 + or_expression(input) 245 + } 246 + 247 + fn or_expression(input: Tokens) -> IResult<Tokens, Expression> { 248 + let (input, left) = and_expression(input)?; 249 + 250 + let (input, rights) = many0(preceded( 251 + |i| expect_token(i, &Token::Or), 252 + and_expression, 253 + ))(input)?; 254 + 255 + Ok((input, rights.into_iter().fold(left, |acc, right| { 256 + Expression::Or(Box::new(acc), Box::new(right)) 257 + }))) 258 + } 259 + 260 + fn and_expression(input: Tokens) -> IResult<Tokens, Expression> { 261 + let (input, left) = comparison_expression(input)?; 262 + 263 + let (input, rights) = many0(preceded( 264 + |i| expect_token(i, &Token::And), 265 + comparison_expression, 266 + ))(input)?; 267 + 268 + Ok((input, rights.into_iter().fold(left, |acc, right| { 269 + Expression::And(Box::new(acc), Box::new(right)) 270 + }))) 271 + } 272 + 273 + fn comparison_expression(input: Tokens) -> IResult<Tokens, Expression> { 274 + let (input, left) = additive_expression(input)?; 275 + 276 + if let Ok((input, _)) = expect_token(input, &Token::Equal) { 277 + let (input, right) = additive_expression(input)?; 278 + return Ok((input, Expression::Equal(Box::new(left), Box::new(right)))); 279 + } 280 + 281 + Ok((input, left)) 282 + } 283 + 284 + fn additive_expression(input: Tokens) -> IResult<Tokens, Expression> { 285 + let (input, left) = multiplicative_expression(input)?; 286 + 287 + let (input, ops) = many0(tuple(( 288 + alt(( 289 + value(true, |i| expect_token(i, &Token::Plus)), 290 + value(false, |i| expect_token(i, &Token::Minus)), 291 + )), 292 + multiplicative_expression, 293 + )))(input)?; 294 + 295 + Ok((input, ops.into_iter().fold(left, |acc, (is_add, right)| { 296 + if is_add { 297 + Expression::Add(Box::new(acc), Box::new(right)) 298 + } else { 299 + Expression::Subtract(Box::new(acc), Box::new(right)) 300 + } 301 + }))) 302 + } 303 + 304 + fn multiplicative_expression(input: Tokens) -> IResult<Tokens, Expression> { 305 + let (input, left) = primary_expression(input)?; 306 + Ok((input, left)) 307 + } 308 + 309 + fn primary_expression(input: Tokens) -> IResult<Tokens, Expression> { 310 + alt(( 311 + map(literal, |lit| Expression::Literal(lit)), 312 + map(identifier, Expression::Variable), 313 + delimited( 314 + |i| expect_token(i, &Token::LeftParen), 315 + expression, 316 + |i| expect_token(i, &Token::RightParen), 317 + ), 318 + ))(input) 319 + } 320 + 321 + fn literal(input: Tokens) -> IResult<Tokens, PropertyValue> { 322 + if input.is_empty() { 323 + return Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Eof))); 324 + } 325 + 326 + match &input[0] { 327 + Token::Integer(n) => Ok((&input[1..], PropertyValue::Integer(*n))), 328 + Token::Float(f) => Ok((&input[1..], PropertyValue::Float(*f))), 329 + Token::String(s) => Ok((&input[1..], PropertyValue::String(s.clone()))), 330 + Token::True => Ok((&input[1..], PropertyValue::Boolean(true))), 331 + Token::False => Ok((&input[1..], PropertyValue::Boolean(false))), 332 + Token::Null => Ok((&input[1..], PropertyValue::Null)), 333 + _ => Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Tag))), 334 + } 335 + } 336 + 337 + fn identifier(input: Tokens) -> IResult<Tokens, String> { 338 + if input.is_empty() { 339 + return Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Eof))); 340 + } 341 + 342 + match &input[0] { 343 + Token::Identifier(s) => Ok((&input[1..], s.clone())), 344 + _ => Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Tag))), 345 + } 346 + } 347 + 348 + fn expect_token<'a>(input: &'a [Token], expected: &Token) -> IResult<&'a [Token], &'a Token> { 349 + if input.is_empty() { 350 + return Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Eof))); 351 + } 352 + 353 + if std::mem::discriminant(&input[0]) == std::mem::discriminant(expected) { 354 + Ok((&input[1..], &input[0])) 355 + } else { 356 + Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Tag))) 357 + } 358 + }
+111
src/cypher/planner.rs
··· 1 + use crate::cypher::ast::*; 2 + use crate::{Result, GigabrainError}; 3 + 4 + #[derive(Debug, Clone)] 5 + pub enum QueryPlan { 6 + Scan(ScanPlan), 7 + Filter(FilterPlan), 8 + Join(JoinPlan), 9 + Project(ProjectPlan), 10 + Sort(SortPlan), 11 + Limit(LimitPlan), 12 + Create(CreatePlan), 13 + Delete(DeletePlan), 14 + } 15 + 16 + #[derive(Debug, Clone)] 17 + pub struct ScanPlan { 18 + pub variable: String, 19 + pub labels: Vec<String>, 20 + } 21 + 22 + #[derive(Debug, Clone)] 23 + pub struct FilterPlan { 24 + pub input: Box<QueryPlan>, 25 + pub predicate: Expression, 26 + } 27 + 28 + #[derive(Debug, Clone)] 29 + pub struct JoinPlan { 30 + pub left: Box<QueryPlan>, 31 + pub right: Box<QueryPlan>, 32 + pub condition: Expression, 33 + } 34 + 35 + #[derive(Debug, Clone)] 36 + pub struct ProjectPlan { 37 + pub input: Box<QueryPlan>, 38 + pub projections: Vec<(String, Expression)>, 39 + } 40 + 41 + #[derive(Debug, Clone)] 42 + pub struct SortPlan { 43 + pub input: Box<QueryPlan>, 44 + pub order_by: Vec<OrderByItem>, 45 + } 46 + 47 + #[derive(Debug, Clone)] 48 + pub struct LimitPlan { 49 + pub input: Box<QueryPlan>, 50 + pub skip: Option<usize>, 51 + pub limit: usize, 52 + } 53 + 54 + #[derive(Debug, Clone)] 55 + pub struct CreatePlan { 56 + pub pattern: Pattern, 57 + } 58 + 59 + #[derive(Debug, Clone)] 60 + pub struct DeletePlan { 61 + pub input: Box<QueryPlan>, 62 + pub expressions: Vec<Expression>, 63 + pub detach: bool, 64 + } 65 + 66 + pub fn plan_query(query: &CypherQuery) -> Result<QueryPlan> { 67 + match query { 68 + CypherQuery::Match(match_clause) => plan_match(match_clause), 69 + CypherQuery::Create(create_clause) => plan_create(create_clause), 70 + CypherQuery::Return(return_clause) => plan_return(return_clause), 71 + _ => Err(GigabrainError::Query("Query planning not implemented for this query type".to_string())), 72 + } 73 + } 74 + 75 + fn plan_match(match_clause: &MatchClause) -> Result<QueryPlan> { 76 + let mut plan = plan_pattern(&match_clause.pattern)?; 77 + 78 + if let Some(where_clause) = &match_clause.where_clause { 79 + plan = QueryPlan::Filter(FilterPlan { 80 + input: Box::new(plan), 81 + predicate: where_clause.clone(), 82 + }); 83 + } 84 + 85 + Ok(plan) 86 + } 87 + 88 + fn plan_create(create_clause: &CreateClause) -> Result<QueryPlan> { 89 + Ok(QueryPlan::Create(CreatePlan { 90 + pattern: create_clause.pattern.clone(), 91 + })) 92 + } 93 + 94 + fn plan_return(_return_clause: &ReturnClause) -> Result<QueryPlan> { 95 + Err(GigabrainError::Query("RETURN clause planning not implemented".to_string())) 96 + } 97 + 98 + fn plan_pattern(pattern: &Pattern) -> Result<QueryPlan> { 99 + for element in &pattern.elements { 100 + if let PatternElement::Node(node_pattern) = element { 101 + if let Some(variable) = &node_pattern.variable { 102 + return Ok(QueryPlan::Scan(ScanPlan { 103 + variable: variable.clone(), 104 + labels: node_pattern.labels.clone(), 105 + })); 106 + } 107 + } 108 + } 109 + 110 + Err(GigabrainError::Query("No scannable node pattern found".to_string())) 111 + }
+34
src/distributed/mod.rs
··· 1 + use std::sync::Arc; 2 + use dashmap::DashMap; 3 + use crate::{NodeId, Result, GigabrainError}; 4 + 5 + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 6 + pub struct ShardId(pub u32); 7 + 8 + pub struct ShardManager { 9 + shard_count: u32, 10 + node_to_shard: Arc<DashMap<NodeId, ShardId>>, 11 + } 12 + 13 + impl ShardManager { 14 + pub fn new(shard_count: u32) -> Self { 15 + Self { 16 + shard_count, 17 + node_to_shard: Arc::new(DashMap::new()), 18 + } 19 + } 20 + 21 + pub fn get_shard_for_node(&self, node_id: NodeId) -> ShardId { 22 + if let Some(shard) = self.node_to_shard.get(&node_id) { 23 + return *shard; 24 + } 25 + 26 + let shard_id = ShardId((node_id.0 % self.shard_count as u64) as u32); 27 + self.node_to_shard.insert(node_id, shard_id); 28 + shard_id 29 + } 30 + 31 + pub fn rebalance(&self) -> Result<()> { 32 + Err(GigabrainError::Distributed("Rebalancing not implemented".to_string())) 33 + } 34 + }
+39
src/error.rs
··· 1 + use thiserror::Error; 2 + 3 + #[derive(Error, Debug)] 4 + pub enum GigabrainError { 5 + #[error("IO error: {0}")] 6 + Io(#[from] std::io::Error), 7 + 8 + #[error("Storage error: {0}")] 9 + Storage(String), 10 + 11 + #[error("Transaction error: {0}")] 12 + Transaction(String), 13 + 14 + #[error("Query error: {0}")] 15 + Query(String), 16 + 17 + #[error("Index error: {0}")] 18 + Index(String), 19 + 20 + #[error("Node not found: {0:?}")] 21 + NodeNotFound(crate::NodeId), 22 + 23 + #[error("Relationship not found: {0:?}")] 24 + RelationshipNotFound(crate::RelationshipId), 25 + 26 + #[error("Property not found: {0}")] 27 + PropertyNotFound(String), 28 + 29 + #[error("Cypher parse error: {0}")] 30 + CypherParse(String), 31 + 32 + #[error("Distributed operation error: {0}")] 33 + Distributed(String), 34 + 35 + #[error("Serialization error: {0}")] 36 + Serialization(#[from] bincode::Error), 37 + } 38 + 39 + pub type Result<T> = std::result::Result<T, GigabrainError>;
+63
src/index/mod.rs
··· 1 + use roaring::RoaringBitmap; 2 + use dashmap::DashMap; 3 + use std::sync::Arc; 4 + use crate::{NodeId, LabelId, PropertyKeyId, Result}; 5 + use crate::core::PropertyValue; 6 + 7 + pub struct IndexManager { 8 + label_index: Arc<DashMap<LabelId, RoaringBitmap>>, 9 + property_index: Arc<DashMap<(PropertyKeyId, PropertyValue), RoaringBitmap>>, 10 + } 11 + 12 + impl IndexManager { 13 + pub fn new() -> Self { 14 + Self { 15 + label_index: Arc::new(DashMap::new()), 16 + property_index: Arc::new(DashMap::new()), 17 + } 18 + } 19 + 20 + pub fn add_node_label(&self, node_id: NodeId, label_id: LabelId) { 21 + self.label_index 22 + .entry(label_id) 23 + .or_insert_with(RoaringBitmap::new) 24 + .insert(node_id.0 as u32); 25 + } 26 + 27 + pub fn remove_node_label(&self, node_id: NodeId, label_id: LabelId) { 28 + if let Some(mut bitmap) = self.label_index.get_mut(&label_id) { 29 + bitmap.remove(node_id.0 as u32); 30 + } 31 + } 32 + 33 + pub fn get_nodes_by_label(&self, label_id: LabelId) -> Vec<NodeId> { 34 + self.label_index 35 + .get(&label_id) 36 + .map(|bitmap| { 37 + bitmap.iter() 38 + .map(|id| NodeId(id as u64)) 39 + .collect() 40 + }) 41 + .unwrap_or_default() 42 + } 43 + 44 + pub fn add_node_property(&self, node_id: NodeId, property_key: PropertyKeyId, value: PropertyValue) { 45 + let key = (property_key, value); 46 + self.property_index 47 + .entry(key) 48 + .or_insert_with(RoaringBitmap::new) 49 + .insert(node_id.0 as u32); 50 + } 51 + 52 + pub fn get_nodes_by_property(&self, property_key: PropertyKeyId, value: &PropertyValue) -> Vec<NodeId> { 53 + let key = (property_key, value.clone()); 54 + self.property_index 55 + .get(&key) 56 + .map(|bitmap| { 57 + bitmap.iter() 58 + .map(|id| NodeId(id as u64)) 59 + .collect() 60 + }) 61 + .unwrap_or_default() 62 + } 63 + }
+24
src/lib.rs
··· 1 + pub mod core; 2 + pub mod storage; 3 + pub mod cypher; 4 + pub mod index; 5 + pub mod transaction; 6 + pub mod distributed; 7 + pub mod error; 8 + 9 + pub use core::{Graph, Node, Relationship, Property}; 10 + pub use error::{GigabrainError, Result}; 11 + 12 + use serde::{Serialize, Deserialize}; 13 + 14 + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] 15 + pub struct NodeId(pub u64); 16 + 17 + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] 18 + pub struct RelationshipId(pub u64); 19 + 20 + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] 21 + pub struct LabelId(pub u32); 22 + 23 + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] 24 + pub struct PropertyKeyId(pub u32);
+50
src/main.rs
··· 1 + use gigabrain::{Graph, NodeId, RelationshipId}; 2 + use gigabrain::cypher::parse_cypher; 3 + use gigabrain::storage::MemoryStore; 4 + use std::collections::HashMap; 5 + use tracing::{info, warn}; 6 + use tracing_subscriber; 7 + 8 + #[tokio::main] 9 + async fn main() -> Result<(), Box<dyn std::error::Error>> { 10 + tracing_subscriber::fmt() 11 + .with_max_level(tracing::Level::INFO) 12 + .init(); 13 + 14 + info!("Starting GigaBrain Graph Database"); 15 + 16 + let graph = Graph::new(); 17 + 18 + let mut schema = graph.schema().write(); 19 + let person_label = schema.get_or_create_label("Person"); 20 + let name_prop = schema.get_or_create_property_key("name"); 21 + let age_prop = schema.get_or_create_property_key("age"); 22 + let knows_rel = schema.get_or_create_relationship_type("KNOWS"); 23 + drop(schema); 24 + 25 + let alice = graph.create_node(); 26 + let bob = graph.create_node(); 27 + let charlie = graph.create_node(); 28 + 29 + graph.create_relationship(alice, bob, knows_rel)?; 30 + graph.create_relationship(bob, charlie, knows_rel)?; 31 + 32 + info!("Created sample graph with 3 nodes and 2 relationships"); 33 + 34 + let query = "MATCH (n:Person)-[:KNOWS]->(m) RETURN n, m"; 35 + match parse_cypher(query) { 36 + Ok(parsed) => { 37 + info!("Successfully parsed Cypher query: {:?}", parsed); 38 + } 39 + Err(e) => { 40 + warn!("Failed to parse Cypher query: {}", e); 41 + } 42 + } 43 + 44 + let storage = MemoryStore::new(); 45 + info!("Initialized persistent storage"); 46 + 47 + info!("GigaBrain Graph Database started successfully!"); 48 + 49 + Ok(()) 50 + }
+147
src/storage/btree.rs
··· 1 + use std::cmp::Ordering; 2 + use serde::{Serialize, Deserialize}; 3 + use crate::{Result, GigabrainError}; 4 + 5 + const BTREE_ORDER: usize = 256; 6 + const MIN_KEYS: usize = BTREE_ORDER / 2 - 1; 7 + const MAX_KEYS: usize = BTREE_ORDER - 1; 8 + 9 + #[derive(Debug, Clone, Serialize, Deserialize)] 10 + pub struct BTreeNode<K: Ord + Clone, V: Clone> { 11 + keys: Vec<K>, 12 + values: Vec<V>, 13 + children: Vec<BTreeNode<K, V>>, 14 + is_leaf: bool, 15 + } 16 + 17 + impl<K: Ord + Clone, V: Clone> BTreeNode<K, V> { 18 + pub fn new(is_leaf: bool) -> Self { 19 + Self { 20 + keys: Vec::with_capacity(MAX_KEYS), 21 + values: Vec::with_capacity(MAX_KEYS), 22 + children: if is_leaf { Vec::new() } else { Vec::with_capacity(BTREE_ORDER) }, 23 + is_leaf, 24 + } 25 + } 26 + 27 + pub fn search(&self, key: &K) -> Option<&V> { 28 + match self.keys.binary_search(key) { 29 + Ok(idx) => Some(&self.values[idx]), 30 + Err(idx) => { 31 + if self.is_leaf { 32 + None 33 + } else if idx < self.children.len() { 34 + self.children[idx].search(key) 35 + } else { 36 + None 37 + } 38 + } 39 + } 40 + } 41 + 42 + pub fn insert(&mut self, key: K, value: V) -> Result<Option<(K, V, Self)>> { 43 + if self.is_leaf { 44 + match self.keys.binary_search(&key) { 45 + Ok(idx) => { 46 + self.values[idx] = value; 47 + Ok(None) 48 + } 49 + Err(idx) => { 50 + self.keys.insert(idx, key); 51 + self.values.insert(idx, value); 52 + 53 + if self.keys.len() > MAX_KEYS { 54 + Ok(Some(self.split())) 55 + } else { 56 + Ok(None) 57 + } 58 + } 59 + } 60 + } else { 61 + let child_idx = match self.keys.binary_search(&key) { 62 + Ok(idx) => idx + 1, 63 + Err(idx) => idx, 64 + }; 65 + 66 + if let Some((median_key, median_value, new_child)) = 67 + self.children[child_idx].insert(key, value)? { 68 + 69 + let insert_idx = match self.keys.binary_search(&median_key) { 70 + Ok(_) => unreachable!(), 71 + Err(idx) => idx, 72 + }; 73 + 74 + self.keys.insert(insert_idx, median_key); 75 + self.values.insert(insert_idx, median_value); 76 + self.children.insert(insert_idx + 1, new_child); 77 + 78 + if self.keys.len() > MAX_KEYS { 79 + Ok(Some(self.split())) 80 + } else { 81 + Ok(None) 82 + } 83 + } else { 84 + Ok(None) 85 + } 86 + } 87 + } 88 + 89 + fn split(&mut self) -> (K, V, Self) { 90 + let mid = self.keys.len() / 2; 91 + 92 + let median_key = self.keys[mid].clone(); 93 + let median_value = self.values[mid].clone(); 94 + 95 + let mut new_node = Self::new(self.is_leaf); 96 + 97 + new_node.keys = self.keys.split_off(mid + 1); 98 + new_node.values = self.values.split_off(mid + 1); 99 + 100 + self.keys.pop(); 101 + self.values.pop(); 102 + 103 + if !self.is_leaf { 104 + new_node.children = self.children.split_off(mid + 1); 105 + } 106 + 107 + (median_key, median_value, new_node) 108 + } 109 + } 110 + 111 + #[derive(Debug, Clone, Serialize, Deserialize)] 112 + pub struct BTree<K: Ord + Clone, V: Clone> { 113 + root: Option<BTreeNode<K, V>>, 114 + } 115 + 116 + impl<K: Ord + Clone, V: Clone> BTree<K, V> { 117 + pub fn new() -> Self { 118 + Self { root: None } 119 + } 120 + 121 + pub fn search(&self, key: &K) -> Option<&V> { 122 + self.root.as_ref()?.search(key) 123 + } 124 + 125 + pub fn insert(&mut self, key: K, value: V) -> Result<()> { 126 + if let Some(root) = &mut self.root { 127 + if let Some((median_key, median_value, new_child)) = root.insert(key, value)? { 128 + let mut new_root = BTreeNode::new(false); 129 + new_root.keys.push(median_key); 130 + new_root.values.push(median_value); 131 + new_root.children.push(std::mem::replace(root, BTreeNode::new(true))); 132 + new_root.children.push(new_child); 133 + self.root = Some(new_root); 134 + } 135 + } else { 136 + let mut root = BTreeNode::new(true); 137 + root.keys.push(key); 138 + root.values.push(value); 139 + self.root = Some(root); 140 + } 141 + Ok(()) 142 + } 143 + 144 + pub fn remove(&mut self, _key: &K) -> Result<Option<V>> { 145 + todo!("B-tree deletion is complex, implement if needed") 146 + } 147 + }
+138
src/storage/memory_store.rs
··· 1 + use async_trait::async_trait; 2 + use bytes::Bytes; 3 + use dashmap::DashMap; 4 + use std::sync::Arc; 5 + use crate::{ 6 + NodeId, RelationshipId, Node, Relationship, Result, 7 + storage::StorageEngine, 8 + }; 9 + 10 + pub struct MemoryStore { 11 + data: Arc<DashMap<Vec<u8>, Vec<u8>>>, 12 + } 13 + 14 + impl MemoryStore { 15 + pub fn new() -> Self { 16 + Self { 17 + data: Arc::new(DashMap::new()), 18 + } 19 + } 20 + } 21 + 22 + #[async_trait] 23 + impl StorageEngine for MemoryStore { 24 + async fn put_node(&self, node: &Node) -> Result<()> { 25 + let key = format!("node:{}", node.id.0).into_bytes(); 26 + let value = bincode::serialize(node)?; 27 + self.data.insert(key, value); 28 + Ok(()) 29 + } 30 + 31 + async fn get_node(&self, id: NodeId) -> Result<Option<Node>> { 32 + let key = format!("node:{}", id.0).into_bytes(); 33 + match self.data.get(&key) { 34 + Some(value) => { 35 + let node = bincode::deserialize(&value)?; 36 + Ok(Some(node)) 37 + } 38 + None => Ok(None), 39 + } 40 + } 41 + 42 + async fn delete_node(&self, id: NodeId) -> Result<()> { 43 + let key = format!("node:{}", id.0).into_bytes(); 44 + self.data.remove(&key); 45 + Ok(()) 46 + } 47 + 48 + async fn put_relationship(&self, rel: &Relationship) -> Result<()> { 49 + let rel_key = format!("rel:{}", rel.id.0).into_bytes(); 50 + let rel_value = bincode::serialize(rel)?; 51 + self.data.insert(rel_key, rel_value); 52 + 53 + let start_key = format!("node_rels:{}", rel.start_node.0).into_bytes(); 54 + let mut start_rels = self.get_node_relationships(rel.start_node).await?; 55 + if !start_rels.contains(&rel.id) { 56 + start_rels.push(rel.id); 57 + } 58 + self.data.insert(start_key, bincode::serialize(&start_rels)?); 59 + 60 + if rel.start_node != rel.end_node { 61 + let end_key = format!("node_rels:{}", rel.end_node.0).into_bytes(); 62 + let mut end_rels = self.get_node_relationships(rel.end_node).await?; 63 + if !end_rels.contains(&rel.id) { 64 + end_rels.push(rel.id); 65 + } 66 + self.data.insert(end_key, bincode::serialize(&end_rels)?); 67 + } 68 + 69 + Ok(()) 70 + } 71 + 72 + async fn get_relationship(&self, id: RelationshipId) -> Result<Option<Relationship>> { 73 + let key = format!("rel:{}", id.0).into_bytes(); 74 + match self.data.get(&key) { 75 + Some(value) => { 76 + let rel = bincode::deserialize(&value)?; 77 + Ok(Some(rel)) 78 + } 79 + None => Ok(None), 80 + } 81 + } 82 + 83 + async fn delete_relationship(&self, id: RelationshipId) -> Result<()> { 84 + if let Some(rel) = self.get_relationship(id).await? { 85 + let rel_key = format!("rel:{}", id.0).into_bytes(); 86 + self.data.remove(&rel_key); 87 + 88 + let start_key = format!("node_rels:{}", rel.start_node.0).into_bytes(); 89 + let mut start_rels = self.get_node_relationships(rel.start_node).await?; 90 + start_rels.retain(|&r| r != id); 91 + self.data.insert(start_key, bincode::serialize(&start_rels)?); 92 + 93 + if rel.start_node != rel.end_node { 94 + let end_key = format!("node_rels:{}", rel.end_node.0).into_bytes(); 95 + let mut end_rels = self.get_node_relationships(rel.end_node).await?; 96 + end_rels.retain(|&r| r != id); 97 + self.data.insert(end_key, bincode::serialize(&end_rels)?); 98 + } 99 + } 100 + Ok(()) 101 + } 102 + 103 + async fn get_node_relationships(&self, node_id: NodeId) -> Result<Vec<RelationshipId>> { 104 + let key = format!("node_rels:{}", node_id.0).into_bytes(); 105 + match self.data.get(&key) { 106 + Some(value) => { 107 + let rels = bincode::deserialize(&value)?; 108 + Ok(rels) 109 + } 110 + None => Ok(Vec::new()), 111 + } 112 + } 113 + 114 + async fn put_raw(&self, key: &[u8], value: &[u8]) -> Result<()> { 115 + self.data.insert(key.to_vec(), value.to_vec()); 116 + Ok(()) 117 + } 118 + 119 + async fn get_raw(&self, key: &[u8]) -> Result<Option<Bytes>> { 120 + match self.data.get(key) { 121 + Some(value) => Ok(Some(Bytes::from(value.clone()))), 122 + None => Ok(None), 123 + } 124 + } 125 + 126 + async fn delete_raw(&self, key: &[u8]) -> Result<()> { 127 + self.data.remove(key); 128 + Ok(()) 129 + } 130 + 131 + async fn flush(&self) -> Result<()> { 132 + Ok(()) 133 + } 134 + 135 + async fn compact(&self) -> Result<()> { 136 + Ok(()) 137 + } 138 + }
+64
src/storage/mod.rs
··· 1 + use async_trait::async_trait; 2 + use bytes::Bytes; 3 + use crate::{NodeId, RelationshipId, Node, Relationship, Result}; 4 + 5 + pub mod memory_store; 6 + pub mod page; 7 + pub mod btree; 8 + pub mod wal; 9 + 10 + pub use memory_store::MemoryStore; 11 + 12 + #[async_trait] 13 + pub trait StorageEngine: Send + Sync { 14 + async fn put_node(&self, node: &Node) -> Result<()>; 15 + async fn get_node(&self, id: NodeId) -> Result<Option<Node>>; 16 + async fn delete_node(&self, id: NodeId) -> Result<()>; 17 + 18 + async fn put_relationship(&self, rel: &Relationship) -> Result<()>; 19 + async fn get_relationship(&self, id: RelationshipId) -> Result<Option<Relationship>>; 20 + async fn delete_relationship(&self, id: RelationshipId) -> Result<()>; 21 + 22 + async fn get_node_relationships(&self, node_id: NodeId) -> Result<Vec<RelationshipId>>; 23 + 24 + async fn put_raw(&self, key: &[u8], value: &[u8]) -> Result<()>; 25 + async fn get_raw(&self, key: &[u8]) -> Result<Option<Bytes>>; 26 + async fn delete_raw(&self, key: &[u8]) -> Result<()>; 27 + 28 + async fn flush(&self) -> Result<()>; 29 + async fn compact(&self) -> Result<()>; 30 + } 31 + 32 + #[derive(Debug, Clone, Copy)] 33 + pub enum KeyPrefix { 34 + Node = 0, 35 + Relationship = 1, 36 + NodeRelationships = 2, 37 + Index = 3, 38 + Schema = 4, 39 + Transaction = 5, 40 + } 41 + 42 + impl KeyPrefix { 43 + pub fn as_byte(&self) -> u8 { 44 + *self as u8 45 + } 46 + } 47 + 48 + pub fn encode_node_key(id: NodeId) -> Vec<u8> { 49 + let mut key = vec![KeyPrefix::Node.as_byte()]; 50 + key.extend_from_slice(&id.0.to_be_bytes()); 51 + key 52 + } 53 + 54 + pub fn encode_relationship_key(id: RelationshipId) -> Vec<u8> { 55 + let mut key = vec![KeyPrefix::Relationship.as_byte()]; 56 + key.extend_from_slice(&id.0.to_be_bytes()); 57 + key 58 + } 59 + 60 + pub fn encode_node_relationships_key(node_id: NodeId) -> Vec<u8> { 61 + let mut key = vec![KeyPrefix::NodeRelationships.as_byte()]; 62 + key.extend_from_slice(&node_id.0.to_be_bytes()); 63 + key 64 + }
+121
src/storage/page.rs
··· 1 + use memmap2::MmapMut; 2 + use std::fs::{File, OpenOptions}; 3 + use std::path::Path; 4 + use std::sync::Arc; 5 + use parking_lot::RwLock; 6 + use crate::{Result, GigabrainError}; 7 + 8 + pub const PAGE_SIZE: usize = 4096; 9 + 10 + #[derive(Debug)] 11 + pub struct PageId(pub u64); 12 + 13 + pub struct Page { 14 + data: [u8; PAGE_SIZE], 15 + dirty: bool, 16 + id: PageId, 17 + } 18 + 19 + impl Page { 20 + pub fn new(id: PageId) -> Self { 21 + Self { 22 + data: [0; PAGE_SIZE], 23 + dirty: false, 24 + id, 25 + } 26 + } 27 + 28 + pub fn read(&self, offset: usize, buf: &mut [u8]) -> Result<usize> { 29 + if offset >= PAGE_SIZE { 30 + return Ok(0); 31 + } 32 + 33 + let read_len = std::cmp::min(buf.len(), PAGE_SIZE - offset); 34 + buf[..read_len].copy_from_slice(&self.data[offset..offset + read_len]); 35 + Ok(read_len) 36 + } 37 + 38 + pub fn write(&mut self, offset: usize, data: &[u8]) -> Result<usize> { 39 + if offset >= PAGE_SIZE { 40 + return Ok(0); 41 + } 42 + 43 + let write_len = std::cmp::min(data.len(), PAGE_SIZE - offset); 44 + self.data[offset..offset + write_len].copy_from_slice(&data[..write_len]); 45 + self.dirty = true; 46 + Ok(write_len) 47 + } 48 + 49 + pub fn is_dirty(&self) -> bool { 50 + self.dirty 51 + } 52 + 53 + pub fn mark_clean(&mut self) { 54 + self.dirty = false; 55 + } 56 + } 57 + 58 + pub struct PageFile { 59 + file: File, 60 + mmap: Arc<RwLock<Option<MmapMut>>>, 61 + size: Arc<RwLock<u64>>, 62 + } 63 + 64 + impl PageFile { 65 + pub fn create<P: AsRef<Path>>(path: P) -> Result<Self> { 66 + let file = OpenOptions::new() 67 + .read(true) 68 + .write(true) 69 + .create(true) 70 + .open(&path) 71 + .map_err(|e| GigabrainError::Io(e))?; 72 + 73 + Ok(Self { 74 + file, 75 + mmap: Arc::new(RwLock::new(None)), 76 + size: Arc::new(RwLock::new(0)), 77 + }) 78 + } 79 + 80 + pub fn read_page(&self, page_id: PageId) -> Result<Page> { 81 + let offset = page_id.0 * PAGE_SIZE as u64; 82 + let mut page = Page::new(page_id); 83 + 84 + if let Some(ref mmap) = *self.mmap.read() { 85 + if offset + PAGE_SIZE as u64 <= mmap.len() as u64 { 86 + page.data.copy_from_slice(&mmap[offset as usize..(offset as usize + PAGE_SIZE)]); 87 + } 88 + } 89 + 90 + Ok(page) 91 + } 92 + 93 + pub fn write_page(&self, page: &Page) -> Result<()> { 94 + let offset = page.id.0 * PAGE_SIZE as u64; 95 + let required_size = offset + PAGE_SIZE as u64; 96 + 97 + if required_size > *self.size.read() { 98 + self.resize(required_size)?; 99 + } 100 + 101 + if let Some(ref mut mmap) = *self.mmap.write() { 102 + mmap[offset as usize..(offset as usize + PAGE_SIZE)] 103 + .copy_from_slice(&page.data); 104 + mmap.flush()?; 105 + } 106 + 107 + Ok(()) 108 + } 109 + 110 + fn resize(&self, new_size: u64) -> Result<()> { 111 + self.file.set_len(new_size)?; 112 + 113 + let mut mmap_guard = self.mmap.write(); 114 + *mmap_guard = Some(unsafe { MmapMut::map_mut(&self.file)? }); 115 + 116 + let mut size_guard = self.size.write(); 117 + *size_guard = new_size; 118 + 119 + Ok(()) 120 + } 121 + }
+98
src/storage/wal.rs
··· 1 + use tokio::fs::{File, OpenOptions}; 2 + use tokio::io::{AsyncWriteExt, AsyncReadExt, BufReader, AsyncBufReadExt}; 3 + use std::path::{Path, PathBuf}; 4 + use serde::{Serialize, Deserialize}; 5 + use crate::{Result, GigabrainError}; 6 + 7 + #[derive(Debug, Clone, Serialize, Deserialize)] 8 + pub enum WalEntry { 9 + CreateNode { id: u64 }, 10 + UpdateNode { id: u64, data: Vec<u8> }, 11 + DeleteNode { id: u64 }, 12 + CreateRelationship { id: u64, start: u64, end: u64, rel_type: u32 }, 13 + UpdateRelationship { id: u64, data: Vec<u8> }, 14 + DeleteRelationship { id: u64 }, 15 + Checkpoint { lsn: u64 }, 16 + } 17 + 18 + pub struct WriteAheadLog { 19 + path: PathBuf, 20 + file: File, 21 + current_lsn: u64, 22 + } 23 + 24 + impl WriteAheadLog { 25 + pub async fn create<P: AsRef<Path>>(path: P) -> Result<Self> { 26 + let path = path.as_ref().to_path_buf(); 27 + let file = OpenOptions::new() 28 + .create(true) 29 + .append(true) 30 + .open(&path) 31 + .await?; 32 + 33 + Ok(Self { 34 + path, 35 + file, 36 + current_lsn: 0, 37 + }) 38 + } 39 + 40 + pub async fn append(&mut self, entry: WalEntry) -> Result<u64> { 41 + let lsn = self.current_lsn; 42 + self.current_lsn += 1; 43 + 44 + let data = bincode::serialize(&entry)?; 45 + let len = data.len() as u32; 46 + 47 + self.file.write_all(&len.to_le_bytes()).await?; 48 + self.file.write_all(&data).await?; 49 + self.file.write_all(&lsn.to_le_bytes()).await?; 50 + self.file.flush().await?; 51 + 52 + Ok(lsn) 53 + } 54 + 55 + pub async fn replay<F>(&self, mut callback: F) -> Result<u64> 56 + where 57 + F: FnMut(u64, WalEntry) -> Result<()>, 58 + { 59 + let file = File::open(&self.path).await?; 60 + let mut reader = BufReader::new(file); 61 + let mut last_lsn = 0; 62 + let mut buffer = Vec::new(); 63 + 64 + loop { 65 + let mut len_bytes = [0u8; 4]; 66 + match reader.read_exact(&mut len_bytes).await { 67 + Ok(_) => {}, 68 + Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => break, 69 + Err(e) => return Err(e.into()), 70 + } 71 + 72 + let len = u32::from_le_bytes(len_bytes) as usize; 73 + buffer.resize(len, 0); 74 + reader.read_exact(&mut buffer).await?; 75 + 76 + let mut lsn_bytes = [0u8; 8]; 77 + reader.read_exact(&mut lsn_bytes).await?; 78 + let lsn = u64::from_le_bytes(lsn_bytes); 79 + 80 + let entry: WalEntry = bincode::deserialize(&buffer)?; 81 + callback(lsn, entry)?; 82 + last_lsn = lsn; 83 + } 84 + 85 + Ok(last_lsn) 86 + } 87 + 88 + pub async fn checkpoint(&mut self) -> Result<()> { 89 + self.append(WalEntry::Checkpoint { lsn: self.current_lsn }).await?; 90 + Ok(()) 91 + } 92 + 93 + pub async fn truncate(&mut self) -> Result<()> { 94 + self.file.set_len(0).await?; 95 + self.current_lsn = 0; 96 + Ok(()) 97 + } 98 + }
+92
src/transaction/mod.rs
··· 1 + use std::sync::atomic::{AtomicU64, Ordering}; 2 + use std::sync::Arc; 3 + use parking_lot::RwLock; 4 + use std::collections::HashMap; 5 + use crate::{Result, GigabrainError}; 6 + 7 + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 8 + pub struct TransactionId(pub u64); 9 + 10 + #[derive(Debug, Clone, Copy, PartialEq, Eq)] 11 + pub enum IsolationLevel { 12 + ReadUncommitted, 13 + ReadCommitted, 14 + RepeatableRead, 15 + Serializable, 16 + } 17 + 18 + pub struct TransactionManager { 19 + next_tx_id: Arc<AtomicU64>, 20 + active_transactions: Arc<RwLock<HashMap<TransactionId, Transaction>>>, 21 + } 22 + 23 + impl TransactionManager { 24 + pub fn new() -> Self { 25 + Self { 26 + next_tx_id: Arc::new(AtomicU64::new(0)), 27 + active_transactions: Arc::new(RwLock::new(HashMap::new())), 28 + } 29 + } 30 + 31 + pub fn begin(&self, isolation_level: IsolationLevel) -> Result<TransactionId> { 32 + let tx_id = TransactionId(self.next_tx_id.fetch_add(1, Ordering::SeqCst)); 33 + let transaction = Transaction::new(tx_id, isolation_level); 34 + 35 + self.active_transactions.write().insert(tx_id, transaction); 36 + Ok(tx_id) 37 + } 38 + 39 + pub fn commit(&self, tx_id: TransactionId) -> Result<()> { 40 + let mut transactions = self.active_transactions.write(); 41 + let transaction = transactions 42 + .remove(&tx_id) 43 + .ok_or_else(|| GigabrainError::Transaction("Transaction not found".to_string()))?; 44 + 45 + transaction.commit()?; 46 + Ok(()) 47 + } 48 + 49 + pub fn rollback(&self, tx_id: TransactionId) -> Result<()> { 50 + let mut transactions = self.active_transactions.write(); 51 + transactions 52 + .remove(&tx_id) 53 + .ok_or_else(|| GigabrainError::Transaction("Transaction not found".to_string()))?; 54 + 55 + Ok(()) 56 + } 57 + } 58 + 59 + pub struct Transaction { 60 + id: TransactionId, 61 + isolation_level: IsolationLevel, 62 + start_timestamp: u64, 63 + state: TransactionState, 64 + } 65 + 66 + #[derive(Debug, Clone, Copy, PartialEq, Eq)] 67 + enum TransactionState { 68 + Active, 69 + Committed, 70 + Aborted, 71 + } 72 + 73 + impl Transaction { 74 + fn new(id: TransactionId, isolation_level: IsolationLevel) -> Self { 75 + Self { 76 + id, 77 + isolation_level, 78 + start_timestamp: std::time::SystemTime::now() 79 + .duration_since(std::time::UNIX_EPOCH) 80 + .unwrap() 81 + .as_millis() as u64, 82 + state: TransactionState::Active, 83 + } 84 + } 85 + 86 + fn commit(&self) -> Result<()> { 87 + if self.state != TransactionState::Active { 88 + return Err(GigabrainError::Transaction("Transaction is not active".to_string())); 89 + } 90 + Ok(()) 91 + } 92 + }