1use crate::ffi;
2use libc::{c_char, size_t};
3
4use crate::{handle::Handle, ColumnFamily, Error, WriteOptions};
5
6pub trait Merge<W> {
7 fn merge_full<K, V>(&self, key: K, value: V, writeopts: Option<&W>) -> Result<(), Error>
8 where
9 K: AsRef<[u8]>,
10 V: AsRef<[u8]>;
11
12 fn merge<K, V>(&self, key: K, value: V) -> Result<(), Error>
13 where
14 K: AsRef<[u8]>,
15 V: AsRef<[u8]>,
16 {
17 self.merge_full(key, value, None)
18 }
19
20 fn merge_opt<K, V>(&self, key: K, value: V, writeopts: &W) -> Result<(), Error>
21 where
22 K: AsRef<[u8]>,
23 V: AsRef<[u8]>,
24 {
25 self.merge_full(key, value, Some(writeopts))
26 }
27}
28
29pub trait MergeCF<W> {
30 fn merge_cf_full<K, V>(
31 &self,
32 cf: Option<&ColumnFamily>,
33 key: K,
34 value: V,
35 writeopts: Option<&W>,
36 ) -> Result<(), Error>
37 where
38 K: AsRef<[u8]>,
39 V: AsRef<[u8]>;
40
41 fn merge_cf<K, V>(&self, cf: &ColumnFamily, key: K, value: V) -> Result<(), Error>
42 where
43 K: AsRef<[u8]>,
44 V: AsRef<[u8]>,
45 {
46 self.merge_cf_full(Some(cf), key, value, None)
47 }
48
49 fn merge_cf_opt<K, V>(
50 &self,
51 cf: &ColumnFamily,
52 key: K,
53 value: V,
54 writeopts: &W,
55 ) -> Result<(), Error>
56 where
57 K: AsRef<[u8]>,
58 V: AsRef<[u8]>,
59 {
60 self.merge_cf_full(Some(cf), key, value, Some(writeopts))
61 }
62}
63
64impl<T, W> Merge<W> for T
65where
66 T: MergeCF<W>,
67{
68 fn merge_full<K: AsRef<[u8]>, V: AsRef<[u8]>>(
69 &self,
70 key: K,
71 value: V,
72 writeopts: Option<&W>,
73 ) -> Result<(), Error> {
74 self.merge_cf_full(None, key, value, writeopts)
75 }
76}
77
78impl<T> MergeCF<WriteOptions> for T
79where
80 T: Handle<ffi::rocksdb_t> + super::Write,
81{
82 fn merge_cf_full<K, V>(
83 &self,
84 cf: Option<&ColumnFamily>,
85 key: K,
86 value: V,
87 writeopts: Option<&WriteOptions>,
88 ) -> Result<(), Error>
89 where
90 K: AsRef<[u8]>,
91 V: AsRef<[u8]>,
92 {
93 let mut default_writeopts = None;
94
95 let wo_handle = WriteOptions::input_or_default(writeopts, &mut default_writeopts)?;
96
97 let key = key.as_ref();
98 let value = value.as_ref();
99 let key_ptr = key.as_ptr() as *const c_char;
100 let key_len = key.len() as size_t;
101 let val_ptr = value.as_ptr() as *const c_char;
102 let val_len = value.len() as size_t;
103
104 unsafe {
105 match cf {
106 Some(cf) => ffi_try!(ffi::rocksdb_merge_cf(
107 self.handle(),
108 wo_handle,
109 cf.handle(),
110 key_ptr,
111 key_len,
112 val_ptr,
113 val_len,
114 )),
115 None => ffi_try!(ffi::rocksdb_merge(
116 self.handle(),
117 wo_handle,
118 key_ptr,
119 key_len,
120 val_ptr,
121 val_len,
122 )),
123 }
124
125 Ok(())
126 }
127 }
128}