1use crate::{error::Error, ewkb, types as postgis};
20use byteorder::ReadBytesExt;
21use std::f64;
22use std::fmt;
23use std::io::prelude::*;
24use std::slice::Iter;
25use std::u8;
26
27#[derive(PartialEq, Clone, Copy, Debug)]
28pub struct Point {
29 pub x: f64,
30 pub y: f64, }
32
33#[derive(PartialEq, Clone, Debug)]
34pub struct LineString {
35 pub points: Vec<Point>,
36}
37
38#[derive(PartialEq, Clone, Debug)]
39pub struct Polygon {
40 pub rings: Vec<LineString>,
41}
42
43#[derive(PartialEq, Clone, Debug)]
44pub struct MultiPoint {
45 pub points: Vec<Point>,
46 pub ids: Option<Vec<u64>>,
47}
48
49#[derive(PartialEq, Clone, Debug)]
50pub struct MultiLineString {
51 pub lines: Vec<LineString>,
52 pub ids: Option<Vec<u64>>,
53}
54
55#[derive(PartialEq, Clone, Debug)]
56pub struct MultiPolygon {
57 pub polygons: Vec<Polygon>,
58 pub ids: Option<Vec<u64>>,
59}
60
61#[doc(hidden)]
62#[derive(Default, Debug)]
63pub struct TwkbInfo {
64 geom_type: u8,
65 precision: i8,
66 has_idlist: bool,
67 is_empty_geom: bool,
68 size: Option<u64>,
69 has_z: bool,
70 has_m: bool,
71 prec_z: Option<u8>,
72 prec_m: Option<u8>,
73}
74
75pub trait TwkbGeom: fmt::Debug + Sized {
76 fn read_twkb<R: Read>(raw: &mut R) -> Result<Self, Error> {
77 let mut twkb_info: TwkbInfo = Default::default();
78 let type_and_prec = raw.read_u8()?;
84 twkb_info.geom_type = type_and_prec & 0x0F;
85 twkb_info.precision = decode_zig_zag_64(((type_and_prec & 0xF0) >> 4) as u64) as i8;
86 let metadata_header = raw.read_u8()?;
87 let has_bbox = (metadata_header & 0b0001) != 0;
88 let has_size_attribute = (metadata_header & 0b0010) != 0;
89 twkb_info.has_idlist = (metadata_header & 0b0100) != 0;
90 let has_ext_prec_info = (metadata_header & 0b1000) != 0;
91 twkb_info.is_empty_geom = (metadata_header & 0b10000) != 0;
92 if has_ext_prec_info {
93 let ext_prec_info = raw.read_u8()?;
94 twkb_info.has_z = ext_prec_info & 0b0001 != 0;
95 twkb_info.has_m = ext_prec_info & 0b0010 != 0;
96 twkb_info.prec_z = Some((ext_prec_info & 0x1C) >> 2);
97 twkb_info.prec_m = Some((ext_prec_info & 0xE0) >> 5);
98 }
99 if has_size_attribute {
100 twkb_info.size = Some(read_raw_varint64(raw)?);
101 }
102 if has_bbox {
103 let _xmin = read_int64(raw)?;
104 let _deltax = read_int64(raw)?;
105 let _ymin = read_int64(raw)?;
106 let _deltay = read_int64(raw)?;
107 if twkb_info.has_z {
108 let _zmin = read_int64(raw)?;
109 let _deltaz = read_int64(raw)?;
110 }
111 if twkb_info.has_m {
112 let _mmin = read_int64(raw)?;
113 let _deltam = read_int64(raw)?;
114 }
115 }
116 Self::read_twkb_body(raw, &twkb_info)
117 }
118
119 #[doc(hidden)]
120 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error>;
121
122 #[doc(hidden)]
123 fn read_relative_point<R: Read>(
124 raw: &mut R,
125 twkb_info: &TwkbInfo,
126 x: f64,
127 y: f64,
128 z: Option<f64>,
129 m: Option<f64>,
130 ) -> Result<(f64, f64, Option<f64>, Option<f64>), Error> {
131 let x2 = x + read_varint64_as_f64(raw, twkb_info.precision)?;
132 let y2 = y + read_varint64_as_f64(raw, twkb_info.precision)?;
133 let z2 = if twkb_info.has_z {
134 let dz = read_varint64_as_f64(raw, twkb_info.precision)?;
135 z.map(|v| v + dz)
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 } else {
143 None
144 };
145 Ok((x2, y2, z2, m2))
146 }
147
148 fn read_idlist<R: Read>(raw: &mut R, size: usize) -> Result<Vec<u64>, Error> {
149 let mut idlist = Vec::new();
150 idlist.reserve(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 = 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 } else {
191 (decode_zig_zag_64(varint) as f64) * 10u64.pow(precision.abs() as u32) as f64
192 }
193}
194
195fn read_varint64_as_f64<R: Read>(raw: &mut R, precision: i8) -> Result<f64, Error> {
196 read_raw_varint64(raw).map(|v| varint64_to_f64(v, precision))
197}
198
199impl Point {
202 fn new_from_opt_vals(x: f64, y: f64, _z: Option<f64>, _m: Option<f64>) -> Self {
203 Point { x: x, y: y }
204 }
205}
206
207impl postgis::Point for Point {
208 fn x(&self) -> f64 {
209 self.x
210 }
211 fn y(&self) -> f64 {
212 self.y
213 }
214}
215
216impl TwkbGeom for Point {
217 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
218 if twkb_info.is_empty_geom {
219 return Ok(Point::new_from_opt_vals(f64::NAN, f64::NAN, None, None));
220 }
221 let x = read_varint64_as_f64(raw, twkb_info.precision)?;
222 let y = read_varint64_as_f64(raw, twkb_info.precision)?;
223 let z = if twkb_info.has_z {
224 Some(read_varint64_as_f64(raw, twkb_info.precision)?)
225 } else {
226 None
227 };
228 let m = if twkb_info.has_m {
229 Some(read_varint64_as_f64(raw, twkb_info.precision)?)
230 } else {
231 None
232 };
233 Ok(Self::new_from_opt_vals(x, y, z, m))
234 }
235}
236
237impl<'a> ewkb::AsEwkbPoint<'a> for Point {
238 fn as_ewkb(&'a self) -> ewkb::EwkbPoint<'a> {
239 ewkb::EwkbPoint {
240 geom: self,
241 srid: None,
242 point_type: ewkb::PointType::Point,
243 }
244 }
245}
246
247impl TwkbGeom for LineString {
248 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
249 let mut points: Vec<Point> = Vec::new();
252 if !twkb_info.is_empty_geom {
253 let npoints = read_raw_varint64(raw)?;
254 points.reserve(npoints as usize);
255 let mut x = 0.0;
256 let mut y = 0.0;
257 let mut z = if twkb_info.has_z { Some(0.0) } else { None };
258 let mut m = if twkb_info.has_m { Some(0.0) } else { None };
259 for _ in 0..npoints {
260 let (x2, y2, z2, m2) = Self::read_relative_point(raw, twkb_info, x, y, z, m)?;
261 points.push(Point::new_from_opt_vals(x2, y2, z2, m2));
262 x = x2;
263 y = y2;
264 z = z2;
265 m = m2;
266 }
267 }
268 Ok(LineString { points: points })
269 }
270}
271
272impl<'a> postgis::LineString<'a> for LineString {
273 type ItemType = Point;
274 type Iter = Iter<'a, Self::ItemType>;
275 fn points(&'a self) -> Self::Iter {
276 self.points.iter()
277 }
278}
279
280impl<'a> ewkb::AsEwkbLineString<'a> for LineString {
281 type PointType = Point;
282 type Iter = Iter<'a, Point>;
283 fn as_ewkb(&'a self) -> ewkb::EwkbLineString<'a, Self::PointType, Self::Iter> {
284 ewkb::EwkbLineString {
285 geom: self,
286 srid: None,
287 point_type: ewkb::PointType::Point,
288 }
289 }
290}
291
292impl TwkbGeom for Polygon {
293 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
294 let mut rings: Vec<LineString> = Vec::new();
301 let nrings = read_raw_varint64(raw)?;
302 rings.reserve(nrings as usize);
303 let mut x = 0.0;
304 let mut y = 0.0;
305 let mut z = if twkb_info.has_z { Some(0.0) } else { None };
306 let mut m = if twkb_info.has_m { Some(0.0) } else { None };
307 for _ in 0..nrings {
308 let mut points: Vec<Point> = Vec::new();
309 let npoints = read_raw_varint64(raw)?;
310 points.reserve(npoints as usize);
311 let (x0, y0, z0, m0) = (x, y, z, m);
312 for _ in 0..npoints {
313 let (x2, y2, z2, m2) = Self::read_relative_point(raw, twkb_info, x, y, z, m)?;
314 points.push(Point::new_from_opt_vals(x2, y2, z2, m2));
315 x = x2;
316 y = y2;
317 z = z2;
318 m = m2;
319 }
320 if x != x0 && y != y0 && z != z0 && m != m0 {
322 points.push(Point::new_from_opt_vals(x0, y0, z0, m0));
323 }
324 rings.push(LineString { points: points });
325 }
326 Ok(Polygon { rings: rings })
327 }
328}
329
330impl<'a> postgis::Polygon<'a> for Polygon {
331 type ItemType = LineString;
332 type Iter = Iter<'a, Self::ItemType>;
333 fn rings(&'a self) -> Self::Iter {
334 self.rings.iter()
335 }
336}
337
338impl<'a> ewkb::AsEwkbPolygon<'a> for Polygon {
339 type PointType = Point;
340 type PointIter = Iter<'a, Point>;
341 type ItemType = LineString;
342 type Iter = Iter<'a, Self::ItemType>;
343 fn as_ewkb(
344 &'a self,
345 ) -> ewkb::EwkbPolygon<'a, Self::PointType, Self::PointIter, Self::ItemType, Self::Iter> {
346 ewkb::EwkbPolygon {
347 geom: self,
348 srid: None,
349 point_type: ewkb::PointType::Point,
350 }
351 }
352}
353
354impl TwkbGeom for MultiPoint {
355 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
356 let mut points: Vec<Point> = Vec::new();
360 let mut ids: Option<Vec<u64>> = None;
361 if !twkb_info.is_empty_geom {
362 let npoints = read_raw_varint64(raw)?;
363 points.reserve(npoints as usize);
364
365 if twkb_info.has_idlist {
366 let idlist = Self::read_idlist(raw, npoints as usize)?;
367 ids = Some(idlist);
368 }
369
370 let mut x = 0.0;
371 let mut y = 0.0;
372 let mut z = if twkb_info.has_z { Some(0.0) } else { None };
373 let mut m = if twkb_info.has_m { Some(0.0) } else { None };
374 for _ in 0..npoints {
375 let (x2, y2, z2, m2) = Self::read_relative_point(raw, twkb_info, x, y, z, m)?;
376 points.push(Point::new_from_opt_vals(x2, y2, z2, m2));
377 x = x2;
378 y = y2;
379 z = z2;
380 m = m2;
381 }
382 }
383 Ok(MultiPoint {
384 points: points,
385 ids: ids,
386 })
387 }
388}
389
390impl<'a> postgis::MultiPoint<'a> for MultiPoint {
391 type ItemType = Point;
392 type Iter = Iter<'a, Self::ItemType>;
393 fn points(&'a self) -> Self::Iter {
394 self.points.iter()
395 }
396}
397
398impl<'a> ewkb::AsEwkbMultiPoint<'a> for MultiPoint {
399 type PointType = Point;
400 type Iter = Iter<'a, Point>;
401 fn as_ewkb(&'a self) -> ewkb::EwkbMultiPoint<'a, Self::PointType, Self::Iter> {
402 ewkb::EwkbMultiPoint {
403 geom: self,
404 srid: None,
405 point_type: ewkb::PointType::Point,
406 }
407 }
408}
409
410impl TwkbGeom for MultiLineString {
411 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
412 let mut lines: Vec<LineString> = Vec::new();
420 let mut ids: Option<Vec<u64>> = None;
421 let nlines = read_raw_varint64(raw)?;
422 lines.reserve(nlines as usize);
423
424 if twkb_info.has_idlist {
425 let idlist = Self::read_idlist(raw, nlines as usize)?;
426 ids = Some(idlist);
427 }
428
429 let mut x = 0.0;
430 let mut y = 0.0;
431 let mut z = if twkb_info.has_z { Some(0.0) } else { None };
432 let mut m = if twkb_info.has_m { Some(0.0) } else { None };
433 for _ in 0..nlines {
434 let mut points: Vec<Point> = Vec::new();
435 let npoints = read_raw_varint64(raw)?;
436 points.reserve(npoints as usize);
437 for _ in 0..npoints {
438 let (x2, y2, z2, m2) = Self::read_relative_point(raw, twkb_info, x, y, z, m)?;
439 points.push(Point::new_from_opt_vals(x2, y2, z2, m2));
440 x = x2;
441 y = y2;
442 z = z2;
443 m = m2;
444 }
445 lines.push(LineString { points: points });
446 }
447 Ok(MultiLineString {
448 lines: lines,
449 ids: ids,
450 })
451 }
452}
453
454impl<'a> postgis::MultiLineString<'a> for MultiLineString {
455 type ItemType = LineString;
456 type Iter = Iter<'a, Self::ItemType>;
457 fn lines(&'a self) -> Self::Iter {
458 self.lines.iter()
459 }
460}
461
462impl<'a> ewkb::AsEwkbMultiLineString<'a> for MultiLineString {
463 type PointType = Point;
464 type PointIter = Iter<'a, Point>;
465 type ItemType = LineString;
466 type Iter = Iter<'a, Self::ItemType>;
467 fn as_ewkb(
468 &'a self,
469 ) -> ewkb::EwkbMultiLineString<'a, Self::PointType, Self::PointIter, Self::ItemType, Self::Iter>
470 {
471 ewkb::EwkbMultiLineString {
472 geom: self,
473 srid: None,
474 point_type: ewkb::PointType::Point,
475 }
476 }
477}
478
479impl TwkbGeom for MultiPolygon {
480 fn read_twkb_body<R: Read>(raw: &mut R, twkb_info: &TwkbInfo) -> Result<Self, Error> {
481 let mut polygons: Vec<Polygon> = Vec::new();
491 let mut ids: Option<Vec<u64>> = None;
492 let npolygons = read_raw_varint64(raw)?;
493 polygons.reserve(npolygons as usize);
494
495 if twkb_info.has_idlist {
496 let idlist = Self::read_idlist(raw, npolygons as usize)?;
497 ids = Some(idlist);
498 }
499
500 let mut x = 0.0;
501 let mut y = 0.0;
502 let mut z = if twkb_info.has_z { Some(0.0) } else { None };
503 let mut m = if twkb_info.has_m { Some(0.0) } else { None };
504 for _ in 0..npolygons {
505 let mut rings: Vec<LineString> = Vec::new();
506 let nrings = read_raw_varint64(raw)?;
507 rings.reserve(nrings as usize);
508 for _ in 0..nrings {
509 let mut points: Vec<Point> = Vec::new();
510 let npoints = read_raw_varint64(raw)?;
511 points.reserve(npoints as usize);
512 let (x0, y0, z0, m0) = (x, y, z, m);
513 for _ in 0..npoints {
514 let (x2, y2, z2, m2) = Self::read_relative_point(raw, twkb_info, x, y, z, m)?;
515 points.push(Point::new_from_opt_vals(x2, y2, z2, m2));
516 x = x2;
517 y = y2;
518 z = z2;
519 m = m2;
520 }
521 if x != x0 && y != y0 && z != z0 && m != m0 {
523 points.push(Point::new_from_opt_vals(x0, y0, z0, m0));
524 }
525 rings.push(LineString { points: points });
526 }
527 polygons.push(Polygon { rings: rings });
528 }
529 Ok(MultiPolygon {
530 polygons: polygons,
531 ids: ids,
532 })
533 }
534}
535
536impl<'a> postgis::MultiPolygon<'a> for MultiPolygon {
537 type ItemType = Polygon;
538 type Iter = Iter<'a, Self::ItemType>;
539 fn polygons(&'a self) -> Self::Iter {
540 self.polygons.iter()
541 }
542}
543
544impl<'a> ewkb::AsEwkbMultiPolygon<'a> for MultiPolygon {
545 type PointType = Point;
546 type PointIter = Iter<'a, Point>;
547 type LineType = LineString;
548 type LineIter = Iter<'a, Self::LineType>;
549 type ItemType = Polygon;
550 type Iter = Iter<'a, Self::ItemType>;
551 fn as_ewkb(
552 &'a self,
553 ) -> ewkb::EwkbMultiPolygon<
554 'a,
555 Self::PointType,
556 Self::PointIter,
557 Self::LineType,
558 Self::LineIter,
559 Self::ItemType,
560 Self::Iter,
561 > {
562 ewkb::EwkbMultiPolygon {
563 geom: self,
564 srid: None,
565 point_type: ewkb::PointType::Point,
566 }
567 }
568}
569
570#[cfg(test)]
571use ewkb::{
572 AsEwkbLineString, AsEwkbMultiLineString, AsEwkbMultiPoint, AsEwkbMultiPolygon, AsEwkbPoint,
573 AsEwkbPolygon, EwkbWrite,
574};
575
576#[cfg(test)]
577#[cfg_attr(rustfmt, rustfmt_skip)]
578fn hex_to_vec(hexstr: &str) -> Vec<u8> {
579 hexstr.as_bytes().chunks(2).map(|chars| {
580 let hb = if chars[0] <= 57 { chars[0] - 48 } else { chars[0] - 87 };
581 let lb = if chars[1] <= 57 { chars[1] - 48 } else { chars[1] - 87 };
582 hb * 16 + lb
583 }).collect::<Vec<_>>()
584}
585
586#[test]
587#[cfg_attr(rustfmt, rustfmt_skip)]
588fn test_read_point() {
589 let twkb = hex_to_vec("01001427"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
591 assert_eq!(format!("{:.0?}", point), "Point { x: 10, y: -20 }");
592
593 let twkb = hex_to_vec("0108011427c601"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
595 assert_eq!(format!("{:.0?}", point), "Point { x: 10, y: -20 }");
596
597 let twkb = hex_to_vec("2100ca019503"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
599 assert_eq!(format!("{:.1?}", point), "Point { x: 10.1, y: -20.3 }");
600
601 let twkb = hex_to_vec("11000203"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
603 assert_eq!(format!("{:.0?}", point), "Point { x: 10, y: -20 }");
604
605 let twkb = hex_to_vec("0110"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
607 assert_eq!(format!("{:?}", point), "Point { x: NaN, y: NaN }");
608
609 let twkb = hex_to_vec("a10080897aff91f401"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
611 assert_eq!(format!("{:.0?}", point), "Point { x: 10, y: -20 }");
612}
613
614#[test]
615#[cfg_attr(rustfmt, rustfmt_skip)]
616fn test_read_line() {
617 let twkb = hex_to_vec("02000214271326"); let line = LineString::read_twkb(&mut twkb.as_slice()).unwrap();
619 assert_eq!(format!("{:.0?}", line), "LineString { points: [Point { x: 10, y: -20 }, Point { x: 0, y: -1 }] }");
620
621 let twkb = hex_to_vec("220002c8018f03c7018603"); let line = LineString::read_twkb(&mut twkb.as_slice()).unwrap();
623 assert_eq!(format!("{:.1?}", line), "LineString { points: [Point { x: 10.0, y: -20.0 }, Point { x: 0.0, y: -0.5 }] }");
624
625 let twkb = hex_to_vec("0210"); let line = LineString::read_twkb(&mut twkb.as_slice()).unwrap();
627 assert_eq!(format!("{:?}", line), "LineString { points: [] }");
628}
629
630#[test]
631#[cfg_attr(rustfmt, rustfmt_skip)]
632fn test_read_polygon() {
633 let twkb = hex_to_vec("03000205000004000004030000030514141700001718000018"); let poly = Polygon::read_twkb(&mut twkb.as_slice()).unwrap();
635 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 }] }] }");
636}
637
638#[test]
639#[cfg_attr(rustfmt, rustfmt_skip)]
640fn test_read_multipoint() {
641 let twkb = hex_to_vec("04000214271326"); let points = MultiPoint::read_twkb(&mut twkb.as_slice()).unwrap();
643 assert_eq!(format!("{:.0?}", points), "MultiPoint { points: [Point { x: 10, y: -20 }, Point { x: 0, y: -1 }], ids: None }");
644}
645
646#[test]
647#[cfg_attr(rustfmt, rustfmt_skip)]
648fn test_read_multiline() {
649 let twkb = hex_to_vec("05000202142713260200020400"); let lines = MultiLineString::read_twkb(&mut twkb.as_slice()).unwrap();
651 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 }");
652}
653
654#[test]
655#[cfg_attr(rustfmt, rustfmt_skip)]
656fn test_read_multipolygon() {
657 let twkb = hex_to_vec("060002010500000400000403000003010514141700001718000018"); let polys = MultiPolygon::read_twkb(&mut twkb.as_slice()).unwrap();
659 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 }");
660}
661
662#[test]
663#[cfg_attr(rustfmt, rustfmt_skip)]
664fn test_write_point() {
665 let twkb = hex_to_vec("01001427"); let point = Point::read_twkb(&mut twkb.as_slice()).unwrap();
667 assert_eq!(format!("{:?}", point.as_ewkb()), "EwkbPoint");
668 assert_eq!(point.as_ewkb().to_hex_ewkb(), "0101000000000000000000244000000000000034C0");
669}
670
671#[test]
672#[cfg_attr(rustfmt, rustfmt_skip)]
673fn test_write_line() {
674 let twkb = hex_to_vec("220002c8018f03c7018603"); let line = LineString::read_twkb(&mut twkb.as_slice()).unwrap();
676 assert_eq!(format!("{:?}", line.as_ewkb()), "EwkbLineString");
677 assert_eq!(line.as_ewkb().to_hex_ewkb(), "010200000002000000000000000000244000000000000034C00000000000000000000000000000E0BF");
678}
679
680#[test]
681#[cfg_attr(rustfmt, rustfmt_skip)]
682fn test_write_polygon() {
683 let twkb = hex_to_vec("03000205000004000004030000030514141700001718000018"); let polygon = Polygon::read_twkb(&mut twkb.as_slice()).unwrap();
685 assert_eq!(format!("{:?}", polygon.as_ewkb()), "EwkbPolygon");
686 assert_eq!(polygon.as_ewkb().to_hex_ewkb(), "010300000002000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000050000000000000000002440000000000000244000000000000000C0000000000000244000000000000000C000000000000000C0000000000000244000000000000000C000000000000024400000000000002440");
687}
688
689#[test]
690#[cfg_attr(rustfmt, rustfmt_skip)]
691fn test_write_multipoint() {
692 let twkb = hex_to_vec("04000214271326"); let multipoint = MultiPoint::read_twkb(&mut twkb.as_slice()).unwrap();
694 assert_eq!(format!("{:?}", multipoint.as_ewkb()), "EwkbMultiPoint");
695 assert_eq!(multipoint.as_ewkb().to_hex_ewkb(), "0104000000020000000101000000000000000000244000000000000034C001010000000000000000000000000000000000F0BF");
698}
699
700#[test]
701#[cfg_attr(rustfmt, rustfmt_skip)]
702fn test_write_multiline() {
703 let twkb = hex_to_vec("05000202142713260200020400"); let multiline = MultiLineString::read_twkb(&mut twkb.as_slice()).unwrap();
705 assert_eq!(format!("{:?}", multiline.as_ewkb()), "EwkbMultiLineString");
706 assert_eq!(multiline.as_ewkb().to_hex_ewkb(), "010500000002000000010200000002000000000000000000244000000000000034C00000000000000000000000000000F0BF0102000000020000000000000000000000000000000000000000000000000000400000000000000000");
709}
710
711#[test]
712#[cfg_attr(rustfmt, rustfmt_skip)]
713fn test_write_multipoly() {
714 let twkb = hex_to_vec("060002010500000400000403000003010514141700001718000018"); let multipoly = MultiPolygon::read_twkb(&mut twkb.as_slice()).unwrap();
716 assert_eq!(format!("{:?}", multipoly.as_ewkb()), "EwkbMultiPolygon");
717 assert_eq!(multipoly.as_ewkb().to_hex_ewkb(), "010600000002000000010300000001000000050000000000000000000000000000000000000000000000000000400000000000000000000000000000004000000000000000400000000000000000000000000000004000000000000000000000000000000000010300000001000000050000000000000000002440000000000000244000000000000000C0000000000000244000000000000000C000000000000000C0000000000000244000000000000000C000000000000024400000000000002440");
718}