1use 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#[inline]
27pub fn bool_to_sql(v: bool, buf: &mut BytesMut) {
28 buf.put_u8(v as u8);
29}
30
31#[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#[inline]
43pub fn bytea_to_sql(v: &[u8], buf: &mut BytesMut) {
44 buf.put_slice(v);
45}
46
47#[inline]
49pub fn bytea_from_sql(buf: &[u8]) -> &[u8] {
50 buf
51}
52
53#[inline]
55pub fn text_to_sql(v: &str, buf: &mut BytesMut) {
56 buf.put_slice(v.as_bytes());
57}
58
59#[inline]
61pub fn text_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
62 Ok(str::from_utf8(buf)?)
63}
64
65#[inline]
67pub fn char_to_sql(v: i8, buf: &mut BytesMut) {
68 buf.put_i8(v);
69}
70
71#[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#[inline]
83pub fn int2_to_sql(v: i16, buf: &mut BytesMut) {
84 buf.put_i16(v);
85}
86
87#[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#[inline]
99pub fn int4_to_sql(v: i32, buf: &mut BytesMut) {
100 buf.put_i32(v);
101}
102
103#[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#[inline]
115pub fn oid_to_sql(v: Oid, buf: &mut BytesMut) {
116 buf.put_u32(v);
117}
118
119#[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#[inline]
131pub fn int8_to_sql(v: i64, buf: &mut BytesMut) {
132 buf.put_i64(v);
133}
134
135#[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#[inline]
147pub fn lsn_to_sql(v: Lsn, buf: &mut BytesMut) {
148 buf.put_u64(v);
149}
150
151#[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#[inline]
163pub fn float4_to_sql(v: f32, buf: &mut BytesMut) {
164 buf.put_f32(v);
165}
166
167#[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#[inline]
179pub fn float8_to_sql(v: f64, buf: &mut BytesMut) {
180 buf.put_f64(v);
181}
182
183#[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#[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#[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
248pub 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#[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#[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
344pub struct Varbit<'a> {
346 len: usize,
347 bytes: &'a [u8],
348}
349
350impl<'a> Varbit<'a> {
351 #[inline]
353 pub fn len(&self) -> usize {
354 self.len
355 }
356
357 #[inline]
359 pub fn is_empty(&self) -> bool {
360 self.len == 0
361 }
362
363 #[inline]
365 pub fn bytes(&self) -> &'a [u8] {
366 self.bytes
367 }
368}
369
370#[inline]
374pub fn timestamp_to_sql(v: i64, buf: &mut BytesMut) {
375 buf.put_i64(v);
376}
377
378#[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#[inline]
394pub fn date_to_sql(v: i32, buf: &mut BytesMut) {
395 buf.put_i32(v);
396}
397
398#[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#[inline]
414pub fn time_to_sql(v: i64, buf: &mut BytesMut) {
415 buf.put_i64(v);
416}
417
418#[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#[inline]
432pub fn macaddr_to_sql(v: [u8; 6], buf: &mut BytesMut) {
433 buf.put_slice(&v);
434}
435
436#[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#[inline]
449pub fn uuid_to_sql(v: [u8; 16], buf: &mut BytesMut) {
450 buf.put_slice(&v);
451}
452
453#[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#[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#[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
550pub 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 #[inline]
562 pub fn has_nulls(&self) -> bool {
563 self.has_nulls
564 }
565
566 #[inline]
568 pub fn element_type(&self) -> Oid {
569 self.element_type
570 }
571
572 #[inline]
574 pub fn dimensions(&self) -> ArrayDimensions<'a> {
575 ArrayDimensions(&self.buf[..self.dimensions as usize * 8])
576 }
577
578 #[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
588pub 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#[derive(Debug, Copy, Clone, PartialEq, Eq)]
616pub struct ArrayDimension {
617 pub len: i32,
619
620 pub lower_bound: i32,
622}
623
624pub 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#[inline]
667pub fn empty_range_to_sql(buf: &mut BytesMut) {
668 buf.put_u8(RANGE_EMPTY);
669}
670
671pub 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
732pub enum RangeBound<T> {
734 Inclusive(T),
736 Exclusive(T),
738 Unbounded,
740}
741
742#[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
792pub enum Range<'a> {
794 Empty,
796 Nonempty(RangeBound<Option<&'a [u8]>>, RangeBound<Option<&'a [u8]>>),
798}
799
800#[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#[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#[derive(Copy, Clone)]
820pub struct Point {
821 x: f64,
822 y: f64,
823}
824
825impl Point {
826 #[inline]
828 pub fn x(&self) -> f64 {
829 self.x
830 }
831
832 #[inline]
834 pub fn y(&self) -> f64 {
835 self.y
836 }
837}
838
839#[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#[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#[derive(Copy, Clone)]
866pub struct Box {
867 upper_right: Point,
868 lower_left: Point,
869}
870
871impl Box {
872 #[inline]
874 pub fn upper_right(&self) -> Point {
875 self.upper_right
876 }
877
878 #[inline]
880 pub fn lower_left(&self) -> Point {
881 self.lower_left
882 }
883}
884
885#[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#[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
925pub struct Path<'a> {
927 closed: bool,
928 points: i32,
929 buf: &'a [u8],
930}
931
932impl<'a> Path<'a> {
933 #[inline]
935 pub fn closed(&self) -> bool {
936 self.closed
937 }
938
939 #[inline]
941 pub fn points(&self) -> PathPoints<'a> {
942 PathPoints {
943 remaining: self.points,
944 buf: self.buf,
945 }
946 }
947}
948
949pub 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#[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); 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#[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()?; 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
1045pub struct Inet {
1047 addr: IpAddr,
1048 netmask: u8,
1049}
1050
1051impl Inet {
1052 #[inline]
1054 pub fn addr(&self) -> IpAddr {
1055 self.addr
1056 }
1057
1058 #[inline]
1060 pub fn netmask(&self) -> u8 {
1061 self.netmask
1062 }
1063}
1064
1065#[inline]
1067pub fn ltree_to_sql(v: &str, buf: &mut BytesMut) {
1068 buf.put_u8(1);
1070 buf.put_slice(v.as_bytes());
1072}
1073
1074#[inline]
1076pub fn ltree_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1077 match buf {
1078 [1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1080 _ => Err("ltree version 1 only supported".into()),
1081 }
1082}
1083
1084#[inline]
1086pub fn lquery_to_sql(v: &str, buf: &mut BytesMut) {
1087 buf.put_u8(1);
1089 buf.put_slice(v.as_bytes());
1091}
1092
1093#[inline]
1095pub fn lquery_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1096 match buf {
1097 [1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1099 _ => Err("lquery version 1 only supported".into()),
1100 }
1101}
1102
1103#[inline]
1105pub fn ltxtquery_to_sql(v: &str, buf: &mut BytesMut) {
1106 buf.put_u8(1);
1108 buf.put_slice(v.as_bytes());
1110}
1111
1112#[inline]
1114pub fn ltxtquery_from_sql(buf: &[u8]) -> Result<&str, StdBox<dyn Error + Sync + Send>> {
1115 match buf {
1116 [1u8, rest @ ..] => Ok(str::from_utf8(rest)?),
1118 _ => Err("ltxtquery version 1 only supported".into()),
1119 }
1120}