use core::ops::Deref;
use super::types::Content;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NonEmpty<T>(T);
impl<T> NonEmpty<T> {
#[doc(hidden)]
#[must_use]
pub const fn new_unchecked(value: T) -> Self {
Self(value)
}
#[must_use]
pub const fn into_inner(self) -> T
where
T: Copy,
{
self.0
}
#[must_use]
pub const fn as_inner(&self) -> &T {
&self.0
}
}
impl<T> Deref for NonEmpty<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<'src> NonEmpty<Content<'src>> {
#[must_use]
pub fn new(content: Content<'src>) -> Option<Self> {
match content {
Content::Plain(s) if !s.is_empty() => Some(Self(content)),
Content::Segments(segs) if !segs.is_empty() => Some(Self(content)),
_ => None,
}
}
#[must_use]
pub const fn get(self) -> Content<'src> {
self.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct NonEmptyStr<'src>(&'src str);
impl<'src> NonEmptyStr<'src> {
#[must_use]
pub const fn new(s: &'src str) -> Option<Self> {
if s.is_empty() { None } else { Some(Self(s)) }
}
#[doc(hidden)]
#[must_use]
pub const fn new_unchecked(s: &'src str) -> Self {
Self(s)
}
#[must_use]
pub const fn as_str(self) -> &'src str {
self.0
}
}
impl Deref for NonEmptyStr<'_> {
type Target = str;
fn deref(&self) -> &str {
self.0
}
}
#[cfg(test)]
mod tests {
use super::super::types::Segment;
use super::*;
#[test]
fn new_rejects_plain_empty_string() {
assert!(NonEmpty::new(Content::Plain("")).is_none());
}
#[test]
fn new_rejects_empty_segments_slice() {
assert!(NonEmpty::new(Content::Segments(&[])).is_none());
}
#[test]
fn new_accepts_plain_non_empty() {
let ne = NonEmpty::new(Content::Plain("text")).expect("non-empty");
assert!(matches!(ne.get(), Content::Plain("text")));
}
#[test]
fn new_accepts_non_empty_segments() {
static SEGS: &[Segment<'static>] = &[Segment::Text("a")];
let ne = NonEmpty::new(Content::Segments(SEGS)).expect("non-empty");
assert!(matches!(ne.get(), Content::Segments(s) if s.len() == 1));
}
#[test]
fn deref_gives_inner_methods() {
let ne = NonEmpty::new(Content::Plain("abc")).expect("non-empty");
assert_eq!(ne.as_plain(), Some("abc"));
}
#[test]
fn empty_content_const_is_rejected() {
assert!(NonEmpty::new(Content::EMPTY).is_none());
}
}