use byteorder::{LittleEndian, NetworkEndian, WriteBytesExt};
use chrono::{TimeZone, Utc};
use geo_types::Geometry;
use geojson::{conversion::TryInto, GeoJson};
use std::{
error::Error,
io::{self, prelude::*},
mem::size_of,
};
use uuid::Uuid;
use wkb::geom_to_wkb;
type NE = NetworkEndian;
#[rustfmt::skip]
fn main() -> Result<(), Box<dyn Error>> {
let stdout = io::stdout();
let mut out = stdout.lock();
out.write_all(b"PGCOPY\n")?;
out.write_all(&[0o377])?;
out.write_all(b"\r\n\0")?;
out.write_u32::<NE>(0)?;
out.write_u32::<NE>(0)?;
out.write_i16::<NE>(15)?;
out.write_i32::<NE>(-1)?;
out.write_i32::<NE>(8*4)?; out.write_i32::<NE>(1)?; out.write_i32::<NE>(1)?; out.write_i32::<NE>(23)?;
out.write_i32::<NE>(2)?; out.write_i32::<NE>(1)?;
out.write_i32::<NE>(-1)?; out.write_i32::<NE>(size_of::<i32>() as i32)?; out.write_i32::<NE>(32)?;
out.write_i32::<NE>(size_of::<u8>() as i32)?;
out.write_u8(1)?;
out.write_i32::<NE>(size_of::<i32>() as i32)?;
out.write_i32::<NE>(-11122)?;
out.write_i32::<NE>(size_of::<f32>() as i32)?;
out.write_f32::<NE>(32.0)?;
out.write_i32::<NE>(size_of::<f64>() as i32)?;
out.write_f64::<NE>(64.0)?;
let geojson = r#"{
"type": "Point",
"coordinates": [
-71.05446875095367,
42.36631683939881
]
}"#.parse::<GeoJson>().expect("invalid GeoJSON");
let mut wkb = if let GeoJson::Geometry(geometry) = geojson {
let point: Geometry<f64> = geometry.value.try_into()
.expect("couldn't convert point");
geom_to_wkb(&point)
} else {
panic!("expected geometry");
};
wkb[4] |= 0x20; let mut srid = Vec::with_capacity(4);
srid.write_u32::<LittleEndian>(4326)?;
wkb.splice(5..5, srid); out.write_i32::<NE>(wkb.len() as i32)?;
out.write_all(&wkb)?;
out.write_i32::<NE>(size_of::<i16>() as i32)?;
out.write_i16::<NE>(16)?;
out.write_i32::<NE>(size_of::<i32>() as i32)?;
out.write_i32::<NE>(32)?;
out.write_i32::<NE>(size_of::<i64>() as i32)?;
out.write_i64::<NE>(64)?;
let json = r#"{ "x": 2 }"#;
out.write_i32::<NE>((json.len() + 1) as i32)?;
out.write_u8(1)?; out.write_all(json.as_bytes())?;
let text = "Hello";
out.write_i32::<NE>(text.len() as i32)?;
out.write_all(text.as_bytes())?;
let j_epoch = Utc.ymd(2000, 01, 01).and_hms(0, 0, 0);
let date_time = Utc.ymd(1969, 07, 20).and_hms(20, 17, 39);
let duration = date_time - j_epoch;
let microseconds = duration.num_microseconds()
.expect("date math overflow");
out.write_i32::<NE>(size_of::<i64>() as i32)?;
out.write_i64::<NE>(microseconds)?;
out.write_i32::<NE>(size_of::<i64>() as i32)?;
out.write_i64::<NE>(microseconds)?;
let uuid = "fc438a75-3bf8-4941-8751-9208526e9516".parse::<Uuid>()?;
out.write_i32::<NE>(uuid.as_bytes().len() as i32)?;
out.write_all(uuid.as_bytes())?;
out.write_i16::<NE>(-1)?;
Ok(())
}