#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![no_std]
#![forbid(unsafe_code)]
extern crate alloc;
#[cfg(feature = "time-zones")]
mod dates;
#[cfg(feature = "intl")]
mod numbers;
use alloc::string::String;
use js_sys::{JsString, Number};
use mf2_runtime::Host;
#[cfg(feature = "intl")]
pub use numbers::{IntlNumbers, NUMBERS_HOST};
#[derive(Clone, Copy, Default, Debug)]
pub struct WebHost;
pub static HOST: WebHost = WebHost;
#[cfg(feature = "time-zones")]
#[derive(Clone, Copy, Default, Debug)]
pub struct ZonesWebHost;
#[cfg(feature = "time-zones")]
pub static ZONES_HOST: ZonesWebHost = ZonesWebHost;
#[cfg(feature = "datetime-intl")]
#[derive(Clone, Copy, Default, Debug)]
pub struct IntlWebHost;
#[cfg(feature = "datetime-intl")]
pub static INTL_HOST: IntlWebHost = IntlWebHost;
impl Host for WebHost {
fn nfc<'a>(&self, s: &'a str, buf: &'a mut String) -> &'a str {
let normalized = JsString::from(s).normalize("NFC");
buf.clear();
match normalized.as_string() {
Some(text) => {
*buf = text;
buf
}
None => s,
}
}
fn f64_to_text<'b>(&self, x: f64, buf: &'b mut [u8; 32]) -> Option<&'b str> {
if !x.is_finite() {
return None;
}
let text = Number::from(x).to_string_with_radix(10).ok()?.as_string()?;
let out = buf.get_mut(..text.len())?;
out.copy_from_slice(text.as_bytes());
core::str::from_utf8(out).ok()
}
}
#[cfg(feature = "time-zones")]
impl Host for ZonesWebHost {
fn nfc<'a>(&self, s: &'a str, buf: &'a mut String) -> &'a str {
WebHost.nfc(s, buf)
}
fn f64_to_text<'b>(&self, x: f64, buf: &'b mut [u8; 32]) -> Option<&'b str> {
WebHost.f64_to_text(x, buf)
}
fn zone_offset(&self, zone: &str, epoch_ms: i64) -> Option<i32> {
dates::zone_offset(zone, epoch_ms)
}
}
#[cfg(feature = "datetime-intl")]
impl Host for IntlWebHost {
fn nfc<'a>(&self, s: &'a str, buf: &'a mut String) -> &'a str {
WebHost.nfc(s, buf)
}
fn f64_to_text<'b>(&self, x: f64, buf: &'b mut [u8; 32]) -> Option<&'b str> {
WebHost.f64_to_text(x, buf)
}
fn zone_offset(&self, zone: &str, epoch_ms: i64) -> Option<i32> {
dates::zone_offset(zone, epoch_ms)
}
fn format_date_time(
&self,
locale: &str,
request: &mf2_runtime::DateTimeRequest<'_>,
out: &mut dyn mf2_runtime::Sink,
) -> bool {
dates::format(locale, request, out)
}
}