use crate::observations::Observation;
use crate::observers::Observer;
use smallvec::SmallVec;
use std::borrow::Cow;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::sync::Arc;
pub const DPI: f64 = 2. * std::f64::consts::PI;
pub const SECONDS_PER_DAY: f64 = 86_400.0;
pub const AU: f64 = 149_597_870.7;
pub const EPS: f64 = 1e-6;
pub const T2000: f64 = 51544.5;
pub const JDTOMJD: f64 = 2400000.5;
pub const RADEG: f64 = std::f64::consts::PI / 180.0;
pub const RADSEC: f64 = std::f64::consts::PI / 648000.0;
pub const RAD2ARC: f64 = 648000.0 / std::f64::consts::PI;
pub const RADH: f64 = DPI / 24.0;
pub const EARTH_MAJOR_AXIS: f64 = 6_378_137.0;
pub const EARTH_MINOR_AXIS: f64 = 6_356_752.3;
pub const ERAU: f64 = (EARTH_MAJOR_AXIS / 1000.) / AU;
pub const GAUSS_GRAV: f64 = 0.01720209895;
pub const GAUSS_GRAV_SQUARED: f64 = GAUSS_GRAV * GAUSS_GRAV;
pub const VLIGHT: f64 = 2.99792458e5;
pub const VLIGHT_AU: f64 = VLIGHT / AU * SECONDS_PER_DAY;
pub type Degree = f64;
pub type ArcSec = f64;
pub type Radian = f64;
pub type Kilometer = f64;
pub type Meter = f64;
pub type MpcCode = String;
pub type MpcCodeObs = HashMap<MpcCode, Arc<Observer>>;
pub type MJD = f64;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum ObjectNumber {
Int(u32),
String(String),
}
impl std::fmt::Display for ObjectNumber {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ObjectNumber::Int(n) => write!(f, "{n}"),
ObjectNumber::String(s) => write!(f, "{s}"),
}
}
}
impl From<u32> for ObjectNumber {
#[inline]
fn from(n: u32) -> Self {
ObjectNumber::Int(n)
}
}
impl From<u16> for ObjectNumber {
#[inline]
fn from(n: u16) -> Self {
ObjectNumber::Int(n as u32)
}
}
impl From<u8> for ObjectNumber {
#[inline]
fn from(n: u8) -> Self {
ObjectNumber::Int(n as u32)
}
}
impl From<&u32> for ObjectNumber {
#[inline]
fn from(n: &u32) -> Self {
ObjectNumber::Int(*n)
}
}
impl From<String> for ObjectNumber {
#[inline]
fn from(s: String) -> Self {
ObjectNumber::String(s)
}
}
impl From<&String> for ObjectNumber {
#[inline]
fn from(s: &String) -> Self {
ObjectNumber::String(s.clone())
}
}
impl From<&str> for ObjectNumber {
#[inline]
fn from(s: &str) -> Self {
ObjectNumber::String(s.to_string())
}
}
impl<'a> From<Cow<'a, str>> for ObjectNumber {
#[inline]
fn from(c: Cow<'a, str>) -> Self {
match c {
Cow::Borrowed(s) => ObjectNumber::String(s.to_string()),
Cow::Owned(s) => ObjectNumber::String(s),
}
}
}
impl TryFrom<usize> for ObjectNumber {
type Error = std::num::TryFromIntError;
#[inline]
fn try_from(n: usize) -> Result<Self, Self::Error> {
Ok(ObjectNumber::Int(u32::try_from(n)?))
}
}
impl TryFrom<u64> for ObjectNumber {
type Error = std::num::TryFromIntError;
#[inline]
fn try_from(n: u64) -> Result<Self, Self::Error> {
Ok(ObjectNumber::Int(u32::try_from(n)?))
}
}
impl TryFrom<i64> for ObjectNumber {
type Error = &'static str;
#[inline]
fn try_from(n: i64) -> Result<Self, Self::Error> {
if n < 0 {
return Err("negative value is not a valid ObjectNumber::Int");
}
let n = u64::try_from(n).map_err(|_| "conversion failed")?;
let n = u32::try_from(n).map_err(|_| "value exceeds u32 range")?;
Ok(ObjectNumber::Int(n))
}
}
impl std::str::FromStr for ObjectNumber {
type Err = std::num::ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.parse::<u32>() {
Ok(n) => Ok(ObjectNumber::Int(n)),
Err(e) => {
if s.chars().any(|c| !c.is_ascii_digit()) {
Ok(ObjectNumber::String(s.to_string()))
} else {
Err(e)
}
}
}
}
}
pub type Observations = SmallVec<[Observation; 6]>;