// the goal of this module is to provide an intermediate type
// that is guaranteed to be some kind of number, and provide
// methods to coerce it into various more specific types.

#[derive(Clone,Copy)]
pub enum Number{
	Integer(i64),
	Number(f64),
}
macro_rules! impl_ty{
	($ident:ident,$ty:ty)=>{
		impl Number{
			#[inline]
			pub fn $ident(self)->$ty{
				match self{
					Self::Integer(int)=>int as $ty,
					Self::Number(num)=>num as $ty,
				}
			}
		}
		impl From<Number> for $ty{
			fn from(value:Number)->$ty{
				value.$ident()
			}
		}
	};
}
impl_ty!(to_u32,u32);
impl_ty!(to_i32,i32);
impl_ty!(to_f32,f32);
impl_ty!(to_u64,u64);
impl_ty!(to_i64,i64);
impl_ty!(to_f64,f64);

impl mlua::FromLua for Number{
	fn from_lua(value:mlua::Value,_lua:&mlua::Lua)->Result<Self,mlua::Error>{
		match value{
			mlua::Value::Integer(int)=>Ok(Number::Integer(int)),
			mlua::Value::Number(num)=>Ok(Number::Number(num)),
			other=>Err(mlua::Error::runtime(format!("Expected {} got {:?}",stringify!(Number),other))),
		}
	}
}
