1use bytes::{Buf, Bytes};
3
4use crate::{
5 ext::BindParams,
6 postgres::{Oid, PgType},
7 value::ValueRef,
8};
9
10pub trait Encode<'q> {
12 fn encode(self) -> Encoded<'q>;
14}
15
16pub struct Encoded<'q> {
18 value: ValueRef<'q>,
19 is_null: bool,
20 oid: Oid,
21}
22
23impl<'q> Encoded<'q> {
24 pub fn from_slice(slice: &'q [u8], oid: Oid) -> Encoded<'q> {
26 Encoded {
27 value: ValueRef::Slice(slice),
28 is_null: false,
29 oid,
30 }
31 }
32
33 pub fn copy_from_slice(slice: &[u8], oid: Oid) -> Encoded<'static> {
35 Encoded {
36 value: ValueRef::Bytes(Bytes::copy_from_slice(slice)),
37 is_null: false,
38 oid,
39 }
40 }
41
42 pub fn owned(value: impl Into<Bytes>, oid: Oid) -> Encoded<'static> {
44 Encoded {
45 value: ValueRef::Bytes(value.into()),
46 is_null: false,
47 oid,
48 }
49 }
50
51 pub fn null() -> Encoded<'static> {
53 Encoded {
54 value: ValueRef::Slice(&[]),
55 is_null: true,
56 oid: 0,
57 }
58 }
59
60 pub fn oid(&self) -> Oid {
62 match self.is_null {
63 true => 0,
64 false => self.oid,
65 }
66 }
67
68 pub(crate) fn value(&self) -> &ValueRef<'q> {
69 &self.value
70 }
71}
72
73impl Buf for Encoded<'_> {
74 fn remaining(&self) -> usize {
75 self.value.remaining()
76 }
77
78 fn chunk(&self) -> &[u8] {
79 self.value.chunk()
80 }
81
82 fn advance(&mut self, cnt: usize) {
83 self.value.advance(cnt);
84 }
85}
86
87impl BindParams for Encoded<'_> {
88 fn size(&self) -> i32 {
89 match self.is_null {
90 true => -1,
91 false => self.remaining().try_into().unwrap(),
92 }
93 }
94}
95
96macro_rules! encode {
97 (<$lf:tt,$ty:ty>$pat:tt => $body:expr) => {
98 impl<$lf> Encode<$lf> for &$lf $ty {
99 fn encode($pat) -> Encoded<$lf> {
100 Encoded {
101 value: $body,
102 oid: <$ty>::OID,
103 is_null: false,
104 }
105 }
106 }
107 };
108 (<$ty:ty>$pat:tt => $body:expr) => {
109 impl Encode<'static> for $ty {
110 fn encode($pat) -> Encoded<'static> {
111 Encoded {
112 value: $body,
113 oid: <$ty>::OID,
114 is_null: false,
115 }
116 }
117 }
118 };
119}
120
121encode!(<bool>self => ValueRef::inline(&(self as u8).to_be_bytes()));
122encode!(<i32>self => ValueRef::inline(&self.to_be_bytes()));
123encode!(<'a,str>self => ValueRef::Slice(self.as_bytes()));
124encode!(<'a,String>self => ValueRef::Slice(self.as_bytes()));
125
126impl std::fmt::Debug for Encoded<'_> {
127 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
128 f.debug_tuple("Encoded")
129 .field(if self.is_null { &"NULL" } else { &self.value })
130 .field(&self.oid)
131 .finish()
132 }
133}
134