Skip to main content

postgres_protocol/
lib.rs

1//! Low level Postgres protocol APIs.
2//!
3//! This crate implements the low level components of Postgres's communication
4//! protocol, including message and value serialization and deserialization.
5//! It is designed to be used as a building block by higher level APIs such as
6//! `rust-postgres`, and should not typically be used directly.
7//!
8//! # Note
9//!
10//! This library assumes that the `client_encoding` backend parameter has been
11//! set to `UTF8`. It will most likely not behave properly if that is not the case.
12#![warn(missing_docs, rust_2018_idioms, clippy::all)]
13
14use byteorder::{BigEndian, ByteOrder};
15use bytes::{BufMut, BytesMut};
16use std::io;
17
18pub mod authentication;
19pub mod escape;
20mod hex;
21pub mod message;
22pub mod password;
23pub mod types;
24
25/// A Postgres OID.
26pub type Oid = u32;
27
28/// A Postgres Log Sequence Number (LSN).
29pub type Lsn = u64;
30
31/// An enum indicating if a value is `NULL` or not.
32pub enum IsNull {
33    /// The value is `NULL`.
34    Yes,
35    /// The value is not `NULL`.
36    No,
37}
38
39fn write_nullable<F, E>(serializer: F, buf: &mut BytesMut) -> Result<(), E>
40where
41    F: FnOnce(&mut BytesMut) -> Result<IsNull, E>,
42    E: From<io::Error>,
43{
44    let base = buf.len();
45    buf.put_i32(0);
46    let size = match serializer(buf)? {
47        IsNull::No => i32::from_usize(buf.len() - base - 4)?,
48        IsNull::Yes => -1,
49    };
50    BigEndian::write_i32(&mut buf[base..], size);
51
52    Ok(())
53}
54
55trait FromUsize: Sized {
56    fn from_usize(x: usize) -> Result<Self, io::Error>;
57}
58
59macro_rules! from_usize {
60    ($t:ty) => {
61        impl FromUsize for $t {
62            #[inline]
63            fn from_usize(x: usize) -> io::Result<$t> {
64                if x > <$t>::MAX as usize {
65                    Err(io::Error::new(
66                        io::ErrorKind::InvalidInput,
67                        "value too large to transmit",
68                    ))
69                } else {
70                    Ok(x as $t)
71                }
72            }
73        }
74    };
75}
76
77from_usize!(i16);
78from_usize!(u16);
79from_usize!(i32);