// SPDX-FileCopyrightText: 2023 - 2024 Markus Haug (Korrat)
//
// SPDX-License-Identifier: EUPL-1.2

extern crate alloc;

use alloc::borrow::Cow;
use alloc::rc::Rc;
use alloc::sync::Arc;
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt;
use core::fmt::Display;
use core::fmt::Formatter;
use core::hash::Hash;
use core::hash::Hasher;
use core::iter::FusedIterator;
use core::ops::Deref;
use core::str::FromStr;
use core::str::Split;

use delegate::delegate;
use miette::Diagnostic;
use momo::momo;
use serde::Deserialize;
use serde::Deserializer;
use snafu::ensure;
use snafu::Backtrace;
use snafu::Snafu;

#[derive(Debug)]
#[repr(transparent)]
/// A borrowed account name (akin to [`str`])
///
/// This type supports a number of operations for inspecting an account name, including breaking the account name into its segments.
///
/// This is an _unsized_ type, meaning that it must always be used behind a pointer like `&` or [`Box`].
/// For an owned version of this type see, see [`Account`].
pub struct Acc {
    name: str,
}

impl Acc {
    /// Produces an iterator over `Acc` and its ancestors.
    ///
    /// The iterator will yield all `Acc`s that are returned if the [`parent`](Self::parent) method is used zero or more times.
    /// The iterator will always yield at least one value, namely `&self`.
    pub fn ancestors(&self) -> impl Iterator<Item = &Self> + '_ {
        Ancestors { next: Some(self) }
    }

    /// Returns the final segment of the account name.
    #[must_use]
    pub fn leaf_name(&self) -> &Seg {
        let leaf = self
            .name
            .rsplit_once(':')
            .map_or(&self.name, |(_, leaf)| leaf);

        unsafe {
            // SAFETY: By construction, if `self` is a valid account name, `leaf` is a valid account segment.
            Seg::from_unchecked(leaf)
        }
    }

    /// Returns the account name without the final segment, if there is one.
    #[must_use]
    pub fn parent(&self) -> Option<&Self> {
        self.name.rsplit_once(':').map(|(parent, _)| {
            #[allow(unsafe_code)]
            unsafe {
                // SAFETY: By construction, if `self` is a valid account name, `self.parent` is also a valid account name.
                Self::from_unchecked(parent)
            }
        })
    }

    /// Produces an iterator over the segments of the path.
    pub fn segments(&self) -> Segments<'_> {
        Segments {
            inner: self.name.split(':'),
        }
    }
}

impl Acc {
    /// Create a new `Acc` from a `str` without validating the name before.
    ///
    /// # Safety
    ///
    /// Other functions on this type assume that `name` is a valid account name, as defined by beancount.
    /// You must ensure that this is the case.
    /// See [`is_valid_account_name`] for a function providing that guarantee.
    #[allow(unsafe_code)]
    const unsafe fn from_unchecked(name: &str) -> &Self {
        unsafe {
            // SAFETY: Acc is repr(transparent), so it has the same representation as a str, which makes the cast safe.
            let name: *const _ = name;
            let name = name as *const _;
            &*name
        }
    }
}

impl AsRef<str> for Acc {
    #[inline]
    fn as_ref(&self) -> &str {
        self.borrow()
    }
}

impl AsRef<Self> for Acc {
    #[inline]
    fn as_ref(&self) -> &Self {
        self
    }
}

impl Borrow<str> for Acc {
    #[inline]
    fn borrow(&self) -> &str {
        self
    }
}

impl Deref for Acc {
    type Target = str;

    fn deref(&self) -> &Self::Target {
        &self.name
    }
}

impl<'de> Deserialize<'de> for &'de Acc {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = <&'de str>::deserialize(deserializer)?;
        s.try_into().map_err(serde::de::Error::custom)
    }
}

impl Display for Acc {
    #[inline]
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.pad(&self.name)
    }
}

impl Eq for Acc {}

impl From<&Acc> for Arc<Acc> {
    fn from(value: &Acc) -> Self {
        let raw = Arc::<str>::from(&value.name);
        unsafe { Self::from_raw(Arc::into_raw(raw) as _) }
    }
}

impl From<Account> for Arc<Acc> {
    fn from(value: Account) -> Self {
        let raw = Arc::<str>::from(value.name);
        unsafe { Self::from_raw(Arc::into_raw(raw) as _) }
    }
}

impl From<&Acc> for Box<Acc> {
    fn from(value: &Acc) -> Self {
        let raw = Box::<str>::from(&value.name);
        unsafe { Self::from_raw(Box::into_raw(raw) as _) }
    }
}

impl From<Account> for Box<Acc> {
    fn from(value: Account) -> Self {
        let raw = value.name.into_boxed_str();
        unsafe { Self::from_raw(Box::into_raw(raw) as _) }
    }
}

impl From<&Acc> for Rc<Acc> {
    fn from(value: &Acc) -> Self {
        let raw = Rc::<str>::from(&value.name);
        unsafe { Self::from_raw(Rc::into_raw(raw) as _) }
    }
}

impl From<Account> for Rc<Acc> {
    fn from(value: Account) -> Self {
        let raw = Rc::<str>::from(value.name);
        unsafe { Self::from_raw(Rc::into_raw(raw) as _) }
    }
}

impl Hash for Acc {
    #[inline]
    fn hash<H>(&self, state: &mut H)
    where
        H: Hasher,
    {
        self.name.hash(state);
    }
}

impl Ord for Acc {
    #[inline]
    fn cmp(&self, other: &Self) -> Ordering {
        self.segments().cmp(other.segments())
    }
}

impl PartialEq for Acc {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.cmp(other).is_eq()
    }
}

impl PartialEq<&str> for Acc {
    #[inline]
    fn eq(&self, other: &&str) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Acc> for &str {
    #[inline]
    fn eq(&self, other: &Acc) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Acc> for Cow<'_, Acc> {
    #[inline]
    fn eq(&self, other: &Acc) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Acc> for Cow<'_, str> {
    #[inline]
    fn eq(&self, other: &Acc) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Acc> for String {
    #[inline]
    fn eq(&self, other: &Acc) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Acc> for str {
    #[inline]
    fn eq(&self, other: &Acc) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Cow<'_, Self>> for Acc {
    #[inline]
    fn eq(&self, other: &Cow<'_, Self>) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Cow<'_, str>> for Acc {
    #[inline]
    fn eq(&self, other: &Cow<'_, str>) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<String> for Acc {
    #[inline]
    fn eq(&self, other: &String) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<str> for Acc {
    #[inline]
    fn eq(&self, other: &str) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialOrd for Acc {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialOrd<&str> for Acc {
    #[inline]
    fn partial_cmp(&self, other: &&str) -> Option<Ordering> {
        self.partial_cmp(*other)
    }
}

impl PartialOrd<Acc> for &str {
    #[inline]
    fn partial_cmp(&self, other: &Acc) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Acc> for Cow<'_, Acc> {
    #[inline]
    fn partial_cmp(&self, other: &Acc) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Acc> for Cow<'_, str> {
    #[inline]
    fn partial_cmp(&self, other: &Acc) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Acc> for String {
    #[inline]
    fn partial_cmp(&self, other: &Acc) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Acc> for str {
    #[inline]
    fn partial_cmp(&self, other: &Acc) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Cow<'_, Self>> for Acc {
    fn partial_cmp(&self, other: &Cow<'_, Self>) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<Cow<'_, str>> for Acc {
    fn partial_cmp(&self, other: &Cow<'_, str>) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<String> for Acc {
    #[inline]
    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<str> for Acc {
    #[inline]
    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
        other.try_into().ok().map(|other| self.cmp(other))
    }
}

impl ToOwned for Acc {
    type Owned = Account;

    fn to_owned(&self) -> Self::Owned {
        Account {
            name: self.name.to_owned(),
        }
    }
}

impl<'a> TryFrom<&'a Seg> for &'a Acc {
    type Error = AccountError;

    fn try_from(segment: &'a Seg) -> Result<Self, Self::Error> {
        Self::try_from(&segment.inner)
    }
}

impl<'a> TryFrom<&'a str> for &'a Acc {
    type Error = AccountError;

    fn try_from(name: &'a str) -> Result<Self, Self::Error> {
        ensure!(is_valid_account_name(name), AccountSnafu { name });
        Ok(
            #[allow(unsafe_code)]
            unsafe {
                // SAFETY: we have ensured that `name` is valid.
                Acc::from_unchecked(name)
            },
        )
    }
}

#[derive(Clone, Debug, Deserialize)]
#[repr(transparent)]
#[serde(try_from = "String")]
pub struct Account {
    name: String,
}

impl Account {
    #[momo]
    pub fn join(self, segment: impl AsRef<Seg>) -> Self {
        let mut this = self;

        this.name.push(':');
        this.name.push_str(segment.as_ref().as_ref());

        this
    }
}

impl AsRef<Acc> for Account {
    #[inline]
    fn as_ref(&self) -> &Acc {
        self
    }
}

impl AsRef<str> for Account {
    #[inline]
    fn as_ref(&self) -> &str {
        self
    }
}

impl Borrow<Acc> for Account {
    #[inline]
    fn borrow(&self) -> &Acc {
        self
    }
}

impl Deref for Account {
    type Target = Acc;

    #[inline]
    fn deref(&self) -> &Self::Target {
        #[allow(unsafe_code)]
        unsafe {
            // SAFETY: `self` is a valid `Account`, therefore `self.name` is a valid account name, by construction.
            Acc::from_unchecked(&self.name)
        }
    }
}

impl Display for Account {
    #[inline]
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        (**self).fmt(f)
    }
}

impl Eq for Account {}

impl From<&Acc> for Account {
    #[inline]
    fn from(acc: &Acc) -> Self {
        acc.to_owned()
    }
}

impl From<&Self> for Account {
    #[inline]
    fn from(value: &Self) -> Self {
        value.clone()
    }
}

impl FromStr for Account {
    type Err = <Self as TryFrom<&'static str>>::Error;

    #[inline]
    fn from_str(name: &str) -> Result<Self, Self::Err> {
        Self::try_from(name)
    }
}

impl Hash for Account {
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

impl Ord for Account {
    #[inline]
    fn cmp(&self, other: &Self) -> Ordering {
        (**self).cmp(&**other)
    }
}

impl PartialEq for Account {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.cmp(other).is_eq()
    }
}

impl PartialEq<&Acc> for Account {
    #[inline]
    fn eq(&self, other: &&Acc) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<&str> for Account {
    #[inline]
    fn eq(&self, other: &&str) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Acc> for Account {
    #[inline]
    fn eq(&self, other: &Acc) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Account> for &Acc {
    #[inline]
    fn eq(&self, other: &Account) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Account> for &str {
    #[inline]
    fn eq(&self, other: &Account) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Account> for Acc {
    #[inline]
    fn eq(&self, other: &Account) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Account> for Cow<'_, Acc> {
    #[inline]
    fn eq(&self, other: &Account) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Account> for Cow<'_, str> {
    #[inline]
    fn eq(&self, other: &Account) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Account> for String {
    #[inline]
    fn eq(&self, other: &Account) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Account> for str {
    #[inline]
    fn eq(&self, other: &Account) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Cow<'_, Acc>> for Account {
    #[inline]
    fn eq(&self, other: &Cow<'_, Acc>) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<Cow<'_, str>> for Account {
    #[inline]
    fn eq(&self, other: &Cow<'_, str>) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<String> for Account {
    #[inline]
    fn eq(&self, other: &String) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialEq<str> for Account {
    #[inline]
    fn eq(&self, other: &str) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialOrd for Account {
    #[inline]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialOrd<&Acc> for Account {
    #[inline]
    fn partial_cmp(&self, other: &&Acc) -> Option<Ordering> {
        self.partial_cmp(*other)
    }
}

impl PartialOrd<&str> for Account {
    #[inline]
    fn partial_cmp(&self, other: &&str) -> Option<Ordering> {
        self.partial_cmp(*other)
    }
}

impl PartialOrd<Acc> for Account {
    #[inline]
    fn partial_cmp(&self, other: &Acc) -> Option<Ordering> {
        (**self).partial_cmp(other)
    }
}

impl PartialOrd<Account> for &Acc {
    #[inline]
    fn partial_cmp(&self, other: &Account) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Account> for &str {
    #[inline]
    fn partial_cmp(&self, other: &Account) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Account> for Acc {
    #[inline]
    fn partial_cmp(&self, other: &Account) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Account> for Cow<'_, Acc> {
    #[inline]
    fn partial_cmp(&self, other: &Account) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Account> for Cow<'_, str> {
    #[inline]
    fn partial_cmp(&self, other: &Account) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Account> for String {
    #[inline]
    fn partial_cmp(&self, other: &Account) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Account> for str {
    #[inline]
    fn partial_cmp(&self, other: &Account) -> Option<Ordering> {
        other.partial_cmp(self).map(Ordering::reverse)
    }
}

impl PartialOrd<Cow<'_, Acc>> for Account {
    fn partial_cmp(&self, other: &Cow<'_, Acc>) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<Cow<'_, str>> for Account {
    fn partial_cmp(&self, other: &Cow<'_, str>) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<String> for Account {
    #[inline]
    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<str> for Account {
    #[inline]
    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
        (**self).partial_cmp(other)
    }
}

impl TryFrom<&str> for Account {
    type Error = AccountError;

    #[inline]
    fn try_from(name: &str) -> Result<Self, Self::Error> {
        <&Acc>::try_from(name).map(Self::from)
    }
}

impl TryFrom<&Seg> for Account {
    type Error = <Self as TryFrom<&'static str>>::Error;

    fn try_from(segment: &Seg) -> Result<Self, Self::Error> {
        Self::try_from(&segment.inner)
    }
}

impl TryFrom<Segment> for Account {
    type Error = <Self as TryFrom<String>>::Error;

    fn try_from(segment: Segment) -> Result<Self, Self::Error> {
        Self::try_from(segment.inner)
    }
}

impl TryFrom<String> for Account {
    type Error = <Self as TryFrom<&'static str>>::Error;

    #[inline]
    fn try_from(name: String) -> Result<Self, Self::Error> {
        ensure!(is_valid_account_name(&name), AccountSnafu { name });

        Ok(Self { name })
    }
}

#[derive(Debug, Diagnostic, Snafu)]
#[snafu(display("invalid account: {name:?}"))]
pub struct AccountError {
    name: String,

    backtrace: Backtrace,
}

#[must_use]
struct Ancestors<'a> {
    next: Option<&'a Acc>,
}

impl FusedIterator for Ancestors<'_> {}

impl<'a> Iterator for Ancestors<'a> {
    type Item = &'a Acc;

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.next?;
        self.next = next.parent();
        Some(next)
    }
}

#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Seg {
    inner: str,
}

impl Seg {
    /// Create a new `Seg` from a `str` without validating the name before.
    ///
    /// # Safety
    ///
    /// Other functions on this type assume that `name` is a valid account name, as defined by beancount.
    /// You must ensure that this is the case.
    /// See [`is_valid_account_segment`] for a function providing that guarantee.
    #[allow(unsafe_code)]
    #[inline]
    const unsafe fn from_unchecked(name: &str) -> &Self {
        let name: *const _ = name;
        let name = name as *const _;

        unsafe {
            // SAFETY: Seg is repr(transparent), so it has the same representation as a str, which makes the cast safe.
            &*name
        }
    }
}

impl AsRef<str> for Seg {
    #[inline]
    fn as_ref(&self) -> &str {
        self.borrow()
    }
}

impl AsRef<Self> for Seg {
    #[inline]
    fn as_ref(&self) -> &Self {
        self
    }
}

impl Borrow<str> for Seg {
    #[inline]
    fn borrow(&self) -> &str {
        self
    }
}

impl Deref for Seg {
    type Target = str;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl Display for Seg {
    delegate! {
        to self.inner {
            #[allow(clippy::inline_always)]
            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result;
        }
    }
}

impl PartialEq<&str> for Seg {
    #[inline]
    fn eq(&self, other: &&str) -> bool {
        self.eq(*other)
    }
}

impl PartialEq<Cow<'_, Self>> for Seg {
    #[inline]
    fn eq(&self, other: &Cow<'_, Self>) -> bool {
        self.eq(&**other)
    }
}

impl PartialEq<Cow<'_, str>> for Seg {
    #[inline]
    fn eq(&self, other: &Cow<'_, str>) -> bool {
        self.eq(&**other)
    }
}

impl PartialEq<Seg> for &str {
    #[inline]
    fn eq(&self, other: &Seg) -> bool {
        other.eq(self)
    }
}

impl PartialEq<Seg> for Cow<'_, Seg> {
    #[inline]
    fn eq(&self, other: &Seg) -> bool {
        other.eq(self)
    }
}

impl PartialEq<Seg> for Cow<'_, str> {
    #[inline]
    fn eq(&self, other: &Seg) -> bool {
        other.eq(self)
    }
}

impl PartialEq<Seg> for String {
    #[inline]
    fn eq(&self, other: &Seg) -> bool {
        other.eq(self)
    }
}

impl PartialEq<Seg> for str {
    #[inline]
    fn eq(&self, other: &Seg) -> bool {
        other.eq(self)
    }
}

impl PartialEq<String> for Seg {
    #[inline]
    fn eq(&self, other: &String) -> bool {
        self.eq(&**other)
    }
}

impl PartialEq<str> for Seg {
    #[inline]
    fn eq(&self, other: &str) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialOrd<Cow<'_, Self>> for Seg {
    #[inline]
    fn partial_cmp(&self, other: &Cow<'_, Self>) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<Cow<'_, str>> for Seg {
    #[inline]
    fn partial_cmp(&self, other: &Cow<'_, str>) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<Seg> for &str {
    #[inline]
    fn partial_cmp(&self, other: &Seg) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<Seg> for Cow<'_, Seg> {
    #[inline]
    fn partial_cmp(&self, other: &Seg) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<Seg> for Cow<'_, str> {
    #[inline]
    fn partial_cmp(&self, other: &Seg) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<Seg> for String {
    #[inline]
    fn partial_cmp(&self, other: &Seg) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<Seg> for str {
    #[inline]
    fn partial_cmp(&self, other: &Seg) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<String> for Seg {
    #[inline]
    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<&str> for Seg {
    #[inline]
    fn partial_cmp(&self, other: &&str) -> Option<Ordering> {
        self.partial_cmp(*other)
    }
}

impl PartialOrd<str> for Seg {
    #[inline]
    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
        self.inner.partial_cmp(other)
    }
}

impl ToOwned for Seg {
    type Owned = Segment;

    #[inline]
    fn to_owned(&self) -> Self::Owned {
        self.into()
    }
}

impl<'s> TryFrom<&'s str> for &'s Seg {
    type Error = SegmentError;

    fn try_from(segment: &'s str) -> Result<Self, Self::Error> {
        ensure!(is_valid_account_segment(segment), SegmentSnafu { segment });

        Ok(
            #[allow(unsafe_code)]
            unsafe {
                // SAFETY: we have ensured that `value` is valid.
                Seg::from_unchecked(segment)
            },
        )
    }
}

#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Segment {
    inner: String,
}

impl AsRef<Seg> for Segment {
    #[inline]
    fn as_ref(&self) -> &Seg {
        self.borrow()
    }
}

impl AsRef<str> for Segment {
    #[inline]
    fn as_ref(&self) -> &str {
        self
    }
}

impl Borrow<Seg> for Segment {
    #[inline]
    fn borrow(&self) -> &Seg {
        self
    }
}

impl Deref for Segment {
    type Target = Seg;

    #[inline]
    fn deref(&self) -> &Self::Target {
        #[allow(unsafe_code)]
        unsafe {
            // SAFETY: `self` is a valid `Segment`, therefore `self.inner` is a valid segment, by construction.
            Self::Target::from_unchecked(&self.inner)
        }
    }
}

impl Display for Segment {
    delegate! {
        to self.inner {
            #[allow(clippy::inline_always)]
            fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result;
        }
    }
}

impl From<&Seg> for Segment {
    #[inline]
    fn from(seg: &Seg) -> Self {
        let inner = seg.inner.into();
        Self { inner }
    }
}

impl PartialEq<&str> for Segment {
    #[inline]
    fn eq(&self, other: &&str) -> bool {
        self.eq(*other)
    }
}

impl PartialEq<Cow<'_, Seg>> for Segment {
    #[inline]
    fn eq(&self, other: &Cow<'_, Seg>) -> bool {
        self.eq(&**other)
    }
}

impl PartialEq<Cow<'_, str>> for Segment {
    #[inline]
    fn eq(&self, other: &Cow<'_, str>) -> bool {
        self.eq(&**other)
    }
}

impl PartialEq<Seg> for Segment {
    #[inline]
    fn eq(&self, other: &Seg) -> bool {
        (**self).eq(other)
    }
}

impl PartialEq<Segment> for &str {
    #[inline]
    fn eq(&self, other: &Segment) -> bool {
        other.eq(self)
    }
}

impl PartialEq<Segment> for Cow<'_, Seg> {
    #[inline]
    fn eq(&self, other: &Segment) -> bool {
        other.eq(self)
    }
}

impl PartialEq<Segment> for Cow<'_, str> {
    #[inline]
    fn eq(&self, other: &Segment) -> bool {
        other.eq(self)
    }
}

impl PartialEq<Segment> for Seg {
    #[inline]
    fn eq(&self, other: &Segment) -> bool {
        other.eq(self)
    }
}

impl PartialEq<Segment> for String {
    #[inline]
    fn eq(&self, other: &Segment) -> bool {
        other.eq(self)
    }
}

impl PartialEq<Segment> for str {
    #[inline]
    fn eq(&self, other: &Segment) -> bool {
        other.eq(self)
    }
}

impl PartialEq<String> for Segment {
    #[inline]
    fn eq(&self, other: &String) -> bool {
        self.eq(&**other)
    }
}

impl PartialEq<str> for Segment {
    #[inline]
    fn eq(&self, other: &str) -> bool {
        self.partial_cmp(other).map_or(false, Ordering::is_eq)
    }
}

impl PartialOrd<Cow<'_, Seg>> for Segment {
    #[inline]
    fn partial_cmp(&self, other: &Cow<'_, Seg>) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<Cow<'_, str>> for Segment {
    #[inline]
    fn partial_cmp(&self, other: &Cow<'_, str>) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<Seg> for Segment {
    #[inline]
    fn partial_cmp(&self, other: &Seg) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<Segment> for &str {
    #[inline]
    fn partial_cmp(&self, other: &Segment) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<Segment> for Cow<'_, Seg> {
    #[inline]
    fn partial_cmp(&self, other: &Segment) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<Segment> for Cow<'_, str> {
    #[inline]
    fn partial_cmp(&self, other: &Segment) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<Segment> for Seg {
    #[inline]
    fn partial_cmp(&self, other: &Segment) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<Segment> for String {
    #[inline]
    fn partial_cmp(&self, other: &Segment) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<Segment> for str {
    #[inline]
    fn partial_cmp(&self, other: &Segment) -> Option<Ordering> {
        other.partial_cmp(self)
    }
}

impl PartialOrd<String> for Segment {
    #[inline]
    fn partial_cmp(&self, other: &String) -> Option<Ordering> {
        self.partial_cmp(&**other)
    }
}

impl PartialOrd<&str> for Segment {
    #[inline]
    fn partial_cmp(&self, other: &&str) -> Option<Ordering> {
        self.partial_cmp(*other)
    }
}

impl PartialOrd<str> for Segment {
    #[inline]
    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
        (*self.inner).partial_cmp(other)
    }
}

impl TryFrom<&str> for Segment {
    type Error = <&'static Seg as TryFrom<&'static str>>::Error;

    #[inline]
    fn try_from(name: &str) -> Result<Self, Self::Error> {
        <&Seg>::try_from(name).map(Self::from)
    }
}

impl TryFrom<String> for Segment {
    type Error = <Self as TryFrom<&'static str>>::Error;

    #[inline]
    fn try_from(segment: String) -> Result<Self, Self::Error> {
        ensure!(is_valid_account_segment(&segment), SegmentSnafu { segment });

        Ok(Self { inner: segment })
    }
}

#[derive(Debug, Diagnostic, Snafu)]
#[snafu(display("invalid account segment: {segment:?}"))]
pub struct SegmentError {
    segment: String,

    backtrace: Backtrace,
}

#[derive(Clone, Debug)]
#[must_use]
pub struct Segments<'a> {
    inner: Split<'a, char>,
}

impl DoubleEndedIterator for Segments<'_> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.inner.next_back().map(|seg| {
            #[allow(unsafe_code)]
            unsafe {
                // SAFETY: `self` is a valid `Acc`, therefore each `seg` is a valid segment, by construction.
                Seg::from_unchecked(seg)
            }
        })
    }
}

impl FusedIterator for Segments<'_> {}

impl<'a> Iterator for Segments<'a> {
    type Item = &'a Seg;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next().map(|seg| {
            #[allow(unsafe_code)]
            unsafe {
                // SAFETY: `self` is a valid `Acc`, therefore each `seg` is a valid segment, by construction.
                Seg::from_unchecked(seg)
            }
        })
    }
}

fn is_valid_account_name(name: &str) -> bool {
    lazy_regex::regex_is_match!(
        r#"^(?:[\p{Lu}\p{Nd}][-\p{L}\p{Nd}]*)(?::[\p{Lu}\p{Nd}][-\p{L}\p{Nd}]*)*$"#,
        name
    )
}

fn is_valid_account_segment(name: &str) -> bool {
    lazy_regex::regex_is_match!(r#"^(?:[\p{Lu}\p{Nd}][-\p{L}\p{Nd}]*)$"#, name)
}