1use std::io::Cursor;
2
3use crate::frame::{FromBytes, FromCursor, IntoBytes};
4use crate::error;
5use crate::types::*;
6use crate::types::rows::Row;
7use crate::frame::events::SchemaChange;
8
9#[derive(Debug)]
11pub enum ResultKind {
12 Void,
14 Rows,
16 SetKeyspace,
18 Prepared,
20 SchemaChange,
22}
23
24impl IntoBytes for ResultKind {
25 fn into_cbytes(&self) -> Vec<u8> {
26 match *self {
27 ResultKind::Void => to_int(0x0001),
28 ResultKind::Rows => to_int(0x0002),
29 ResultKind::SetKeyspace => to_int(0x0003),
30 ResultKind::Prepared => to_int(0x0004),
31 ResultKind::SchemaChange => to_int(0x0005),
32 }
33 }
34}
35
36impl FromBytes for ResultKind {
37 fn from_bytes(bytes: &[u8]) -> error::Result<ResultKind> {
38 try_from_bytes(bytes).map_err(Into::into)
39 .and_then(|r| match r {
40 0x0001 => Ok(ResultKind::Void),
41 0x0002 => Ok(ResultKind::Rows),
42 0x0003 => Ok(ResultKind::SetKeyspace),
43 0x0004 => Ok(ResultKind::Prepared),
44 0x0005 => Ok(ResultKind::SchemaChange),
45 _ => Err("Unexpected result kind".into()),
46 })
47 }
48}
49
50impl FromCursor for ResultKind {
51 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<ResultKind> {
52 cursor_next_value(&mut cursor, INT_LEN as u64)
53 .and_then(|bytes| ResultKind::from_bytes(bytes.as_slice()))
54 }
55}
56
57#[derive(Debug)]
60pub enum ResResultBody {
61 Void(BodyResResultVoid),
63 Rows(BodyResResultRows),
65 SetKeyspace(BodyResResultSetKeyspace),
68 Prepared(BodyResResultPrepared),
70 SchemaChange(SchemaChange),
72}
73
74impl ResResultBody {
75 fn parse_body_from_cursor(mut cursor: &mut Cursor<&[u8]>,
78 result_kind: ResultKind)
79 -> error::Result<ResResultBody> {
80 Ok(match result_kind {
81 ResultKind::Void => ResResultBody::Void(BodyResResultVoid::from_cursor(&mut cursor)?),
82 ResultKind::Rows => ResResultBody::Rows(BodyResResultRows::from_cursor(&mut cursor)?),
83 ResultKind::SetKeyspace => {
84 ResResultBody::SetKeyspace(BodyResResultSetKeyspace::from_cursor(&mut cursor)?)
85 }
86 ResultKind::Prepared => {
87 ResResultBody::Prepared(BodyResResultPrepared::from_cursor(&mut cursor)?)
88 }
89 ResultKind::SchemaChange => {
90 ResResultBody::SchemaChange(SchemaChange::from_cursor(&mut cursor)?)
91 }
92 })
93 }
94
95 pub fn into_rows(self) -> Option<Vec<Row>> {
97 match self {
98 ResResultBody::Rows(rows_body) => Some(Row::from_frame_body(rows_body)),
99 _ => None,
100 }
101 }
102
103 pub fn as_rows_metadata(&self) -> Option<RowsMetadata> {
105 match *self {
106 ResResultBody::Rows(ref rows_body) => Some(rows_body.metadata.clone()),
107 _ => None,
108 }
109 }
110
111 pub fn into_prepared(self) -> Option<BodyResResultPrepared> {
114 match self {
115 ResResultBody::Prepared(p) => Some(p),
116 _ => None,
117 }
118 }
119
120 pub fn into_set_keyspace(self) -> Option<BodyResResultSetKeyspace> {
123 match self {
124 ResResultBody::SetKeyspace(p) => Some(p),
125 _ => None,
126 }
127 }
128}
129
130impl FromCursor for ResResultBody {
131 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<ResResultBody> {
132 let result_kind = ResultKind::from_cursor(&mut cursor)?;
133
134 ResResultBody::parse_body_from_cursor(&mut cursor, result_kind)
135 }
136}
137
138#[derive(Debug, Default)]
140pub struct BodyResResultVoid {}
141
142impl FromBytes for BodyResResultVoid {
143 fn from_bytes(_bytes: &[u8]) -> error::Result<BodyResResultVoid> {
144 let body: BodyResResultVoid = Default::default();
146 Ok(body)
147 }
148}
149
150impl FromCursor for BodyResResultVoid {
151 fn from_cursor(mut _cursor: &mut Cursor<&[u8]>) -> error::Result<BodyResResultVoid> {
152 let body: BodyResResultVoid = Default::default();
153 Ok(body)
154 }
155}
156
157#[derive(Debug)]
159pub struct BodyResResultSetKeyspace {
160 pub body: CString,
162}
163
164impl BodyResResultSetKeyspace {
165 pub fn new(body: CString) -> BodyResResultSetKeyspace {
168 BodyResResultSetKeyspace { body: body }
169 }
170}
171
172impl FromCursor for BodyResResultSetKeyspace {
173 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<BodyResResultSetKeyspace> {
174 CString::from_cursor(&mut cursor).map(BodyResResultSetKeyspace::new)
175 }
176}
177
178#[derive(Debug)]
181pub struct BodyResResultRows {
182 pub metadata: RowsMetadata,
184 pub rows_count: CInt,
186 pub rows_content: Vec<Vec<CBytes>>,
188}
189
190impl BodyResResultRows {
191 fn get_rows_content(mut cursor: &mut Cursor<&[u8]>,
193 rows_count: i32,
194 columns_count: i32)
195 -> Vec<Vec<CBytes>> {
196 (0..rows_count).map(|_| {
197 (0..columns_count)
198 .map(|_| CBytes::from_cursor(&mut cursor).unwrap() as CBytes)
200 .collect()
201 })
202 .collect()
203 }
204}
205
206impl FromCursor for BodyResResultRows {
207 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<BodyResResultRows> {
208 let metadata = RowsMetadata::from_cursor(&mut cursor)?;
209 let rows_count = CInt::from_cursor(&mut cursor)?;
210 let rows_content: Vec<Vec<CBytes>> =
211 BodyResResultRows::get_rows_content(&mut cursor, rows_count, metadata.columns_count);
212
213 Ok(BodyResResultRows { metadata: metadata,
214 rows_count: rows_count,
215 rows_content: rows_content, })
216 }
217}
218
219#[derive(Debug, Clone)]
221pub struct RowsMetadata {
222 pub flags: i32,
226 pub columns_count: i32,
228 pub paging_state: Option<CBytes>,
230 pub global_table_space: Option<Vec<CString>>,
234 pub col_specs: Vec<ColSpec>,
236}
237
238impl FromCursor for RowsMetadata {
239 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<RowsMetadata> {
240 let flags = CInt::from_cursor(&mut cursor)?;
241 let columns_count = CInt::from_cursor(&mut cursor)?;
242
243 let mut paging_state: Option<CBytes> = None;
244 if RowsMetadataFlag::has_has_more_pages(flags) {
245 paging_state = Some(CBytes::from_cursor(&mut cursor)?)
246 }
247
248 let mut global_table_space: Option<Vec<CString>> = None;
249 let has_global_table_space = RowsMetadataFlag::has_global_table_space(flags);
250 if has_global_table_space {
251 let keyspace = CString::from_cursor(&mut cursor)?;
252 let tablename = CString::from_cursor(&mut cursor)?;
253 global_table_space = Some(vec![keyspace, tablename])
254 }
255
256 let col_specs = ColSpec::parse_colspecs(&mut cursor, columns_count, has_global_table_space);
257
258 Ok(RowsMetadata { flags: flags,
259 columns_count: columns_count,
260 paging_state: paging_state,
261 global_table_space: global_table_space,
262 col_specs: col_specs, })
263 }
264}
265
266const GLOBAL_TABLE_SPACE: i32 = 0x0001;
267const HAS_MORE_PAGES: i32 = 0x0002;
268const NO_METADATA: i32 = 0x0004;
269
270pub enum RowsMetadataFlag {
272 GlobalTableSpace,
273 HasMorePages,
274 NoMetadata,
275}
276
277impl RowsMetadataFlag {
278 pub fn has_global_table_space(flag: i32) -> bool {
280 (flag & GLOBAL_TABLE_SPACE) != 0
281 }
282
283 pub fn set_global_table_space(flag: i32) -> i32 {
285 flag | GLOBAL_TABLE_SPACE
286 }
287
288 pub fn has_has_more_pages(flag: i32) -> bool {
290 (flag & HAS_MORE_PAGES) != 0
291 }
292
293 pub fn set_has_more_pages(flag: i32) -> i32 {
295 flag | HAS_MORE_PAGES
296 }
297
298 pub fn has_no_metadata(flag: i32) -> bool {
300 (flag & NO_METADATA) != 0
301 }
302
303 pub fn set_no_metadata(flag: i32) -> i32 {
305 flag | NO_METADATA
306 }
307}
308
309impl IntoBytes for RowsMetadataFlag {
310 fn into_cbytes(&self) -> Vec<u8> {
311 match *self {
312 RowsMetadataFlag::GlobalTableSpace => to_int(GLOBAL_TABLE_SPACE),
313 RowsMetadataFlag::HasMorePages => to_int(HAS_MORE_PAGES),
314 RowsMetadataFlag::NoMetadata => to_int(NO_METADATA),
315 }
316 }
317}
318
319impl FromBytes for RowsMetadataFlag {
320 fn from_bytes(bytes: &[u8]) -> error::Result<RowsMetadataFlag> {
321 try_from_bytes(bytes).map_err(Into::into)
322 .and_then(|f| match f as i32 {
323 GLOBAL_TABLE_SPACE => {
324 Ok(RowsMetadataFlag::GlobalTableSpace)
325 }
326 HAS_MORE_PAGES => Ok(RowsMetadataFlag::HasMorePages),
327 NO_METADATA => Ok(RowsMetadataFlag::NoMetadata),
328 _ => Err("Unexpected rows metadata flag".into()),
329 })
330 }
331}
332
333#[derive(Debug, Clone)]
335pub struct ColSpec {
336 pub ksname: Option<CString>,
339 pub tablename: Option<CString>,
342 pub name: CString,
344 pub col_type: ColTypeOption,
346}
347
348impl ColSpec {
349 pub fn parse_colspecs(mut cursor: &mut Cursor<&[u8]>,
353 column_count: i32,
354 with_globale_table_spec: bool)
355 -> Vec<ColSpec> {
356 (0..column_count).map(|_| {
357 let ksname: Option<CString> = if !with_globale_table_spec {
358 Some(CString::from_cursor(&mut cursor).unwrap())
359 } else {
360 None
361 };
362
363 let tablename = if !with_globale_table_spec {
364 Some(CString::from_cursor(&mut cursor).unwrap())
365 } else {
366 None
367 };
368
369 let name = CString::from_cursor(&mut cursor).unwrap();
371 let col_type = ColTypeOption::from_cursor(&mut cursor).unwrap();
372
373 ColSpec { ksname: ksname,
374 tablename: tablename,
375 name: name,
376 col_type: col_type, }
377 })
378 .collect()
379 }
380}
381
382#[derive(Debug, Clone)]
384pub enum ColType {
385 Custom,
386 Ascii,
387 Bigint,
388 Blob,
389 Boolean,
390 Counter,
391 Decimal,
392 Double,
393 Float,
394 Int,
395 Timestamp,
396 Uuid,
397 Varchar,
398 Varint,
399 Timeuuid,
400 Inet,
401 Date,
402 Time,
403 Smallint,
404 Tinyint,
405 List,
406 Map,
407 Set,
408 Udt,
409 Tuple,
410 Null,
411}
412
413impl FromBytes for ColType {
414 fn from_bytes(bytes: &[u8]) -> error::Result<ColType> {
415 try_from_bytes(bytes).map_err(Into::into)
416 .and_then(|b| match b {
417 0x0000 => Ok(ColType::Custom),
418 0x0001 => Ok(ColType::Ascii),
419 0x0002 => Ok(ColType::Bigint),
420 0x0003 => Ok(ColType::Blob),
421 0x0004 => Ok(ColType::Boolean),
422 0x0005 => Ok(ColType::Counter),
423 0x0006 => Ok(ColType::Decimal),
424 0x0007 => Ok(ColType::Double),
425 0x0008 => Ok(ColType::Float),
426 0x0009 => Ok(ColType::Int),
427 0x000B => Ok(ColType::Timestamp),
428 0x000C => Ok(ColType::Uuid),
429 0x000D => Ok(ColType::Varchar),
430 0x000E => Ok(ColType::Varint),
431 0x000F => Ok(ColType::Timeuuid),
432 0x0010 => Ok(ColType::Inet),
433 0x0011 => Ok(ColType::Date),
434 0x0012 => Ok(ColType::Time),
435 0x0013 => Ok(ColType::Smallint),
436 0x0014 => Ok(ColType::Tinyint),
437 0x0020 => Ok(ColType::List),
438 0x0021 => Ok(ColType::Map),
439 0x0022 => Ok(ColType::Set),
440 0x0030 => Ok(ColType::Udt),
441 0x0031 => Ok(ColType::Tuple),
442 _ => Err("Unexpected column type".into()),
443 })
444 }
445}
446
447impl FromCursor for ColType {
448 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<ColType> {
449 cursor_next_value(&mut cursor, SHORT_LEN as u64)
450 .and_then(|bytes| ColType::from_bytes(bytes.as_slice()))
451 .map_err(Into::into)
452 }
453}
454
455#[derive(Debug, Clone)]
457pub struct ColTypeOption {
458 pub id: ColType,
460 pub value: Option<ColTypeOptionValue>,
464}
465
466impl FromCursor for ColTypeOption {
467 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<ColTypeOption> {
468 let id = ColType::from_cursor(&mut cursor)?;
469 let value = match id {
470 ColType::Custom => {
471 Some(ColTypeOptionValue::CString(CString::from_cursor(&mut cursor)?))
472 }
473 ColType::Set => {
474 let col_type = ColTypeOption::from_cursor(&mut cursor)?;
475 Some(ColTypeOptionValue::CSet(Box::new(col_type)))
476 }
477 ColType::List => {
478 let col_type = ColTypeOption::from_cursor(&mut cursor)?;
479 Some(ColTypeOptionValue::CList(Box::new(col_type)))
480 }
481 ColType::Udt => Some(ColTypeOptionValue::UdtType(CUdt::from_cursor(&mut cursor)?)),
482 ColType::Tuple => {
483 Some(ColTypeOptionValue::TupleType(CTuple::from_cursor(&mut cursor)?))
484 }
485 ColType::Map => {
486 let name_type = ColTypeOption::from_cursor(&mut cursor)?;
487 let value_type = ColTypeOption::from_cursor(&mut cursor)?;
488 Some(ColTypeOptionValue::CMap((Box::new(name_type), Box::new(value_type))))
489 }
490 _ => None,
491 };
492
493 Ok(ColTypeOption { id: id,
494 value: value, })
495 }
496}
497
498#[derive(Debug, Clone)]
500pub enum ColTypeOptionValue {
501 CString(CString),
502 ColType(ColType),
503 CSet(Box<ColTypeOption>),
504 CList(Box<ColTypeOption>),
505 UdtType(CUdt),
506 TupleType(CTuple),
507 CMap((Box<ColTypeOption>, Box<ColTypeOption>)),
508}
509
510#[derive(Debug, Clone)]
513pub struct CUdt {
514 pub ks: CString,
516 pub udt_name: CString,
518 pub descriptions: Vec<(CString, ColTypeOption)>,
520}
521
522impl FromCursor for CUdt {
523 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<CUdt> {
524 let ks = CString::from_cursor(&mut cursor)?;
525 let udt_name = CString::from_cursor(&mut cursor)?;
526 let n = try_from_bytes(cursor_next_value(&mut cursor, SHORT_LEN as u64)?.as_slice())?;
527 let mut descriptions = Vec::with_capacity(n as usize);
528 for _ in 0..n {
529 let name = CString::from_cursor(&mut cursor)?;
530 let col_type = ColTypeOption::from_cursor(&mut cursor)?;
531 descriptions.push((name, col_type));
532 }
533
534 Ok(CUdt { ks: ks,
535 udt_name: udt_name,
536 descriptions: descriptions, })
537 }
538}
539
540#[derive(Debug, Clone)]
543pub struct CTuple {
544 pub types: Vec<ColTypeOption>,
546}
547
548impl FromCursor for CTuple {
549 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<CTuple> {
550 let n = try_from_bytes(cursor_next_value(&mut cursor, SHORT_LEN as u64)?.as_slice())?;
551 let mut types = Vec::with_capacity(n as usize);
552 for _ in 0..n {
553 let col_type = ColTypeOption::from_cursor(&mut cursor)?;
554 types.push(col_type);
555 }
556
557 Ok(CTuple { types: types })
558 }
559}
560
561#[derive(Debug)]
563pub struct BodyResResultPrepared {
564 pub id: CBytesShort,
566 pub metadata: PreparedMetadata,
568 pub result_metadata: RowsMetadata,
571}
572
573impl FromCursor for BodyResResultPrepared {
574 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<BodyResResultPrepared> {
575 let id = CBytesShort::from_cursor(&mut cursor)?;
576 let metadata = PreparedMetadata::from_cursor(&mut cursor)?;
577 let result_metadata = RowsMetadata::from_cursor(&mut cursor)?;
578
579 Ok(BodyResResultPrepared { id: id,
580 metadata: metadata,
581 result_metadata: result_metadata, })
582 }
583}
584
585#[derive(Debug)]
587pub struct PreparedMetadata {
588 pub flags: i32,
589 pub columns_count: i32,
590 pub pk_count: i32,
591 pub pk_indexes: Vec<i16>,
592 pub global_table_spec: Option<(CString, CString)>,
593 pub col_specs: Vec<ColSpec>,
594}
595
596impl FromCursor for PreparedMetadata {
597 fn from_cursor(mut cursor: &mut Cursor<&[u8]>) -> error::Result<PreparedMetadata> {
598 let flags = CInt::from_cursor(&mut cursor)?;
599 let columns_count = CInt::from_cursor(&mut cursor)?;
600 let pk_count = if cfg!(feature = "v3") {
601 0
602 } else {
603 CInt::from_cursor(&mut cursor)?
605 };
606 let pk_index_results: Vec<Option<i16>> = (0..pk_count).map(|_| {
607 cursor_next_value(&mut cursor, SHORT_LEN as u64)
608 .ok()
609 .and_then(|b| try_i16_from_bytes(b.as_slice()).ok())
610 })
611 .collect();
612
613 let pk_indexes: Vec<i16> = if pk_index_results.iter().any(Option::is_none) {
614 return Err("pk indexes error".into());
615 } else {
616 pk_index_results.iter()
617 .cloned()
618 .map(|r| r.unwrap())
619 .collect()
620 };
621 let mut global_table_space: Option<(CString, CString)> = None;
622 let has_global_table_space = RowsMetadataFlag::has_global_table_space(flags);
623 if has_global_table_space {
624 let keyspace = CString::from_cursor(&mut cursor)?;
625 let tablename = CString::from_cursor(&mut cursor)?;
626 global_table_space = Some((keyspace, tablename))
627 }
628 let col_specs = ColSpec::parse_colspecs(&mut cursor, columns_count, has_global_table_space);
629
630 Ok(PreparedMetadata { flags: flags,
631 columns_count: columns_count,
632 pk_count: pk_count,
633 pk_indexes: pk_indexes,
634 global_table_spec: global_table_space,
635 col_specs: col_specs, })
636 }
637}