icu_locale_core/extensions/unicode/
attribute.rs1#[repr(transparent)]
#[doc = r" An attribute used in a set of [`Attributes`](super::Attributes)."]
#[doc = r""]
#[doc = r" An attribute has to be a sequence of alphanumerical characters no"]
#[doc = r" shorter than three and no longer than eight characters."]
#[doc = r""]
#[doc = r""]
#[doc = r" # Examples"]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" use icu::locale::extensions::unicode::{attribute, Attribute};"]
#[doc = r""]
#[doc = r" let attr: Attribute ="]
#[doc = r#" "buddhist".parse().expect("Failed to parse an Attribute.");"#]
#[doc = r""]
#[doc = r#" assert_eq!(attr, attribute!("buddhist"));"#]
#[doc = r" ```"]
pub struct Attribute(tinystr::TinyAsciiStr<8>);
#[automatically_derived]
impl ::core::fmt::Debug for Attribute {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Attribute",
&&self.0)
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for Attribute { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Attribute {
#[inline]
fn eq(&self, other: &Attribute) -> bool { self.0 == other.0 }
}
#[automatically_derived]
impl ::core::cmp::Eq for Attribute {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<tinystr::TinyAsciiStr<8>>;
}
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Attribute { }
#[automatically_derived]
impl ::core::clone::Clone for Attribute {
#[inline]
fn clone(&self) -> Attribute {
let _: ::core::clone::AssertParamIsClone<tinystr::TinyAsciiStr<8>>;
*self
}
}
#[automatically_derived]
impl ::core::hash::Hash for Attribute {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.0, state)
}
}
#[automatically_derived]
impl ::core::cmp::PartialOrd for Attribute {
#[inline]
fn partial_cmp(&self, other: &Attribute)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl ::core::cmp::Ord for Attribute {
#[inline]
fn cmp(&self, other: &Attribute) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}
#[automatically_derived]
impl ::core::marker::Copy for Attribute { }
impl Attribute {
#[doc = "produces a well-formed [`Attribute`]."]
#[doc = "use icu_locale_core::extensions :: unicode ::Attribute;"]
#[doc = "assert!(Attribute::try_from_str(\"foo12\").is_ok());"]
#[doc = "assert!(Attribute::try_from_str(\"no\").is_err());"]
#[inline]
pub const fn try_from_str(s: &str)
-> Result<Self, crate::parser::errors::ParseError> {
Self::try_from_utf8(s.as_bytes())
}
pub const fn try_from_utf8(code_units: &[u8])
-> Result<Self, crate::parser::errors::ParseError> {
if code_units.len() < 3 || code_units.len() > 8 {
return Err(crate::parser::errors::ParseError::InvalidExtension);
}
match tinystr::TinyAsciiStr::try_from_utf8(code_units) {
Ok(s) if s.is_ascii_alphanumeric() =>
Ok(Self(s.to_ascii_lowercase())),
_ => Err(crate::parser::errors::ParseError::InvalidExtension),
}
}
#[doc = "Safely creates a [`Attribute`] from its raw format"]
pub const fn try_from_raw(raw: [u8; 8])
-> Result<Self, crate::parser::errors::ParseError> {
if let Ok(s) = tinystr::TinyAsciiStr::<8>::try_from_raw(raw) {
if s.len() >= 3 &&
(s.is_ascii_alphanumeric() && s.is_ascii_lowercase()) {
Ok(Self(s))
} else {
Err(crate::parser::errors::ParseError::InvalidExtension)
}
} else { Err(crate::parser::errors::ParseError::InvalidExtension) }
}
#[doc = "Unsafely creates a [`Attribute`] from its raw format"]
pub const unsafe fn from_raw_unchecked(v: [u8; 8]) -> Self {
Self(tinystr::TinyAsciiStr::from_utf8_unchecked(v))
}
pub const fn into_raw(self) -> [u8; 8] { *self.0.all_bytes() }
#[inline]
pub const fn as_str(&self) -> &str { self.0.as_str() }
#[doc(hidden)]
pub const fn to_tinystr(&self) -> tinystr::TinyAsciiStr<8> { self.0 }
#[inline]
pub fn strict_cmp(self, other: &[u8]) -> core::cmp::Ordering {
self.as_str().as_bytes().cmp(other)
}
#[inline]
pub fn normalizing_eq(self, other: &str) -> bool {
self.as_str().eq_ignore_ascii_case(other)
}
}
impl core::str::FromStr for Attribute {
type Err = crate::parser::errors::ParseError;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> { Self::try_from_str(s) }
}
impl<'l> From<&'l Attribute> for &'l str {
fn from(input: &'l Attribute) -> Self { input.as_str() }
}
impl From<Attribute> for tinystr::TinyAsciiStr<8> {
fn from(input: Attribute) -> Self { input.to_tinystr() }
}
impl writeable::Writeable for Attribute {
#[inline]
fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W)
-> core::fmt::Result {
sink.write_str(self.as_str())
}
#[inline]
fn writeable_length_hint(&self) -> writeable::LengthHint {
writeable::LengthHint::exact(self.0.len())
}
fn writeable_borrow(&self) -> Option<&str> { Some(self.0.as_str()) }
}
impl core::fmt::Display for Attribute {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
::writeable::Writeable::write_to(&self, f)
}
}
#[doc =
"A macro allowing for compile-time construction of valid [`Attribute`] subtags."]
#[doc = " icu_locale_core::extensions::unicode::attribute!(\"foo12\"),"]
#[doc =
" \"foo12\".parse::<icu_locale_core::extensions::unicode::Attribute>().unwrap()"]
#[doc = "icu_locale_core::extensions::unicode::attribute!(\"no\");"]
#[doc = "[`Attribute`]: crate::extensions::unicode::Attribute"]
#[macro_export]
#[doc(hidden)]
macro_rules! extensions_unicode_attribute {
($string : literal) =>
{
const
{
use crate :: extensions :: unicode :: Attribute; match Attribute
:: try_from_utf8($string.as_bytes())
{
Ok(r) => r, _ => panic!
(concat!
("Invalid ", stringify! (extensions), "::", stringify!
(unicode), "::", stringify! (Attribute), ": ", $string)),
}
}
};
}
#[doc(inline)]
pub use extensions_unicode_attribute as attribute;
unsafe impl zerovec::ule::ULE for Attribute {
fn validate_bytes(bytes: &[u8]) -> Result<(), zerovec::ule::UleError> {
let it = bytes.chunks_exact(core::mem::size_of::<Self>());
if !it.remainder().is_empty() {
return Err(zerovec::ule::UleError::length::<Self>(bytes.len()));
}
for v in it {
let mut a = [0; core::mem::size_of::<Self>()];
a.copy_from_slice(v);
if Self::try_from_raw(a).is_err() {
return Err(zerovec::ule::UleError::parse::<Self>());
}
}
Ok(())
}
}
impl zerovec::ule::NicheBytes<8> for Attribute {
const NICHE_BIT_PATTERN: [u8; 8] =
<tinystr::TinyAsciiStr<8>>::NICHE_BIT_PATTERN;
}
impl zerovec::ule::AsULE for Attribute {
type ULE = Self;
fn to_unaligned(self) -> Self::ULE { self }
fn from_unaligned(unaligned: Self::ULE) -> Self { unaligned }
}impl_tinystr_subtag!(
6 Attribute,
23 extensions::unicode,
24 attribute,
25 extensions_unicode_attribute,
26 3..=8,
27 s,
28 s.is_ascii_alphanumeric(),
29 s.to_ascii_lowercase(),
30 s.is_ascii_alphanumeric() && s.is_ascii_lowercase(),
31 InvalidExtension,
32 ["foo12"],
33 ["no", "toolooong"],
34);