11#![ allow( missing_docs) ]
22
3- use byteorder:: { BigEndian , ReadBytesExt } ;
3+ use byteorder:: { BigEndian , ByteOrder , ReadBytesExt } ;
44use bytes:: { Bytes , BytesMut } ;
55use fallible_iterator:: FallibleIterator ;
66use memchr:: memchr;
@@ -11,6 +11,66 @@ use std::str;
1111
1212use crate :: Oid ;
1313
14+ pub const PARSE_COMPLETE_TAG : u8 = b'1' ;
15+ pub const BIND_COMPLETE_TAG : u8 = b'2' ;
16+ pub const CLOSE_COMPLETE_TAG : u8 = b'3' ;
17+ pub const NOTIFICATION_RESPONSE_TAG : u8 = b'A' ;
18+ pub const COPY_DONE_TAG : u8 = b'c' ;
19+ pub const COMMAND_COMPLETE_TAG : u8 = b'C' ;
20+ pub const COPY_DATA_TAG : u8 = b'd' ;
21+ pub const DATA_ROW_TAG : u8 = b'D' ;
22+ pub const ERROR_RESPONSE_TAG : u8 = b'E' ;
23+ pub const COPY_IN_RESPONSE_TAG : u8 = b'G' ;
24+ pub const COPY_OUT_RESPONSE_TAG : u8 = b'H' ;
25+ pub const EMPTY_QUERY_RESPONSE_TAG : u8 = b'I' ;
26+ pub const BACKEND_KEY_DATA_TAG : u8 = b'K' ;
27+ pub const NO_DATA_TAG : u8 = b'n' ;
28+ pub const NOTICE_RESPONSE_TAG : u8 = b'N' ;
29+ pub const AUTHENTICATION_TAG : u8 = b'R' ;
30+ pub const PORTAL_SUSPENDED_TAG : u8 = b's' ;
31+ pub const PARAMETER_STATUS_TAG : u8 = b'S' ;
32+ pub const PARAMETER_DESCRIPTION_TAG : u8 = b't' ;
33+ pub const ROW_DESCRIPTION_TAG : u8 = b'T' ;
34+ pub const READY_FOR_QUERY_TAG : u8 = b'Z' ;
35+
36+ #[ derive( Debug , Copy , Clone ) ]
37+ pub struct Header {
38+ tag : u8 ,
39+ len : i32 ,
40+ }
41+
42+ #[ allow( clippy:: len_without_is_empty) ]
43+ impl Header {
44+ #[ inline]
45+ pub fn parse ( buf : & [ u8 ] ) -> io:: Result < Option < Header > > {
46+ if buf. len ( ) < 5 {
47+ return Ok ( None ) ;
48+ }
49+
50+ let tag = buf[ 0 ] ;
51+ let len = BigEndian :: read_i32 ( & buf[ 1 ..] ) ;
52+
53+ if len < 4 {
54+ return Err ( io:: Error :: new (
55+ io:: ErrorKind :: InvalidData ,
56+ "invalid message length" ,
57+ ) ) ;
58+ }
59+
60+ Ok ( Some ( Header { tag, len } ) )
61+ }
62+
63+ #[ inline]
64+ pub fn tag ( self ) -> u8 {
65+ self . tag
66+ }
67+
68+ #[ inline]
69+ pub fn len ( self ) -> i32 {
70+ self . len
71+ }
72+ }
73+
1474/// An enum representing Postgres backend messages.
1575pub enum Message {
1676 AuthenticationCleartextPassword ,
@@ -80,10 +140,10 @@ impl Message {
80140 } ;
81141
82142 let message = match tag {
83- b'1' => Message :: ParseComplete ,
84- b'2' => Message :: BindComplete ,
85- b'3' => Message :: CloseComplete ,
86- b'A' => {
143+ PARSE_COMPLETE_TAG => Message :: ParseComplete ,
144+ BIND_COMPLETE_TAG => Message :: BindComplete ,
145+ CLOSE_COMPLETE_TAG => Message :: CloseComplete ,
146+ NOTIFICATION_RESPONSE_TAG => {
87147 let process_id = buf. read_i32 :: < BigEndian > ( ) ?;
88148 let channel = buf. read_cstr ( ) ?;
89149 let message = buf. read_cstr ( ) ?;
@@ -93,25 +153,25 @@ impl Message {
93153 message,
94154 } )
95155 }
96- b'c' => Message :: CopyDone ,
97- b'C' => {
156+ COPY_DONE_TAG => Message :: CopyDone ,
157+ COMMAND_COMPLETE_TAG => {
98158 let tag = buf. read_cstr ( ) ?;
99159 Message :: CommandComplete ( CommandCompleteBody { tag } )
100160 }
101- b'd' => {
161+ COPY_DATA_TAG => {
102162 let storage = buf. read_all ( ) ;
103163 Message :: CopyData ( CopyDataBody { storage } )
104164 }
105- b'D' => {
165+ DATA_ROW_TAG => {
106166 let len = buf. read_u16 :: < BigEndian > ( ) ?;
107167 let storage = buf. read_all ( ) ;
108168 Message :: DataRow ( DataRowBody { storage, len } )
109169 }
110- b'E' => {
170+ ERROR_RESPONSE_TAG => {
111171 let storage = buf. read_all ( ) ;
112172 Message :: ErrorResponse ( ErrorResponseBody { storage } )
113173 }
114- b'G' => {
174+ COPY_IN_RESPONSE_TAG => {
115175 let format = buf. read_u8 ( ) ?;
116176 let len = buf. read_u16 :: < BigEndian > ( ) ?;
117177 let storage = buf. read_all ( ) ;
@@ -121,7 +181,7 @@ impl Message {
121181 storage,
122182 } )
123183 }
124- b'H' => {
184+ COPY_OUT_RESPONSE_TAG => {
125185 let format = buf. read_u8 ( ) ?;
126186 let len = buf. read_u16 :: < BigEndian > ( ) ?;
127187 let storage = buf. read_all ( ) ;
@@ -131,21 +191,21 @@ impl Message {
131191 storage,
132192 } )
133193 }
134- b'I' => Message :: EmptyQueryResponse ,
135- b'K' => {
194+ EMPTY_QUERY_RESPONSE_TAG => Message :: EmptyQueryResponse ,
195+ BACKEND_KEY_DATA_TAG => {
136196 let process_id = buf. read_i32 :: < BigEndian > ( ) ?;
137197 let secret_key = buf. read_i32 :: < BigEndian > ( ) ?;
138198 Message :: BackendKeyData ( BackendKeyDataBody {
139199 process_id,
140200 secret_key,
141201 } )
142202 }
143- b'n' => Message :: NoData ,
144- b'N' => {
203+ NO_DATA_TAG => Message :: NoData ,
204+ NOTICE_RESPONSE_TAG => {
145205 let storage = buf. read_all ( ) ;
146206 Message :: NoticeResponse ( NoticeResponseBody { storage } )
147207 }
148- b'R' => match buf. read_i32 :: < BigEndian > ( ) ? {
208+ AUTHENTICATION_TAG => match buf. read_i32 :: < BigEndian > ( ) ? {
149209 0 => Message :: AuthenticationOk ,
150210 2 => Message :: AuthenticationKerberosV5 ,
151211 3 => Message :: AuthenticationCleartextPassword ,
@@ -180,23 +240,23 @@ impl Message {
180240 ) ) ;
181241 }
182242 } ,
183- b's' => Message :: PortalSuspended ,
184- b'S' => {
243+ PORTAL_SUSPENDED_TAG => Message :: PortalSuspended ,
244+ PARAMETER_STATUS_TAG => {
185245 let name = buf. read_cstr ( ) ?;
186246 let value = buf. read_cstr ( ) ?;
187247 Message :: ParameterStatus ( ParameterStatusBody { name, value } )
188248 }
189- b't' => {
249+ PARAMETER_DESCRIPTION_TAG => {
190250 let len = buf. read_u16 :: < BigEndian > ( ) ?;
191251 let storage = buf. read_all ( ) ;
192252 Message :: ParameterDescription ( ParameterDescriptionBody { storage, len } )
193253 }
194- b'T' => {
254+ ROW_DESCRIPTION_TAG => {
195255 let len = buf. read_u16 :: < BigEndian > ( ) ?;
196256 let storage = buf. read_all ( ) ;
197257 Message :: RowDescription ( RowDescriptionBody { storage, len } )
198258 }
199- b'Z' => {
259+ READY_FOR_QUERY_TAG => {
200260 let status = buf. read_u8 ( ) ?;
201261 Message :: ReadyForQuery ( ReadyForQueryBody { status } )
202262 }
0 commit comments