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::{write_nullable, FromUsize, IsNull, Lsn, Oid};
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.buf.split_at(key_len as usize);
277        let key = str::from_utf8(key)?;
278        self.buf = buf;
279
280        let value_len = self.buf.read_i32::<BigEndian>()?;
281        let value = if value_len < 0 {
282            None
283        } else {
284            let (value, buf) = self.buf.split_at(value_len as usize);
285            let value = str::from_utf8(value)?;
286            self.buf = buf;
287            Some(value)
288        };
289
290        Ok(Some((key, value)))
291    }
292
293    #[inline]
294    fn size_hint(&self) -> (usize, Option<usize>) {
295        let len = self.remaining as usize;
296        (len, Some(len))
297    }
298}
299
300/// Serializes a `VARBIT` or `BIT` value.
301#[inline]
302pub fn varbit_to_sql<I>(
303    len: usize,
304    v: I,
305    buf: &mut BytesMut,
306) -> Result<(), StdBox<dyn Error + Sync + Send>>
307where
308    I: Iterator<Item = u8>,
309{
310    let len = i32::from_usize(len)?;
311    buf.put_i32(len);
312
313    for byte in v {
314        buf.put_u8(byte);
315    }
316
317    Ok(())
318}
319
320/// Deserializes a `VARBIT` or `BIT` value.
321#[inline]
322pub fn varbit_from_sql(mut buf: &[u8]) -> Result<Varbit<'_>, StdBox<dyn Error + Sync + Send>> {
323    let len = buf.read_i32::<BigEndian>()?;
324    if len < 0 {
325        return Err("invalid varbit length: varbit < 0".into());
326    }
327    let bytes = (len as usize + 7) / 8;
328    if buf.len() != bytes {
329        return Err("invalid message length: varbit mismatch".into());
330    }
331
332    Ok(Varbit {
333        len: len as usize,
334        bytes: buf,
335    })
336}
337
338/// A `VARBIT` value.
339pub struct Varbit<'a> {
340    len: usize,
341    bytes: &'a [u8],
342}
343
344impl<'a> Varbit<'a> {
345    /// Returns the number of bits.
346    #[inline]
347    pub fn len(&self) -> usize {
348        self.len
349    }
350
351    /// Determines if the value has no bits.
352    #[inline]
353    pub fn is_empty(&self) -> bool {
354        self.len == 0
355    }
356
357    /// Returns the bits as a slice of bytes.
358    #[inline]
359    pub fn bytes(&self) -> &'a [u8] {
360        self.bytes
361    }
362}
363
364/// Serializes a `TIMESTAMP` or `TIMESTAMPTZ` value.
365///
366/// The value should represent the number of microseconds since midnight, January 1st, 2000.
367#[inline]
368pub fn timestamp_to_sql(v: i64, buf: &mut BytesMut) {
369    buf.put_i64(v);
370}
371
372/// Deserializes a `TIMESTAMP` or `TIMESTAMPTZ` value.
373///
374/// The value represents the number of microseconds since midnight, January 1st, 2000.
375#[inline]
376pub fn timestamp_from_sql(mut buf: &[u8]) -> Result<i64, StdBox<dyn Error + Sync + Send>> {
377    let v = buf.read_i64::<BigEndian>()?;
378    if !buf.is_empty() {
379        return Err("invalid message length: timestamp not drained".into());
380    }
381    Ok(v)
382}
383
384/// Serializes a `DATE` value.
385///
386/// The value should represent the number of days since January 1st, 2000.
387#[inline]
388pub fn date_to_sql(v: i32, buf: &mut BytesMut) {
389    buf.put_i32(v);
390}
391
392/// Deserializes a `DATE` value.
393///
394/// The value represents the number of days since January 1st, 2000.
395#[inline]
396pub fn date_from_sql(mut buf: &[u8]) -> Result<i32, StdBox<dyn Error + Sync + Send>> {
397    let v = buf.read_i32::<BigEndian>()?;
398    if !buf.is_empty() {
399        return Err("invalid message length: date not drained".into());
400    }
401    Ok(v)
402}
403
404/// Serializes a `TIME` or `TIMETZ` value.
405///
406/// The value should represent the number of microseconds since midnight.
407#[inline]
408pub fn time_to_sql(v: i64, buf: &mut BytesMut) {
409    buf.put_i64(v);
410}
411
412/// Deserializes a `TIME` or `TIMETZ` value.
413///
414/// The value represents the number of microseconds since midnight.
415#[inline]
416pub fn time_from_sql(mut buf: &[u8]) -> Result<i64, StdBox<dyn Error + Sync + Send>> {
417    let v = buf.read_i64::<BigEndian>()?;
418    if !buf.is_empty() {
419        return Err("invalid message length: time not drained".into());
420    }
421    Ok(v)
422}
423
424/// Serializes a `MACADDR` value.
425#[inline]
426pub fn macaddr_to_sql(v: [u8; 6], buf: &mut BytesMut) {
427    buf.put_slice(&v);
428}
429
430/// Deserializes a `MACADDR` value.
431#[inline]
432pub fn macaddr_from_sql(buf: &[u8]) -> Result<[u8; 6], StdBox<dyn Error + Sync + Send>> {
433    if buf.len() != 6 {
434        return Err("invalid message length: macaddr length mismatch".into());
435    }
436    let mut out = [0; 6];
437    out.copy_from_slice(buf);
438    Ok(out)
439}
440
441/// Serializes a `UUID` value.
442#[inline]
443pub fn uuid_to_sql(v: [u8; 16], buf: &mut BytesMut) {
444    buf.put_slice(&v);
445}
446
447/// Deserializes a `UUID` value.
448#[inline]
449pub fn uuid_from_sql(buf: &[u8]) -> Result<[u8; 16], StdBox<dyn Error + Sync + Send>> {
450    if buf.len() != 16 {
451        return Err("invalid message length: uuid size mismatch".into());
452    }
453    let mut out = [0; 16];
454    out.copy_from_slice(buf);
455    Ok(out)
456}
457
458/// Serializes an array value.
459#[inline]
460pub fn array_to_sql<T, I, J, F>(
461    dimensions: I,
462    element_type: Oid,
463    elements: J,
464    mut serializer: F,
465    buf: &mut BytesMut,
466) -> Result<(), StdBox<dyn Error + Sync + Send>>
467where
468    I: IntoIterator<Item = ArrayDimension>,
469    J: IntoIterator<Item = T>,
470    F: FnMut(T, &mut BytesMut) -> Result<IsNull, StdBox<dyn Error + Sync + Send>>,
471{
472    let dimensions_idx = buf.len();
473    buf.put_i32(0);
474    let flags_idx = buf.len();
475    buf.put_i32(0);
476    buf.put_u32(element_type);
477
478    let mut num_dimensions = 0;
479    for dimension in dimensions {
480        num_dimensions += 1;
481        buf.put_i32(dimension.len);
482        buf.put_i32(dimension.lower_bound);
483    }
484
485    let num_dimensions = i32::from_usize(num_dimensions)?;
486    BigEndian::write_i32(&mut buf[dimensions_idx..], num_dimensions);
487
488    let mut has_nulls = false;
489    for element in elements {
490        write_nullable(
491            |buf| {
492                let r = serializer(element, buf);
493                if let Ok(IsNull::Yes) = r {
494                    has_nulls = true;
495                }
496                r
497            },
498            buf,
499        )?;
500    }
501
502    BigEndian::write_i32(&mut buf[flags_idx..], has_nulls as i32);
503
504    Ok(())
505}
506
507/// Deserializes an array value.
508#[inline]
509pub fn array_from_sql(mut buf: &[u8]) -> Result<Array<'_>, StdBox<dyn Error + Sync + Send>> {
510    let dimensions = buf.read_i32::<BigEndian>()?;
511    if dimensions < 0 {
512        return Err("invalid dimension count".into());
513    }
514    let has_nulls = buf.read_i32::<BigEndian>()? != 0;
515    let element_type = buf.read_u32::<BigEndian>()?;
516
517    let mut r = buf;
518    let mut elements = 1i32;
519    for _ in 0..dimensions {
520        let len = r.read_i32::<BigEndian>()?;
521        if len < 0 {
522            return Err("invalid dimension size".into());
523        }
524        let _lower_bound = r.read_i32::<BigEndian>()?;
525        elements = match elements.checked_mul(len) {
526            Some(elements) => elements,
527            None => return Err("too many array elements".into()),
528        };
529    }
530
531    if dimensions == 0 {
532        elements = 0;
533    }
534
535    Ok(Array {
536        dimensions,
537        has_nulls,
538        element_type,
539        elements,
540        buf,
541    })
542}
543
544/// A Postgres array.
545pub struct Array<'a> {
546    dimensions: i32,
547    has_nulls: bool,
548    element_type: Oid,
549    elements: i32,
550    buf: &'a [u8],
551}
552
553impl<'a> Array<'a> {
554    /// Returns true if there are `NULL` elements.
555    #[inline]
556    pub fn has_nulls(&self) -> bool {
557        self.has_nulls
558    }
559
560    /// Returns the OID of the elements of the array.
561    #[inline]
562    pub fn element_type(&self) -> Oid {
563        self.element_type
564    }
565
566    /// Returns an iterator over the dimensions of the array.
567    #[inline]
568    pub fn dimensions(&self) -> ArrayDimensions<'a> {
569        ArrayDimensions(&self.buf[..self.dimensions as usize * 8])
570    }
571
572    /// Returns an iterator over the values of the array.
573    #[inline]
574    pub fn values(&self) -> ArrayValues<'a> {
575        ArrayValues {
576            remaining: self.elements,
577            buf: &self.buf[self.dimensions as usize * 8..],
578        }
579    }
580}
581
582/// An iterator over the dimensions of an array.
583pub struct ArrayDimensions<'a>(&'a [u8]);
584
585impl FallibleIterator for ArrayDimensions<'_> {
586    type Item = ArrayDimension;
587    type Error = StdBox<dyn Error + Sync + Send>;
588
589    #[inline]
590    fn next(&mut self) -> Result<Option<ArrayDimension>, StdBox<dyn Error + Sync + Send>> {
591        if self.0.is_empty() {
592            return Ok(None);
593        }
594
595        let len = self.0.read_i32::<BigEndian>()?;
596        let lower_bound = self.0.read_i32::<BigEndian>()?;
597
598        Ok(Some(ArrayDimension { len, lower_bound }))
599    }
600
601    #[inline]
602    fn size_hint(&self) -> (usize, Option<usize>) {
603        let len = self.0.len() / 8;
604        (len, Some(len))
605    }
606}
607
608/// Information about a dimension of an array.
609#[derive(Debug, Copy, Clone, PartialEq, Eq)]
610pub struct ArrayDimension {
611    /// The length of this dimension.
612    pub len: i32,
613
614    /// The base value used to index into this dimension.
615    pub lower_bound: i32,
616}
617
618/// An iterator over the values of an array, in row-major order.
619pub struct ArrayValues<'a> {
620    remaining: i32,
621    buf: &'a [u8],
622}
623
624impl<'a> FallibleIterator for ArrayValues<'a> {
625    type Item = Option<&'a [u8]>;
626    type Error = StdBox<dyn Error + Sync + Send>;
627
628    #[inline]
629    fn next(&mut self) -> Result<Option<Option<&'a [u8]>>, StdBox<dyn Error + Sync + Send>> {
630        if self.remaining == 0 {
631            if !self.buf.is_empty() {
632                return Err("invalid message length: arrayvalue not drained".into());
633            }
634            return Ok(None);
635        }
636        self.remaining -= 1;
637
638        let len = self.buf.read_i32::<BigEndian>()?;
639        let val = if len < 0 {
640            None
641        } else {
642            if self.buf.len() < len as usize {
643                return Err("invalid value length".into());
644            }
645
646            let (val, buf) = self.buf.split_at(len as usize);
647            self.buf = buf;
648            Some(val)
649        };
650
651        Ok(Some(val))
652    }
653
654    fn size_hint(&self) -> (usize, Option<usize>) {
655        let len = self.remaining as usize;
656        (len, Some(len))
657    }
658}
659
660/// Serializes an empty range.
661#[inline]
662pub fn empty_range_to_sql(buf: &mut BytesMut) {
663    buf.put_u8(RANGE_EMPTY);
664}
665
666/// Serializes a range value.
667pub fn range_to_sql<F, G>(
668    lower: F,
669    upper: G,
670    buf: &mut BytesMut,
671) -> Result<(), StdBox<dyn Error + Sync + Send>>
672where
673    F: FnOnce(&mut BytesMut) -> Result<RangeBound<IsNull>, StdBox<dyn Error + Sync + Send>>,
674    G: FnOnce(&mut BytesMut) -> Result<RangeBound<IsNull>, StdBox<dyn Error + Sync + Send>>,
675{
676    let tag_idx = buf.len();
677    buf.put_u8(0);
678    let mut tag = 0;
679
680    match write_bound(lower, buf)? {
681        RangeBound::Inclusive(()) => tag |= RANGE_LOWER_INCLUSIVE,
682        RangeBound::Exclusive(()) => {}
683        RangeBound::Unbounded => tag |= RANGE_LOWER_UNBOUNDED,
684    }
685
686    match write_bound(upper, buf)? {
687        RangeBound::Inclusive(()) => tag |= RANGE_UPPER_INCLUSIVE,
688        RangeBound::Exclusive(()) => {}
689        RangeBound::Unbounded => tag |= RANGE_UPPER_UNBOUNDED,
690    }
691
692    buf[tag_idx] = tag;
693
694    Ok(())
695}
696
697fn write_bound<F>(
698    bound: F,
699    buf: &mut BytesMut,
700) -> Result<RangeBound<()>, StdBox<dyn Error + Sync + Send>>
701where
702    F: FnOnce(&mut BytesMut) -> Result<RangeBound<IsNull>, StdBox<dyn Error + Sync + Send>>,
703{
704    let base = buf.len();
705    buf.put_i32(0);
706
707    let (null, ret) = match bound(buf)? {
708        RangeBound::Inclusive(null) => (Some(null), RangeBound::Inclusive(())),
709        RangeBound::Exclusive(null) => (Some(null), RangeBound::Exclusive(())),
710        RangeBound::Unbounded => (None, RangeBound::Unbounded),
711    };
712
713    match null {
714        Some(null) => {
715            let len = match null {
716                IsNull::No => i32::from_usize(buf.len() - base - 4)?,
717                IsNull::Yes => -1,
718            };
719            BigEndian::write_i32(&mut buf[base..], len);
720        }
721        None => buf.truncate(base),
722    }
723
724    Ok(ret)
725}
726
727/// One side of a range.
728pub enum RangeBound<T> {
729    /// An inclusive bound.
730    Inclusive(T),
731    /// An exclusive bound.
732    Exclusive(T),
733    /// No bound.
734    Unbounded,
735}
736
737/// Deserializes a range value.
738#[inline]
739pub fn range_from_sql(mut buf: &[u8]) -> Result<Range<'_>, StdBox<dyn Error + Sync + Send>> {
740    let tag = buf.read_u8()?;
741
742    if tag == RANGE_EMPTY {
743        if !buf.is_empty() {
744            return Err("invalid message size".into());
745        }
746        return Ok(Range::Empty);
747    }
748
749    let lower = read_bound(&mut buf, tag, RANGE_LOWER_UNBOUNDED, RANGE_LOWER_INCLUSIVE)?;
750    let upper = read_bound(&mut buf, tag, RANGE_UPPER_UNBOUNDED, RANGE_UPPER_INCLUSIVE)?;
751
752    if !buf.is_empty() {
753        return Err("invalid message size".into());
754    }
755
756    Ok(Range::Nonempty(lower, upper))
757}
758
759#[inline]
760fn read_bound<'a>(
761    buf: &mut &'a [u8],
762    tag: u8,
763    unbounded: u8,
764    inclusive: u8,
765) -> Result<RangeBound<Option<&'a [u8]>>, StdBox<dyn Error + Sync + Send>> {
766    if tag & unbounded != 0 {
767        Ok(RangeBound::Unbounded)
768    } else {
769        let len = buf.read_i32::<BigEndian>()?;
770        let value = if len < 0 {
771            None
772        } else {
773            let len = len as usize;
774            if buf.len() < len {
775                return Err("invalid message size".into());
776            }
777            let (value, tail) = buf.split_at(len);
778            *buf = tail;
779            Some(value)
780        };
781
782        if tag & inclusive != 0 {
783            Ok(RangeBound::Inclusive(value))
784        } else {
785            Ok(RangeBound::Exclusive(value))
786        }
787    }
788}
789
790/// A Postgres range.
791pub enum Range<'a> {
792    /// An empty range.
793    Empty,
794    /// A nonempty range.
795    Nonempty(RangeBound<Option<&'a [u8]>>, RangeBound<Option<&'a [u8]>>),
796}
797
798/// Serializes a point value.
799#[inline]
800pub fn point_to_sql(x: f64, y: f64, buf: &mut BytesMut) {
801    buf.put_f64(x);
802    buf.put_f64(y);
803}
804
805/// Deserializes a point value.
806#[inline]
807pub fn point_from_sql(mut buf: &[u8]) -> Result<Point, StdBox<dyn Error + Sync + Send>> {
808    let x = buf.read_f64::<BigEndian>()?;
809    let y = buf.read_f64::<BigEndian>()?;
810    if !buf.is_empty() {
811        return Err("invalid buffer size".into());
812    }
813    Ok(Point { x, y })
814}
815
816/// A Postgres point.
817#[derive(Copy, Clone)]
818pub struct Point {
819    x: f64,
820    y: f64,
821}
822
823impl Point {
824    /// Returns the x coordinate of the point.
825    #[inline]
826    pub fn x(&self) -> f64 {
827        self.x
828    }
829
830    /// Returns the y coordinate of the point.
831    #[inline]
832    pub fn y(&self) -> f64 {
833        self.y
834    }
835}
836
837/// Serializes a box value.
838#[inline]
839pub fn box_to_sql(x1: f64, y1: f64, x2: f64, y2: f64, buf: &mut BytesMut) {
840    buf.put_f64(x1);
841    buf.put_f64(y1);
842    buf.put_f64(x2);
843    buf.put_f64(y2);
844}
845
846/// Deserializes a box value.
847#[inline]
848pub fn box_from_sql(mut buf: &[u8]) -> Result<Box, StdBox<dyn Error + Sync + Send>> {
849    let x1 = buf.read_f64::<BigEndian>()?;
850    let y1 = buf.read_f64::<BigEndian>()?;
851    let x2 = buf.read_f64::<BigEndian>()?;
852    let y2 = buf.read_f64::<BigEndian>()?;
853    if !buf.is_empty() {
854        return Err("invalid buffer size".into());
855    }
856    Ok(Box {
857        upper_right: Point { x: x1, y: y1 },
858        lower_left: Point { x: x2, y: y2 },
859    })
860}
861
862/// A Postgres box.
863#[derive(Copy, Clone)]
864pub struct Box {
865    upper_right: Point,
866    lower_left: Point,
867}
868
869impl Box {
870    /// Returns the upper right corner of the box.
871    #[inline]
872    pub fn upper_right(&self) -> Point {
873        self.upper_right
874    }
875
876    /// Returns the lower left corner of the box.
877    #[inline]
878    pub fn lower_left(&self) -> Point {
879        self.lower_left
880    }
881}
882
883/// Serializes a Postgres path.
884#[inline]
885pub fn path_to_sql<I>(
886    closed: bool,
887    points: I,
888    buf: &mut BytesMut,
889) -> Result<(), StdBox<dyn Error + Sync + Send>>
890where
891    I: IntoIterator<Item = (f64, f64)>,
892{
893    buf.put_u8(closed as u8);
894    let points_idx = buf.len();
895    buf.put_i32(0);
896
897    let mut num_points = 0;
898    for (x, y) in points {
899        num_points += 1;
900        buf.put_f64(x);
901        buf.put_f64(y);
902    }
903
904    let num_points = i32::from_usize(num_points)?;
905    BigEndian::write_i32(&mut buf[points_idx..], num_points);
906
907    Ok(())
908}
909
910/// Deserializes a Postgres path.
911#[inline]
912pub fn path_from_sql(mut buf: &[u8]) -> Result<Path<'_>, StdBox<dyn Error + Sync + Send>> {
913    let closed = buf.read_u8()? != 0;
914    let points = buf.read_i32::<BigEndian>()?;
915
916    Ok(Path {
917        closed,
918        points,
919        buf,
920    })
921}
922
923/// A Postgres point.
924pub struct Path<'a> {
925    closed: bool,
926    points: i32,
927    buf: &'a [u8],
928}
929
930impl<'a> Path<'a> {
931    /// Determines if the path is closed or open.
932    #[inline]
933    pub fn closed(&self) -> bool {
934        self.closed
935    }
936
937    /// Returns an iterator over the points in the path.
938    #[inline]
939    pub fn points(&self) -> PathPoints<'a> {
940        PathPoints {
941            remaining: self.points,
942            buf: self.buf,
943        }
944    }
945}
946
947/// An iterator over the points of a Postgres path.
948pub struct PathPoints<'a> {
949    remaining: i32,
950    buf: &'a [u8],
951}
952
953impl FallibleIterator for PathPoints<'_> {
954    type Item = Point;
955    type Error = StdBox<dyn Error + Sync + Send>;
956
957    #[inline]
958    fn next(&mut self) -> Result<Option<Point>, StdBox<dyn Error + Sync + Send>> {
959        if self.remaining == 0 {
960            if !self.buf.is_empty() {
961                return Err("invalid message length: path points not drained".into());
962            }
963            return Ok(None);
964        }
965        self.remaining -= 1;
966
967        let x = self.buf.read_f64::<BigEndian>()?;
968        let y = self.buf.read_f64::<BigEndian>()?;
969
970        Ok(Some(Point { x, y }))
971    }
972
973    #[inline]
974    fn size_hint(&self) -> (usize, Option<usize>) {
975        let len = self.remaining as usize;
976        (len, Some(len))
977    }
978}
979
980/// Serializes a Postgres inet.
981#[inline]
982pub fn inet_to_sql(addr: IpAddr, netmask: u8, buf: &mut BytesMut) {
983    let family = match addr {
984        IpAddr::V4(_) => PGSQL_AF_INET,
985        IpAddr::V6(_) => PGSQL_AF_INET6,
986    };
987    buf.put_u8(family);
988    buf.put_u8(netmask);
989    buf.put_u8(0); // is_cidr
990    match addr {
991        IpAddr::V4(addr) => {
992            buf.put_u8(4);
993            buf.put_slice(&addr.octets());
994        }
995        IpAddr::V6(addr) => {
996            buf.put_u8(16);
997            buf.put_slice(&addr.octets());
998        }
999    }
1000}
1001
1002/// Deserializes a Postgres inet.
1003#[inline]
1004pub fn inet_from_sql(mut buf: &[u8]) -> Result<Inet, StdBox<dyn Error + Sync + Send>> {
1005    let family = buf.read_u8()?;
1006    let netmask = buf.read_u8()?;
1007    buf.read_u8()?; // is_cidr
1008    let len = buf.read_u8()?;
1009
1010    let addr = match family {
1011        PGSQL_AF_INET => {
1012            if netmask > 32 {
1013                return Err("invalid IPv4 netmask".into());
1014            }
1015            if len != 4 {
1016                return Err("invalid IPv4 address length".into());
1017            }
1018            let mut addr = [0; 4];
1019            buf.read_exact(&mut addr)?;
1020            IpAddr::V4(Ipv4Addr::from(addr))
1021        }
1022        PGSQL_AF_INET6 => {
1023            if netmask > 128 {
1024                return Err("invalid IPv6 netmask".into());
1025            }
1026            if len != 16 {
1027                return Err("invalid IPv6 address length".into());
1028            }
1029            let mut addr = [0; 16];
1030            buf.read_exact(&mut addr)?;
1031            IpAddr::V6(Ipv6Addr::from(addr))
1032        }
1033        _ => return Err("invalid IP family".into()),
1034    };
1035
1036    if !buf.is_empty() {
1037        return Err("invalid buffer size".into());
1038    }
1039
1040    Ok(Inet { addr, netmask })
1041}
1042
1043/// A Postgres network address.
1044pub struct Inet {
1045    addr: IpAddr,
1046    netmask: u8,
1047}
1048
1049impl Inet {
1050    /// Returns the IP address.
1051    #[inline]
1052    pub fn addr(&self) -> IpAddr {
1053        self.addr
1054    }
1055
1056    /// Returns the netmask.
1057    #[inline]
1058    pub fn netmask(&self) -> u8 {
1059        self.netmask
1060    }
1061}
1062
1063/// Serializes a Postgres ltree string
1064#[inline]
1065pub fn ltree_to_sql(v: &str, buf: &mut BytesMut) {
1066    // A version number is prepended to an ltree string per spec
1067    buf.put_u8(1);
1068    // Append the rest of the query
1069    buf.put_slice(v.as_bytes());
1070}
1071
1072/// Deserialize a Postgres ltree string
1073#[inline]
1074pub fn ltree_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1075    match buf {
1076        // Remove the version number from the front of the ltree per spec
1077        [1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1078        _ => Err("ltree version 1 only supported".into()),
1079    }
1080}
1081
1082/// Serializes a Postgres lquery string
1083#[inline]
1084pub fn lquery_to_sql(v: &str, buf: &mut BytesMut) {
1085    // A version number is prepended to an lquery string per spec
1086    buf.put_u8(1);
1087    // Append the rest of the query
1088    buf.put_slice(v.as_bytes());
1089}
1090
1091/// Deserialize a Postgres lquery string
1092#[inline]
1093pub fn lquery_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1094    match buf {
1095        // Remove the version number from the front of the lquery per spec
1096        [1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1097        _ => Err("lquery version 1 only supported".into()),
1098    }
1099}
1100
1101/// Serializes a Postgres ltxtquery string
1102#[inline]
1103pub fn ltxtquery_to_sql(v: &str, buf: &mut BytesMut) {
1104    // A version number is prepended to an ltxtquery string per spec
1105    buf.put_u8(1);
1106    // Append the rest of the query
1107    buf.put_slice(v.as_bytes());
1108}
1109
1110/// Deserialize a Postgres ltxtquery string
1111#[inline]
1112pub fn ltxtquery_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1113    match buf {
1114        // Remove the version number from the front of the ltxtquery per spec
1115        [1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1116        _ => Err("ltxtquery version 1 only supported".into()),
1117    }
1118}