1use std::io::{Read,ErrorKind};
2use anyhow::{bail,Result};
3use serde::{Serialize,Deserialize};
4
5pub type PolygonId = usize;
6
7#[derive(Debug,Clone,Serialize,Deserialize,PartialEq)]
8pub enum Level {
9 Land,
10 Lake,
11 IslandInLake,
12 PondInIslandInLake,
13 AntarcticIceFront,
14 AntarcticGroundingLine,
15 Other(u8)
16}
17
18#[derive(Debug,Clone,Serialize,Deserialize,PartialEq)]
19pub enum Source {
20 CiaWdbii,
21 Wvs,
22 Other(u8)
23}
24
25#[derive(Debug,Clone,Serialize,Deserialize)]
27pub struct Polygon {
28 pub id:PolygonId,
30
31 pub n:usize,
33
34 pub level:Level,
36 pub version:u8,
37 pub greenwich_crossed:bool,
38 pub source:Source,
39 pub river:bool,
40
41 pub west:i32,
43 pub east:i32,
44 pub south:i32,
45 pub north:i32,
46
47 pub area:u32,
49
50 pub area_full:u32,
52
53 pub container:Option<PolygonId>,
55
56 pub ancestor:Option<PolygonId>,
58
59 pub points:Vec<Point>,
61
62 pub children:Vec<PolygonId>
64}
65
66#[derive(Debug,Clone,Serialize,Deserialize)]
68pub struct Point {
69 pub x:i32,
70 pub y:i32
71}
72
73#[derive(Debug,Clone,Serialize,Deserialize)]
74pub struct Gshhg {
75 pub polygons:Vec<Polygon>
76}
77
78fn read_u32<R:Read>(mut r:R)->Result<u32> {
79 let mut x = [0;4];
80 r.read_exact(&mut x)?;
81 Ok(u32::from_be_bytes(x))
82}
83
84fn read_i32<R:Read>(mut r:R)->Result<i32> {
85 let mut x = [0;4];
86 r.read_exact(&mut x)?;
87 Ok(i32::from_be_bytes(x))
88}
89
90fn read_id_option<R:Read>(r:R)->Result<Option<PolygonId>> {
91 let id = read_i32(r)?;
92 if id < 0 {
93 Ok(None)
94 } else {
95 Ok(Some(id as usize))
96 }
97}
98
99impl From<u8> for Level {
100 fn from(x:u8)->Self {
101 match x {
102 1 => Self::Land,
103 2 => Self::Lake,
104 3 => Self::IslandInLake,
105 4 => Self::PondInIslandInLake,
106 5 => Self::AntarcticIceFront,
107 6 => Self::AntarcticGroundingLine,
108 _ => Self::Other(x)
109 }
110 }
111}
112
113impl From<u8> for Source {
114 fn from(x:u8)->Self {
115 match x {
116 0 => Self::CiaWdbii,
117 1 => Self::Wvs,
118 _ => Self::Other(x)
119 }
120 }
121}
122
123impl Point {
124 pub fn from_reader<R:Read>(mut r:R)->Result<Self> {
125 let x = read_i32(&mut r)?;
126 let y = read_i32(&mut r)?;
127 Ok(Self{ x,y })
128 }
129}
130
131impl Polygon {
132 pub fn from_reader<R:Read>(mut r:R,expected_id:Option<PolygonId>)
133 ->Result<Option<Self>> {
134 let id =
135 match read_id_option(&mut r) {
136 Ok(Some(id)) => {
137 if let Some(eid) = expected_id {
138 if eid != id {
139 bail!("Unexpected polygon ID {} (was expecting {})",
140 id,eid);
141 }
142 }
143 id
144 }
145 Ok(None) => bail!("Invalid polygon ID"),
146 Err(e) => {
147 if let Some(ed) = e.downcast_ref::<std::io::Error>() {
148 match ed.kind() {
149 ErrorKind::UnexpectedEof => return Ok(None),
150 _ => return Err(e)
151 }
152 }
153 return Ok(None)
154 }
155 };
156 let n = read_u32(&mut r)? as usize;
157 let flag = read_u32(&mut r)?;
158
159 let level = Level::from((flag & 255) as u8);
160 let version = ((flag >> 8) & 255) as u8;
161 let greenwich_crossed = ((flag >> 16) & 1) != 0;
162 let source = Source::from(((flag >> 24) & 255) as u8);
163 let river = ((flag >> 24) & 1) != 0;
164
165 let west = read_i32(&mut r)?;
166 let east = read_i32(&mut r)?;
167 let south = read_i32(&mut r)?;
168 let north = read_i32(&mut r)?;
169 let area = read_u32(&mut r)?;
170 let area_full = read_u32(&mut r)?;
171 let container = read_id_option(&mut r)?;
172 let ancestor = read_id_option(&mut r)?;
173 let mut points = Vec::with_capacity(n);
174 for _ in 0..n {
175 points.push(Point::from_reader(&mut r)?);
176 }
177 Ok(Some(Self{
178 id,
179 n,
180 level,
181 version,
182 greenwich_crossed,
183 source,
184 river,
185 west,
186 east,
187 south,
188 north,
189 area,
190 area_full,
191 container,
192 ancestor,
193 points,
194 children:Vec::new()
195 }))
196 }
197}
198
199impl Gshhg {
200 pub fn from_reader<R:Read>(mut r:R)->Result<Self> {
201 let mut polygons = Vec::new();
202 let mut expected_id = Some(0);
203 loop {
204 match Polygon::from_reader(&mut r,expected_id)? {
205 Some(poly) => polygons.push(poly),
206 None => break
207 }
208 expected_id = None;
209 }
210
211 let npoly = polygons.len();
213 for ipoly in 0..npoly {
214 if let Some(iparent) = polygons[ipoly].container {
215 polygons[iparent].children.push(ipoly);
216 }
217 }
218
219 Ok(Self{
220 polygons
221 })
222 }
223}