use core::fmt::Display;
use core::marker::PhantomData;
use crate::arg::ArgValue;
use crate::into_arg::{IntoArg, display};
pub struct Probe<T>(PhantomData<T>);
impl<T> Clone for Probe<T> {
fn clone(&self) -> Probe<T> {
*self
}
}
impl<T> Copy for Probe<T> {}
impl<T> core::fmt::Debug for Probe<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("Probe")
}
}
#[derive(Clone, Copy, Debug)]
pub struct ViaIntoArg;
#[derive(Clone, Copy, Debug)]
pub struct ViaFrom;
#[derive(Clone, Copy, Debug)]
pub struct ViaDisplay;
#[derive(Clone, Copy, Debug)]
pub struct ViaNeither;
pub trait KindIntoArg {
fn __mf2_kind(self) -> ViaIntoArg;
}
impl<T: IntoArg> KindIntoArg for &&&Probe<T> {
#[inline(always)]
#[allow(clippy::inline_always, reason = "a zero-sized value")]
fn __mf2_kind(self) -> ViaIntoArg {
ViaIntoArg
}
}
pub trait KindFrom {
fn __mf2_kind(self) -> ViaFrom;
}
impl<T: Into<ArgValue>> KindFrom for &&Probe<T> {
#[inline(always)]
#[allow(clippy::inline_always, reason = "a zero-sized value")]
fn __mf2_kind(self) -> ViaFrom {
ViaFrom
}
}
pub trait KindDisplay {
fn __mf2_kind(self) -> ViaDisplay;
}
impl<T: Display> KindDisplay for &Probe<T> {
#[inline(always)]
#[allow(clippy::inline_always, reason = "a zero-sized value")]
fn __mf2_kind(self) -> ViaDisplay {
ViaDisplay
}
}
pub trait KindNeither<T> {
fn __mf2_kind(self) -> ViaNeither
where
T: IntoArg;
}
impl<T> KindNeither<T> for Probe<T> {
#[inline(always)]
#[allow(clippy::inline_always, reason = "a zero-sized value")]
fn __mf2_kind(self) -> ViaNeither
where
T: IntoArg,
{
ViaNeither
}
}
pub trait Convert<T> {
fn __mf2_convert(self, value: T) -> ArgValue;
}
impl<T: IntoArg> Convert<T> for ViaIntoArg {
#[inline(always)]
#[allow(
clippy::inline_always,
reason = "the whole of a call site's conversion"
)]
fn __mf2_convert(self, value: T) -> ArgValue {
value.into_arg()
}
}
impl<T: Into<ArgValue>> Convert<T> for ViaFrom {
#[inline(always)]
#[allow(
clippy::inline_always,
reason = "the whole of a call site's conversion"
)]
fn __mf2_convert(self, value: T) -> ArgValue {
value.into()
}
}
impl<T: Display> Convert<T> for ViaDisplay {
#[inline]
fn __mf2_convert(self, value: T) -> ArgValue {
display(&value)
}
}
impl<T> Convert<T> for ViaNeither {
#[inline]
fn __mf2_convert(self, _value: T) -> ArgValue {
ArgValue::Unset
}
}
#[inline(always)]
#[allow(
clippy::inline_always,
reason = "the whole of a call site's conversion"
)]
pub fn convert<T, K: Convert<T>>(value: T, kind: impl FnOnce(Probe<T>) -> K) -> ArgValue {
kind(Probe(PhantomData)).__mf2_convert(value)
}