use core::{fmt, iter};
#[cfg(any(feature = "alloc", test))]
use core::ops::Deref;
use crate::component::{self, NamespaceComponent};
use combinators::{CacheComponentsHint, Join};
pub use components_hint_iterator::{
ComponentsSizeHintOverrideIter, IntoComponentsSizeHintOverrideIter,
};
pub use into_conversions::{IntoNamespacePath, IntoRawNamespacePath};
pub use into_into_raw_ns_path::IntoIntoRawNSPath;
pub use raw_ns_path_wrapper::RawNamespacePathWrapper;
pub use render::RenderStyle;
pub mod combinators;
mod components_hint_iterator;
mod into_conversions;
mod into_into_raw_ns_path;
mod multiplicity_recurse_impls;
mod raw_ns_path_wrapper;
mod reference_recurse_impls;
pub mod render;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct SingleEmptyComponent;
impl NamespacePath for SingleEmptyComponent {
#[inline(always)]
fn components(&self) -> impl IntoIterator<Item = NamespaceComponent<'_>> {
iter::once(unsafe { NamespaceComponent::new_unchecked("") })
}
#[inline(always)]
fn components_hint(&self) -> NamespaceComponentsHint {
NamespaceComponentsHint::new(1, 0)
}
}
impl RawNamespacePath for SingleEmptyComponent {
#[inline(always)]
fn raw_components(&self) -> impl IntoIterator<Item = impl fmt::Display> {
iter::once(SingleEmptyComponent)
}
}
impl fmt::Display for SingleEmptyComponent {
#[inline(always)]
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
Ok(())
}
}
pub trait RawNamespacePath {
#[must_use]
fn raw_components(&self) -> impl IntoIterator<Item = impl fmt::Display>;
#[must_use]
#[inline]
fn raw_by_ref(&self) -> &Self {
self
}
#[must_use]
#[inline]
fn raw_join<O: IntoRawNamespacePath>(self, suffix: O) -> Join<Self, O::RawNSPath>
where
Self: Sized,
{
Join::new(self, suffix.into_raw_namespace_path())
}
#[must_use]
#[inline]
fn raw_render(self, render_style: RenderStyle) -> render::RawNamespacePathRender<Self>
where
Self: Sized,
{
render::RawNamespacePathRender::new(self, render_style)
}
#[must_use]
#[inline]
fn raw_fallback<O: IntoRawNamespacePath>(
self,
fallback: O,
) -> combinators::Fallback<Self, O::RawNSPath>
where
Self: Sized,
{
combinators::Fallback::new(self, fallback.into_raw_namespace_path())
}
#[must_use]
#[inline]
fn raw_maybe_fallback<O: IntoRawNamespacePath>(
self,
maybe_fallback: Option<O>,
) -> combinators::MaybeFallback<Self, O::RawNSPath>
where
Self: Sized,
{
combinators::MaybeFallback::new(
self,
maybe_fallback.map(IntoRawNamespacePath::into_raw_namespace_path),
)
}
}
impl RawNamespacePath for () {
#[inline]
fn raw_components(&self) -> impl IntoIterator<Item = impl fmt::Display> {
iter::empty::<NamespaceComponent<'static>>()
}
}
impl RawNamespacePath for str {
#[inline]
fn raw_components(&self) -> impl IntoIterator<Item = impl fmt::Display> {
component::get_components(self)
}
}
#[cfg(any(feature = "alloc", test))]
impl RawNamespacePath for alloc::string::String {
#[inline]
fn raw_components(&self) -> impl IntoIterator<Item = impl fmt::Display> {
self.as_str().raw_components()
}
}
#[cfg(any(feature = "alloc", test))]
impl RawNamespacePath for alloc::borrow::Cow<'_, str> {
#[inline]
fn raw_components(&self) -> impl IntoIterator<Item = impl fmt::Display> {
self.deref().raw_components()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct NamespaceComponentsHint {
pub component_count: usize,
pub total_component_length: usize,
}
impl NamespaceComponentsHint {
#[inline]
#[must_use]
pub const fn new(component_count: usize, total_component_length: usize) -> Self {
Self {
component_count,
total_component_length,
}
}
#[inline]
#[must_use]
pub const fn with_appended(&self, other: Self) -> Self {
Self {
component_count: self.component_count + other.component_count,
total_component_length: self.total_component_length + other.total_component_length,
}
}
#[inline]
#[must_use]
pub const fn single(v: NamespaceComponent<'_>) -> Self {
Self::new(1, v.len())
}
#[inline]
#[must_use]
pub const fn has_components(&self) -> bool {
self.component_count >= 1
}
#[inline]
#[must_use]
pub const fn has_components_or_else(&self, if_no_components: Self) -> Self {
if self.has_components() {
*self
} else {
if_no_components
}
}
#[inline]
#[must_use]
pub const fn empty() -> Self {
Self::new(0, 0)
}
#[inline]
#[must_use]
pub fn count_from_iterator<'v, I: IntoIterator<Item = NamespaceComponent<'v>>>(
iter: I,
) -> Self {
iter.into_iter()
.map(Self::single)
.fold(Self::empty(), |hint_so_far, next_component_hint| {
hint_so_far.with_appended(next_component_hint)
})
}
#[inline]
#[must_use]
pub const fn estimated_string_bytes(&self, render_style: RenderStyle) -> usize {
let separator_bytes = "::".len() * render_style.separator_count(self.component_count);
self.total_component_length + separator_bytes
}
}
pub trait NamespacePath {
#[must_use]
fn components(&self) -> impl IntoIterator<Item = NamespaceComponent<'_>>;
#[must_use]
#[inline]
fn components_with_size_hint(
&self,
) -> IntoComponentsSizeHintOverrideIter<impl IntoIterator<Item = NamespaceComponent<'_>>> {
IntoComponentsSizeHintOverrideIter::new(self.components(), self.components_hint())
}
#[must_use]
fn collect_components<'s, F: FromIterator<NamespaceComponent<'s>>>(&'s self) -> F {
F::from_iter(self.components_with_size_hint())
}
#[must_use]
fn components_hint(&self) -> NamespaceComponentsHint;
#[must_use]
#[inline]
fn by_ref_cache(&self) -> CacheComponentsHint<&Self> {
self.by_ref_only().cache_components_hint()
}
#[must_use]
#[inline]
fn by_ref_only(&self) -> &Self {
self
}
#[must_use]
#[inline]
fn join<O: IntoNamespacePath>(self, suffix: O) -> Join<Self, O::NSPath>
where
Self: Sized,
{
Join::new(self, suffix.into_namespace_path())
}
#[must_use]
#[inline]
fn render(self, render_style: RenderStyle) -> render::NamespacePathRender<Self>
where
Self: Sized,
{
render::NamespacePathRender::new(self, render_style)
}
#[must_use]
#[inline]
fn fallback<O: IntoNamespacePath>(self, fallback: O) -> combinators::Fallback<Self, O::NSPath>
where
Self: Sized,
{
combinators::Fallback::new(self, fallback.into_namespace_path())
}
#[must_use]
#[inline]
fn maybe_fallback<O: IntoNamespacePath>(
self,
maybe_fallback: Option<O>,
) -> combinators::MaybeFallback<Self, O::NSPath>
where
Self: Sized,
{
combinators::MaybeFallback::new(
self,
maybe_fallback.map(IntoNamespacePath::into_namespace_path),
)
}
#[cfg(any(feature = "alloc", test))]
#[must_use]
fn build_cache_string(&self) -> CacheComponentsHint<alloc::string::String> {
let components_hint = self.components_hint();
let rendered_string = self.render(RenderStyle::WithFirstSeparator).to_string();
unsafe { CacheComponentsHint::new_unchecked(rendered_string, components_hint) }
}
#[must_use]
#[inline]
fn cache_components_hint(self) -> CacheComponentsHint<Self>
where
Self: Sized,
{
CacheComponentsHint::new(self)
}
#[must_use]
#[inline]
fn into_raw(self) -> RawNamespacePathWrapper<Self>
where
Self: Sized,
{
self.into()
}
}
impl NamespacePath for () {
#[inline(always)]
fn components(&self) -> impl IntoIterator<Item = NamespaceComponent<'_>> {
iter::empty()
}
#[inline]
fn components_hint(&self) -> NamespaceComponentsHint {
NamespaceComponentsHint::empty()
}
}
impl NamespacePath for str {
#[inline]
fn components(&self) -> impl IntoIterator<Item = NamespaceComponent<'_>> {
component::get_components(self)
}
#[inline]
fn components_hint(&self) -> NamespaceComponentsHint {
NamespaceComponentsHint::count_from_iterator(self.components())
}
}
#[cfg(any(feature = "alloc", test))]
impl NamespacePath for alloc::string::String {
#[inline]
fn components(&self) -> impl IntoIterator<Item = NamespaceComponent<'_>> {
self.as_str().components()
}
#[inline]
fn components_hint(&self) -> NamespaceComponentsHint {
self.as_str().components_hint()
}
}
#[cfg(any(feature = "alloc", test))]
impl NamespacePath for alloc::borrow::Cow<'_, str> {
#[inline]
fn components(&self) -> impl IntoIterator<Item = NamespaceComponent<'_>> {
self.deref().components()
}
#[inline]
fn components_hint(&self) -> NamespaceComponentsHint {
self.deref().components_hint()
}
}