mod buf_mut;
pub use buf_mut::PgBufMutExt;
use std::fmt;
use std::fmt::{Display, Formatter};
use std::num::{NonZeroU32, Saturating};
pub(crate) use sqlx_core::io::*;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) struct StatementId(IdInner);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) struct PortalId(IdInner);
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct IdInner(Option<NonZeroU32>);
pub(crate) struct DisplayId {
prefix: &'static str,
id: NonZeroU32,
}
impl StatementId {
#[allow(dead_code)]
pub const UNNAMED: Self = Self(IdInner::UNNAMED);
pub const NAMED_START: Self = Self(IdInner::NAMED_START);
#[cfg(test)]
pub const TEST_VAL: Self = Self(IdInner::TEST_VAL);
const NAME_PREFIX: &'static str = "sqlx_s_";
pub fn next(&self) -> Self {
Self(self.0.next())
}
pub fn name_len(&self) -> Saturating<usize> {
self.0.name_len(Self::NAME_PREFIX)
}
#[inline(always)]
pub fn display(&self) -> Option<DisplayId> {
self.0.display(Self::NAME_PREFIX)
}
pub fn put_name_with_nul(&self, buf: &mut Vec<u8>) {
self.0.put_name_with_nul(Self::NAME_PREFIX, buf)
}
}
impl Display for DisplayId {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}{}", self.prefix, self.id)
}
}
#[allow(dead_code)]
impl PortalId {
pub const UNNAMED: Self = PortalId(IdInner::UNNAMED);
pub const NAMED_START: Self = PortalId(IdInner::NAMED_START);
#[cfg(test)]
pub const TEST_VAL: Self = Self(IdInner::TEST_VAL);
const NAME_PREFIX: &'static str = "sqlx_p_";
pub fn next(&self) -> Self {
Self(self.0.next())
}
pub fn name_len(&self) -> Saturating<usize> {
self.0.name_len(Self::NAME_PREFIX)
}
pub fn put_name_with_nul(&self, buf: &mut Vec<u8>) {
self.0.put_name_with_nul(Self::NAME_PREFIX, buf)
}
}
impl IdInner {
const UNNAMED: Self = Self(None);
const NAMED_START: Self = Self(Some(NonZeroU32::MIN));
#[cfg(test)]
pub const TEST_VAL: Self = Self(NonZeroU32::new(1234567890));
#[inline(always)]
fn next(&self) -> Self {
Self(
self.0
.map(|id| id.checked_add(1).unwrap_or(NonZeroU32::MIN)),
)
}
#[inline(always)]
fn display(&self, prefix: &'static str) -> Option<DisplayId> {
self.0.map(|id| DisplayId { prefix, id })
}
#[inline(always)]
fn name_len(&self, name_prefix: &str) -> Saturating<usize> {
let mut len = Saturating(0);
if let Some(id) = self.0 {
len += name_prefix.len();
len += id.get().ilog10() as usize;
len += 1;
}
len += 1;
len
}
#[inline(always)]
fn put_name_with_nul(&self, name_prefix: &str, buf: &mut Vec<u8>) {
if let Some(id) = self.0 {
buf.extend_from_slice(name_prefix.as_bytes());
buf.extend_from_slice(itoa::Buffer::new().format(id.get()).as_bytes());
}
buf.push(0);
}
}
#[test]
fn statement_id_display_matches_encoding() {
const EXPECTED_STR: &str = "sqlx_s_1234567890";
const EXPECTED_BYTES: &[u8] = b"sqlx_s_1234567890\0";
let mut bytes = Vec::new();
StatementId::TEST_VAL.put_name_with_nul(&mut bytes);
assert_eq!(bytes, EXPECTED_BYTES);
let str = StatementId::TEST_VAL.display().unwrap().to_string();
assert_eq!(str, EXPECTED_STR);
}