#[cfg(feature = "serde")]
use ::serde::{Deserialize, Serialize};
#[doc(inline)]
pub use display::to_string;
#[doc(inline)]
pub use error::{ParseError, ParseValueError, ValidationError};
#[doc(inline)]
pub use parse::from_str;
mod arithm;
mod display;
mod error;
mod parse;
#[cfg(feature = "serde")]
mod serde;
mod token;
mod validation;
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct ISG {
#[cfg_attr(feature = "serde", serde(default))]
pub comment: String,
pub header: Header,
pub data: Data,
}
impl Clone for ISG {
#[inline]
fn clone(&self) -> Self {
Self {
comment: self.comment.clone(),
header: self.header.clone(),
data: self.data.clone(),
}
}
#[inline]
fn clone_from(&mut self, source: &Self) {
self.comment.clone_from(&source.comment);
self.header.clone_from(&source.header);
self.data.clone_from(&source.data);
}
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[allow(non_snake_case)]
pub struct Header {
pub model_name: Option<String>,
pub model_year: Option<String>,
pub model_type: Option<ModelType>,
pub data_type: Option<DataType>,
pub data_units: Option<DataUnits>,
pub data_format: DataFormat,
pub data_ordering: Option<DataOrdering>,
pub ref_ellipsoid: Option<String>,
pub ref_frame: Option<String>,
pub height_datum: Option<String>,
pub tide_system: Option<TideSystem>,
pub coord_type: CoordType,
pub coord_units: CoordUnits,
pub map_projection: Option<String>,
pub EPSG_code: Option<String>,
#[cfg_attr(feature = "serde", serde(flatten))]
pub data_bounds: DataBounds,
pub nrows: usize,
pub ncols: usize,
pub nodata: Option<f64>,
pub creation_date: Option<CreationDate>,
pub ISG_format: String,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
pub enum Data {
Grid(Vec<Vec<Option<f64>>>),
Sparse(Vec<(Coord, Coord, f64)>),
}
impl Data {
pub fn new_grid(
data: impl IntoIterator<Item = impl IntoIterator<Item = impl Into<Option<f64>>>>,
) -> Self {
Self::Grid(
data.into_iter()
.map(|row| row.into_iter().map(Into::into).collect())
.collect(),
)
}
pub fn new_sparse(data: impl IntoIterator<Item = impl Into<(Coord, Coord, f64)>>) -> Self {
Self::Sparse(data.into_iter().map(Into::into).collect())
}
#[inline]
pub fn grid_data(&self) -> &Vec<Vec<Option<f64>>> {
match self {
Data::Grid(data) => data,
Data::Sparse(_) => panic!("self is `Data::Sparse`, expected `Data::Grid`"),
}
}
#[inline]
pub fn sparse_data(&self) -> &Vec<(Coord, Coord, f64)> {
match self {
Data::Grid(_) => panic!(""),
Data::Sparse(_) => panic!("self is `Data::Grid`, expected `Data::Sparse`"),
}
}
}
impl Clone for Data {
#[inline]
fn clone(&self) -> Self {
match self {
Self::Grid(data) => Self::Grid(data.clone()),
Self::Sparse(data) => Self::Sparse(data.clone()),
}
}
#[inline]
fn clone_from(&mut self, source: &Self) {
if let Data::Grid(dst) = self {
if let Data::Grid(org) = source {
dst.clone_from(org)
} else {
*self = source.clone();
}
} else if let Data::Sparse(dst) = self {
if let Data::Sparse(org) = source {
dst.clone_from(org)
} else {
*self = source.clone();
}
} else {
*self = source.clone();
}
}
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum ModelType {
Gravimetric,
Geometric,
Hybrid,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum DataType {
Geoid,
QuasiGeoid,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum DataUnits {
Meters,
Feet,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum DataFormat {
Grid,
Sparse,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum DataOrdering {
N2SW2E,
LatLonN,
EastNorthN,
N,
Zeta,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum TideSystem {
TideFree,
MeanTide,
ZeroTide,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum CoordType {
Geodetic,
Projected,
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum CoordUnits {
DMS,
Deg,
Meters,
Feet,
}
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[cfg_attr(feature = "serde", serde(untagged))]
pub enum DataBounds {
GridGeodetic {
lat_min: Coord,
lat_max: Coord,
lon_min: Coord,
lon_max: Coord,
delta_lat: Coord,
delta_lon: Coord,
},
GridProjected {
north_min: Coord,
north_max: Coord,
east_min: Coord,
east_max: Coord,
delta_north: Coord,
delta_east: Coord,
},
SparseGeodetic {
lat_min: Coord,
lat_max: Coord,
lon_min: Coord,
lon_max: Coord,
},
SparseProjected {
north_min: Coord,
north_max: Coord,
east_min: Coord,
east_max: Coord,
},
}
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct CreationDate {
pub year: u16,
pub month: u8,
pub day: u8,
}
impl CreationDate {
pub fn new(year: u16, month: u8, day: u8) -> Self {
Self { year, month, day }
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Coord {
DMS {
degree: i16,
minutes: u8,
second: u8,
},
Dec(f64),
}
impl Coord {
#[inline]
pub fn with_dms(degree: i16, minutes: u8, second: u8) -> Self {
Self::DMS {
degree,
minutes,
second,
}
}
#[inline]
pub fn with_dec(value: f64) -> Self {
Self::Dec(value)
}
}