1#![doc = include_str!("../README.md")]
2#![allow(clippy::doc_markdown)]
3
4pub mod auth;
5pub mod cancel;
6pub mod cleanliness;
7pub mod codec;
8pub mod credentials;
9pub mod demux;
10pub mod erased;
11pub mod grammar;
12pub mod integrations;
13pub mod intermediary;
14pub mod pipeline;
15pub mod pre_startup;
16pub mod replication;
17pub mod resources;
18pub mod scram;
19pub mod server_auth;
20pub mod server_session;
21pub mod session;
22pub mod startup;
23pub mod tls;
24pub mod transport;
25
26use std::marker::PhantomData;
27
28#[must_use = "dropping a connection abandons the PostgreSQL session"]
30#[derive(Debug)]
31pub struct Conn<Transport, Phase, Cleanliness = Pristine> {
32 transport: Option<Transport>,
33 _state: PhantomData<(Phase, Cleanliness)>,
34}
35
36impl<Transport, Phase, Cleanliness> Conn<Transport, Phase, Cleanliness> {
37 pub(crate) fn transition<NextPhase, NextCleanliness>(
38 mut self,
39 ) -> Conn<Transport, NextPhase, NextCleanliness> {
40 Conn {
41 transport: self.transport.take(),
42 _state: PhantomData,
43 }
44 }
45
46 pub fn into_transport(mut self) -> Transport {
52 self.transport
53 .take()
54 .expect("live connection has a transport")
55 }
56
57 pub fn map_transport<Next>(
63 mut self,
64 map: impl FnOnce(Transport) -> Next,
65 ) -> Conn<Next, Phase, Cleanliness> {
66 Conn {
67 transport: Some(map(self
68 .transport
69 .take()
70 .expect("live connection has a transport"))),
71 _state: PhantomData,
72 }
73 }
74
75 pub(crate) const fn transport(&self) -> &Transport {
76 match &self.transport {
77 Some(transport) => transport,
78 None => panic!("connection transport has already moved"),
79 }
80 }
81
82 pub(crate) const fn transport_mut(&mut self) -> &mut Transport {
83 match &mut self.transport {
84 Some(transport) => transport,
85 None => panic!("connection transport has already moved"),
86 }
87 }
88}
89
90impl<Transport> Conn<Transport, pre_startup::PreStartup, Pristine> {
91 pub const fn new(transport: Transport) -> Self {
93 Self {
94 transport: Some(transport),
95 _state: PhantomData,
96 }
97 }
98}
99
100#[cfg(debug_assertions)]
101impl<Transport, Phase, Cleanliness> Drop for Conn<Transport, Phase, Cleanliness> {
102 fn drop(&mut self) {
103 assert!(
104 self.transport.is_none() || std::thread::panicking(),
105 "live PostgreSQL connection dropped before a terminal transition; call into_transport() to abort deliberately"
106 );
107 }
108}
109
110#[derive(Debug)]
112pub enum Pristine {}
113
114#[derive(Debug)]
116pub enum Dirty {}