Skip to content

Commit 97a2ee6

Browse files
authored
Merge pull request #19 from tantaraio/GH-18/core-engine-api
feat: core engine api
2 parents 7430716 + 59f68ce commit 97a2ee6

File tree

5 files changed

+177
-38
lines changed

5 files changed

+177
-38
lines changed

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ crate-type = ["cdylib", "rlib"]
1111
default = ["console_error_panic_hook"]
1212

1313
[dependencies]
14-
wasm-bindgen = "0.2.63"
14+
wasm-bindgen = "0.2.83"
15+
getrandom = { version = "0.2", features = ["js"] }
1516

1617
# The `console_error_panic_hook` crate provides better debugging of panics by
1718
# logging them with `console.error`. This is great for development, but requires
@@ -27,6 +28,7 @@ wee_alloc = { version = "0.4.5", optional = true }
2728
tantivy = "0.19.0"
2829
serde = { version = "1.0.150", features = ["derive"] }
2930
serde_json = "1.0.89"
31+
serde-wasm-bindgen = "0.4"
3032

3133
[dev-dependencies]
3234
wasm-bindgen-test = "0.3.13"

src/engine/mod.rs

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use schema::{create_schema, SchemaConfig};
2+
use tantivy::collector::TopDocs;
3+
use tantivy::query::QueryParser;
4+
use tantivy::schema::*;
5+
use tantivy::DocAddress;
6+
use tantivy::IndexReader;
7+
use tantivy::IndexWriter;
8+
use tantivy::ReloadPolicy;
9+
use tantivy::Result;
10+
11+
mod schema;
12+
13+
pub struct Registry {
14+
index: tantivy::Index,
15+
schema: Schema,
16+
fields: Vec<Field>,
17+
writer: IndexWriter,
18+
reader: IndexReader,
19+
}
20+
21+
pub struct Input {
22+
schema: SchemaConfig,
23+
}
24+
25+
pub fn create(input: Input) -> Result<Registry> {
26+
let mut schema_builder = Schema::builder();
27+
28+
create_schema(&input.schema, &mut schema_builder);
29+
30+
let fields = vec![];
31+
let schema = schema_builder.build();
32+
let index = tantivy::Index::create_in_ram(schema.clone());
33+
let writer = index.writer(50_000_000)?;
34+
let reader = index
35+
.reader_builder()
36+
.reload_policy(ReloadPolicy::OnCommit)
37+
.try_into()?;
38+
39+
Ok(Registry {
40+
index,
41+
schema,
42+
fields,
43+
writer,
44+
reader,
45+
})
46+
}
47+
48+
pub fn add(index: Registry, docs: Vec<Document>) -> Result<Registry> {
49+
docs.iter().try_for_each(|doc| -> Result<()> {
50+
index.writer.add_document(doc.clone())?;
51+
Ok(())
52+
})?;
53+
54+
Ok(index)
55+
}
56+
57+
pub fn commit(mut index: Registry) -> Result<Registry> {
58+
index.writer.commit()?;
59+
index.reader.reload()?;
60+
61+
Ok(index)
62+
}
63+
64+
pub fn remove(index: Registry, field: Field, text: &str) -> Result<Registry> {
65+
let term = Term::from_field_text(field, text);
66+
67+
index.writer.delete_term(term);
68+
69+
Ok(index)
70+
}
71+
72+
pub fn search(
73+
index: Registry,
74+
query: &str,
75+
limit: Option<usize>,
76+
) -> tantivy::Result<Vec<(f32, DocAddress)>> {
77+
let limit = limit.unwrap_or(10);
78+
let parser = QueryParser::for_index(&index.index, index.fields);
79+
let query = parser.parse_query(query)?;
80+
let searcher = index.reader.searcher();
81+
let result = searcher.search(&query, &TopDocs::with_limit(limit))?;
82+
83+
Ok(result)
84+
}

src/engine/schema.rs

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use tantivy::schema::{NumericOptions, SchemaBuilder, TextOptions};
2+
3+
struct FieldOptions {
4+
stored: bool,
5+
indexed: bool,
6+
}
7+
8+
enum FieldType {
9+
Text,
10+
U64,
11+
}
12+
13+
pub struct Field {
14+
name: String,
15+
field_type: FieldType,
16+
options: FieldOptions,
17+
}
18+
19+
pub type SchemaConfig = Vec<Field>;
20+
21+
pub fn create_schema(config: &SchemaConfig, schema_builder: &mut SchemaBuilder) {
22+
config.iter().for_each(|field| {
23+
match field.field_type {
24+
FieldType::Text => {
25+
let options = get_text_options(&field.options);
26+
schema_builder.add_text_field(&field.name, options);
27+
}
28+
FieldType::U64 => {
29+
let options = get_u64_options(&field.options);
30+
schema_builder.add_u64_field(&field.name, options);
31+
}
32+
};
33+
})
34+
}
35+
36+
fn get_text_options(config: &FieldOptions) -> TextOptions {
37+
let mut options = TextOptions::default();
38+
39+
if config.stored {
40+
options = options.set_stored();
41+
}
42+
43+
options
44+
}
45+
46+
fn get_u64_options(config: &FieldOptions) -> NumericOptions {
47+
let mut options = NumericOptions::default();
48+
49+
if config.stored {
50+
options = options.set_stored();
51+
}
52+
if config.indexed {
53+
options = options.set_indexed();
54+
}
55+
56+
options
57+
}

src/lib.rs

+2-37
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,9 @@
1+
mod engine;
2+
mod log;
13
mod utils;
24

3-
use wasm_bindgen::prelude::*;
4-
55
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
66
// allocator.
77
#[cfg(feature = "wee_alloc")]
88
#[global_allocator]
99
static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
10-
11-
#[wasm_bindgen]
12-
extern "C" {
13-
fn alert(s: &str);
14-
15-
// Use `js_namespace` here to bind `console.log(..)` instead of just
16-
// `log(..)`
17-
#[wasm_bindgen(js_namespace = console)]
18-
fn log(s: &str);
19-
20-
// The `console.log` is quite polymorphic, so we can bind it with multiple
21-
// signatures. Note that we need to use `js_name` to ensure we always call
22-
// `log` in JS.
23-
#[wasm_bindgen(js_namespace = console, js_name = log)]
24-
fn log_u32(a: u32);
25-
26-
// Multiple arguments too!
27-
#[wasm_bindgen(js_namespace = console, js_name = log)]
28-
fn log_many(a: &str, b: &str);
29-
}
30-
31-
// Next let's define a macro that's like `println!`, only it works for
32-
// `console.log`. Note that `println!` doesn't actually work on the wasm target
33-
// because the standard library currently just eats all output. To get
34-
// `println!`-like behavior in your app you'll likely want a macro like this.
35-
macro_rules! console_log {
36-
// Note that this is using the `log` function imported above during
37-
// `bare_bones`
38-
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
39-
}
40-
41-
#[wasm_bindgen]
42-
pub fn greet() {
43-
console_log!("Hello from WASM🦀🕸!")
44-
}

src/log.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use wasm_bindgen::prelude::*;
2+
3+
#[wasm_bindgen]
4+
extern "C" {
5+
fn alert(s: &str);
6+
7+
// Use `js_namespace` here to bind `console.log(..)` instead of just
8+
// `log(..)`
9+
#[wasm_bindgen(js_namespace = console)]
10+
fn log(s: &str);
11+
12+
// The `console.log` is quite polymorphic, so we can bind it with multiple
13+
// signatures. Note that we need to use `js_name` to ensure we always call
14+
// `log` in JS.
15+
#[wasm_bindgen(js_namespace = console, js_name = log)]
16+
fn log_u32(a: u32);
17+
18+
// Multiple arguments too!
19+
#[wasm_bindgen(js_namespace = console, js_name = log)]
20+
fn log_many(a: &str, b: &str);
21+
}
22+
23+
// Next let's define a macro that's like `println!`, only it works for
24+
// `console.log`. Note that `println!` doesn't actually work on the wasm target
25+
// because the standard library currently just eats all output. To get
26+
// `println!`-like behavior in your app you'll likely want a macro like this.
27+
macro_rules! console_log {
28+
// Note that this is using the `log` function imported above during
29+
// `bare_bones`
30+
($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
31+
}

0 commit comments

Comments
 (0)