use core::hash::Hash;
use crate::utils;
#[derive(static_automata::Validate, str_newtype::StrNewType)]
#[automaton(crate::grammar::Variant)]
#[newtype(
no_deref,
ord([u8], &[u8], str, &str)
)]
#[cfg_attr(
feature = "std",
newtype(ord(Vec<u8>, String), owned(VariantBuf, derive(PartialEq, Eq, PartialOrd, Ord, Hash)))
)]
#[cfg_attr(feature = "serde", newtype(serde))]
pub struct Variant(str);
impl PartialEq for Variant {
fn eq(&self, other: &Self) -> bool {
utils::case_insensitive_eq(self.as_bytes(), other.as_bytes())
}
}
impl Eq for Variant {}
impl PartialOrd for Variant {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Variant {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
utils::case_insensitive_cmp(self.as_bytes(), other.as_bytes())
}
}
impl Hash for Variant {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
utils::case_insensitive_hash(self.as_bytes(), state)
}
}
#[derive(static_automata::Validate, str_newtype::StrNewType)]
#[automaton(crate::grammar::Variants)]
#[newtype(
no_deref,
ord([u8], &[u8], str, &str)
)]
#[cfg_attr(
feature = "std",
newtype(ord(Vec<u8>, String), owned(VariantsBuf, derive(PartialEq, Eq, PartialOrd, Ord, Hash)))
)]
#[cfg_attr(feature = "serde", newtype(serde))]
pub struct Variants(str);
impl Variants {
pub const EMPTY: &Self = unsafe { Self::new_unchecked("") };
pub fn iter(&self) -> VariantsIter<'_> {
VariantsIter::new(&self.0)
}
pub fn first(&self) -> Option<&Variant> {
self.iter().next()
}
pub fn last(&self) -> Option<&Variant> {
self.iter().next_back()
}
}
impl PartialEq for Variants {
fn eq(&self, other: &Self) -> bool {
utils::case_insensitive_eq(self.as_bytes(), other.as_bytes())
}
}
impl Eq for Variants {}
impl PartialOrd for Variants {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Variants {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
utils::case_insensitive_cmp(self.as_bytes(), other.as_bytes())
}
}
impl Hash for Variants {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
utils::case_insensitive_hash(self.as_bytes(), state)
}
}
#[derive(Default)]
pub struct VariantsIter<'a> {
data: &'a str,
offset: usize,
end: usize,
}
impl<'a> VariantsIter<'a> {
fn new(data: &'a str) -> Self {
Self {
data,
offset: 0,
end: data.len(),
}
}
pub fn empty() -> Self {
Self::default()
}
}
impl<'a> Iterator for VariantsIter<'a> {
type Item = &'a Variant;
fn next(&mut self) -> Option<Self::Item> {
if self.offset < self.end {
let end = super::find_segment_end(self.data, self.offset);
let item = unsafe { Variant::new_unchecked(&self.data[self.offset..end]) };
self.offset = end + 1;
Some(item)
} else {
None
}
}
}
impl<'a> DoubleEndedIterator for VariantsIter<'a> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.end > self.offset {
let start = super::find_segment_start(self.data, self.end);
let item = unsafe { Variant::new_unchecked(&self.data[start..self.end]) };
self.end = if start > 0 { start - 1 } else { 0 };
Some(item)
} else {
None
}
}
}