Skip to main content

postgres_protocol/types/
mod.rs

1//! Conversions to and from Postgres's binary format for various types.
2use byteorder::{BigEndian, ByteOrder, ReadBytesExt};
3use bytes::{BufMut, BytesMut};
4use fallible_iterator::FallibleIterator;
5use std::boxed::Box as StdBox;
6use std::error::Error;
7use std::io::Read;
8use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
9use std::str;
10
11use crate::{FromUsize, IsNull, Lsn, Oid, write_nullable};
12
13#[cfg(test)]
14mod test;
15
16const RANGE_UPPER_UNBOUNDED: u8 = 0b0001_0000;
17const RANGE_LOWER_UNBOUNDED: u8 = 0b0000_1000;
18const RANGE_UPPER_INCLUSIVE: u8 = 0b0000_0100;
19const RANGE_LOWER_INCLUSIVE: u8 = 0b0000_0010;
20const RANGE_EMPTY: u8 = 0b0000_0001;
21
22const PGSQL_AF_INET: u8 = 2;
23const PGSQL_AF_INET6: u8 = 3;
24
25/// Serializes a `BOOL` value.
26#[inline]
27pub fn bool_to_sql(v: bool, buf: &mut BytesMut) {
28    buf.put_u8(v as u8);
29}
30
31/// Deserializes a `BOOL` value.
32#[inline]
33pub fn bool_from_sql(buf: &[u8]) -> Result<bool, StdBox<dyn Error + Sync + Send>> {
34    if buf.len() != 1 {
35        return Err("invalid buffer size".into());
36    }
37
38    Ok(buf[0] != 0)
39}
40
41/// Serializes a `BYTEA` value.
42#[inline]
43pub fn bytea_to_sql(v: &[u8], buf: &mut BytesMut) {
44    buf.put_slice(v);
45}
46
47/// Deserializes a `BYTEA value.
48#[inline]
49pub fn bytea_from_sql(buf: &[u8]) -> &[u8] {
50    buf
51}
52
53/// Serializes a `TEXT`, `VARCHAR`, `CHAR(n)`, `NAME`, or `CITEXT` value.
54#[inline]
55pub fn text_to_sql(v: &str, buf: &mut BytesMut) {
56    buf.put_slice(v.as_bytes());
57}
58
59/// Deserializes a `TEXT`, `VARCHAR`, `CHAR(n)`, `NAME`, or `CITEXT` value.
60#[inline]
61pub fn text_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
62    Ok(str::from_utf8(buf)?)
63}
64
65/// Serializes a `"char"` value.
66#[inline]
67pub fn char_to_sql(v: i8, buf: &mut BytesMut) {
68    buf.put_i8(v);
69}
70
71/// Deserializes a `"char"` value.
72#[inline]
73pub fn char_from_sql(mut buf: &[u8]) -> Result<i8, StdBox<dyn Error + Sync + Send>> {
74    let v = buf.read_i8()?;
75    if !buf.is_empty() {
76        return Err("invalid buffer size".into());
77    }
78    Ok(v)
79}
80
81/// Serializes an `INT2` value.
82#[inline]
83pub fn int2_to_sql(v: i16, buf: &mut BytesMut) {
84    buf.put_i16(v);
85}
86
87/// Deserializes an `INT2` value.
88#[inline]
89pub fn int2_from_sql(mut buf: &[u8]) -> Result<i16, StdBox<dyn Error + Sync + Send>> {
90    let v = buf.read_i16::<BigEndian>()?;
91    if !buf.is_empty() {
92        return Err("invalid buffer size".into());
93    }
94    Ok(v)
95}
96
97/// Serializes an `INT4` value.
98#[inline]
99pub fn int4_to_sql(v: i32, buf: &mut BytesMut) {
100    buf.put_i32(v);
101}
102
103/// Deserializes an `INT4` value.
104#[inline]
105pub fn int4_from_sql(mut buf: &[u8]) -> Result<i32, StdBox<dyn Error + Sync + Send>> {
106    let v = buf.read_i32::<BigEndian>()?;
107    if !buf.is_empty() {
108        return Err("invalid buffer size".into());
109    }
110    Ok(v)
111}
112
113/// Serializes an `OID` value.
114#[inline]
115pub fn oid_to_sql(v: Oid, buf: &mut BytesMut) {
116    buf.put_u32(v);
117}
118
119/// Deserializes an `OID` value.
120#[inline]
121pub fn oid_from_sql(mut buf: &[u8]) -> Result<Oid, StdBox<dyn Error + Sync + Send>> {
122    let v = buf.read_u32::<BigEndian>()?;
123    if !buf.is_empty() {
124        return Err("invalid buffer size".into());
125    }
126    Ok(v)
127}
128
129/// Serializes an `INT8` value.
130#[inline]
131pub fn int8_to_sql(v: i64, buf: &mut BytesMut) {
132    buf.put_i64(v);
133}
134
135/// Deserializes an `INT8` value.
136#[inline]
137pub fn int8_from_sql(mut buf: &[u8]) -> Result<i64, StdBox<dyn Error + Sync + Send>> {
138    let v = buf.read_i64::<BigEndian>()?;
139    if !buf.is_empty() {
140        return Err("invalid buffer size".into());
141    }
142    Ok(v)
143}
144
145/// Serializes a `PG_LSN` value.
146#[inline]
147pub fn lsn_to_sql(v: Lsn, buf: &mut BytesMut) {
148    buf.put_u64(v);
149}
150
151/// Deserializes a `PG_LSN` value.
152#[inline]
153pub fn lsn_from_sql(mut buf: &[u8]) -> Result<Lsn, StdBox<dyn Error + Sync + Send>> {
154    let v = buf.read_u64::<BigEndian>()?;
155    if !buf.is_empty() {
156        return Err("invalid buffer size".into());
157    }
158    Ok(v)
159}
160
161/// Serializes a `FLOAT4` value.
162#[inline]
163pub fn float4_to_sql(v: f32, buf: &mut BytesMut) {
164    buf.put_f32(v);
165}
166
167/// Deserializes a `FLOAT4` value.
168#[inline]
169pub fn float4_from_sql(mut buf: &[u8]) -> Result<f32, StdBox<dyn Error + Sync + Send>> {
170    let v = buf.read_f32::<BigEndian>()?;
171    if !buf.is_empty() {
172        return Err("invalid buffer size".into());
173    }
174    Ok(v)
175}
176
177/// Serializes a `FLOAT8` value.
178#[inline]
179pub fn float8_to_sql(v: f64, buf: &mut BytesMut) {
180    buf.put_f64(v);
181}
182
183/// Deserializes a `FLOAT8` value.
184#[inline]
185pub fn float8_from_sql(mut buf: &[u8]) -> Result<f64, StdBox<dyn Error + Sync + Send>> {
186    let v = buf.read_f64::<BigEndian>()?;
187    if !buf.is_empty() {
188        return Err("invalid buffer size".into());
189    }
190    Ok(v)
191}
192
193/// Serializes an `HSTORE` value.
194#[inline]
195pub fn hstore_to_sql<'a, I>(
196    values: I,
197    buf: &mut BytesMut,
198) -> Result<(), StdBox<dyn Error + Sync + Send>>
199where
200    I: IntoIterator<Item = (&'a str, Option<&'a str>)>,
201{
202    let base = buf.len();
203    buf.put_i32(0);
204
205    let mut count = 0;
206    for (key, value) in values {
207        count += 1;
208
209        write_pascal_string(key, buf)?;
210
211        match value {
212            Some(value) => {
213                write_pascal_string(value, buf)?;
214            }
215            None => buf.put_i32(-1),
216        }
217    }
218
219    let count = i32::from_usize(count)?;
220    BigEndian::write_i32(&mut buf[base..], count);
221
222    Ok(())
223}
224
225fn write_pascal_string(s: &str, buf: &mut BytesMut) -> Result<(), StdBox<dyn Error + Sync + Send>> {
226    let size = i32::from_usize(s.len())?;
227    buf.put_i32(size);
228    buf.put_slice(s.as_bytes());
229    Ok(())
230}
231
232/// Deserializes an `HSTORE` value.
233#[inline]
234pub fn hstore_from_sql(
235    mut buf: &[u8],
236) -> Result<HstoreEntries<'_>, StdBox<dyn Error + Sync + Send>> {
237    let count = buf.read_i32::<BigEndian>()?;
238    if count < 0 {
239        return Err("invalid entry count".into());
240    }
241
242    Ok(HstoreEntries {
243        remaining: count,
244        buf,
245    })
246}
247
248/// A fallible iterator over `HSTORE` entries.
249pub struct HstoreEntries<'a> {
250    remaining: i32,
251    buf: &'a [u8],
252}
253
254impl<'a> FallibleIterator for HstoreEntries<'a> {
255    type Item = (&'a str, Option<&'a str>);
256    type Error = StdBox<dyn Error + Sync + Send>;
257
258    #[inline]
259    #[allow(clippy::type_complexity)]
260    fn next(
261        &mut self,
262    ) -> Result<Option<(&'a str, Option<&'a str>)>, StdBox<dyn Error + Sync + Send>> {
263        if self.remaining == 0 {
264            if !self.buf.is_empty() {
265                return Err("invalid buffer size".into());
266            }
267            return Ok(None);
268        }
269
270        self.remaining -= 1;
271
272        let key_len = self.buf.read_i32::<BigEndian>()?;
273        if key_len < 0 {
274            return Err("invalid key length".into());
275        }
276        let (key, buf) = self
277            .buf
278            .split_at_checked(key_len as usize)
279            .ok_or("invalid key length")?;
280        let key = str::from_utf8(key)?;
281        self.buf = buf;
282
283        let value_len = self.buf.read_i32::<BigEndian>()?;
284        let value = if value_len < 0 {
285            None
286        } else {
287            let (value, buf) = self
288                .buf
289                .split_at_checked(value_len as usize)
290                .ok_or("invalid value length")?;
291            let value = str::from_utf8(value)?;
292            self.buf = buf;
293            Some(value)
294        };
295
296        Ok(Some((key, value)))
297    }
298
299    #[inline]
300    fn size_hint(&self) -> (usize, Option<usize>) {
301        let len = self.remaining as usize;
302        (len, Some(len))
303    }
304}
305
306/// Serializes a `VARBIT` or `BIT` value.
307#[inline]
308pub fn varbit_to_sql<I>(
309    len: usize,
310    v: I,
311    buf: &mut BytesMut,
312) -> Result<(), StdBox<dyn Error + Sync + Send>>
313where
314    I: Iterator<Item = u8>,
315{
316    let len = i32::from_usize(len)?;
317    buf.put_i32(len);
318
319    for byte in v {
320        buf.put_u8(byte);
321    }
322
323    Ok(())
324}
325
326/// Deserializes a `VARBIT` or `BIT` value.
327#[inline]
328pub fn varbit_from_sql(mut buf: &[u8]) -> Result<Varbit<'_>, StdBox<dyn Error + Sync + Send>> {
329    let len = buf.read_i32::<BigEndian>()?;
330    if len < 0 {
331        return Err("invalid varbit length: varbit < 0".into());
332    }
333    let bytes = (len as usize).div_ceil(8);
334    if buf.len() != bytes {
335        return Err("invalid message length: varbit mismatch".into());
336    }
337
338    Ok(Varbit {
339        len: len as usize,
340        bytes: buf,
341    })
342}
343
344/// A `VARBIT` value.
345pub struct Varbit<'a> {
346    len: usize,
347    bytes: &'a [u8],
348}
349
350impl<'a> Varbit<'a> {
351    /// Returns the number of bits.
352    #[inline]
353    pub fn len(&self) -> usize {
354        self.len
355    }
356
357    /// Determines if the value has no bits.
358    #[inline]
359    pub fn is_empty(&self) -> bool {
360        self.len == 0
361    }
362
363    /// Returns the bits as a slice of bytes.
364    #[inline]
365    pub fn bytes(&self) -> &'a [u8] {
366        self.bytes
367    }
368}
369
370/// Serializes a `TIMESTAMP` or `TIMESTAMPTZ` value.
371///
372/// The value should represent the number of microseconds since midnight, January 1st, 2000.
373#[inline]
374pub fn timestamp_to_sql(v: i64, buf: &mut BytesMut) {
375    buf.put_i64(v);
376}
377
378/// Deserializes a `TIMESTAMP` or `TIMESTAMPTZ` value.
379///
380/// The value represents the number of microseconds since midnight, January 1st, 2000.
381#[inline]
382pub fn timestamp_from_sql(mut buf: &[u8]) -> Result<i64, StdBox<dyn Error + Sync + Send>> {
383    let v = buf.read_i64::<BigEndian>()?;
384    if !buf.is_empty() {
385        return Err("invalid message length: timestamp not drained".into());
386    }
387    Ok(v)
388}
389
390/// Serializes a `DATE` value.
391///
392/// The value should represent the number of days since January 1st, 2000.
393#[inline]
394pub fn date_to_sql(v: i32, buf: &mut BytesMut) {
395    buf.put_i32(v);
396}
397
398/// Deserializes a `DATE` value.
399///
400/// The value represents the number of days since January 1st, 2000.
401#[inline]
402pub fn date_from_sql(mut buf: &[u8]) -> Result<i32, StdBox<dyn Error + Sync + Send>> {
403    let v = buf.read_i32::<BigEndian>()?;
404    if !buf.is_empty() {
405        return Err("invalid message length: date not drained".into());
406    }
407    Ok(v)
408}
409
410/// Serializes a `TIME` or `TIMETZ` value.
411///
412/// The value should represent the number of microseconds since midnight.
413#[inline]
414pub fn time_to_sql(v: i64, buf: &mut BytesMut) {
415    buf.put_i64(v);
416}
417
418/// Deserializes a `TIME` or `TIMETZ` value.
419///
420/// The value represents the number of microseconds since midnight.
421#[inline]
422pub fn time_from_sql(mut buf: &[u8]) -> Result<i64, StdBox<dyn Error + Sync + Send>> {
423    let v = buf.read_i64::<BigEndian>()?;
424    if !buf.is_empty() {
425        return Err("invalid message length: time not drained".into());
426    }
427    Ok(v)
428}
429
430/// Serializes a `MACADDR` value.
431#[inline]
432pub fn macaddr_to_sql(v: [u8; 6], buf: &mut BytesMut) {
433    buf.put_slice(&v);
434}
435
436/// Deserializes a `MACADDR` value.
437#[inline]
438pub fn macaddr_from_sql(buf: &[u8]) -> Result<[u8; 6], StdBox<dyn Error + Sync + Send>> {
439    if buf.len() != 6 {
440        return Err("invalid message length: macaddr length mismatch".into());
441    }
442    let mut out = [0; 6];
443    out.copy_from_slice(buf);
444    Ok(out)
445}
446
447/// Serializes a `UUID` value.
448#[inline]
449pub fn uuid_to_sql(v: [u8; 16], buf: &mut BytesMut) {
450    buf.put_slice(&v);
451}
452
453/// Deserializes a `UUID` value.
454#[inline]
455pub fn uuid_from_sql(buf: &[u8]) -> Result<[u8; 16], StdBox<dyn Error + Sync + Send>> {
456    if buf.len() != 16 {
457        return Err("invalid message length: uuid size mismatch".into());
458    }
459    let mut out = [0; 16];
460    out.copy_from_slice(buf);
461    Ok(out)
462}
463
464/// Serializes an array value.
465#[inline]
466pub fn array_to_sql<T, I, J, F>(
467    dimensions: I,
468    element_type: Oid,
469    elements: J,
470    mut serializer: F,
471    buf: &mut BytesMut,
472) -> Result<(), StdBox<dyn Error + Sync + Send>>
473where
474    I: IntoIterator<Item = ArrayDimension>,
475    J: IntoIterator<Item = T>,
476    F: FnMut(T, &mut BytesMut) -> Result<IsNull, StdBox<dyn Error + Sync + Send>>,
477{
478    let dimensions_idx = buf.len();
479    buf.put_i32(0);
480    let flags_idx = buf.len();
481    buf.put_i32(0);
482    buf.put_u32(element_type);
483
484    let mut num_dimensions = 0;
485    for dimension in dimensions {
486        num_dimensions += 1;
487        buf.put_i32(dimension.len);
488        buf.put_i32(dimension.lower_bound);
489    }
490
491    let num_dimensions = i32::from_usize(num_dimensions)?;
492    BigEndian::write_i32(&mut buf[dimensions_idx..], num_dimensions);
493
494    let mut has_nulls = false;
495    for element in elements {
496        write_nullable(
497            |buf| {
498                let r = serializer(element, buf);
499                if let Ok(IsNull::Yes) = r {
500                    has_nulls = true;
501                }
502                r
503            },
504            buf,
505        )?;
506    }
507
508    BigEndian::write_i32(&mut buf[flags_idx..], has_nulls as i32);
509
510    Ok(())
511}
512
513/// Deserializes an array value.
514#[inline]
515pub fn array_from_sql(mut buf: &[u8]) -> Result<Array<'_>, StdBox<dyn Error + Sync + Send>> {
516    let dimensions = buf.read_i32::<BigEndian>()?;
517    if dimensions < 0 {
518        return Err("invalid dimension count".into());
519    }
520    let has_nulls = buf.read_i32::<BigEndian>()? != 0;
521    let element_type = buf.read_u32::<BigEndian>()?;
522
523    let mut r = buf;
524    let mut elements = 1i32;
525    for _ in 0..dimensions {
526        let len = r.read_i32::<BigEndian>()?;
527        if len < 0 {
528            return Err("invalid dimension size".into());
529        }
530        let _lower_bound = r.read_i32::<BigEndian>()?;
531        elements = match elements.checked_mul(len) {
532            Some(elements) => elements,
533            None => return Err("too many array elements".into()),
534        };
535    }
536
537    if dimensions == 0 {
538        elements = 0;
539    }
540
541    Ok(Array {
542        dimensions,
543        has_nulls,
544        element_type,
545        elements,
546        buf,
547    })
548}
549
550/// A Postgres array.
551pub struct Array<'a> {
552    dimensions: i32,
553    has_nulls: bool,
554    element_type: Oid,
555    elements: i32,
556    buf: &'a [u8],
557}
558
559impl<'a> Array<'a> {
560    /// Returns true if there are `NULL` elements.
561    #[inline]
562    pub fn has_nulls(&self) -> bool {
563        self.has_nulls
564    }
565
566    /// Returns the OID of the elements of the array.
567    #[inline]
568    pub fn element_type(&self) -> Oid {
569        self.element_type
570    }
571
572    /// Returns an iterator over the dimensions of the array.
573    #[inline]
574    pub fn dimensions(&self) -> ArrayDimensions<'a> {
575        ArrayDimensions(&self.buf[..self.dimensions as usize * 8])
576    }
577
578    /// Returns an iterator over the values of the array.
579    #[inline]
580    pub fn values(&self) -> ArrayValues<'a> {
581        ArrayValues {
582            remaining: self.elements,
583            buf: &self.buf[self.dimensions as usize * 8..],
584        }
585    }
586}
587
588/// An iterator over the dimensions of an array.
589pub struct ArrayDimensions<'a>(&'a [u8]);
590
591impl FallibleIterator for ArrayDimensions<'_> {
592    type Item = ArrayDimension;
593    type Error = StdBox<dyn Error + Sync + Send>;
594
595    #[inline]
596    fn next(&mut self) -> Result<Option<ArrayDimension>, StdBox<dyn Error + Sync + Send>> {
597        if self.0.is_empty() {
598            return Ok(None);
599        }
600
601        let len = self.0.read_i32::<BigEndian>()?;
602        let lower_bound = self.0.read_i32::<BigEndian>()?;
603
604        Ok(Some(ArrayDimension { len, lower_bound }))
605    }
606
607    #[inline]
608    fn size_hint(&self) -> (usize, Option<usize>) {
609        let len = self.0.len() / 8;
610        (len, Some(len))
611    }
612}
613
614/// Information about a dimension of an array.
615#[derive(Debug, Copy, Clone, PartialEq, Eq)]
616pub struct ArrayDimension {
617    /// The length of this dimension.
618    pub len: i32,
619
620    /// The base value used to index into this dimension.
621    pub lower_bound: i32,
622}
623
624/// An iterator over the values of an array, in row-major order.
625pub struct ArrayValues<'a> {
626    remaining: i32,
627    buf: &'a [u8],
628}
629
630impl<'a> FallibleIterator for ArrayValues<'a> {
631    type Item = Option<&'a [u8]>;
632    type Error = StdBox<dyn Error + Sync + Send>;
633
634    #[inline]
635    fn next(&mut self) -> Result<Option<Option<&'a [u8]>>, StdBox<dyn Error + Sync + Send>> {
636        if self.remaining == 0 {
637            if !self.buf.is_empty() {
638                return Err("invalid message length: arrayvalue not drained".into());
639            }
640            return Ok(None);
641        }
642        self.remaining -= 1;
643
644        let len = self.buf.read_i32::<BigEndian>()?;
645        let val = if len < 0 {
646            None
647        } else {
648            let (val, buf) = self
649                .buf
650                .split_at_checked(len as usize)
651                .ok_or("invalid value length")?;
652            self.buf = buf;
653            Some(val)
654        };
655
656        Ok(Some(val))
657    }
658
659    fn size_hint(&self) -> (usize, Option<usize>) {
660        let len = self.remaining as usize;
661        (len, Some(len))
662    }
663}
664
665/// Serializes an empty range.
666#[inline]
667pub fn empty_range_to_sql(buf: &mut BytesMut) {
668    buf.put_u8(RANGE_EMPTY);
669}
670
671/// Serializes a range value.
672pub fn range_to_sql<F, G>(
673    lower: F,
674    upper: G,
675    buf: &mut BytesMut,
676) -> Result<(), StdBox<dyn Error + Sync + Send>>
677where
678    F: FnOnce(&mut BytesMut) -> Result<RangeBound<IsNull>, StdBox<dyn Error + Sync + Send>>,
679    G: FnOnce(&mut BytesMut) -> Result<RangeBound<IsNull>, StdBox<dyn Error + Sync + Send>>,
680{
681    let tag_idx = buf.len();
682    buf.put_u8(0);
683    let mut tag = 0;
684
685    match write_bound(lower, buf)? {
686        RangeBound::Inclusive(()) => tag |= RANGE_LOWER_INCLUSIVE,
687        RangeBound::Exclusive(()) => {}
688        RangeBound::Unbounded => tag |= RANGE_LOWER_UNBOUNDED,
689    }
690
691    match write_bound(upper, buf)? {
692        RangeBound::Inclusive(()) => tag |= RANGE_UPPER_INCLUSIVE,
693        RangeBound::Exclusive(()) => {}
694        RangeBound::Unbounded => tag |= RANGE_UPPER_UNBOUNDED,
695    }
696
697    buf[tag_idx] = tag;
698
699    Ok(())
700}
701
702fn write_bound<F>(
703    bound: F,
704    buf: &mut BytesMut,
705) -> Result<RangeBound<()>, StdBox<dyn Error + Sync + Send>>
706where
707    F: FnOnce(&mut BytesMut) -> Result<RangeBound<IsNull>, StdBox<dyn Error + Sync + Send>>,
708{
709    let base = buf.len();
710    buf.put_i32(0);
711
712    let (null, ret) = match bound(buf)? {
713        RangeBound::Inclusive(null) => (Some(null), RangeBound::Inclusive(())),
714        RangeBound::Exclusive(null) => (Some(null), RangeBound::Exclusive(())),
715        RangeBound::Unbounded => (None, RangeBound::Unbounded),
716    };
717
718    match null {
719        Some(null) => {
720            let len = match null {
721                IsNull::No => i32::from_usize(buf.len() - base - 4)?,
722                IsNull::Yes => -1,
723            };
724            BigEndian::write_i32(&mut buf[base..], len);
725        }
726        None => buf.truncate(base),
727    }
728
729    Ok(ret)
730}
731
732/// One side of a range.
733pub enum RangeBound<T> {
734    /// An inclusive bound.
735    Inclusive(T),
736    /// An exclusive bound.
737    Exclusive(T),
738    /// No bound.
739    Unbounded,
740}
741
742/// Deserializes a range value.
743#[inline]
744pub fn range_from_sql(mut buf: &[u8]) -> Result<Range<'_>, StdBox<dyn Error + Sync + Send>> {
745    let tag = buf.read_u8()?;
746
747    if tag == RANGE_EMPTY {
748        if !buf.is_empty() {
749            return Err("invalid message size".into());
750        }
751        return Ok(Range::Empty);
752    }
753
754    let lower = read_bound(&mut buf, tag, RANGE_LOWER_UNBOUNDED, RANGE_LOWER_INCLUSIVE)?;
755    let upper = read_bound(&mut buf, tag, RANGE_UPPER_UNBOUNDED, RANGE_UPPER_INCLUSIVE)?;
756
757    if !buf.is_empty() {
758        return Err("invalid message size".into());
759    }
760
761    Ok(Range::Nonempty(lower, upper))
762}
763
764#[inline]
765fn read_bound<'a>(
766    buf: &mut &'a [u8],
767    tag: u8,
768    unbounded: u8,
769    inclusive: u8,
770) -> Result<RangeBound<Option<&'a [u8]>>, StdBox<dyn Error + Sync + Send>> {
771    if tag & unbounded != 0 {
772        Ok(RangeBound::Unbounded)
773    } else {
774        let len = buf.read_i32::<BigEndian>()?;
775        let value = if len < 0 {
776            None
777        } else {
778            let len = len as usize;
779            let (value, tail) = buf.split_at_checked(len).ok_or("invalid message size")?;
780            *buf = tail;
781            Some(value)
782        };
783
784        if tag & inclusive != 0 {
785            Ok(RangeBound::Inclusive(value))
786        } else {
787            Ok(RangeBound::Exclusive(value))
788        }
789    }
790}
791
792/// A Postgres range.
793pub enum Range<'a> {
794    /// An empty range.
795    Empty,
796    /// A nonempty range.
797    Nonempty(RangeBound<Option<&'a [u8]>>, RangeBound<Option<&'a [u8]>>),
798}
799
800/// Serializes a point value.
801#[inline]
802pub fn point_to_sql(x: f64, y: f64, buf: &mut BytesMut) {
803    buf.put_f64(x);
804    buf.put_f64(y);
805}
806
807/// Deserializes a point value.
808#[inline]
809pub fn point_from_sql(mut buf: &[u8]) -> Result<Point, StdBox<dyn Error + Sync + Send>> {
810    let x = buf.read_f64::<BigEndian>()?;
811    let y = buf.read_f64::<BigEndian>()?;
812    if !buf.is_empty() {
813        return Err("invalid buffer size".into());
814    }
815    Ok(Point { x, y })
816}
817
818/// A Postgres point.
819#[derive(Copy, Clone)]
820pub struct Point {
821    x: f64,
822    y: f64,
823}
824
825impl Point {
826    /// Returns the x coordinate of the point.
827    #[inline]
828    pub fn x(&self) -> f64 {
829        self.x
830    }
831
832    /// Returns the y coordinate of the point.
833    #[inline]
834    pub fn y(&self) -> f64 {
835        self.y
836    }
837}
838
839/// Serializes a box value.
840#[inline]
841pub fn box_to_sql(x1: f64, y1: f64, x2: f64, y2: f64, buf: &mut BytesMut) {
842    buf.put_f64(x1);
843    buf.put_f64(y1);
844    buf.put_f64(x2);
845    buf.put_f64(y2);
846}
847
848/// Deserializes a box value.
849#[inline]
850pub fn box_from_sql(mut buf: &[u8]) -> Result<Box, StdBox<dyn Error + Sync + Send>> {
851    let x1 = buf.read_f64::<BigEndian>()?;
852    let y1 = buf.read_f64::<BigEndian>()?;
853    let x2 = buf.read_f64::<BigEndian>()?;
854    let y2 = buf.read_f64::<BigEndian>()?;
855    if !buf.is_empty() {
856        return Err("invalid buffer size".into());
857    }
858    Ok(Box {
859        upper_right: Point { x: x1, y: y1 },
860        lower_left: Point { x: x2, y: y2 },
861    })
862}
863
864/// A Postgres box.
865#[derive(Copy, Clone)]
866pub struct Box {
867    upper_right: Point,
868    lower_left: Point,
869}
870
871impl Box {
872    /// Returns the upper right corner of the box.
873    #[inline]
874    pub fn upper_right(&self) -> Point {
875        self.upper_right
876    }
877
878    /// Returns the lower left corner of the box.
879    #[inline]
880    pub fn lower_left(&self) -> Point {
881        self.lower_left
882    }
883}
884
885/// Serializes a Postgres path.
886#[inline]
887pub fn path_to_sql<I>(
888    closed: bool,
889    points: I,
890    buf: &mut BytesMut,
891) -> Result<(), StdBox<dyn Error + Sync + Send>>
892where
893    I: IntoIterator<Item = (f64, f64)>,
894{
895    buf.put_u8(closed as u8);
896    let points_idx = buf.len();
897    buf.put_i32(0);
898
899    let mut num_points = 0;
900    for (x, y) in points {
901        num_points += 1;
902        buf.put_f64(x);
903        buf.put_f64(y);
904    }
905
906    let num_points = i32::from_usize(num_points)?;
907    BigEndian::write_i32(&mut buf[points_idx..], num_points);
908
909    Ok(())
910}
911
912/// Deserializes a Postgres path.
913#[inline]
914pub fn path_from_sql(mut buf: &[u8]) -> Result<Path<'_>, StdBox<dyn Error + Sync + Send>> {
915    let closed = buf.read_u8()? != 0;
916    let points = buf.read_i32::<BigEndian>()?;
917
918    Ok(Path {
919        closed,
920        points,
921        buf,
922    })
923}
924
925/// A Postgres point.
926pub struct Path<'a> {
927    closed: bool,
928    points: i32,
929    buf: &'a [u8],
930}
931
932impl<'a> Path<'a> {
933    /// Determines if the path is closed or open.
934    #[inline]
935    pub fn closed(&self) -> bool {
936        self.closed
937    }
938
939    /// Returns an iterator over the points in the path.
940    #[inline]
941    pub fn points(&self) -> PathPoints<'a> {
942        PathPoints {
943            remaining: self.points,
944            buf: self.buf,
945        }
946    }
947}
948
949/// An iterator over the points of a Postgres path.
950pub struct PathPoints<'a> {
951    remaining: i32,
952    buf: &'a [u8],
953}
954
955impl FallibleIterator for PathPoints<'_> {
956    type Item = Point;
957    type Error = StdBox<dyn Error + Sync + Send>;
958
959    #[inline]
960    fn next(&mut self) -> Result<Option<Point>, StdBox<dyn Error + Sync + Send>> {
961        if self.remaining == 0 {
962            if !self.buf.is_empty() {
963                return Err("invalid message length: path points not drained".into());
964            }
965            return Ok(None);
966        }
967        self.remaining -= 1;
968
969        let x = self.buf.read_f64::<BigEndian>()?;
970        let y = self.buf.read_f64::<BigEndian>()?;
971
972        Ok(Some(Point { x, y }))
973    }
974
975    #[inline]
976    fn size_hint(&self) -> (usize, Option<usize>) {
977        let len = self.remaining as usize;
978        (len, Some(len))
979    }
980}
981
982/// Serializes a Postgres inet.
983#[inline]
984pub fn inet_to_sql(addr: IpAddr, netmask: u8, buf: &mut BytesMut) {
985    let family = match addr {
986        IpAddr::V4(_) => PGSQL_AF_INET,
987        IpAddr::V6(_) => PGSQL_AF_INET6,
988    };
989    buf.put_u8(family);
990    buf.put_u8(netmask);
991    buf.put_u8(0); // is_cidr
992    match addr {
993        IpAddr::V4(addr) => {
994            buf.put_u8(4);
995            buf.put_slice(&addr.octets());
996        }
997        IpAddr::V6(addr) => {
998            buf.put_u8(16);
999            buf.put_slice(&addr.octets());
1000        }
1001    }
1002}
1003
1004/// Deserializes a Postgres inet.
1005#[inline]
1006pub fn inet_from_sql(mut buf: &[u8]) -> Result<Inet, StdBox<dyn Error + Sync + Send>> {
1007    let family = buf.read_u8()?;
1008    let netmask = buf.read_u8()?;
1009    buf.read_u8()?; // is_cidr
1010    let len = buf.read_u8()?;
1011
1012    let addr = match family {
1013        PGSQL_AF_INET => {
1014            if netmask > 32 {
1015                return Err("invalid IPv4 netmask".into());
1016            }
1017            if len != 4 {
1018                return Err("invalid IPv4 address length".into());
1019            }
1020            let mut addr = [0; 4];
1021            buf.read_exact(&mut addr)?;
1022            IpAddr::V4(Ipv4Addr::from(addr))
1023        }
1024        PGSQL_AF_INET6 => {
1025            if netmask > 128 {
1026                return Err("invalid IPv6 netmask".into());
1027            }
1028            if len != 16 {
1029                return Err("invalid IPv6 address length".into());
1030            }
1031            let mut addr = [0; 16];
1032            buf.read_exact(&mut addr)?;
1033            IpAddr::V6(Ipv6Addr::from(addr))
1034        }
1035        _ => return Err("invalid IP family".into()),
1036    };
1037
1038    if !buf.is_empty() {
1039        return Err("invalid buffer size".into());
1040    }
1041
1042    Ok(Inet { addr, netmask })
1043}
1044
1045/// A Postgres network address.
1046pub struct Inet {
1047    addr: IpAddr,
1048    netmask: u8,
1049}
1050
1051impl Inet {
1052    /// Returns the IP address.
1053    #[inline]
1054    pub fn addr(&self) -> IpAddr {
1055        self.addr
1056    }
1057
1058    /// Returns the netmask.
1059    #[inline]
1060    pub fn netmask(&self) -> u8 {
1061        self.netmask
1062    }
1063}
1064
1065/// Serializes a Postgres ltree string
1066#[inline]
1067pub fn ltree_to_sql(v: &str, buf: &mut BytesMut) {
1068    // A version number is prepended to an ltree string per spec
1069    buf.put_u8(1);
1070    // Append the rest of the query
1071    buf.put_slice(v.as_bytes());
1072}
1073
1074/// Deserialize a Postgres ltree string
1075#[inline]
1076pub fn ltree_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1077    match buf {
1078        // Remove the version number from the front of the ltree per spec
1079        [1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1080        _ => Err("ltree version 1 only supported".into()),
1081    }
1082}
1083
1084/// Serializes a Postgres lquery string
1085#[inline]
1086pub fn lquery_to_sql(v: &str, buf: &mut BytesMut) {
1087    // A version number is prepended to an lquery string per spec
1088    buf.put_u8(1);
1089    // Append the rest of the query
1090    buf.put_slice(v.as_bytes());
1091}
1092
1093/// Deserialize a Postgres lquery string
1094#[inline]
1095pub fn lquery_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1096    match buf {
1097        // Remove the version number from the front of the lquery per spec
1098        [1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1099        _ => Err("lquery version 1 only supported".into()),
1100    }
1101}
1102
1103/// Serializes a Postgres ltxtquery string
1104#[inline]
1105pub fn ltxtquery_to_sql(v: &str, buf: &mut BytesMut) {
1106    // A version number is prepended to an ltxtquery string per spec
1107    buf.put_u8(1);
1108    // Append the rest of the query
1109    buf.put_slice(v.as_bytes());
1110}
1111
1112/// Deserialize a Postgres ltxtquery string
1113#[inline]
1114pub fn ltxtquery_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1115    match buf {
1116        // Remove the version number from the front of the ltxtquery per spec
1117        [1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1118        _ => Err("ltxtquery version 1 only supported".into()),
1119    }
1120}