Skip to main content

mf2_fn_datetime/
intl.rs

1//! The `datetime-intl` backend in the browser (`plans/03-runtime.md` §5.1):
2//! the plan goes to the host's date formatter, `Host::format_date_time` —
3//! `mf2-host-web`'s `Intl.DateTimeFormat` — as a `DateTimeRequest`
4//! ([`Plan::request`]), so the wasm carries no date-formatting code and the
5//! catalog no date data. Server text (ICU4X, CLDR 48) and browser text can
6//! differ cosmetically (P0.10: harmless to hydration).
7
8use mf2_runtime::{Dir, FnContext, FormatError, Sink};
9
10use crate::neutral::Neutral;
11use crate::plan::{Backend, Plan};
12
13/// The host's date formatter (`Host::format_date_time`). A host without one
14/// (it answers `false`, the default: an application that names
15/// `mf2_host_web::HOST` rather than `INTL_HOST`), or one that rejects the
16/// request, gets the neutral text.
17#[derive(Clone, Copy, Default, Debug)]
18pub struct Intl;
19
20/// ECMA-402's time range: ±8.64 × 10¹⁵ ms around the epoch (±100,000,000
21/// days).
22const MAX_MS: i64 = 8_640_000_000_000_000;
23
24impl Backend for Intl {
25    /// A plan outside ECMA-402's time range is an *Unsupported Operation*
26    /// (the ICU4X backend's range is narrower still).
27    fn supports(&self, _cx: &FnContext<'_>, plan: &Plan<'_>) -> Result<(), FormatError> {
28        if plan.request().epoch_ms.unsigned_abs() > MAX_MS.unsigned_abs() {
29            return Err(FormatError::UnsupportedOperation);
30        }
31        Ok(())
32    }
33
34    fn format(&self, cx: &FnContext<'_>, plan: &Plan<'_>, out: &mut dyn Sink) {
35        if !cx
36            .host()
37            .format_date_time(cx.locale(), &plan.request(), out)
38        {
39            Neutral.format(cx, plan, out);
40        }
41    }
42
43    /// Localized text has the catalog's direction.
44    fn dir(&self, cx: &FnContext<'_>, _plan: &Plan<'_>) -> Dir {
45        cx.catalog().dir()
46    }
47}