Skip to content

Commit babe11e

Browse files
authored
add rdb backward load (RedisJSON#43)
* add rdb backward load
1 parent a411d0c commit babe11e

File tree

6 files changed

+98
-12
lines changed

6 files changed

+98
-12
lines changed

Cargo.lock

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ crate-type = ["cdylib"]
1111
serde_json = "1.0"
1212
libc = "0.2"
1313
jsonpath_lib = { git="https://github.com/gkorland/jsonpath.git", branch="reaplce_with_ownership_parser" }
14-
redismodule = { git = "https://github.com/RedisLabsModules/redismodule-rs.git", branch = "master" }
14+
redismodule = { git="https://github.com/redislabsmodules/redismodule-rs.git", branch="load_rdb" }

src/backward.rs

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use redismodule::raw;
2+
use serde_json::map::Map;
3+
use serde_json::Number;
4+
use serde_json::Value;
5+
use std::vec::Vec;
6+
7+
#[derive(Debug, PartialEq)]
8+
enum NodeType {
9+
Null, // used in masks and consistent type checking
10+
String,
11+
Number,
12+
Integer,
13+
Boolean,
14+
Dict,
15+
Array,
16+
KeyVal,
17+
// N_DATETIME = 0x100
18+
// N_BINARY = 0x200
19+
}
20+
21+
impl From<u64> for NodeType {
22+
fn from(n: u64) -> Self {
23+
match n {
24+
0x1u64 => NodeType::Null,
25+
0x2u64 => NodeType::String,
26+
0x4u64 => NodeType::Number,
27+
0x8u64 => NodeType::Integer,
28+
0x10u64 => NodeType::Boolean,
29+
0x20u64 => NodeType::Dict,
30+
0x40u64 => NodeType::Array,
31+
0x80u64 => NodeType::KeyVal,
32+
_ => panic!("Can't load old RedisJSON RDB1"),
33+
}
34+
}
35+
}
36+
37+
pub unsafe fn json_rdb_load(rdb: *mut raw::RedisModuleIO) -> Value {
38+
let node_type = raw::load_unsigned(rdb).into();
39+
match node_type {
40+
NodeType::Null => Value::Null,
41+
NodeType::Boolean => {
42+
let mut str_len = 0;
43+
let str_buffer = raw::load_string_buffer(rdb, &mut str_len);
44+
Value::Bool(str_buffer.starts_with("1"))
45+
}
46+
NodeType::Integer => Value::Number(raw::load_signed(rdb).into()),
47+
NodeType::Number => Value::Number(Number::from_f64(raw::load_double(rdb)).unwrap()),
48+
NodeType::String => {
49+
let mut str_len = 0;
50+
let str_buffer = raw::load_string_buffer(rdb, &mut str_len);
51+
Value::String(str_buffer.to_string())
52+
}
53+
NodeType::Dict => {
54+
let len = raw::load_unsigned(rdb);
55+
let mut m = Map::with_capacity(len as usize);
56+
for _ in 0..len {
57+
let t: NodeType = raw::load_unsigned(rdb).into();
58+
if t != NodeType::KeyVal {
59+
panic!("Can't load old RedisJSON RDB");
60+
}
61+
let mut str_len = 0;
62+
let name = &raw::load_string_buffer(rdb, &mut str_len);
63+
m.insert(name.to_string(), json_rdb_load(rdb));
64+
}
65+
Value::Object(m)
66+
}
67+
NodeType::Array => {
68+
let len = raw::load_unsigned(rdb);
69+
let mut v = Vec::with_capacity(len as usize);
70+
for _ in 0..len {
71+
v.push(json_rdb_load(rdb))
72+
}
73+
Value::Array(v)
74+
}
75+
NodeType::KeyVal => panic!("Can't load old RedisJSON RDB"),
76+
}
77+
}

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use redismodule::{Context, NextArg, RedisError, RedisResult, RedisValue, REDIS_O
66
use serde_json::{Number, Value};
77
use std::{i64, usize};
88

9+
mod backward;
910
mod index;
1011
mod nodevisitor;
1112
mod redisjson;

src/nodevisitor.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub struct NodeVisitorImpl {
1616
impl NodeVisitorImpl {
1717
///
1818
/// Checks if path is static & valid
19-
///
19+
///
2020
pub fn check(input: &str) -> Result<bool, String> {
2121
let node = Parser::compile(input)?;
2222
let mut visitor = NodeVisitorImpl {

src/redisjson.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Translate between JSON and tree of Redis objects:
44
// User-provided JSON is converted to a tree. This tree is stored transparently in Redis.
55
// It can be operated on (e.g. INCR) and serialized back to JSON.
6+
use crate::backward;
67
use crate::nodevisitor::NodeVisitorImpl;
78
use jsonpath_lib::{JsonPathError, SelectorMut};
89
use redismodule::raw;
@@ -14,7 +15,6 @@ pub struct Error {
1415
msg: String,
1516
}
1617

17-
1818
#[derive(Debug, PartialEq)]
1919
pub enum SetOptions {
2020
NotExists,
@@ -106,11 +106,16 @@ impl RedisJSON {
106106
Ok(Self { data: v })
107107
}
108108

109-
pub fn set_value(&mut self, data: &str, path: &str, option: &Option<SetOptions>) -> Result<bool, Error> {
109+
pub fn set_value(
110+
&mut self,
111+
data: &str,
112+
path: &str,
113+
option: &Option<SetOptions>,
114+
) -> Result<bool, Error> {
110115
// Parse the string of data into serde_json::Value.
111116
let json: Value = serde_json::from_str(data)?;
112117

113-
if path == "$" {
118+
if path == "$" {
114119
if Some(SetOptions::NotExists) == *option {
115120
Ok(false)
116121
} else {
@@ -283,10 +288,13 @@ impl RedisJSON {
283288

284289
#[allow(non_snake_case, unused)]
285290
pub unsafe extern "C" fn json_rdb_load(rdb: *mut raw::RedisModuleIO, encver: c_int) -> *mut c_void {
286-
if encver < 2 {
287-
panic!("Can't load old RedisJSON RDB"); // TODO add support for backward
288-
}
289-
let json = RedisJSON::from_str(&raw::load_string(rdb)).unwrap();
291+
let json = match encver {
292+
0 => RedisJSON {
293+
data: backward::json_rdb_load(rdb),
294+
},
295+
2 => RedisJSON::from_str(&raw::load_string(rdb)).unwrap(),
296+
_ => panic!("Can't load old RedisJSON RDB"),
297+
};
290298
Box::into_raw(Box::new(json)) as *mut c_void
291299
}
292300

0 commit comments

Comments
 (0)