1use crate::{error::Error, ewkb, types as postgis};
16use byteorder::ReadBytesExt;
17use std::{f64, fmt, io::prelude::*, slice::Iter};
18
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20#[derive(PartialEq, Clone, Copy, Debug, Default)]
21pub struct Point {
22 pub x: f64,
23 pub y: f64, }
25
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27#[derive(PartialEq, Clone, Debug)]
28pub struct LineString {
29 pub points: Vec<Point>,
30}
31
32#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
33#[derive(PartialEq, Clone, Debug)]
34pub struct Polygon {
35 pub rings: Vec<LineString>,
36}
37
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39#[derive(PartialEq, Clone, Debug)]
40pub struct MultiPoint {
41 pub points: Vec<Point>,
42 pub ids: Option<Vec<u64>>,
43}
44
45#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
46#[derive(PartialEq, Clone, Debug)]
47pub struct MultiLineString {
48 pub lines: Vec<LineString>,
49 pub ids: Option<Vec<u64>>,
50}
51
52#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
53#[derive(PartialEq, Clone, Debug)]
54pub struct MultiPolygon {
55 pub polygons: Vec<Polygon>,
56 pub ids: Option<Vec<u64>>,
57}
58
59#[doc(hidden)]
60#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
61#[derive(Default, Debug)]
62pub struct TwkbInfo {
63 geom_type: u8,
64 precision: i8,
65 has_idlist: bool,
66 is_empty_geom: bool,
67 size: Option<u64>,
68 has_z: bool,
69 has_m: bool,
70 prec_z: Option<u8>,
71 prec_m: Option<u8>,
72}
73
74pub trait TwkbGeom: fmt::Debug + Sized {
75 fn read_twkb<R: Read>(raw: &mut R) -> Result<Self, Error> {
76 let mut twkb_info: TwkbInfo = Default::default();
77 let type_and_prec = raw.read_u8()?;
83 twkb_info.geom_type = type_and_prec & 0x0F;
84 twkb_info.precision = decode_zig_zag_64(((type_and_prec & 0xF0) >> 4) as u64) as i8;
85 let metadata_header = raw.read_u8()?;
86 let has_bbox = (metadata_header & 0b0001) != 0;
87 let has_size_attribute = (metadata_header & 0b0010) != 0;
88 twkb_info.has_idlist = (metadata_header & 0b0100) != 0;
89 let has_ext_prec_info = (metadata_header & 0b1000) != 0;
90 twkb_info.is_empty_geom = (metadata_header & 0b10000) != 0;
91 if has_ext_prec_info {
92 let ext_prec_info = raw.read_u8()?;
93 twkb_info.has_z = ext_prec_info & 0b0001 != 0;
94 twkb_info.has_m = ext_prec_info & 0b0010 != 0;
95 twkb_info.prec_z = Some((ext_prec_info & 0x1C) >> 2);
96 twkb_info.prec_m = Some((ext_prec_info & 0xE0) >> 5);
97 }
98 if has_size_attribute {
99 twkb_info.size = Some(read_raw_varint64(raw)?);
100 }
101 if has_bbox {
102 let _xmin = read_int64(raw)?;
103 let _deltax = read_int64(raw)?;
104 let _ymin = read_int64(raw)?;
105 let _deltay = read_int64(raw)?;
106 if twkb_info.has_z {
107 let _zmin = read_int64(raw)?;
108 let _deltaz = read_int64(raw)?;
109 }
110 if twkb_info.has_m {
111 let _mmin = read_int64(raw)?;
112 let _deltam = read_int64(raw)?;
113 }
114 }
115 Self::read_twkb_body(raw, &twkb_info)
116 }
117
118 #[doc(hidden)]
119 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error>;
120
121 #[doc(hidden)]
122 fn read_relative_point<R: Read>(
123 raw: &mut R,
124 twkb_info: &TwkbInfo,
125 x: f64,
126 y: f64,
127 z: Option<f64>,
128 m: Option<f64>,
129 ) -> Result<(f64, f64, Option<f64>, Option<f64>), Error> {
130 let x2 = x + read_varint64_as_f64(raw, twkb_info.precision)?;
131 let y2 = y + read_varint64_as_f64(raw, twkb_info.precision)?;
132 let z2 = if twkb_info.has_z {
133 let dz = read_varint64_as_f64(raw, twkb_info.precision)?;
134 z.map(|v| v + dz)
135 }
136 else {
137 None
138 };
139 let m2 = if twkb_info.has_m {
140 let dm = read_varint64_as_f64(raw, twkb_info.precision)?;
141 m.map(|v| v + dm)
142 }
143 else {
144 None
145 };
146 Ok((x2, y2, z2, m2))
147 }
148
149 fn read_idlist<R: Read>(raw: &mut R, size: usize) -> Result<Vec<u64>, Error> {
150 let mut idlist = Vec::with_capacity(size);
151 for _ in 0..size {
152 let id = read_raw_varint64(raw)?;
153 idlist.push(id);
154 }
155 Ok(idlist)
156 }
157}
158
159fn read_raw_varint64<R: Read>(raw: &mut R) -> Result<u64, Error> {
162 let mut r: u64 = 0;
164 let mut i = 0;
165 loop {
166 if i == 10 {
167 return Err(Error::Read("invalid varint".into()));
168 }
169 let b = raw.read_u8()?;
170 r |= ((b & 0x7f) as u64) << (i * 7);
172 i += 1;
173 if b < 0x80 {
174 return Ok(r);
175 }
176 }
177}
178
179fn read_int64<R: Read>(raw: &mut R) -> Result<i64, Error> {
180 read_raw_varint64(raw).map(|v| v as i64)
181}
182
183fn decode_zig_zag_64(n: u64) -> i64 {
184 ((n >> 1) as i64) ^ (-((n & 1) as i64))
185}
186
187fn varint64_to_f64(varint: u64, precision: i8) -> f64 {
188 if precision >= 0 {
189 (decode_zig_zag_64(varint) as f64) / 10u64.pow(precision as u32) as f64
190 }
191 else {
192 (decode_zig_zag_64(varint) as f64) * 10u64.pow(precision.unsigned_abs() as u32) as f64
193 }
194}
195
196fn read_varint64_as_f64<R: Read>(raw: &mut R, precision: i8) -> Result<f64, Error> {
197 read_raw_varint64(raw).map(|v| varint64_to_f64(v, precision))
198}
199
200impl Point {
203 fn new_from_opt_vals(x: f64, y: f64, _z: Option<f64>, _m: Option<f64>) -> Self {
204 Self { x, y }
205 }
206}
207
208impl From<(f64, f64)> for Point {
209 fn from((x, y): (f64, f64)) -> Self {
210 Self { x, y }
211 }
212}
213
214impl postgis::Point for Point {
215 fn x(&self) -> f64 {
216 self.x
217 }
218
219 fn y(&self) -> f64 {
220 self.y
221 }
222}
223
224impl TwkbGeom for Point {
225 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
226 if twkb_info.is_empty_geom {
227 return Ok(Point::new_from_opt_vals(f64::NAN, f64::NAN, None, None));
228 }
229 let x = read_varint64_as_f64(raw, twkb_info.precision)?;
230 let y = read_varint64_as_f64(raw, twkb_info.precision)?;
231 let z = if twkb_info.has_z {
232 Some(read_varint64_as_f64(raw, twkb_info.precision)?)
233 }
234 else {
235 None
236 };
237 let m = if twkb_info.has_m {
238 Some(read_varint64_as_f64(raw, twkb_info.precision)?)
239 }
240 else {
241 None
242 };
243 Ok(Self::new_from_opt_vals(x, y, z, m))
244 }
245}
246
247impl<'a> ewkb::AsEwkbPoint<'a> for Point {
248 fn as_ewkb(&'a self) -> ewkb::EwkbPoint<'a> {
249 ewkb::EwkbPoint {
250 geom: self,
251 srid: None,
252 point_type: ewkb::PointType::Point,
253 }
254 }
255}
256
257impl TwkbGeom for LineString {
258 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
259 let mut points: Vec<Point> = Vec::new();
262 if !twkb_info.is_empty_geom {
263 let npoints = read_raw_varint64(raw)?;
264 points.reserve(npoints as usize);
265 let mut x = 0.0;
266 let mut y = 0.0;
267 let mut z = if twkb_info.has_z { Some(0.0) } else { None };
268 let mut m = if twkb_info.has_m { Some(0.0) } else { None };
269 for _ in 0..npoints {
270 let (x2, y2, z2, m2) = Self::read_relative_point(raw, twkb_info, x, y, z, m)?;
271 points.push(Point::new_from_opt_vals(x2, y2, z2, m2));
272 x = x2;
273 y = y2;
274 z = z2;
275 m = m2;
276 }
277 }
278 Ok(LineString { points })
279 }
280}
281
282impl<'a> postgis::LineString<'a> for LineString {
283 type ItemType = Point;
284 type Iter = Iter<'a, Self::ItemType>;
285
286 fn points(&'a self) -> Self::Iter {
287 self.points.iter()
288 }
289}
290
291impl<'a> ewkb::AsEwkbLineString<'a> for LineString {
292 type Iter = Iter<'a, Point>;
293 type PointType = Point;
294
295 fn as_ewkb(&'a self) -> ewkb::EwkbLineString<'a, Self::PointType, Self::Iter> {
296 ewkb::EwkbLineString {
297 geom: self,
298 srid: None,
299 point_type: ewkb::PointType::Point,
300 }
301 }
302}
303
304impl TwkbGeom for Polygon {
305 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
306 let mut rings: Vec<LineString> = Vec::new();
313 let nrings = read_raw_varint64(raw)?;
314 rings.reserve(nrings as usize);
315 let mut x = 0.0;
316 let mut y = 0.0;
317 let mut z = if twkb_info.has_z { Some(0.0) } else { None };
318 let mut m = if twkb_info.has_m { Some(0.0) } else { None };
319 for _ in 0..nrings {
320 let mut points: Vec<Point> = Vec::new();
321 let npoints = read_raw_varint64(raw)?;
322 points.reserve(npoints as usize);
323 let (x0, y0, z0, m0) = (x, y, z, m);
324 for _ in 0..npoints {
325 let (x2, y2, z2, m2) = Self::read_relative_point(raw, twkb_info, x, y, z, m)?;
326 points.push(Point::new_from_opt_vals(x2, y2, z2, m2));
327 x = x2;
328 y = y2;
329 z = z2;
330 m = m2;
331 }
332 if x != x0 && y != y0 && z != z0 && m != m0 {
334 points.push(Point::new_from_opt_vals(x0, y0, z0, m0));
335 }
336 rings.push(LineString { points });
337 }
338 Ok(Polygon { rings })
339 }
340}
341
342impl<'a> postgis::Polygon<'a> for Polygon {
343 type ItemType = LineString;
344 type Iter = Iter<'a, Self::ItemType>;
345
346 fn rings(&'a self) -> Self::Iter {
347 self.rings.iter()
348 }
349}
350
351impl<'a> ewkb::AsEwkbPolygon<'a> for Polygon {
352 type ItemType = LineString;
353 type Iter = Iter<'a, Self::ItemType>;
354 type PointIter = Iter<'a, Point>;
355 type PointType = Point;
356
357 fn as_ewkb(
358 &'a self,
359 ) -> ewkb::EwkbPolygon<'a, Self::PointType, Self::PointIter, Self::ItemType, Self::Iter> {
360 ewkb::EwkbPolygon {
361 geom: self,
362 srid: None,
363 point_type: ewkb::PointType::Point,
364 }
365 }
366}
367
368impl TwkbGeom for MultiPoint {
369 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
370 let mut points: Vec<Point> = Vec::new();
374 let mut ids: Option<Vec<u64>> = None;
375 if !twkb_info.is_empty_geom {
376 let npoints = read_raw_varint64(raw)?;
377 points.reserve(npoints as usize);
378
379 if twkb_info.has_idlist {
380 let idlist = Self::read_idlist(raw, npoints as usize)?;
381 ids = Some(idlist);
382 }
383
384 let mut x = 0.0;
385 let mut y = 0.0;
386 let mut z = if twkb_info.has_z { Some(0.0) } else { None };
387 let mut m = if twkb_info.has_m { Some(0.0) } else { None };
388 for _ in 0..npoints {
389 let (x2, y2, z2, m2) = Self::read_relative_point(raw, twkb_info, x, y, z, m)?;
390 points.push(Point::new_from_opt_vals(x2, y2, z2, m2));
391 x = x2;
392 y = y2;
393 z = z2;
394 m = m2;
395 }
396 }
397 Ok(MultiPoint { points, ids })
398 }
399}
400
401impl<'a> postgis::MultiPoint<'a> for MultiPoint {
402 type ItemType = Point;
403 type Iter = Iter<'a, Self::ItemType>;
404
405 fn points(&'a self) -> Self::Iter {
406 self.points.iter()
407 }
408}
409
410impl<'a> ewkb::AsEwkbMultiPoint<'a> for MultiPoint {
411 type Iter = Iter<'a, Point>;
412 type PointType = Point;
413
414 fn as_ewkb(&'a self) -> ewkb::EwkbMultiPoint<'a, Self::PointType, Self::Iter> {
415 ewkb::EwkbMultiPoint {
416 geom: self,
417 srid: None,
418 point_type: ewkb::PointType::Point,
419 }
420 }
421}
422
423impl TwkbGeom for MultiLineString {
424 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
425 let mut lines: Vec<LineString> = Vec::new();
433 let mut ids: Option<Vec<u64>> = None;
434 let nlines = read_raw_varint64(raw)?;
435 lines.reserve(nlines as usize);
436
437 if twkb_info.has_idlist {
438 let idlist = Self::read_idlist(raw, nlines as usize)?;
439 ids = Some(idlist);
440 }
441
442 let mut x = 0.0;
443 let mut y = 0.0;
444 let mut z = if twkb_info.has_z { Some(0.0) } else { None };
445 let mut m = if twkb_info.has_m { Some(0.0) } else { None };
446 for _ in 0..nlines {
447 let mut points: Vec<Point> = Vec::new();
448 let npoints = read_raw_varint64(raw)?;
449 points.reserve(npoints as usize);
450 for _ in 0..npoints {
451 let (x2, y2, z2, m2) = Self::read_relative_point(raw, twkb_info, x, y, z, m)?;
452 points.push(Point::new_from_opt_vals(x2, y2, z2, m2));
453 x = x2;
454 y = y2;
455 z = z2;
456 m = m2;
457 }
458 lines.push(LineString { points });
459 }
460 Ok(MultiLineString { lines, ids })
461 }
462}
463
464impl<'a> postgis::MultiLineString<'a> for MultiLineString {
465 type ItemType = LineString;
466 type Iter = Iter<'a, Self::ItemType>;
467
468 fn lines(&'a self) -> Self::Iter {
469 self.lines.iter()
470 }
471}
472
473impl<'a> ewkb::AsEwkbMultiLineString<'a> for MultiLineString {
474 type ItemType = LineString;
475 type Iter = Iter<'a, Self::ItemType>;
476 type PointIter = Iter<'a, Point>;
477 type PointType = Point;
478
479 fn as_ewkb(
480 &'a self,
481 ) -> ewkb::EwkbMultiLineString<'a, Self::PointType, Self::PointIter, Self::ItemType, Self::Iter>
482 {
483 ewkb::EwkbMultiLineString {
484 geom: self,
485 srid: None,
486 point_type: ewkb::PointType::Point,
487 }
488 }
489}
490
491impl TwkbGeom for MultiPolygon {
492 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
493 let mut polygons: Vec<Polygon> = Vec::new();
503 let mut ids: Option<Vec<u64>> = None;
504 let npolygons = read_raw_varint64(raw)?;
505 polygons.reserve(npolygons as usize);
506
507 if twkb_info.has_idlist {
508 let idlist = Self::read_idlist(raw, npolygons as usize)?;
509 ids = Some(idlist);
510 }
511
512 let mut x = 0.0;
513 let mut y = 0.0;
514 let mut z = if twkb_info.has_z { Some(0.0) } else { None };
515 let mut m = if twkb_info.has_m { Some(0.0) } else { None };
516 for _ in 0..npolygons {
517 let mut rings: Vec<LineString> = Vec::new();
518 let nrings = read_raw_varint64(raw)?;
519 rings.reserve(nrings as usize);
520 for _ in 0..nrings {
521 let mut points: Vec<Point> = Vec::new();
522 let npoints = read_raw_varint64(raw)?;
523 points.reserve(npoints as usize);
524 let (x0, y0, z0, m0) = (x, y, z, m);
525 for _ in 0..npoints {
526 let (x2, y2, z2, m2) = Self::read_relative_point(raw, twkb_info, x, y, z, m)?;
527 points.push(Point::new_from_opt_vals(x2, y2, z2, m2));
528 x = x2;
529 y = y2;
530 z = z2;
531 m = m2;
532 }
533 if x != x0 && y != y0 && z != z0 && m != m0 {
535 points.push(Point::new_from_opt_vals(x0, y0, z0, m0));
536 }
537 rings.push(LineString { points });
538 }
539 polygons.push(Polygon { rings });
540 }
541 Ok(MultiPolygon { polygons, ids })
542 }
543}
544
545impl<'a> postgis::MultiPolygon<'a> for MultiPolygon {
546 type ItemType = Polygon;
547 type Iter = Iter<'a, Self::ItemType>;
548
549 fn polygons(&'a self) -> Self::Iter {
550 self.polygons.iter()
551 }
552}
553
554impl<'a> ewkb::AsEwkbMultiPolygon<'a> for MultiPolygon {
555 type ItemType = Polygon;
556 type Iter = Iter<'a, Self::ItemType>;
557 type LineIter = Iter<'a, Self::LineType>;
558 type LineType = LineString;
559 type PointIter = Iter<'a, Point>;
560 type PointType = Point;
561
562 fn as_ewkb(
563 &'a self,
564 ) -> ewkb::EwkbMultiPolygon<
565 'a,
566 Self::PointType,
567 Self::PointIter,
568 Self::LineType,
569 Self::LineIter,
570 Self::ItemType,
571 Self::Iter,
572 > {
573 ewkb::EwkbMultiPolygon {
574 geom: self,
575 srid: None,
576 point_type: ewkb::PointType::Point,
577 }
578 }
579}
580
581#[cfg(test)]
582use ewkb::{
583 AsEwkbLineString, AsEwkbMultiLineString, AsEwkbMultiPoint, AsEwkbMultiPolygon, AsEwkbPoint,
584 AsEwkbPolygon, EwkbWrite,
585};
586
587#[cfg(test)]
588#[rustfmt::skip]
589fn hex_to_vec(hexstr: &str) -> Vec<u8> {
590 hexstr.as_bytes().chunks(2).map(|chars| {
591 let hb = if chars[0] <= 57 { chars[0] - 48 } else { chars[0] - 87 };
592 let lb = if chars[1] <= 57 { chars[1] - 48 } else { chars[1] - 87 };
593 hb * 16 + lb
594 }).collect::<Vec<_>>()
595}
596
597#[test]
598#[rustfmt::skip]
599fn test_read_point() {
600 let twkb = hex_to_vec("01001427"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
602 assert_eq!(format!("{:.0?}", point), "Point { x: 10, y: -20 }");
603
604 let twkb = hex_to_vec("0108011427c601"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
606 assert_eq!(format!("{:.0?}", point), "Point { x: 10, y: -20 }");
607
608 let twkb = hex_to_vec("2100ca019503"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
610 assert_eq!(format!("{:.1?}", point), "Point { x: 10.1, y: -20.3 }");
611
612 let twkb = hex_to_vec("11000203"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
614 assert_eq!(format!("{:.0?}", point), "Point { x: 10, y: -20 }");
615
616 let twkb = hex_to_vec("0110"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
618 assert_eq!(format!("{:?}", point), "Point { x: NaN, y: NaN }");
619
620 let twkb = hex_to_vec("a10080897aff91f401"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
622 assert_eq!(format!("{:.0?}", point), "Point { x: 10, y: -20 }");
623}
624
625#[test]
626#[rustfmt::skip]
627fn test_read_line() {
628 let twkb = hex_to_vec("02000214271326"); let line = LineString::read_twkb(&mut twkb.as_slice()).unwrap();
630 assert_eq!(format!("{:.0?}", line), "LineString { points: [Point { x: 10, y: -20 }, Point { x: 0, y: -1 }] }");
631
632 let twkb = hex_to_vec("220002c8018f03c7018603"); let line = LineString::read_twkb(&mut twkb.as_slice()).unwrap();
634 assert_eq!(format!("{:.1?}", line), "LineString { points: [Point { x: 10.0, y: -20.0 }, Point { x: 0.0, y: -0.5 }] }");
635
636 let twkb = hex_to_vec("0210"); let line = LineString::read_twkb(&mut twkb.as_slice()).unwrap();
638 assert_eq!(format!("{:?}", line), "LineString { points: [] }");
639}
640
641#[test]
642#[rustfmt::skip]
643fn test_read_polygon() {
644 let twkb = hex_to_vec("03000205000004000004030000030514141700001718000018"); let poly = Polygon::read_twkb(&mut twkb.as_slice()).unwrap();
646 assert_eq!(format!("{:.0?}", poly), "Polygon { rings: [LineString { points: [Point { x: 0, y: 0 }, Point { x: 2, y: 0 }, Point { x: 2, y: 2 }, Point { x: 0, y: 2 }, Point { x: 0, y: 0 }] }, LineString { points: [Point { x: 10, y: 10 }, Point { x: -2, y: 10 }, Point { x: -2, y: -2 }, Point { x: 10, y: -2 }, Point { x: 10, y: 10 }] }] }");
647}
648
649#[test]
650#[rustfmt::skip]
651fn test_read_multipoint() {
652 let twkb = hex_to_vec("04000214271326"); let points = MultiPoint::read_twkb(&mut twkb.as_slice()).unwrap();
654 assert_eq!(format!("{:.0?}", points), "MultiPoint { points: [Point { x: 10, y: -20 }, Point { x: 0, y: -1 }], ids: None }");
655}
656
657#[test]
658#[rustfmt::skip]
659fn test_read_multiline() {
660 let twkb = hex_to_vec("05000202142713260200020400"); let lines = MultiLineString::read_twkb(&mut twkb.as_slice()).unwrap();
662 assert_eq!(format!("{:.0?}", lines), "MultiLineString { lines: [LineString { points: [Point { x: 10, y: -20 }, Point { x: 0, y: -1 }] }, LineString { points: [Point { x: 0, y: 0 }, Point { x: 2, y: 0 }] }], ids: None }");
663}
664
665#[test]
666#[rustfmt::skip]
667fn test_read_multipolygon() {
668 let twkb = hex_to_vec("060002010500000400000403000003010514141700001718000018"); let polys = MultiPolygon::read_twkb(&mut twkb.as_slice()).unwrap();
670 assert_eq!(format!("{:.0?}", polys), "MultiPolygon { polygons: [Polygon { rings: [LineString { points: [Point { x: 0, y: 0 }, Point { x: 2, y: 0 }, Point { x: 2, y: 2 }, Point { x: 0, y: 2 }, Point { x: 0, y: 0 }] }] }, Polygon { rings: [LineString { points: [Point { x: 10, y: 10 }, Point { x: -2, y: 10 }, Point { x: -2, y: -2 }, Point { x: 10, y: -2 }, Point { x: 10, y: 10 }] }] }], ids: None }");
671}
672
673#[test]
674#[rustfmt::skip]
675fn test_write_point() {
676 let twkb = hex_to_vec("01001427"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
678 assert_eq!(format!("{:?}", point.as_ewkb()), "EwkbPoint");
679 assert_eq!(point.as_ewkb().to_hex_ewkb(), "0101000000000000000000244000000000000034C0");
680}
681
682#[test]
683#[rustfmt::skip]
684fn test_write_line() {
685 let twkb = hex_to_vec("220002c8018f03c7018603"); let line = LineString::read_twkb(&mut twkb.as_slice()).unwrap();
687 assert_eq!(format!("{:?}", line.as_ewkb()), "EwkbLineString");
688 assert_eq!(line.as_ewkb().to_hex_ewkb(), "010200000002000000000000000000244000000000000034C00000000000000000000000000000E0BF");
689}
690
691#[test]
692#[rustfmt::skip]
693fn test_write_polygon() {
694 let twkb = hex_to_vec("03000205000004000004030000030514141700001718000018"); let polygon = Polygon::read_twkb(&mut twkb.as_slice()).unwrap();
696 assert_eq!(format!("{:?}", polygon.as_ewkb()), "EwkbPolygon");
697 assert_eq!(polygon.as_ewkb().to_hex_ewkb(), "010300000002000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000050000000000000000002440000000000000244000000000000000C0000000000000244000000000000000C000000000000000C0000000000000244000000000000000C000000000000024400000000000002440");
698}
699
700#[test]
701#[rustfmt::skip]
702fn test_write_multipoint() {
703 let twkb = hex_to_vec("04000214271326"); let multipoint = MultiPoint::read_twkb(&mut twkb.as_slice()).unwrap();
705 assert_eq!(format!("{:?}", multipoint.as_ewkb()), "EwkbMultiPoint");
706 assert_eq!(multipoint.as_ewkb().to_hex_ewkb(), "0104000000020000000101000000000000000000244000000000000034C001010000000000000000000000000000000000F0BF");
709}
710
711#[test]
712#[rustfmt::skip]
713fn test_write_multiline() {
714 let twkb = hex_to_vec("05000202142713260200020400"); let multiline = MultiLineString::read_twkb(&mut twkb.as_slice()).unwrap();
716 assert_eq!(format!("{:?}", multiline.as_ewkb()), "EwkbMultiLineString");
717 assert_eq!(multiline.as_ewkb().to_hex_ewkb(), "010500000002000000010200000002000000000000000000244000000000000034C00000000000000000000000000000F0BF0102000000020000000000000000000000000000000000000000000000000000400000000000000000");
720}
721
722#[test]
723#[rustfmt::skip]
724fn test_write_multipoly() {
725 let twkb = hex_to_vec("060002010500000400000403000003010514141700001718000018"); let multipoly = MultiPolygon::read_twkb(&mut twkb.as_slice()).unwrap();
727 assert_eq!(format!("{:?}", multipoly.as_ewkb()), "EwkbMultiPolygon");
728 assert_eq!(multipoly.as_ewkb().to_hex_ewkb(), "010600000002000000010300000001000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000010300000001000000050000000000000000002440000000000000244000000000000000C0000000000000244000000000000000C000000000000000C0000000000000244000000000000000C000000000000024400000000000002440");
729}
730
731#[cfg(all(test, feature = "serde"))]
732mod serde_tests {
733 use super::*;
734 use serde_json;
735
736 #[test]
737 fn test_serde_point() {
738 let point = Point { x: 10.0, y: -20.0 };
739
740 let serialized = serde_json::to_string(&point).unwrap();
741 let deserialized: Point = serde_json::from_str(&serialized).unwrap();
742
743 assert_eq!(point, deserialized);
744 }
745
746 #[test]
747 fn test_serde_linestring() {
748 let line = LineString {
749 points: vec![Point { x: 10.0, y: -20.0 }, Point { x: 0.0, y: -0.5 }],
750 };
751
752 let serialized = serde_json::to_string(&line).unwrap();
753 let deserialized: LineString = serde_json::from_str(&serialized).unwrap();
754
755 assert_eq!(line, deserialized);
756 }
757}