icu_locale_core/extensions/unicode/
attributes.rs1use super::Attribute;
6
7#[cfg(feature = "alloc")]
8use crate::parser::SubtagIterator;
9use crate::shortvec::ShortBoxSlice;
10#[cfg(feature = "alloc")]
11use crate::ParseError;
12#[cfg(feature = "alloc")]
13use alloc::vec::Vec;
14use core::ops::Deref;
15#[cfg(feature = "alloc")]
16use core::str::FromStr;
17
18#[derive(#[automatically_derived]
impl ::core::default::Default for Attributes {
#[inline]
fn default() -> Attributes {
Attributes(::core::default::Default::default())
}
}Default, #[automatically_derived]
impl ::core::fmt::Debug for Attributes {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Attributes",
&&self.0)
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Attributes {
#[inline]
fn eq(&self, other: &Attributes) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Attributes {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<ShortBoxSlice<Attribute>>;
}
}Eq, #[automatically_derived]
impl ::core::clone::Clone for Attributes {
#[inline]
fn clone(&self) -> Attributes {
Attributes(::core::clone::Clone::clone(&self.0))
}
}Clone, #[automatically_derived]
impl ::core::hash::Hash for Attributes {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, #[automatically_derived]
impl ::core::cmp::PartialOrd for Attributes {
#[inline]
fn partial_cmp(&self, other: &Attributes)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
}
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for Attributes {
#[inline]
fn cmp(&self, other: &Attributes) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord)]
41pub struct Attributes(ShortBoxSlice<Attribute>);
42
43impl Attributes {
44 #[inline]
54 pub const fn new() -> Self {
55 Self(ShortBoxSlice::new())
56 }
57
58 #[inline]
63 #[cfg(feature = "alloc")]
64 pub fn try_from_str(s: &str) -> Result<Self, ParseError> {
65 Self::try_from_utf8(s.as_bytes())
66 }
67
68 #[cfg(feature = "alloc")]
72 pub fn try_from_utf8(code_units: &[u8]) -> Result<Self, ParseError> {
73 let mut iter = SubtagIterator::new(code_units);
74 Self::try_from_iter(&mut iter)
75 }
76
77 #[cfg(feature = "alloc")]
99 pub fn from_vec_unchecked(input: Vec<Attribute>) -> Self {
100 Self(input.into())
101 }
102
103 pub fn clear(&mut self) -> Self {
125 core::mem::take(self)
126 }
127
128 #[cfg(feature = "alloc")]
129 pub(crate) fn try_from_iter(iter: &mut SubtagIterator) -> Result<Self, ParseError> {
130 let mut attributes = ShortBoxSlice::new();
131
132 while let Some(subtag) = iter.peek() {
133 if let Ok(attr) = Attribute::try_from_utf8(subtag) {
134 if let Err(idx) = attributes.binary_search(&attr) {
135 attributes.insert(idx, attr);
136 }
137 } else {
138 break;
139 }
140 iter.next();
141 }
142 Ok(Self(attributes))
143 }
144
145 pub(crate) fn for_each_subtag_str<E, F>(&self, f: &mut F) -> Result<(), E>
146 where
147 F: FnMut(&str) -> Result<(), E>,
148 {
149 self.deref().iter().map(|t| t.as_str()).try_for_each(f)
150 }
151
152 #[cfg(feature = "alloc")]
167 pub fn extend_from_attributes(&mut self, other: Attributes) {
168 for attr in other.0 {
169 if let Err(idx) = self.binary_search(&attr) {
170 self.0.insert(idx, attr);
171 }
172 }
173 }
174}
175
176#[cfg(feature = "alloc")]
178impl FromStr for Attributes {
179 type Err = ParseError;
180
181 #[inline]
182 fn from_str(s: &str) -> Result<Self, Self::Err> {
183 Self::try_from_str(s)
184 }
185}
186
187impl writeable::Writeable for Attributes {
fn write_to<W: core::fmt::Write + ?Sized>(&self, sink: &mut W)
-> core::fmt::Result {
let mut initial = true;
self.for_each_subtag_str(&mut |subtag|
{
if initial {
initial = false;
} else { sink.write_char('-')?; }
sink.write_str(subtag)
})
}
#[inline]
fn writeable_length_hint(&self) -> writeable::LengthHint {
let mut result = writeable::LengthHint::exact(0);
let mut initial = true;
self.for_each_subtag_str::<core::convert::Infallible,
_>(&mut |subtag|
{
if initial { initial = false; } else { result += 1; }
result += subtag.len();
Ok(())
}).expect("infallible");
result
}
fn writeable_borrow(&self) -> Option<&str> {
let selff = self;
if selff.0.len() == 1 {
#[allow(clippy :: unwrap_used)]
{ Some(selff.0.get(0).unwrap().as_str()) }
} else { None }
}
}
impl core::fmt::Display for Attributes {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
::writeable::Writeable::write_to(&self, f)
}
}impl_writeable_for_subtag_list!(Attributes, "foobar", "testing");
188
189impl Deref for Attributes {
190 type Target = [Attribute];
191
192 fn deref(&self) -> &[Attribute] {
193 self.0.deref()
194 }
195}
196
197#[cfg(test)]
198mod tests {
199 use super::*;
200
201 #[test]
202 fn test_attributes_fromstr() {
203 let attrs: Attributes = "foo-bar".parse().expect("Failed to parse Attributes");
204 assert_eq!(attrs.to_string(), "bar-foo");
205 }
206}