Skip to content

Commit 780eac8

Browse files
committed
Working support for current RediSearch version
1 parent 740df25 commit 780eac8

File tree

12 files changed

+370
-18
lines changed

12 files changed

+370
-18
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ Cargo.lock
1010
**/*.rs.bk
1111

1212
/.idea
13+
src/raw/bindings.rs
14+
libredisearch.a

Cargo.toml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
[package]
2-
name = "redisearch-api-rs"
2+
name = "redisearch_api"
33
version = "0.1.0"
44
authors = ["Gavrie Philipson <gavrie@redislabs.com>"]
55
edition = "2018"
66

7+
#links = "redisearch"
8+
#build = "build.rs"
9+
710
[[example]]
811
name = "hello_redisearch"
912
crate-type = ["cdylib"]
@@ -12,9 +15,10 @@ crate-type = ["cdylib"]
1215
bitflags = "1.1"
1316
libc = "0.2"
1417
time = "0.1"
15-
enum-primitive-derive = "^0.1"
16-
num-traits = "^0.2"
17-
#failure = "0.1"
18+
enum-primitive-derive = "0.1.2"
19+
num-traits = "0.2.8"
20+
21+
redismodule = { path = "../redismodule-rs" }
1822

1923
[build-dependencies]
2024
bindgen = "0.51"

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
# redisearch-api-rs
2-
Rust RediSearch API binding
32

43
## Rust API for RediSearch
54

65
TODO:
76

87
- Use it from RedisDoc to index JSON docs
8+
9+
## Building
10+
11+
On macOS:
12+
- `brew install llvm`
13+
14+
Make sure you have `libredisearch.a` built. This will be done automatically in the future.

build.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,41 @@
11
extern crate bindgen;
22
extern crate cc;
33

4+
use std::env;
5+
46
fn main() {
5-
// cc::Build::new()
6-
// .file("src/redisearch/redisearch_api.c")
7-
// //.include("src/include/") // For redismodule.h
8-
// .include("src/include/")
9-
// .compile("redisearch_api");
7+
// Generate bindings for RediSearch
108

119
let bindings = bindgen::Builder::default()
1210
.header("src/include/redisearch_api.h")
1311
//.clang_arg("-I src/include") // For redismodule.h
14-
.whitelist_var("(RS|RediSearch).*")
12+
.whitelist_var("(RS|RediSearch|REDISEARCH_|GC_POLICY).*")
13+
.whitelist_function("RediSearch.*")
14+
.blacklist_item("RedisModule.*")
15+
.raw_line("use redismodule::raw::{RedisModuleCtx, RedisModuleString};")
1516
.generate()
1617
.expect("error generating RediSearch bindings");
1718

1819
bindings
1920
.write_to_file("src/raw/bindings.rs")
2021
.expect("failed to write RediSearch bindings to file");
22+
23+
// Find and link statically to libredisearch.a
24+
25+
// TODO: Instead of relying on a pre-built library,
26+
// we should build RediSearch as a static lib, like this:
27+
//
28+
// mkdir -p build
29+
// cd build
30+
// cmake -DRS_BUILD_STATIC=ON ..
31+
// make
32+
//
33+
// Take a look at some `-sys` crates for system library wrappers, and build using the
34+
// same methods that they use.
35+
// In fact, consider splitting this crate into a `-sys` crate for the low level wrappers
36+
// and another one for the high-level bindings.
37+
38+
let lib_search_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
39+
println!("cargo:rustc-link-search=native={}", lib_search_dir);
40+
println!("cargo:rustc-link-lib=static=redisearch");
2141
}

examples/hello_redisearch.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#[macro_use]
2+
extern crate redismodule;
3+
4+
use redisearch_api::{self, init, Document, Index};
5+
use redismodule::{Context, NextArg, RedisError, RedisResult};
6+
7+
fn hello_redisearch(_: &Context, args: Vec<String>) -> RedisResult {
8+
let mut args = args.into_iter().skip(1);
9+
let search_term = args.next_string()?;
10+
11+
// FT.CREATE my_index
12+
// SCHEMA
13+
// $a.b.c TEXT WEIGHT 5.0
14+
// $a.b.d TEXT
15+
// $b.a TEXT
16+
17+
// see RediSearch: t_llapi.cpp
18+
19+
let index_name = "index";
20+
let field_name = "foo";
21+
let score = 1.0;
22+
23+
let index = Index::create(index_name);
24+
index.create_field(field_name);
25+
26+
let doc = Document::create("doc1", score);
27+
doc.add_field(field_name, "bar");
28+
index.add_document(&doc)?;
29+
30+
let doc2 = Document::create("doc2", score);
31+
doc2.add_field(field_name, "quux");
32+
index.add_document(&doc2)?;
33+
34+
let keys: Vec<_> = index.search(search_term.as_str())?.collect();
35+
36+
Ok(keys.into())
37+
}
38+
39+
redis_module! {
40+
name: "hello_redisearch",
41+
version: 1,
42+
data_types: [],
43+
init: init,
44+
commands: [
45+
["hello_redisearch", hello_redisearch, ""],
46+
],
47+
}

src/document.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use std::ffi::CString;
2+
use std::os::raw::c_void;
3+
use std::ptr;
4+
5+
use crate::raw;
6+
7+
pub struct Document {
8+
pub(crate) inner: *mut raw::RSDoc,
9+
}
10+
11+
impl Document {
12+
pub fn create(key: &str, score: f64) -> Self {
13+
let c_key = CString::new(key).unwrap();
14+
let lang = ptr::null(); // Default language
15+
16+
let doc = unsafe {
17+
raw::RediSearch_CreateDocument(c_key.as_ptr() as *const c_void, key.len(), score, lang)
18+
};
19+
20+
Self { inner: doc }
21+
}
22+
23+
pub fn add_field(&self, name: &str, value: &str) {
24+
let name = CString::new(name).unwrap();
25+
let c_value = CString::new(value).unwrap();
26+
unsafe {
27+
raw::RediSearch_DocumentAddFieldString(
28+
self.inner,
29+
name.as_ptr(),
30+
c_value.as_ptr(),
31+
value.len(),
32+
raw::RSFLDTYPE_FULLTEXT,
33+
);
34+
}
35+
}
36+
}

src/include/redisearch_api.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef SRC_REDISEARCH_API_H_
22
#define SRC_REDISEARCH_API_H_
33

4+
#include "redisearch_defines.h"
45
#include "redismodule.h"
56
#include <limits.h>
67

@@ -16,6 +17,12 @@ extern "C" {
1617
#define MODULE_API_FUNC(T, N) T N
1718
#endif
1819

20+
/*
21+
MODULE_API_FUNC(int, RediSearch_GetCApiVersion)();
22+
int RediSearch_GetCApiVersion)();
23+
extern int (*RediSearch_GetCApiVersion)();
24+
*/
25+
1926
typedef struct IndexSpec RSIndex;
2027
typedef size_t RSFieldID;
2128
#define RSFIELD_INVALID SIZE_MAX

src/include/redisearch_defines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#define REDISMODULE_EXPERIMENTAL_API

src/include/redismodule.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#ifndef REDISMODULE_H
1+
#ifndef REDISMODULE_H
22
#define REDISMODULE_H
33

44
#include <sys/types.h>
@@ -134,7 +134,8 @@ typedef struct RedisModuleTypeMethods {
134134
RedisModuleTypeFreeFunc free;
135135
} RedisModuleTypeMethods;
136136

137-
#define REDISMODULE_API_FUNC(T, N) extern T(*N)
137+
//#define REDISMODULE_API_FUNC(T, N) extern T(*N)
138+
#define REDISMODULE_API_FUNC(T, N) T(*N)
138139

139140
REDISMODULE_API_FUNC(int, RedisModule_GetApi)(const char *, void *);
140141
REDISMODULE_API_FUNC(void *, RedisModule_Alloc)(size_t bytes);

0 commit comments

Comments
 (0)