geocoords 0.1.0

A Coordinates struct that is opinionated in that it strictly represents valid latitude and longitude. Represented internally as 64-bit floating points; this provides sub-millimeter precision anywhere on Earth.
Documentation
#![allow(unused_parens)]
use std::str::FromStr;

pub mod error;

#[derive(Clone, Copy, Debug)]
pub struct Coordinates {
	latitude: f64,
	longitude: f64
}

impl FromStr for Coordinates {
	type Err = error::ParseError;
	fn from_str(input: &str) -> Result<Self, Self::Err> {
		let parts: Vec<&str> = input.split(',').collect();
		if(parts.len() != 2) {
			return Err(error::ParseError::InvalidFormat(input.into()));
		}
		let latitude = parts[0].trim().parse()?;
		let longitude = parts[1].trim().parse()?;
		Ok(Coordinates::new(latitude, longitude)?)
	}
}

impl Coordinates {
	#[inline]
	pub fn new(latitude: f64, longitude: f64) -> Result<Self, error::OutOfRange> {
		let mut this = Self{
			latitude: 0.0,
			longitude: 0.0
		};
		this.set_latitude_degrees(latitude)?;
		this.set_longitude_degrees(longitude)?;
		Ok(this)
	}

	#[inline]
	pub fn latitude_degrees(&self) -> f64 {
		self.latitude
	}

	#[inline]
	pub fn longitude_degrees(&self) -> f64 {
		self.longitude
	}

	#[inline]
	pub fn set_latitude_degrees(&mut self, latitude: f64) -> Result<(), error::LatitudeOutOfRange> {
		if(!(-90.0..=90.0).contains(&latitude)) {
			return Err(error::LatitudeOutOfRange(latitude));
		}
		self.latitude = latitude;
		Ok(())
	}

	#[inline]
	pub fn set_longitude_degrees(&mut self, longitude: f64) -> Result<(), error::LongitudeOutOfRange> {
		if(!(-180.0..=180.0).contains(&longitude)) {
			return Err(error::LongitudeOutOfRange(longitude));
		}
		self.longitude = longitude;
		Ok(())
	}
}