use std::num::NonZero;
use crate::position::Error;
use crate::position::Number;
use crate::position::ParseError;
use crate::position::Result;
use crate::system::Interbase;
mod addition;
mod subtraction;
const _: () = {
assert!(size_of::<Position>() == size_of::<Number>());
const fn is_copy<T: Copy>() {}
is_copy::<Position>();
};
pub type Position = crate::Position<Interbase>;
impl Position {
pub const fn new(value: Number) -> Self {
Self {
system: Interbase,
value,
}
}
}
impl super::r#trait::Position<Interbase> for Position {}
impl std::str::FromStr for Position {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
Ok(Self::new(s.parse::<Number>().map_err(|error| {
Error::Parse(ParseError::Int {
system: Interbase::NAME,
inner: error,
value: s.to_string(),
})
})?))
}
}
macro_rules! position_from_smaller_number {
($from:ty) => {
impl From<$from> for Position {
fn from(value: $from) -> Self {
Self::new(value as Number)
}
}
impl From<NonZero<$from>> for Position {
fn from(value: NonZero<$from>) -> Self {
Self::new(value.get() as Number)
}
}
};
}
#[cfg(feature = "position-u64")]
position_from_smaller_number!(u64);
position_from_smaller_number!(u32);
position_from_smaller_number!(u16);
position_from_smaller_number!(u8);
#[cfg(test)]
mod tests {
use std::num::NonZeroU8;
use std::num::NonZeroU16;
#[cfg(feature = "position-u64")]
use std::num::NonZeroU32;
use crate::Position;
use crate::position::Number;
use crate::position::Result;
use crate::system::Interbase;
#[test]
fn try_from_number() {
let position: Position<Interbase> = 1u32.into();
assert_eq!(position.get(), 1);
}
#[test]
fn distance() {
let a = Position::<Interbase>::new(10);
let b = Position::<Interbase>::new(10);
assert_eq!(a.distance_unchecked(&b), 0);
assert_eq!(b.distance_unchecked(&a), 0);
let a = Position::<Interbase>::new(Number::MAX);
let b = Position::<Interbase>::new(0);
assert_eq!(a.distance_unchecked(&b), Number::MAX);
assert_eq!(b.distance_unchecked(&a), Number::MAX);
}
#[test]
fn parse() {
let zero = "0".parse::<Position<Interbase>>().unwrap();
assert_eq!(zero.get(), 0);
let position = "1".parse::<Position<Interbase>>().unwrap();
assert_eq!(position.get(), 1);
let err = "a".parse::<Position<Interbase>>().unwrap_err();
assert_eq!(
err.to_string(),
"parse error: failed to parse interbase coordinate system position from `a`: invalid \
digit found in string"
);
}
#[test]
fn from_smaller_types() -> Result<()> {
#[cfg(feature = "position-u64")]
{
let position = Position::<Interbase>::from(0u32);
assert_eq!(position.get(), 0);
let position = Position::<Interbase>::from(NonZeroU32::new(1).unwrap());
assert_eq!(position.get(), 1);
}
let position = Position::<Interbase>::from(0u16);
assert_eq!(position.get(), 0);
let position = Position::<Interbase>::from(NonZeroU16::new(1).unwrap());
assert_eq!(position.get(), 1);
let position = Position::<Interbase>::from(0u8);
assert_eq!(position.get(), 0);
let position = Position::<Interbase>::from(NonZeroU8::new(1).unwrap());
assert_eq!(position.get(), 1);
Ok(())
}
}