Skip to content

Commit 711c7f7

Browse files
committed
Make kmod potentially work
1 parent 2f9b2b5 commit 711c7f7

41 files changed

Lines changed: 4075 additions & 176 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 2 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,70 @@ repository = "https://github.com/bbqsrc/box"
1111
crate-type = ["rlib"]
1212

1313
[dependencies]
14+
# Core dependencies (no_std compatible)
1415
box-fst.workspace = true
1516
byteorder.workspace = true
16-
mmap-io.workspace = true
17-
tokio = { workspace = true, features = ["fs", "io-util", "sync"] }
18-
tokio-util = { workspace = true, features = ["compat"] }
19-
async-walkdir.workspace = true
20-
futures.workspace = true
21-
blake3 = { workspace = true, features = ["traits-preview", "rayon", "mmap"] }
22-
hex.workspace = true
23-
pathdiff.workspace = true
24-
unic-normal.workspace = true
25-
unic-ucd.workspace = true
26-
relative-path.workspace = true
27-
fastvint = { workspace = true, features = ["async-tokio"] }
28-
tracing.workspace = true
29-
serde_json.workspace = true
30-
lru.workspace = true
31-
thiserror.workspace = true
32-
digest.workspace = true
33-
sysinfo.workspace = true
34-
tempfile.workspace = true
35-
string-interner.workspace = true
17+
fastvint.workspace = true
18+
hashbrown = "0.15"
19+
20+
# Std-only dependencies
21+
mmap-io = { workspace = true, optional = true }
22+
tokio = { workspace = true, features = ["fs", "io-util", "sync"], optional = true }
23+
tokio-util = { workspace = true, features = ["compat"], optional = true }
24+
async-walkdir = { workspace = true, optional = true }
25+
futures = { workspace = true, optional = true }
26+
blake3 = { workspace = true, features = ["traits-preview", "rayon", "mmap"], optional = true }
27+
hex = { workspace = true, optional = true }
28+
pathdiff = { workspace = true, optional = true }
29+
unic-normal = { workspace = true, optional = true }
30+
unic-ucd = { workspace = true, optional = true }
31+
relative-path = { workspace = true, optional = true }
32+
tracing = { workspace = true, optional = true }
33+
serde_json = { workspace = true, optional = true }
34+
lru = { workspace = true, optional = true }
35+
thiserror = { workspace = true, optional = true }
36+
digest = { workspace = true, optional = true }
37+
sysinfo = { workspace = true, optional = true }
38+
tempfile = { workspace = true, optional = true }
39+
string-interner = { workspace = true, optional = true }
3640
xattr = { workspace = true, optional = true }
3741
zstd = { workspace = true, optional = true }
3842
zstd-safe = { workspace = true, optional = true }
3943
xz2 = { workspace = true, optional = true }
4044

4145
[features]
42-
default = ["xz", "zstd", "writer", "reader", "xattr"]
43-
reader = []
46+
default = ["std", "xz", "zstd", "writer", "reader", "xattr"]
47+
48+
# no_std support
49+
std = [
50+
"alloc",
51+
"box-fst/std",
52+
"dep:mmap-io",
53+
"dep:tokio",
54+
"dep:tokio-util",
55+
"dep:async-walkdir",
56+
"dep:futures",
57+
"dep:blake3",
58+
"dep:hex",
59+
"dep:pathdiff",
60+
"dep:unic-normal",
61+
"dep:unic-ucd",
62+
"dep:relative-path",
63+
"dep:tracing",
64+
"dep:serde_json",
65+
"dep:lru",
66+
"dep:thiserror",
67+
"dep:digest",
68+
"dep:sysinfo",
69+
"dep:tempfile",
70+
"dep:string-interner",
71+
]
72+
alloc = ["box-fst/alloc"]
73+
74+
# Minimal kernel build (core parsing only)
75+
kernel = ["alloc"]
76+
77+
reader = ["std"]
4478
writer = ["reader"]
4579

4680
xz = ["dep:xz2"]
@@ -50,6 +84,7 @@ xattr = ["dep:xattr"]
5084
[workspace]
5185
resolver = "3"
5286
members = ["cli", "crates/*"]
87+
exclude = ["kmod/rust"]
5388

5489
[workspace.dependencies]
5590
# Shared dependencies
@@ -120,5 +155,5 @@ block2 = "0.6"
120155

121156
# Workspace crates
122157
box-format = { version = "0.4.0", path = "." }
123-
box-fst = { version = "0.1.0", path = "crates/fst" }
158+
box-fst = { version = "0.1.0", path = "crates/fst", default-features = false }
124159
mimalloc = { version = "0.1", features = ["v3"] }

crates/fst/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ edition = "2024"
55
license = "Apache-2.0 OR MIT"
66
description = "A radix tree that serializes as an FST for fast path lookups"
77

8+
[features]
9+
default = ["std"]
10+
std = ["alloc"]
11+
alloc = []
12+
813
[dependencies]
9-
thiserror.workspace = true
1014
fastvint.workspace = true
15+
hashbrown = "0.15"
1116

1217
[dev-dependencies]
1318
criterion = "0.5"

crates/fst/src/builder.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
#[cfg(feature = "alloc")]
2+
use alloc::{collections::VecDeque, vec::Vec};
3+
4+
use core::cmp::Ordering;
5+
use core::mem::take;
6+
7+
use hashbrown::{HashMap, HashSet};
8+
19
use crate::error::BuildError;
210
use crate::node::{
311
EdgeData, HEADER_SIZE, Header, INDEX_ENTRY_SIZE, INDEXED_THRESHOLD, NodeData, NodeIndex,
@@ -44,9 +52,9 @@ impl FstBuilder {
4452
// Validate ordering
4553
if let Some(ref last) = self.last_key {
4654
match key.cmp(last.as_slice()) {
47-
std::cmp::Ordering::Less => return Err(BuildError::OutOfOrder),
48-
std::cmp::Ordering::Equal => return Err(BuildError::DuplicateKey),
49-
std::cmp::Ordering::Greater => {}
55+
Ordering::Less => return Err(BuildError::OutOfOrder),
56+
Ordering::Equal => return Err(BuildError::DuplicateKey),
57+
Ordering::Greater => {}
5058
}
5159
}
5260

@@ -182,8 +190,8 @@ impl FstBuilder {
182190
Self::insert_into_node(&mut edge.target, &key[common_len..], value);
183191
} else {
184192
// Need to split the edge
185-
let old_label = std::mem::take(&mut edge.label);
186-
let old_target = std::mem::take(&mut edge.target);
193+
let old_label = take(&mut edge.label);
194+
let old_target = take(&mut edge.target);
187195

188196
// Create new intermediate node
189197
let mut intermediate = BuilderNode::default();
@@ -240,12 +248,12 @@ impl FstBuilder {
240248
/// Collect nodes breadth-first for better cache locality.
241249
/// Returns the root node ID (always 0 in BFS order).
242250
fn collect_nodes(&self, root: &BuilderNode, nodes: &mut Vec<NodeData>) -> u32 {
243-
use std::collections::VecDeque;
251+
use VecDeque;
244252

245253
// Phase 1: Assign node IDs in BFS order
246254
// Map from node pointer to assigned ID
247-
let mut node_ids: std::collections::HashMap<*const BuilderNode, u32> =
248-
std::collections::HashMap::new();
255+
let mut node_ids: HashMap<*const BuilderNode, u32> =
256+
HashMap::new();
249257
let mut queue: VecDeque<&BuilderNode> = VecDeque::new();
250258

251259
queue.push_back(root);
@@ -267,8 +275,8 @@ impl FstBuilder {
267275

268276
// Phase 2: Build NodeData in BFS order
269277
queue.push_back(root);
270-
let mut visited: std::collections::HashSet<*const BuilderNode> =
271-
std::collections::HashSet::new();
278+
let mut visited: HashSet<*const BuilderNode> =
279+
HashSet::new();
272280

273281
while let Some(node) = queue.pop_front() {
274282
let ptr = node as *const BuilderNode;

crates/fst/src/error.rs

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,60 @@
1-
use thiserror::Error;
1+
use core::fmt;
22

3-
#[derive(Debug, Error)]
3+
#[derive(Debug)]
44
pub enum BuildError {
5-
#[error("keys must be inserted in lexicographic order")]
65
OutOfOrder,
7-
8-
#[error("duplicate key")]
96
DuplicateKey,
10-
11-
#[error("FST is empty (no keys inserted)")]
127
Empty,
8+
#[cfg(feature = "std")]
9+
Io(std::io::Error),
10+
}
11+
12+
impl fmt::Display for BuildError {
13+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
14+
match self {
15+
BuildError::OutOfOrder => write!(f, "keys must be inserted in lexicographic order"),
16+
BuildError::DuplicateKey => write!(f, "duplicate key"),
17+
BuildError::Empty => write!(f, "FST is empty (no keys inserted)"),
18+
#[cfg(feature = "std")]
19+
BuildError::Io(e) => write!(f, "I/O error: {}", e),
20+
}
21+
}
22+
}
23+
24+
impl core::error::Error for BuildError {
25+
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
26+
match self {
27+
#[cfg(feature = "std")]
28+
BuildError::Io(e) => Some(e),
29+
_ => None,
30+
}
31+
}
32+
}
1333

14-
#[error("I/O error: {0}")]
15-
Io(#[from] std::io::Error),
34+
#[cfg(feature = "std")]
35+
impl From<std::io::Error> for BuildError {
36+
fn from(e: std::io::Error) -> Self {
37+
BuildError::Io(e)
38+
}
1639
}
1740

18-
#[derive(Debug, Error)]
41+
#[derive(Debug)]
1942
pub enum FstError {
20-
#[error("invalid magic bytes")]
2143
InvalidMagic,
22-
23-
#[error("unsupported version: {0}")]
2444
UnsupportedVersion(u8),
25-
26-
#[error("data too short")]
2745
TooShort,
28-
29-
#[error("corrupted data")]
3046
Corrupted,
3147
}
48+
49+
impl fmt::Display for FstError {
50+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51+
match self {
52+
FstError::InvalidMagic => write!(f, "invalid magic bytes"),
53+
FstError::UnsupportedVersion(v) => write!(f, "unsupported version: {}", v),
54+
FstError::TooShort => write!(f, "data too short"),
55+
FstError::Corrupted => write!(f, "corrupted data"),
56+
}
57+
}
58+
}
59+
60+
impl core::error::Error for FstError {}

crates/fst/src/fst.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#[cfg(feature = "alloc")]
2+
use alloc::vec::Vec;
3+
14
use crate::error::FstError;
25
use crate::node::{HEADER_SIZE, Header, INDEX_ENTRY_SIZE, NodeIndex, NodeRef, read_header};
36

@@ -6,11 +9,11 @@ use crate::node::{HEADER_SIZE, Header, INDEX_ENTRY_SIZE, NodeIndex, NodeRef, rea
69
fn prefetch_read(ptr: *const u8) {
710
#[cfg(target_arch = "aarch64")]
811
unsafe {
9-
std::arch::asm!("prfm pldl1keep, [{ptr}]", ptr = in(reg) ptr, options(nostack, preserves_flags));
12+
core::arch::asm!("prfm pldl1keep, [{ptr}]", ptr = in(reg) ptr, options(nostack, preserves_flags));
1013
}
1114
#[cfg(all(target_arch = "x86_64", target_feature = "sse"))]
1215
unsafe {
13-
std::arch::x86_64::_mm_prefetch(ptr as *const i8, std::arch::x86_64::_MM_HINT_T0);
16+
core::arch::x86_64::_mm_prefetch(ptr as *const i8, core::arch::x86_64::_MM_HINT_T0);
1417
}
1518
}
1619

@@ -38,7 +41,7 @@ fn fast_eq(a: &[u8], b: &[u8]) -> bool {
3841
#[cfg(all(target_arch = "aarch64", target_feature = "neon"))]
3942
#[inline]
4043
fn fast_eq_simd_neon(a: &[u8], b: &[u8]) -> bool {
41-
use std::arch::aarch64::*;
44+
use core::arch::aarch64::*;
4245

4346
unsafe {
4447
let mut i = 0;
@@ -64,7 +67,7 @@ fn fast_eq_simd_neon(a: &[u8], b: &[u8]) -> bool {
6467
#[cfg(all(target_arch = "x86_64", target_feature = "sse2"))]
6568
#[inline]
6669
fn fast_eq_simd_sse2(a: &[u8], b: &[u8]) -> bool {
67-
use std::arch::x86_64::*;
70+
use core::arch::x86_64::*;
6871

6972
unsafe {
7073
let mut i = 0;

crates/fst/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1+
#![cfg_attr(not(feature = "std"), no_std)]
2+
3+
#[cfg(feature = "alloc")]
4+
extern crate alloc;
5+
6+
#[cfg(feature = "std")]
17
mod builder;
28
mod error;
39
mod fst;
410
mod node;
511

12+
#[cfg(feature = "std")]
613
pub use builder::FstBuilder;
714
pub use error::{BuildError, FstError};
815
pub use fst::{Fst, PrefixIter};

0 commit comments

Comments
 (0)