1#![doc = include_str!("../README.md")]
2#![allow(
3 clippy::doc_markdown,
4 clippy::enum_variant_names,
5 clippy::redundant_pub_crate
6)]
7#![deny(private_bounds, private_interfaces, unreachable_pub)]
8
9#[allow(dead_code)]
10mod auth;
11#[allow(dead_code)]
12mod cancel;
13#[allow(dead_code)]
14mod cleanliness;
15mod client_component;
16#[allow(dead_code)]
17mod codec;
18#[allow(dead_code)]
19mod credentials;
20#[allow(dead_code)]
21mod demux;
22#[allow(dead_code)]
23mod erased;
24#[allow(dead_code)]
25mod grammar;
26#[allow(dead_code)]
27mod integrations;
28#[allow(dead_code)]
29mod intermediary;
30mod intermediary_component;
31#[allow(dead_code)]
32mod middleware;
33#[allow(dead_code)]
34mod net;
35#[allow(dead_code)]
36mod pipeline;
37#[allow(dead_code)]
38mod pre_startup;
39#[allow(dead_code)]
40mod replication;
41#[allow(dead_code)]
42mod resources;
43mod runtime_middleware;
44#[allow(dead_code)]
45mod scram;
46#[allow(dead_code)]
47mod server_auth;
48mod server_component;
49#[allow(dead_code)]
50mod server_session;
51#[allow(dead_code)]
52mod session;
53#[allow(dead_code)]
54mod startup;
55#[allow(dead_code)]
56mod tls;
57#[allow(dead_code)]
58mod transport;
59
60pub use client_component::{
61 BuildError, CancelError, Client, ClientAuthentication, ClientAuthenticationChallenge,
62 ClientAuthenticationError, ClientAuthenticationFuture, ClientAuthenticationResponse,
63 ClientAuthenticationSession, ClientBuilder, ClientConnection, ClientConnectionContext,
64 ClientInitialContext, ClientTlsConfig, ClientTlsConfiguration, ClientTlsError, ClientTlsPolicy,
65 ClientTlsProvider, ClientTlsStatus, ClientTransport, ConnectError, ConnectTarget,
66 ConnectionChanged, ConnectionClean, IdentityHandler, ProtocolLimitError, ProtocolLimits,
67 QueryError, ReloadableClientTls, StartupParameterError, StartupParameters,
68 TrustClientAuthentication,
69};
70pub use codec::{
71 Authentication, BackendMessage, Bind, Close, CopyResponse, DataRow, Describe, DescribeTarget,
72 DiagnosticField, DiagnosticResponse, Execute, FieldDescription, FrontendMessage, FunctionCall,
73 NegotiateProtocolVersion, Parse, RowDescription, TransactionStatus,
74};
75pub use demux::CancelKey;
76pub use intermediary_component::{
77 AllowAuthenticatedRoute, AuthenticatedRouteContext, AuthenticatedRoutePolicy,
78 CancellationPolicy, CancellationRoute, EstablishmentFailurePolicy, ForwardError,
79 ForwardedMessage, IdentityIntermediaryMiddleware, InitialServerContext, Intermediary,
80 IntermediaryAccept, IntermediaryAcceptError, IntermediaryBuildError, IntermediaryBuilder,
81 IntermediaryCancellationRegistry, IntermediaryConnection, IntermediaryContexts,
82 IntermediaryMiddleware, IntermediaryMiddlewareFactory, RejectCancellation,
83 StartupResolutionError, StartupRouteResolver,
84};
85pub use pipeline::{
86 BackendProjectionError, BoundedPipeline, FrontendProjectionError, NoPipeline,
87 PipelineConfigError, PipelinePolicy,
88};
89pub use pre_startup::{CertificateVerification, PreStartupMessage, SslMode, SslStrategy};
90pub use runtime_middleware::{
91 ClientMiddleware, IdentityMiddleware, MiddlewareChain, MiddlewareFactory, ServerMiddleware,
92};
93pub use server_component::{
94 AcceptError, AcceptedServerTransport, BuildServerError, CancellationRequest, DisabledServerTls,
95 IdentityServerHandler, NegotiatedServerTls, NoServerIdentity, NoServerIdentityProvider,
96 OptionalServerTls, RequiredServerTls, Server, ServerAccept, ServerAcceptFuture,
97 ServerAuthentication, ServerAuthenticationAction, ServerAuthenticationFuture,
98 ServerAuthenticationProvider, ServerAuthenticationRequest, ServerAuthenticationResponse,
99 ServerBuilder, ServerCancellation, ServerConnection, ServerConnectionContext, ServerIdentity,
100 ServerIdentityProvider, ServerProtocolLimits, ServerTlsConfiguration, ServerTlsPolicy,
101 TrustIdentity, TrustServerAuthentication,
102};
103pub use startup::{ProtocolVersion, StartupMessage};
104
105#[cfg(test)]
106extern crate self as pg_proto;
107
108#[cfg(test)]
109mod internal_tests;
110
111use std::marker::PhantomData;
112
113#[must_use = "dropping a connection abandons the PostgreSQL session"]
115#[derive(Debug)]
116pub(crate) struct Conn<Transport, Phase, Cleanliness = Pristine> {
117 transport: Option<Transport>,
118 _state: PhantomData<(Phase, Cleanliness)>,
119}
120
121impl<Transport, Phase, Cleanliness> Conn<Transport, Phase, Cleanliness> {
122 pub(crate) fn transition<NextPhase, NextCleanliness>(
123 mut self,
124 ) -> Conn<Transport, NextPhase, NextCleanliness> {
125 Conn {
126 transport: self.transport.take(),
127 _state: PhantomData,
128 }
129 }
130
131 pub(crate) fn into_transport(mut self) -> Transport {
137 self.transport
138 .take()
139 .expect("live connection has a transport")
140 }
141
142 pub(crate) fn map_transport<Next>(
148 mut self,
149 map: impl FnOnce(Transport) -> Next,
150 ) -> Conn<Next, Phase, Cleanliness> {
151 Conn {
152 transport: Some(map(self
153 .transport
154 .take()
155 .expect("live connection has a transport"))),
156 _state: PhantomData,
157 }
158 }
159
160 pub(crate) const fn transport(&self) -> &Transport {
161 match &self.transport {
162 Some(transport) => transport,
163 None => panic!("connection transport has already moved"),
164 }
165 }
166
167 pub(crate) const fn transport_mut(&mut self) -> &mut Transport {
168 match &mut self.transport {
169 Some(transport) => transport,
170 None => panic!("connection transport has already moved"),
171 }
172 }
173}
174
175impl<Transport> Conn<Transport, pre_startup::PreStartup, Pristine> {
176 pub(crate) const fn new(transport: Transport) -> Self {
178 Self {
179 transport: Some(transport),
180 _state: PhantomData,
181 }
182 }
183}
184
185#[cfg(debug_assertions)]
186impl<Transport, Phase, Cleanliness> Drop for Conn<Transport, Phase, Cleanliness> {
187 fn drop(&mut self) {
188 assert!(
189 self.transport.is_none() || std::thread::panicking(),
190 "live PostgreSQL connection dropped before a terminal transition; call into_transport() to abort deliberately"
191 );
192 }
193}
194
195#[derive(Debug)]
197pub(crate) enum Pristine {}
198
199#[derive(Debug)]
201pub(crate) enum Dirty {}