cassandra_protocol/query/
query_params.rs1use std::collections::HashMap;
2use std::io::Cursor;
3
4use crate::consistency::Consistency;
5use crate::frame::traits::FromCursor;
6use crate::frame::{Serialize, Version};
7use crate::query::query_flags::QueryFlags;
8use crate::query::query_values::QueryValues;
9use crate::types::{from_cursor_str, serialize_str, value::Value, CInt, CIntShort};
10use crate::types::{CBytes, CLong};
11use crate::Error;
12
13#[derive(Debug, Default, Clone, PartialEq, Eq)]
15pub struct QueryParams {
16 pub consistency: Consistency,
18 pub with_names: bool,
20 pub values: Option<QueryValues>,
22 pub page_size: Option<CInt>,
24 pub paging_state: Option<CBytes>,
26 pub serial_consistency: Option<Consistency>,
28 pub timestamp: Option<CLong>,
30 pub keyspace: Option<String>,
33 pub now_in_seconds: Option<CInt>,
36}
37
38impl QueryParams {
39 fn flags(&self) -> QueryFlags {
40 let mut flags = QueryFlags::empty();
41
42 if self.values.is_some() {
43 flags.insert(QueryFlags::VALUE);
44 }
45
46 if self.with_names {
47 flags.insert(QueryFlags::WITH_NAMES_FOR_VALUES);
48 }
49
50 if self.page_size.is_some() {
51 flags.insert(QueryFlags::PAGE_SIZE);
52 }
53
54 if self.paging_state.is_some() {
55 flags.insert(QueryFlags::WITH_PAGING_STATE);
56 }
57
58 if self.serial_consistency.is_some() {
59 flags.insert(QueryFlags::WITH_SERIAL_CONSISTENCY);
60 }
61
62 if self.timestamp.is_some() {
63 flags.insert(QueryFlags::WITH_DEFAULT_TIMESTAMP);
64 }
65
66 if self.keyspace.is_some() {
67 flags.insert(QueryFlags::WITH_KEYSPACE);
68 }
69
70 if self.now_in_seconds.is_some() {
71 flags.insert(QueryFlags::WITH_NOW_IN_SECONDS);
72 }
73
74 flags
75 }
76}
77
78impl Serialize for QueryParams {
79 fn serialize(&self, cursor: &mut Cursor<&mut Vec<u8>>, version: Version) {
80 let consistency: CIntShort = self.consistency.into();
81 consistency.serialize(cursor, version);
82
83 let flag_bits = self.flags().bits();
84 if version >= Version::V5 {
85 flag_bits.serialize(cursor, version);
86 } else {
87 (flag_bits as u8).serialize(cursor, version);
88 };
89
90 if let Some(values) = &self.values {
91 let len = values.len() as CIntShort;
92 len.serialize(cursor, version);
93 values.serialize(cursor, version);
94 }
95
96 if let Some(page_size) = self.page_size {
97 page_size.serialize(cursor, version);
98 }
99
100 if let Some(paging_state) = &self.paging_state {
101 paging_state.serialize(cursor, version);
102 }
103
104 if let Some(serial_consistency) = self.serial_consistency {
105 let serial_consistency: CIntShort = serial_consistency.into();
106 serial_consistency.serialize(cursor, version);
107 }
108
109 if let Some(timestamp) = self.timestamp {
110 timestamp.serialize(cursor, version);
111 }
112
113 if let Some(keyspace) = &self.keyspace {
114 serialize_str(cursor, keyspace.as_str(), version);
115 }
116
117 if let Some(now_in_seconds) = self.now_in_seconds {
118 now_in_seconds.serialize(cursor, version);
119 }
120 }
121}
122
123impl FromCursor for QueryParams {
124 fn from_cursor(cursor: &mut Cursor<&[u8]>, version: Version) -> Result<QueryParams, Error> {
125 let consistency = Consistency::from_cursor(cursor, version)?;
126 let flags = QueryFlags::from_cursor(cursor, version)?;
127
128 let values = if flags.contains(QueryFlags::VALUE) {
129 let number_of_values = CIntShort::from_cursor(cursor, version)?;
130
131 if flags.contains(QueryFlags::WITH_NAMES_FOR_VALUES) {
132 let mut map = HashMap::with_capacity(number_of_values as usize);
133 for _ in 0..number_of_values {
134 map.insert(
135 from_cursor_str(cursor)?.to_string(),
136 Value::from_cursor(cursor, version)?,
137 );
138 }
139 Some(QueryValues::NamedValues(map))
140 } else {
141 let mut vec = Vec::with_capacity(number_of_values as usize);
142 for _ in 0..number_of_values {
143 vec.push(Value::from_cursor(cursor, version)?);
144 }
145 Some(QueryValues::SimpleValues(vec))
146 }
147 } else {
148 None
149 };
150
151 let page_size = if flags.contains(QueryFlags::PAGE_SIZE) {
152 Some(CInt::from_cursor(cursor, version)?)
153 } else {
154 None
155 };
156
157 let paging_state = if flags.contains(QueryFlags::WITH_PAGING_STATE) {
158 Some(CBytes::from_cursor(cursor, version)?)
159 } else {
160 None
161 };
162
163 let serial_consistency = if flags.contains(QueryFlags::WITH_SERIAL_CONSISTENCY) {
164 Some(Consistency::from_cursor(cursor, version)?)
165 } else {
166 None
167 };
168
169 let timestamp = if flags.contains(QueryFlags::WITH_DEFAULT_TIMESTAMP) {
170 Some(CLong::from_cursor(cursor, version)?)
171 } else {
172 None
173 };
174
175 let keyspace = if flags.contains(QueryFlags::WITH_KEYSPACE) {
176 Some(from_cursor_str(cursor)?.to_string())
177 } else {
178 None
179 };
180
181 let now_in_seconds = if flags.contains(QueryFlags::WITH_NOW_IN_SECONDS) {
182 Some(CInt::from_cursor(cursor, version)?)
183 } else {
184 None
185 };
186
187 let with_names = flags.contains(QueryFlags::WITH_NAMES_FOR_VALUES);
188
189 Ok(QueryParams {
190 consistency,
191 with_names,
192 values,
193 page_size,
194 paging_state,
195 serial_consistency,
196 timestamp,
197 keyspace,
198 now_in_seconds,
199 })
200 }
201}