extern crate alloc;
use super::{canon::Canonizable, keyexpr};
use alloc::{borrow::ToOwned, boxed::Box, string::String, sync::Arc};
use core::{
    convert::TryFrom,
    fmt,
    ops::{Deref, Div},
    str::FromStr,
};
#[derive(Clone, PartialEq, Eq, Hash, serde::Deserialize)]
#[serde(try_from = "String")]
pub struct OwnedKeyExpr(pub(crate) Arc<str>);
impl serde::Serialize for OwnedKeyExpr {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.0.serialize(serializer)
    }
}
impl OwnedKeyExpr {
    pub fn new<T, E>(t: T) -> Result<Self, E>
    where
        Self: TryFrom<T, Error = E>,
    {
        Self::try_from(t)
    }
    pub fn autocanonize<T, E>(mut t: T) -> Result<Self, E>
    where
        Self: TryFrom<T, Error = E>,
        T: Canonizable,
    {
        t.canonize();
        Self::new(t)
    }
    pub unsafe fn from_string_unchecked(s: String) -> Self {
        Self::from_boxed_string_unchecked(s.into_boxed_str())
    }
    pub unsafe fn from_boxed_string_unchecked(s: Box<str>) -> Self {
        OwnedKeyExpr(s.into())
    }
}
#[allow(clippy::suspicious_arithmetic_impl)]
impl Div<&keyexpr> for OwnedKeyExpr {
    type Output = Self;
    fn div(self, rhs: &keyexpr) -> Self::Output {
        &self / rhs
    }
}
#[allow(clippy::suspicious_arithmetic_impl)]
impl Div<&keyexpr> for &OwnedKeyExpr {
    type Output = OwnedKeyExpr;
    fn div(self, rhs: &keyexpr) -> Self::Output {
        let s: String = [self.as_str(), "/", rhs.as_str()].concat();
        OwnedKeyExpr::autocanonize(s).unwrap() }
}
#[test]
fn div() {
    let a = OwnedKeyExpr::new("a").unwrap();
    let b = OwnedKeyExpr::new("b").unwrap();
    let k = a / &b;
    assert_eq!(k.as_str(), "a/b")
}
impl fmt::Debug for OwnedKeyExpr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}
impl fmt::Display for OwnedKeyExpr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}
impl Deref for OwnedKeyExpr {
    type Target = keyexpr;
    fn deref(&self) -> &Self::Target {
        unsafe { keyexpr::from_str_unchecked(&self.0) }
    }
}
impl AsRef<str> for OwnedKeyExpr {
    fn as_ref(&self) -> &str {
        &self.0
    }
}
impl FromStr for OwnedKeyExpr {
    type Err = zenoh_result::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::try_from(s.to_owned())
    }
}
impl TryFrom<&str> for OwnedKeyExpr {
    type Error = zenoh_result::Error;
    fn try_from(s: &str) -> Result<Self, Self::Error> {
        Self::try_from(s.to_owned())
    }
}
impl TryFrom<String> for OwnedKeyExpr {
    type Error = zenoh_result::Error;
    fn try_from(value: String) -> Result<Self, Self::Error> {
        <&keyexpr as TryFrom<&str>>::try_from(value.as_str())?;
        Ok(Self(value.into()))
    }
}
impl<'a> From<&'a keyexpr> for OwnedKeyExpr {
    fn from(val: &'a keyexpr) -> Self {
        OwnedKeyExpr(Arc::from(val.as_str()))
    }
}
impl From<OwnedKeyExpr> for Arc<str> {
    fn from(ke: OwnedKeyExpr) -> Self {
        ke.0
    }
}
impl From<OwnedKeyExpr> for String {
    fn from(ke: OwnedKeyExpr) -> Self {
        ke.as_str().to_owned()
    }
}