cassandra_protocol/frame/
message_response.rs

1use std::io::Cursor;
2
3use crate::frame::message_auth_challenge::BodyResAuthChallenge;
4use crate::frame::message_auth_success::BodyReqAuthSuccess;
5use crate::frame::message_authenticate::BodyResAuthenticate;
6use crate::frame::message_error::ErrorBody;
7use crate::frame::message_event::BodyResEvent;
8use crate::frame::message_result::{
9    BodyResResultPrepared, BodyResResultRows, BodyResResultSetKeyspace, ResResultBody, RowsMetadata,
10};
11use crate::frame::message_supported::BodyResSupported;
12use crate::frame::{FromCursor, Opcode, Version};
13use crate::types::rows::Row;
14use crate::{error, Error};
15
16#[derive(Debug, PartialEq, Eq, Clone)]
17#[non_exhaustive]
18pub enum ResponseBody {
19    Error(ErrorBody),
20    Ready,
21    Authenticate(BodyResAuthenticate),
22    Supported(BodyResSupported),
23    Result(ResResultBody),
24    Event(BodyResEvent),
25    AuthChallenge(BodyResAuthChallenge),
26    AuthSuccess(BodyReqAuthSuccess),
27}
28
29// This implementation is incomplete so only enable in tests
30#[cfg(test)]
31use crate::frame::Serialize;
32#[cfg(test)]
33impl Serialize for ResponseBody {
34    fn serialize(&self, cursor: &mut Cursor<&mut Vec<u8>>, version: Version) {
35        match self {
36            ResponseBody::Error(error_body) => {
37                error_body.serialize(cursor, version);
38            }
39            ResponseBody::Ready => {}
40            ResponseBody::Authenticate(auth) => {
41                auth.serialize(cursor, version);
42            }
43            ResponseBody::Supported(supported) => {
44                supported.serialize(cursor, version);
45            }
46            ResponseBody::Result(result) => {
47                result.serialize(cursor, version);
48            }
49            ResponseBody::Event(event) => {
50                event.serialize(cursor, version);
51            }
52            ResponseBody::AuthChallenge(auth_challenge) => {
53                auth_challenge.serialize(cursor, version);
54            }
55            ResponseBody::AuthSuccess(auth_success) => {
56                auth_success.serialize(cursor, version);
57            }
58        }
59    }
60}
61
62impl ResponseBody {
63    pub fn try_from(
64        bytes: &[u8],
65        response_type: Opcode,
66        version: Version,
67    ) -> error::Result<ResponseBody> {
68        let mut cursor: Cursor<&[u8]> = Cursor::new(bytes);
69        match response_type {
70            Opcode::Error => ErrorBody::from_cursor(&mut cursor, version).map(ResponseBody::Error),
71            Opcode::Ready => Ok(ResponseBody::Ready),
72            Opcode::Authenticate => BodyResAuthenticate::from_cursor(&mut cursor, version)
73                .map(ResponseBody::Authenticate),
74            Opcode::Supported => {
75                BodyResSupported::from_cursor(&mut cursor, version).map(ResponseBody::Supported)
76            }
77            Opcode::Result => {
78                ResResultBody::from_cursor(&mut cursor, version).map(ResponseBody::Result)
79            }
80            Opcode::Event => {
81                BodyResEvent::from_cursor(&mut cursor, version).map(ResponseBody::Event)
82            }
83            Opcode::AuthChallenge => BodyResAuthChallenge::from_cursor(&mut cursor, version)
84                .map(ResponseBody::AuthChallenge),
85            Opcode::AuthSuccess => {
86                BodyReqAuthSuccess::from_cursor(&mut cursor, version).map(ResponseBody::AuthSuccess)
87            }
88            _ => Err(Error::NonResponseOpcode(response_type)),
89        }
90    }
91
92    pub fn into_rows(self) -> Option<Vec<Row>> {
93        match self {
94            ResponseBody::Result(res) => res.into_rows(),
95            _ => None,
96        }
97    }
98
99    pub fn as_rows_metadata(&self) -> Option<&RowsMetadata> {
100        match self {
101            ResponseBody::Result(res) => res.as_rows_metadata(),
102            _ => None,
103        }
104    }
105
106    pub fn as_cols(&self) -> Option<&BodyResResultRows> {
107        match *self {
108            ResponseBody::Result(ResResultBody::Rows(ref rows)) => Some(rows),
109            _ => None,
110        }
111    }
112
113    /// Unwraps body and returns BodyResResultPrepared which contains an exact result of
114    /// PREPARE query.
115    pub fn into_prepared(self) -> Option<BodyResResultPrepared> {
116        match self {
117            ResponseBody::Result(res) => res.into_prepared(),
118            _ => None,
119        }
120    }
121
122    /// Unwraps body and returns BodyResResultPrepared which contains an exact result of
123    /// use keyspace query.
124    pub fn into_set_keyspace(self) -> Option<BodyResResultSetKeyspace> {
125        match self {
126            ResponseBody::Result(res) => res.into_set_keyspace(),
127            _ => None,
128        }
129    }
130
131    /// Unwraps body and returns BodyResEvent.
132    pub fn into_server_event(self) -> Option<BodyResEvent> {
133        match self {
134            ResponseBody::Event(event) => Some(event),
135            _ => None,
136        }
137    }
138
139    pub fn authenticator(&self) -> Option<&str> {
140        match *self {
141            ResponseBody::Authenticate(ref auth) => Some(auth.data.as_str()),
142            _ => None,
143        }
144    }
145
146    pub fn into_error(self) -> Option<ErrorBody> {
147        match self {
148            ResponseBody::Error(err) => Some(err),
149            _ => None,
150        }
151    }
152}