1use crate::memdx::error;
20use crate::memdx::opcode::OpCode;
21use bitflags::bitflags;
22
23pub trait SubdocOp {
24 fn is_xattr_op(&self) -> bool;
25}
26
27pub fn reorder_subdoc_ops<T: SubdocOp>(ops: &[T]) -> (Vec<&T>, Vec<usize>) {
28 let mut ordered_ops = Vec::with_capacity(ops.len());
29 let mut op_indexes = Vec::with_capacity(ops.len());
30
31 for (i, op) in ops.iter().enumerate() {
32 if op.is_xattr_op() {
33 ordered_ops.push(op);
34 op_indexes.push(i);
35 }
36 }
37
38 for (i, op) in ops.iter().enumerate() {
39 if !op.is_xattr_op() {
40 ordered_ops.push(op);
41 op_indexes.push(i);
42 }
43 }
44
45 (ordered_ops, op_indexes)
46}
47
48#[derive(Debug, Clone, Copy, Default)]
50pub struct SubdocRequestInfo {
51 pub(crate) flags: SubdocDocFlag,
52 pub(crate) op_count: u8,
53}
54
55#[derive(Debug)]
56pub struct SubDocResult {
57 pub err: Option<error::Error>,
58 pub value: Option<Vec<u8>>,
59}
60
61#[derive(Clone, Debug, Copy, Eq, PartialEq)]
62pub struct LookupInOp<'a> {
63 pub(crate) op: LookupInOpType,
64 pub(crate) flags: SubdocOpFlag,
65 pub(crate) path: &'a [u8],
66}
67
68impl<'a> LookupInOp<'a> {
69 pub fn new(op: LookupInOpType, path: &'a [u8]) -> Self {
70 Self {
71 op,
72 flags: SubdocOpFlag::empty(),
73 path,
74 }
75 }
76
77 pub fn flags(mut self, flags: SubdocOpFlag) -> Self {
78 self.flags = flags;
79 self
80 }
81}
82
83impl SubdocOp for LookupInOp<'_> {
84 fn is_xattr_op(&self) -> bool {
85 self.flags.contains(SubdocOpFlag::XATTR_PATH)
86 }
87}
88
89#[derive(Clone, Debug, Eq, PartialEq)]
90pub struct MutateInOp<'a> {
91 pub(crate) op: MutateInOpType,
92 pub(crate) flags: SubdocOpFlag,
93 pub(crate) path: &'a [u8],
94 pub(crate) value: &'a [u8],
95}
96
97impl<'a> MutateInOp<'a> {
98 pub fn new(op: MutateInOpType, path: &'a [u8], value: &'a [u8]) -> Self {
99 Self {
100 op,
101 flags: SubdocOpFlag::empty(),
102 path,
103 value,
104 }
105 }
106
107 pub fn flags(mut self, flags: SubdocOpFlag) -> Self {
108 self.flags = flags;
109 self
110 }
111}
112
113impl SubdocOp for MutateInOp<'_> {
114 fn is_xattr_op(&self) -> bool {
115 self.flags.contains(SubdocOpFlag::XATTR_PATH)
116 }
117}
118
119bitflags! {
120 #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq)]
121 pub struct SubdocOpFlag: u8 {
122 const MKDIR_P = 0x01;
124
125 const XATTR_PATH = 0x04;
129
130 const EXPAND_MACROS = 0x10;
135 }
136
137 #[derive(Copy, Clone, Debug, Eq, PartialEq, Default, Ord, PartialOrd, Hash)]
138 pub struct SubdocDocFlag: u8 {
139 const MkDoc = 0x01;
141 const AddDoc = 0x02;
143
144 const AccessDeleted = 0x04;
147
148 const CreateAsDeleted = 0x08;
152
153 const ReviveDocument = 0x10;
156 }
157}
158
159#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
161pub enum LookupInOpType {
162 Get,
164 Exists,
166 GetCount,
168 GetDoc,
170}
171
172impl From<LookupInOpType> for OpCode {
173 fn from(op_type: LookupInOpType) -> Self {
174 match op_type {
175 LookupInOpType::Get => OpCode::SubDocGet,
176 LookupInOpType::Exists => OpCode::SubDocExists,
177 LookupInOpType::GetCount => OpCode::SubDocGetCount,
178 LookupInOpType::GetDoc => OpCode::Get,
179 }
180 }
181}
182
183#[derive(Debug, Copy, Clone, PartialEq, Eq)]
185pub enum MutateInOpType {
186 DictAdd,
188 DictSet,
190 Delete,
192 Replace,
194 ArrayPushLast,
196 ArrayPushFirst,
198 ArrayInsert,
200 ArrayAddUnique,
202 Counter,
204 SetDoc,
206 AddDoc,
208 DeleteDoc,
210 ReplaceBodyWithXattr,
213}
214
215impl From<MutateInOpType> for OpCode {
216 fn from(op_type: MutateInOpType) -> Self {
217 match op_type {
218 MutateInOpType::DictAdd => OpCode::SubDocDictAdd,
219 MutateInOpType::DictSet => OpCode::SubDocDictSet,
220 MutateInOpType::Delete => OpCode::SubDocDelete,
221 MutateInOpType::Replace => OpCode::SubDocReplace,
222 MutateInOpType::ArrayPushLast => OpCode::SubDocArrayPushLast,
223 MutateInOpType::ArrayPushFirst => OpCode::SubDocArrayPushFirst,
224 MutateInOpType::ArrayInsert => OpCode::SubDocArrayInsert,
225 MutateInOpType::ArrayAddUnique => OpCode::SubDocArrayAddUnique,
226 MutateInOpType::Counter => OpCode::SubDocCounter,
227 MutateInOpType::SetDoc => OpCode::Set,
228 MutateInOpType::AddDoc => OpCode::Add,
229 MutateInOpType::DeleteDoc => OpCode::Delete,
230 MutateInOpType::ReplaceBodyWithXattr => OpCode::SubDocReplaceBodyWithXattr,
231 }
232 }
233}
234
235pub const SUBDOC_XATTR_PATH_HLC: &[u8] = b"$vbucket.HLC";
236
237pub const SUBDOC_MACRO_NEW_CRC32C: &[u8] = b"\"${Mutation.value_crc32c}\"";
238pub const SUBDOC_MACRO_NEW_CAS: &[u8] = b"\"${Mutation.CAS}\"";
239pub const SUBDOC_MACRO_OLD_REVID: &[u8] = b"\"${$document.revid}\"";
240pub const SUBDOC_MACRO_OLD_EXPTIME: &[u8] = b"\"${$document.exptime}\"";
241pub const SUBDOC_MACRO_OLD_CAS: &[u8] = b"\"${$document.CAS}\"";