diff options
author | Florian Dold <florian@dold.me> | 2023-05-26 13:52:00 +0200 |
---|---|---|
committer | Florian Dold <florian@dold.me> | 2023-05-26 13:52:00 +0200 |
commit | 96d9ea3840626f71efe38018b75748d8338565fa (patch) | |
tree | d1f04ecbb58750af79b3d0cb0420ba4fdf6d05a2 /packages/taler-util/src | |
parent | cd8f76db61f4a1ab1a8a8a4d29b2f3e863b59854 (diff) | |
download | wallet-core-96d9ea3840626f71efe38018b75748d8338565fa.tar.xz |
taler-util,wallet-core: make AbsoluteTime opaque
Diffstat (limited to 'packages/taler-util/src')
-rw-r--r-- | packages/taler-util/src/http-common.ts | 4 | ||||
-rw-r--r-- | packages/taler-util/src/time.ts | 66 | ||||
-rw-r--r-- | packages/taler-util/src/wallet-types.ts | 3 |
3 files changed, 50 insertions, 23 deletions
diff --git a/packages/taler-util/src/http-common.ts b/packages/taler-util/src/http-common.ts index 8da4003b5..4f8f12789 100644 --- a/packages/taler-util/src/http-common.ts +++ b/packages/taler-util/src/http-common.ts @@ -410,9 +410,7 @@ export function getExpiry( if (Number.isNaN(expiryDateMs)) { t = AbsoluteTime.now(); } else { - t = { - t_ms: expiryDateMs, - }; + t = AbsoluteTime.fromMilliseconds(expiryDateMs); } if (opt.minDuration) { const t2 = AbsoluteTime.addDuration(AbsoluteTime.now(), opt.minDuration); diff --git a/packages/taler-util/src/time.ts b/packages/taler-util/src/time.ts index 697bde5c0..717da7ecd 100644 --- a/packages/taler-util/src/time.ts +++ b/packages/taler-util/src/time.ts @@ -27,6 +27,8 @@ declare const flavor_AbsoluteTime: unique symbol; declare const flavor_TalerProtocolTimestamp: unique symbol; declare const flavor_TalerPreciseTimestamp: unique symbol; +const opaque_AbsoluteTime: unique symbol = Symbol("opaque_AbsoluteTime"); + // FIXME: Make this opaque! export interface AbsoluteTime { /** @@ -35,6 +37,10 @@ export interface AbsoluteTime { readonly t_ms: number | "never"; readonly _flavor?: typeof flavor_AbsoluteTime; + + // Make the type opaque, we only want our constructors + // to able to create an AbsoluteTime value. + [opaque_AbsoluteTime]: true; } export interface TalerProtocolTimestamp { @@ -69,7 +75,7 @@ export namespace TalerPreciseTimestamp { export function round(t: TalerPreciseTimestamp): TalerProtocolTimestamp { return { t_s: t.t_s, - } + }; } export function fromSeconds(s: number): TalerPreciseTimestamp { @@ -78,6 +84,13 @@ export namespace TalerPreciseTimestamp { off_us: (s - Math.floor(s)) / 1000 / 1000, }; } + + export function fromMilliseconds(ms: number): TalerPreciseTimestamp { + return { + t_s: Math.floor(ms / 1000), + off_us: Math.floor((ms - Math.floor(ms / 100) * 1000) * 1000), + } + } } export namespace TalerProtocolTimestamp { @@ -269,12 +282,21 @@ export namespace AbsoluteTime { export function now(): AbsoluteTime { return { t_ms: new Date().getTime() + timeshift, + [opaque_AbsoluteTime]: true, }; } export function never(): AbsoluteTime { return { t_ms: "never", + [opaque_AbsoluteTime]: true, + }; + } + + export function fromMilliseconds(ms: number): AbsoluteTime { + return { + t_ms: ms, + [opaque_AbsoluteTime]: true, }; } @@ -299,22 +321,22 @@ export namespace AbsoluteTime { export function min(t1: AbsoluteTime, t2: AbsoluteTime): AbsoluteTime { if (t1.t_ms === "never") { - return { t_ms: t2.t_ms }; + return { t_ms: t2.t_ms, [opaque_AbsoluteTime]: true }; } if (t2.t_ms === "never") { - return { t_ms: t2.t_ms }; + return { t_ms: t2.t_ms, [opaque_AbsoluteTime]: true }; } - return { t_ms: Math.min(t1.t_ms, t2.t_ms) }; + return { t_ms: Math.min(t1.t_ms, t2.t_ms), [opaque_AbsoluteTime]: true }; } export function max(t1: AbsoluteTime, t2: AbsoluteTime): AbsoluteTime { if (t1.t_ms === "never") { - return { t_ms: "never" }; + return { t_ms: "never", [opaque_AbsoluteTime]: true }; } if (t2.t_ms === "never") { - return { t_ms: "never" }; + return { t_ms: "never", [opaque_AbsoluteTime]: true }; } - return { t_ms: Math.max(t1.t_ms, t2.t_ms) }; + return { t_ms: Math.max(t1.t_ms, t2.t_ms), [opaque_AbsoluteTime]: true }; } export function difference(t1: AbsoluteTime, t2: AbsoluteTime): Duration { @@ -331,22 +353,26 @@ export namespace AbsoluteTime { return cmp(t, now()) <= 0; } - export function fromProtocolTimestamp(t: TalerProtocolTimestamp): AbsoluteTime { + export function fromProtocolTimestamp( + t: TalerProtocolTimestamp, + ): AbsoluteTime { if (t.t_s === "never") { - return { t_ms: "never" }; + return { t_ms: "never", [opaque_AbsoluteTime]: true }; } return { t_ms: t.t_s * 1000, + [opaque_AbsoluteTime]: true, }; } export function fromPreciseTimestamp(t: TalerPreciseTimestamp): AbsoluteTime { if (t.t_s === "never") { - return { t_ms: "never" }; + return { t_ms: "never", [opaque_AbsoluteTime]: true }; } const offsetUs = t.off_us ?? 0; return { t_ms: t.t_s * 1000 + offsetUs / 1000, + [opaque_AbsoluteTime]: true, }; } @@ -361,10 +387,12 @@ export namespace AbsoluteTime { return { t_s, off_us, - } + }; } - export function toProtocolTimestamp(at: AbsoluteTime): TalerProtocolTimestamp { + export function toProtocolTimestamp( + at: AbsoluteTime, + ): TalerProtocolTimestamp { if (at.t_ms === "never") { return { t_s: "never" }; } @@ -397,9 +425,9 @@ export namespace AbsoluteTime { export function addDuration(t1: AbsoluteTime, d: Duration): AbsoluteTime { if (t1.t_ms === "never" || d.d_ms === "forever") { - return { t_ms: "never" }; + return { t_ms: "never", [opaque_AbsoluteTime]: true }; } - return { t_ms: t1.t_ms + d.d_ms }; + return { t_ms: t1.t_ms + d.d_ms, [opaque_AbsoluteTime]: true }; } export function subtractDuraction( @@ -407,12 +435,12 @@ export namespace AbsoluteTime { d: Duration, ): AbsoluteTime { if (t1.t_ms === "never") { - return { t_ms: "never" }; + return { t_ms: "never", [opaque_AbsoluteTime]: true }; } if (d.d_ms === "forever") { - return { t_ms: 0 }; + return { t_ms: 0, [opaque_AbsoluteTime]: true }; } - return { t_ms: Math.max(0, t1.t_ms - d.d_ms) }; + return { t_ms: Math.max(0, t1.t_ms - d.d_ms), [opaque_AbsoluteTime]: true }; } export function stringify(t: AbsoluteTime): string { @@ -487,10 +515,10 @@ export const codecForAbsoluteTime: Codec<AbsoluteTime> = { const t_ms = x.t_ms; if (typeof t_ms === "string") { if (t_ms === "never") { - return { t_ms: "never" }; + return { t_ms: "never", [opaque_AbsoluteTime]: true }; } } else if (typeof t_ms === "number") { - return { t_ms }; + return { t_ms, [opaque_AbsoluteTime]: true }; } throw Error(`expected timestamp at ${renderContext(c)}`); }, diff --git a/packages/taler-util/src/wallet-types.ts b/packages/taler-util/src/wallet-types.ts index 38358e734..390df9638 100644 --- a/packages/taler-util/src/wallet-types.ts +++ b/packages/taler-util/src/wallet-types.ts @@ -65,6 +65,7 @@ import { } from "./taler-types.js"; import { AbsoluteTime, + TalerPreciseTimestamp, TalerProtocolDuration, TalerProtocolTimestamp, codecForAbsoluteTime, @@ -2024,7 +2025,7 @@ interface AttentionPushPaymentReceived { export type UserAttentionUnreadList = Array<{ info: AttentionInfo; - when: AbsoluteTime; + when: TalerPreciseTimestamp; read: boolean; }>; |