use alloc::string::String;
use alloc::vec::Vec;
use core::fmt;
use displaydoc::Display;
use icu_locale_core::Locale;
use icu_provider::DataError;
pub trait PersonName {
fn name_locale(&self) -> Option<&Locale>;
fn preferred_order(&self) -> Option<&PreferredOrder>;
fn get(&self, field: &NameField) -> &str;
fn available_name_fields(&self) -> Vec<&NameField>;
fn has_name_field_kind(&self, lookup_name_field: &NameFieldKind) -> bool;
fn has_name_field(&self, lookup_name_field: &NameField) -> bool;
}
#[derive(Clone, Eq, PartialEq, Debug, Display)]
pub enum PersonNamesFormatterError {
#[displaydoc("{0}")]
ParseError(String),
#[displaydoc("Invalid person name")]
InvalidPersonName,
#[displaydoc("Invalid person name")]
InvalidLocale,
#[displaydoc("Invalid CLDR data")]
InvalidCldrData,
#[displaydoc("{0}")]
Data(DataError),
#[displaydoc("{0}")]
Pattern(icu_pattern::Error),
}
impl From<DataError> for PersonNamesFormatterError {
fn from(e: DataError) -> Self {
PersonNamesFormatterError::Data(e)
}
}
impl From<icu_pattern::Error> for PersonNamesFormatterError {
fn from(e: icu_pattern::Error) -> Self {
PersonNamesFormatterError::Pattern(e)
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub(crate) enum FieldModifier {
None,
Informal,
Prefix,
Core,
AllCaps,
InitialCap,
Initial,
Monogram,
}
impl FieldModifier {
pub(crate) fn bit_value(&self) -> u32 {
match &self {
FieldModifier::None => 0,
FieldModifier::Informal => 1 << 0,
FieldModifier::Prefix => 1 << 1,
FieldModifier::Core => 1 << 2,
FieldModifier::AllCaps => 1 << 3,
FieldModifier::InitialCap => 1 << 4,
FieldModifier::Initial => 1 << 5,
FieldModifier::Monogram => 1 << 6,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FieldCapsStyle {
Auto,
AllCaps,
InitialCap,
}
impl From<FieldCapsStyle> for FieldModifier {
fn from(value: FieldCapsStyle) -> Self {
match value {
FieldCapsStyle::Auto => FieldModifier::None,
FieldCapsStyle::AllCaps => FieldModifier::AllCaps,
FieldCapsStyle::InitialCap => FieldModifier::InitialCap,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FieldPart {
Auto,
Core,
Prefix,
}
impl From<FieldPart> for FieldModifier {
fn from(value: FieldPart) -> Self {
match value {
FieldPart::Auto => FieldModifier::None,
FieldPart::Core => FieldModifier::Core,
FieldPart::Prefix => FieldModifier::Prefix,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FieldLength {
Auto,
Initial,
Monogram,
}
impl From<FieldLength> for FieldModifier {
fn from(value: FieldLength) -> Self {
match value {
FieldLength::Auto => FieldModifier::None,
FieldLength::Initial => FieldModifier::Initial,
FieldLength::Monogram => FieldModifier::Monogram,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FieldFormality {
Auto,
Informal,
}
impl From<FieldFormality> for FieldModifier {
fn from(value: FieldFormality) -> Self {
match value {
FieldFormality::Auto => FieldModifier::None,
FieldFormality::Informal => FieldModifier::Informal,
}
}
}
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Copy)]
pub struct FieldModifierSet {
pub(crate) value: u32,
}
impl FieldModifierSet {
pub(crate) fn has_field(&self, modifier: FieldModifier) -> bool {
self.value & modifier.bit_value() == modifier.bit_value()
}
pub(crate) fn with_part(&self, part: FieldPart) -> FieldModifierSet {
FieldModifierSet {
value: (self.value
& (u32::MAX
^ (FieldModifier::Core.bit_value() | FieldModifier::Prefix.bit_value())))
| FieldModifier::from(part).bit_value(),
}
}
pub(crate) fn with_length(&self, length: FieldLength) -> FieldModifierSet {
FieldModifierSet {
value: (self.value
& (u32::MAX
^ (FieldModifier::Monogram.bit_value() | FieldModifier::Initial.bit_value())))
| FieldModifier::from(length).bit_value(),
}
}
pub fn formality(formality: FieldFormality) -> Self {
Self::new(
FieldCapsStyle::Auto,
FieldPart::Auto,
FieldLength::Auto,
formality,
)
}
pub fn style(style: FieldCapsStyle) -> Self {
Self::new(
style,
FieldPart::Auto,
FieldLength::Auto,
FieldFormality::Auto,
)
}
pub fn part(part: FieldPart) -> Self {
Self::new(
FieldCapsStyle::Auto,
part,
FieldLength::Auto,
FieldFormality::Auto,
)
}
pub fn length(length: FieldLength) -> Self {
Self::new(
FieldCapsStyle::Auto,
FieldPart::Auto,
length,
FieldFormality::Auto,
)
}
pub fn new(
style: FieldCapsStyle,
part: FieldPart,
length: FieldLength,
formality: FieldFormality,
) -> Self {
FieldModifierSet {
value: FieldModifier::from(style).bit_value()
| FieldModifier::from(part).bit_value()
| FieldModifier::from(length).bit_value()
| FieldModifier::from(formality).bit_value(),
}
}
}
impl Default for FieldModifierSet {
fn default() -> Self {
Self::new(
FieldCapsStyle::Auto,
FieldPart::Auto,
FieldLength::Auto,
FieldFormality::Auto,
)
}
}
impl fmt::Debug for FieldModifierSet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
let mut debug = f.debug_struct("FieldModifierSet");
debug.field("core", &self.has_field(FieldModifier::Core));
debug.field("informal", &self.has_field(FieldModifier::Informal));
debug.field("monogram", &self.has_field(FieldModifier::Monogram));
debug.field("initial", &self.has_field(FieldModifier::Initial));
debug.field("prefix", &self.has_field(FieldModifier::Prefix));
debug.field("all_caps", &self.has_field(FieldModifier::AllCaps));
debug.field("initial_cap", &self.has_field(FieldModifier::InitialCap));
debug.finish()
}
}
#[derive(Eq, Ord, PartialOrd, PartialEq, Hash, Debug, Clone, Copy)]
pub struct NameField {
pub kind: NameFieldKind,
pub modifier: FieldModifierSet,
}
#[derive(Eq, Ord, PartialOrd, PartialEq, Hash, Debug, Clone, Copy)]
pub enum NameFieldKind {
Title,
Given,
Given2,
Surname,
Surname2,
Generation,
Credentials,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum PreferredOrder {
Default,
GivenFirst,
SurnameFirst,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FormattingOrder {
GivenFirst,
SurnameFirst,
Sorting,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FormattingLength {
Short,
Medium,
Long,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FormattingUsage {
Addressing,
Referring,
Monogram,
}
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum FormattingFormality {
Formal,
Informal,
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct PersonNamesFormatterOptions {
pub target_locale: Locale,
pub order: FormattingOrder,
pub length: FormattingLength,
pub usage: FormattingUsage,
pub formality: FormattingFormality,
}
impl PersonNamesFormatterOptions {
#[cfg(feature = "compiled_data")]
pub fn new(
target_locale: Locale,
order: FormattingOrder,
length: FormattingLength,
usage: FormattingUsage,
formality: FormattingFormality,
) -> Self {
let lc = icu_locale::LocaleExpander::new();
let mut final_locale = target_locale.clone();
lc.maximize(&mut final_locale.id);
Self {
target_locale: final_locale,
order,
length,
usage,
formality,
}
}
}