Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  builtins.rs   Sprache: unbekannt

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

use crate::ffi;
use fluent::types::{FluentNumberOptions, FluentType, FluentValue};
use fluent::FluentArgs;
use intl_memoizer::IntlLangMemoizer;
use intl_memoizer::Memoizable;
use nsstring::nsCString;
use std::borrow::Cow;
use std::ptr::NonNull;
use unic_langid::LanguageIdentifier;

pub struct NumberFormat {
    raw: Option<NonNull<ffi::RawNumberFormatter>>,
}

/**
 * According to http://userguide.icu-project.org/design, as long as we constrain
 * ourselves to const APIs ICU is const-correct.
 */
unsafe impl Send for NumberFormat {}
unsafe impl Sync for NumberFormat {}

impl NumberFormat {
    pub fn new(locale: LanguageIdentifier, options: &FluentNumberOptions) -> Self {
        let loc: String = locale.to_string();
        Self {
            raw: unsafe {
                NonNull::new(ffi::FluentBuiltInNumberFormatterCreate(
                    &loc.into(),
                    &options.into(),
                ))
            },
        }
    }

    pub fn format(&self, input: f64) -> String {
        if let Some(raw) = self.raw {
            unsafe {
                let mut byte_count = 0;
                let mut capacity = 0;
                let buffer = ffi::FluentBuiltInNumberFormatterFormat(
                    raw.as_ptr(),
                    input,
                    &mut byte_count,
                    &mut capacity,
                );
                if buffer.is_null() {
                    return String::new();
                }
                String::from_raw_parts(buffer, byte_count, capacity)
            }
        } else {
            String::new()
        }
    }
}

impl Drop for NumberFormat {
    fn drop(&mut self) {
        if let Some(raw) = self.raw {
            unsafe { ffi::FluentBuiltInNumberFormatterDestroy(raw.as_ptr()) };
        }
    }
}

impl Memoizable for NumberFormat {
    type Args = (FluentNumberOptions,);
    type Error = &'static str;
    fn construct(lang: LanguageIdentifier, args: Self::Args) -> Result<Self, Self::Error> {
        Ok(NumberFormat::new(lang, &args.0))
    }
}

#[repr(C)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum FluentDateTimeStyle {
    Full,
    Long,
    Medium,
    Short,
    None,
}

impl Default for FluentDateTimeStyle {
    fn default() -> Self {
        Self::None
    }
}

impl From<&str> for FluentDateTimeStyle {
    fn from(input: &str) -> Self {
        match input {
            "full" => Self::Full,
            "long" => Self::Long,
            "medium" => Self::Medium,
            "short" => Self::Short,
            _ => Self::None,
        }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum FluentDateTimeHourCycle {
    H24,
    H23,
    H12,
    H11,
    None,
}

impl Default for FluentDateTimeHourCycle {
    fn default() -> Self {
        Self::None
    }
}

impl From<&str> for FluentDateTimeHourCycle {
    fn from(input: &str) -> Self {
        match input {
            "h24" => Self::H24,
            "h23" => Self::H23,
            "h12" => Self::H12,
            "h11" => Self::H11,
            _ => Self::None,
        }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum FluentDateTimeTextComponent {
    Long,
    Short,
    Narrow,
    None,
}

impl Default for FluentDateTimeTextComponent {
    fn default() -> Self {
        Self::None
    }
}

impl From<&str> for FluentDateTimeTextComponent {
    fn from(input: &str) -> Self {
        match input {
            "long" => Self::Long,
            "short" => Self::Short,
            "narrow" => Self::Narrow,
            _ => Self::None,
        }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum FluentDateTimeNumericComponent {
    Numeric,
    TwoDigit,
    None,
}

impl Default for FluentDateTimeNumericComponent {
    fn default() -> Self {
        Self::None
    }
}

impl From<&str> for FluentDateTimeNumericComponent {
    fn from(input: &str) -> Self {
        match input {
            "numeric" => Self::Numeric,
            "2-digit" => Self::TwoDigit,
            _ => Self::None,
        }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum FluentDateTimeMonthComponent {
    Numeric,
    TwoDigit,
    Long,
    Short,
    Narrow,
    None,
}

impl Default for FluentDateTimeMonthComponent {
    fn default() -> Self {
        Self::None
    }
}

impl From<&str> for FluentDateTimeMonthComponent {
    fn from(input: &str) -> Self {
        match input {
            "numeric" => Self::Numeric,
            "2-digit" => Self::TwoDigit,
            "long" => Self::Long,
            "short" => Self::Short,
            "narrow" => Self::Narrow,
            _ => Self::None,
        }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum FluentDateTimeTimeZoneNameComponent {
    Long,
    Short,
    None,
}

impl Default for FluentDateTimeTimeZoneNameComponent {
    fn default() -> Self {
        Self::None
    }
}

impl From<&str> for FluentDateTimeTimeZoneNameComponent {
    fn from(input: &str) -> Self {
        match input {
            "long" => Self::Long,
            "short" => Self::Short,
            _ => Self::None,
        }
    }
}

#[repr(C)]
#[derive(Default, Debug, Clone, Hash, PartialEq, Eq)]
pub struct FluentDateTimeOptions {
    pub date_style: FluentDateTimeStyle,
    pub time_style: FluentDateTimeStyle,
    pub hour_cycle: FluentDateTimeHourCycle,
    pub weekday: FluentDateTimeTextComponent,
    pub era: FluentDateTimeTextComponent,
    pub year: FluentDateTimeNumericComponent,
    pub month: FluentDateTimeMonthComponent,
    pub day: FluentDateTimeNumericComponent,
    pub hour: FluentDateTimeNumericComponent,
    pub minute: FluentDateTimeNumericComponent,
    pub second: FluentDateTimeNumericComponent,
    pub time_zone_name: FluentDateTimeTimeZoneNameComponent,
}

impl FluentDateTimeOptions {
    pub fn merge(&mut self, opts: &FluentArgs) {
        for (key, value) in opts.iter() {
            match (key, value) {
                ("dateStyle", FluentValue::String(n)) => {
                    self.date_style = n.as_ref().into();
                }
                ("timeStyle", FluentValue::String(n)) => {
                    self.time_style = n.as_ref().into();
                }
                ("hourCycle", FluentValue::String(n)) => {
                    self.hour_cycle = n.as_ref().into();
                }
                ("weekday", FluentValue::String(n)) => {
                    self.weekday = n.as_ref().into();
                }
                ("era", FluentValue::String(n)) => {
                    self.era = n.as_ref().into();
                }
                ("year", FluentValue::String(n)) => {
                    self.year = n.as_ref().into();
                }
                ("month", FluentValue::String(n)) => {
                    self.month = n.as_ref().into();
                }
                ("day", FluentValue::String(n)) => {
                    self.day = n.as_ref().into();
                }
                ("hour", FluentValue::String(n)) => {
                    self.hour = n.as_ref().into();
                }
                ("minute", FluentValue::String(n)) => {
                    self.minute = n.as_ref().into();
                }
                ("second", FluentValue::String(n)) => {
                    self.second = n.as_ref().into();
                }
                ("timeZoneName", FluentValue::String(n)) => {
                    self.time_zone_name = n.as_ref().into();
                }
                _ => {}
            }
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct FluentDateTime {
    epoch: f64,
    options: FluentDateTimeOptions,
}

impl FluentType for FluentDateTime {
    fn duplicate(&self) -> Box<dyn FluentType + Send> {
        Box::new(self.clone())
    }
    fn as_string(&self, intls: &IntlLangMemoizer) -> Cow<'static, str> {
        let result = intls
            .with_try_get::<DateTimeFormat, _, _>((self.options.clone(),), |dtf| {
                dtf.format(self.epoch)
            })
            .expect("Failed to retrieve a DateTimeFormat instance.");
        result.into()
    }
    fn as_string_threadsafe(
        &self,
        _: &intl_memoizer::concurrent::IntlLangMemoizer,
    ) -> Cow<'static, str> {
        unimplemented!()
    }
}

impl std::fmt::Display for FluentDateTime {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "DATETIME: {}", self.epoch)
    }
}

impl FluentDateTime {
    pub fn new(epoch: f64, options: FluentDateTimeOptions) -> Self {
        Self { epoch, options }
    }
}

pub struct DateTimeFormat {
    raw: Option<NonNull<ffi::RawDateTimeFormatter>>,
}

/**
 * According to http://userguide.icu-project.org/design, as long as we constrain
 * ourselves to const APIs ICU is const-correct.
 */
unsafe impl Send for DateTimeFormat {}
unsafe impl Sync for DateTimeFormat {}

impl DateTimeFormat {
    pub fn new(locale: LanguageIdentifier, options: FluentDateTimeOptions) -> Self {
        // ICU needs null-termination here, otherwise we could use nsCStr.
        let loc: nsCString = locale.to_string().into();
        Self {
            raw: unsafe { NonNull::new(ffi::FluentBuiltInDateTimeFormatterCreate(&loc, options)) },
        }
    }

    pub fn format(&self, input: f64) -> String {
        if let Some(raw) = self.raw {
            unsafe {
                let mut byte_count = 0;
                let buffer =
                    ffi::FluentBuiltInDateTimeFormatterFormat(raw.as_ptr(), input, &mut byte_count);
                if buffer.is_null() {
                    return String::new();
                }
                String::from_raw_parts(buffer, byte_count as usize, byte_count as usize)
            }
        } else {
            String::new()
        }
    }
}

impl Drop for DateTimeFormat {
    fn drop(&mut self) {
        if let Some(raw) = self.raw {
            unsafe { ffi::FluentBuiltInDateTimeFormatterDestroy(raw.as_ptr()) };
        }
    }
}

impl Memoizable for DateTimeFormat {
    type Args = (FluentDateTimeOptions,);
    type Error = &'static str;
    fn construct(lang: LanguageIdentifier, args: Self::Args) -> Result<Self, Self::Error> {
        Ok(DateTimeFormat::new(lang, args.0))
    }
}

[ Dauer der Verarbeitung: 0.22 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge