refactor: use temporal_rs as pkg
This commit is contained in:
parent
518998fcd8
commit
77ef20eff5
15 changed files with 1227 additions and 771 deletions
10
.gitignore
vendored
10
.gitignore
vendored
|
|
@ -1,11 +1,9 @@
|
||||||
zig-out
|
zig-out
|
||||||
.zig-cache
|
.zig-cache
|
||||||
|
target
|
||||||
|
|
||||||
# Ignore Rust build target directory
|
lib
|
||||||
vendor/temporal/target
|
!lib/*/libtemporal_capi.a
|
||||||
|
!lib/*/temporal_capi.lib
|
||||||
# But track the specific compiled libraries
|
|
||||||
!vendor/temporal/target/**/libtemporal.a
|
|
||||||
!vendor/temporal/target/**/temporal.lib
|
|
||||||
|
|
||||||
tmp
|
tmp
|
||||||
477
Cargo.lock
generated
Normal file
477
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,477 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "calendrical_calculations"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3a0b39595c6ee54a8d0900204ba4c401d0ab4eb45adaf07178e8d017541529e7"
|
||||||
|
dependencies = [
|
||||||
|
"core_maths",
|
||||||
|
"displaydoc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "combine"
|
||||||
|
version = "4.6.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core_maths"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77745e017f5edba1a9c1d854f6f3a52dac8a12dd5af5d2f54aecf61e43d80d30"
|
||||||
|
dependencies = [
|
||||||
|
"libm",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diplomat"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9adb46b05e2f53dcf6a7dfc242e4ce9eb60c369b6b6eb10826a01e93167f59c6"
|
||||||
|
dependencies = [
|
||||||
|
"diplomat_core",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diplomat-runtime"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0569bd3caaf13829da7ee4e83dbf9197a0e1ecd72772da6d08f0b4c9285c8d29"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diplomat_core"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51731530ed7f2d4495019abc7df3744f53338e69e2863a6a64ae91821c763df1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"serde",
|
||||||
|
"smallvec",
|
||||||
|
"strck",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "displaydoc"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_calendar"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d6f0e52e009b6b16ba9c0693578796f2dd4aaa59a7f8f920423706714a89ac4e"
|
||||||
|
dependencies = [
|
||||||
|
"calendrical_calculations",
|
||||||
|
"displaydoc",
|
||||||
|
"icu_calendar_data",
|
||||||
|
"icu_locale",
|
||||||
|
"icu_locale_core",
|
||||||
|
"icu_provider",
|
||||||
|
"tinystr",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_calendar_data"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "527f04223b17edfe0bd43baf14a0cb1b017830db65f3950dc00224860a9a446d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_collections"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"potential_utf",
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_locale"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "532b11722e350ab6bf916ba6eb0efe3ee54b932666afec989465f9243fe6dd60"
|
||||||
|
dependencies = [
|
||||||
|
"icu_collections",
|
||||||
|
"icu_locale_core",
|
||||||
|
"icu_locale_data",
|
||||||
|
"icu_provider",
|
||||||
|
"potential_utf",
|
||||||
|
"tinystr",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_locale_core"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"litemap",
|
||||||
|
"serde",
|
||||||
|
"tinystr",
|
||||||
|
"writeable",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_locale_data"
|
||||||
|
version = "2.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1c5f1d16b4c3a2642d3a719f18f6b06070ab0aef246a6418130c955ae08aa831"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "icu_provider"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"icu_locale_core",
|
||||||
|
"serde",
|
||||||
|
"stable_deref_trait",
|
||||||
|
"writeable",
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
"zerotrie",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ixdtf"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "84de9d95a6d2547d9b77ee3f25fa0ee32e3c3a6484d47a55adebc0439c077992"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-tzdb"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68971ebff725b9e2ca27a601c5eb38a4c5d64422c4cbab0c535f248087eda5c2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "litemap"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "potential_utf"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"writeable",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.228"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smallvec"
|
||||||
|
version = "1.15.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stable_deref_trait"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strck"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42316e70da376f3d113a68d138a60d8a9883c604fe97942721ec2068dab13a9f"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.114"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "synstructure"
|
||||||
|
version = "0.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "temporal_capi"
|
||||||
|
version = "0.1.2"
|
||||||
|
dependencies = [
|
||||||
|
"temporal_capi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"temporal_rs",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "temporal_capi"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a151e402c2bdb6a3a2a2f3f225eddaead2e7ce7dd5d3fa2090deb11b17aa4ed8"
|
||||||
|
dependencies = [
|
||||||
|
"diplomat",
|
||||||
|
"diplomat-runtime",
|
||||||
|
"icu_calendar",
|
||||||
|
"icu_locale",
|
||||||
|
"num-traits",
|
||||||
|
"temporal_rs",
|
||||||
|
"timezone_provider",
|
||||||
|
"writeable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "temporal_rs"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88afde3bd75d2fc68d77a914bece426aa08aa7649ffd0cdd4a11c3d4d33474d1"
|
||||||
|
dependencies = [
|
||||||
|
"core_maths",
|
||||||
|
"icu_calendar",
|
||||||
|
"icu_locale",
|
||||||
|
"ixdtf",
|
||||||
|
"num-traits",
|
||||||
|
"timezone_provider",
|
||||||
|
"tinystr",
|
||||||
|
"writeable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "timezone_provider"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df9ba0000e9e73862f3e7ca1ff159e2ddf915c9d8bb11e38a7874760f445d993"
|
||||||
|
dependencies = [
|
||||||
|
"combine",
|
||||||
|
"jiff-tzdb",
|
||||||
|
"tinystr",
|
||||||
|
"tzif",
|
||||||
|
"zerotrie",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinystr"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
"serde_core",
|
||||||
|
"zerovec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tzif"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0376dfa52cce372f3b095010fd064fb850a5d8fbfd5be8b0ffa3d64eeab5a5d"
|
||||||
|
dependencies = [
|
||||||
|
"combine",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "writeable"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yoke"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
|
||||||
|
dependencies = [
|
||||||
|
"stable_deref_trait",
|
||||||
|
"yoke-derive",
|
||||||
|
"zerofrom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yoke-derive"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"synstructure",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerofrom"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
|
||||||
|
dependencies = [
|
||||||
|
"zerofrom-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerofrom-derive"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"synstructure",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerotrie"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
|
||||||
|
dependencies = [
|
||||||
|
"displaydoc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerovec"
|
||||||
|
version = "0.11.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"yoke",
|
||||||
|
"zerofrom",
|
||||||
|
"zerovec-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerovec-derive"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
21
Cargo.toml
Normal file
21
Cargo.toml
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
[package]
|
||||||
|
name = "temporal_capi"
|
||||||
|
version = "0.1.2"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies.temporal_capi]
|
||||||
|
version = "0.1.2"
|
||||||
|
default-features = false
|
||||||
|
features = ["compiled_data"]
|
||||||
|
|
||||||
|
[dependencies.temporal_rs]
|
||||||
|
version = "*"
|
||||||
|
default-features = false
|
||||||
|
features = ["float64_representable_durations"]
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["staticlib"]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = true
|
||||||
|
lto = true
|
||||||
258
build.zig
258
build.zig
|
|
@ -1,22 +1,85 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const build_crab = @import("build_crab");
|
||||||
|
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) !void {
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
// --- Zig Module: temporalz --- //
|
||||||
const mod = b.addModule("temporalz", .{
|
const mod = b.addModule("temporalz", .{
|
||||||
.root_source_file = b.path("src/root.zig"),
|
.root_source_file = b.path("src/root.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
mod.addObjectFile(b.path(getTemporalRsPath(target)));
|
|
||||||
mod.link_libc = true;
|
// --- Rust C ABI: temporal_capi --- //
|
||||||
if (target.result.os.tag == .linux) mod.linkSystemLibrary("unwind", .{});
|
const temporal_rs = b.dependency("temporal_rs", .{ .target = target, .optimize = optimize });
|
||||||
if (target.result.os.tag == .windows) {
|
mod.addIncludePath(temporal_rs.path("temporal_capi/bindings/c"));
|
||||||
mod.linkSystemLibrary("ws2_32", .{});
|
|
||||||
mod.linkSystemLibrary("bcrypt", .{});
|
// --- Rust Crate: temporal_rs --- //
|
||||||
mod.linkSystemLibrary("advapi32", .{});
|
{
|
||||||
mod.linkSystemLibrary("userenv", .{});
|
// Determine target triple string for pre-built library lookup
|
||||||
|
const arch_str = @tagName(target.result.cpu.arch);
|
||||||
|
const os_str = @tagName(target.result.os.tag);
|
||||||
|
const target_triple = b.fmt("{s}-{s}", .{ arch_str, os_str });
|
||||||
|
const lib_name = if (target.result.os.tag == .windows) "temporal_capi.lib" else "libtemporal_capi.a";
|
||||||
|
|
||||||
|
// Check if pre-built library exists in lib/<target>/
|
||||||
|
const prebuilt_lib_path = b.fmt("lib/{s}/{s}", .{ target_triple, lib_name });
|
||||||
|
const prebuilt_lib_file = b.path(prebuilt_lib_path);
|
||||||
|
|
||||||
|
// Try to use pre-built library if it exists by checking the path object
|
||||||
|
const use_prebuilt = blk: {
|
||||||
|
// Use the LazyPath to check if the library exists
|
||||||
|
const lib_full_path = prebuilt_lib_file.getPath(b);
|
||||||
|
const lib_check_file = std.fs.openFileAbsolute(lib_full_path, .{}) catch break :blk false;
|
||||||
|
lib_check_file.close();
|
||||||
|
break :blk true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (use_prebuilt) {
|
||||||
|
// Use pre-built library (no Rust compiler needed)
|
||||||
|
// std.debug.print("Using pre-built temporal_capi library: {s}\n", .{prebuilt_lib_path});
|
||||||
|
mod.addObjectFile(prebuilt_lib_file);
|
||||||
|
} else {
|
||||||
|
// Build from source using Cargo
|
||||||
|
const build_dir = build_crab.addCargoBuild(
|
||||||
|
b,
|
||||||
|
.{
|
||||||
|
.manifest_path = b.path("Cargo.toml"),
|
||||||
|
.cargo_args = if (optimize == .Debug) &.{} else &.{"--release"},
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.target = target,
|
||||||
|
.optimize = .ReleaseSafe,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Install .a/.lib to lib/<target>/libtemporal_capi.a/temporal_capi.lib
|
||||||
|
const install_lib = b.addInstallDirectory(.{
|
||||||
|
.source_dir = build_dir,
|
||||||
|
.install_dir = .{ .custom = "../lib" },
|
||||||
|
.install_subdir = target_triple,
|
||||||
|
});
|
||||||
|
b.getInstallStep().dependOn(&install_lib.step);
|
||||||
|
mod.addObjectFile(build_dir.path(b, lib_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Rust Misc Deps --- //
|
||||||
|
if (target.result.os.tag == .windows) mod.linkSystemLibrary("userenv", .{});
|
||||||
|
const unwind_stubs = b.addLibrary(.{
|
||||||
|
.linkage = .static,
|
||||||
|
.name = "unwind_stubs",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = b.path("src/unwind_stubs.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
mod.linkLibrary(unwind_stubs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Zig Executable: temporalz --- //
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "temporalz",
|
.name = "temporalz",
|
||||||
.root_module = b.createModule(.{
|
.root_module = b.createModule(.{
|
||||||
|
|
@ -30,20 +93,21 @@ pub fn build(b: *std.Build) void {
|
||||||
});
|
});
|
||||||
b.installArtifact(exe);
|
b.installArtifact(exe);
|
||||||
|
|
||||||
// Run command
|
// --- Steps: Run --- //
|
||||||
const run_cmd = b.addRunArtifact(exe);
|
{
|
||||||
run_cmd.step.dependOn(b.getInstallStep());
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
if (b.args) |args| run_cmd.addArgs(args);
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
const run_step = b.step("run", "Run the app");
|
if (b.args) |args| run_cmd.addArgs(args);
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
}
|
||||||
|
|
||||||
// Docs
|
// --- Steps: Docs --- //
|
||||||
{
|
{
|
||||||
const docs_step = b.step("docs", "Build the temporalz docs");
|
const docs_step = b.step("docs", "Build the temporalz docs");
|
||||||
const docs_obj = b.addObject(.{
|
const docs_obj = b.addObject(.{ .name = "temporalz", .root_module = mod });
|
||||||
.name = "temporalz",
|
|
||||||
.root_module = mod,
|
|
||||||
});
|
|
||||||
const docs = docs_obj.getEmittedDocs();
|
const docs = docs_obj.getEmittedDocs();
|
||||||
|
|
||||||
docs_step.dependOn(&b.addInstallDirectory(.{
|
docs_step.dependOn(&b.addInstallDirectory(.{
|
||||||
.source_dir = docs,
|
.source_dir = docs,
|
||||||
.install_dir = .prefix,
|
.install_dir = .prefix,
|
||||||
|
|
@ -51,9 +115,8 @@ pub fn build(b: *std.Build) void {
|
||||||
}).step);
|
}).step);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests
|
// --- Steps: Test --- //
|
||||||
{
|
{
|
||||||
run_step.dependOn(&run_cmd.step);
|
|
||||||
const test_step = b.step("test", "Run tests");
|
const test_step = b.step("test", "Run tests");
|
||||||
const mod_tests = b.addTest(.{
|
const mod_tests = b.addTest(.{
|
||||||
.root_module = mod,
|
.root_module = mod,
|
||||||
|
|
@ -63,141 +126,46 @@ pub fn build(b: *std.Build) void {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
mod_tests.linkLibC();
|
mod_tests.linkLibC();
|
||||||
if (target.result.os.tag == .linux) mod_tests.linkSystemLibrary("unwind");
|
|
||||||
if (target.result.os.tag == .windows) {
|
|
||||||
mod_tests.linkSystemLibrary("ws2_32");
|
|
||||||
mod_tests.linkSystemLibrary("bcrypt");
|
|
||||||
mod_tests.linkSystemLibrary("advapi32");
|
|
||||||
}
|
|
||||||
test_step.dependOn(&b.addRunArtifact(mod_tests).step);
|
test_step.dependOn(&b.addRunArtifact(mod_tests).step);
|
||||||
const exe_tests = b.addTest(.{ .root_module = exe.root_module });
|
const exe_tests = b.addTest(.{ .root_module = exe.root_module });
|
||||||
test_step.dependOn(&b.addRunArtifact(exe_tests).step);
|
test_step.dependOn(&b.addRunArtifact(exe_tests).step);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rust cross-compilation prebuild
|
// --- Steps: Build all platforms --- //
|
||||||
{
|
{
|
||||||
const rust_prebuild_step = b.step("temporal-rs", "Build and vendor Rust staticlibs for supported targets");
|
const build_lib_step = b.step("lib", "Build libraries for all common platforms");
|
||||||
var rustup_args: [3 + rust_targets.len][]const u8 = undefined;
|
|
||||||
rustup_args[0] = "rustup";
|
|
||||||
rustup_args[1] = "target";
|
|
||||||
rustup_args[2] = "add";
|
|
||||||
for (rust_targets, 0..) |t, i| {
|
|
||||||
rustup_args[3 + i] = t.triple;
|
|
||||||
}
|
|
||||||
const rustup_add = b.addSystemCommand(&rustup_args);
|
|
||||||
rust_prebuild_step.dependOn(&rustup_add.step);
|
|
||||||
|
|
||||||
for (rust_targets) |t| {
|
inline for (platforms) |p| {
|
||||||
const cargo_build = b.addSystemCommand(&.{
|
const query = try std.Build.parseTargetQuery(.{ .arch_os_abi = p });
|
||||||
"cargo",
|
const platform_target = b.resolveTargetQuery(query);
|
||||||
"build",
|
|
||||||
"--release",
|
|
||||||
"--manifest-path",
|
|
||||||
"vendor/temporal/Cargo.toml",
|
|
||||||
"--target",
|
|
||||||
t.triple,
|
|
||||||
});
|
|
||||||
cargo_build.step.dependOn(&rustup_add.step);
|
|
||||||
rust_prebuild_step.dependOn(&cargo_build.step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release builds for all platforms
|
const build_dir = build_crab.addCargoBuild(
|
||||||
{
|
b,
|
||||||
const release_targets = [_]struct {
|
.{
|
||||||
name: []const u8,
|
.manifest_path = b.path("Cargo.toml"),
|
||||||
target: std.Target.Query,
|
.cargo_args = &.{"--release"},
|
||||||
}{
|
},
|
||||||
.{ .name = "linux-x64", .target = .{ .cpu_arch = .x86_64, .os_tag = .linux } },
|
.{
|
||||||
.{ .name = "linux-aarch64", .target = .{ .cpu_arch = .aarch64, .os_tag = .linux } },
|
.target = platform_target,
|
||||||
.{ .name = "macos-x64", .target = .{ .cpu_arch = .x86_64, .os_tag = .macos } },
|
.optimize = .ReleaseSafe,
|
||||||
.{ .name = "macos-aarch64", .target = .{ .cpu_arch = .aarch64, .os_tag = .macos } },
|
},
|
||||||
.{ .name = "windows-x64", .target = .{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .msvc } },
|
|
||||||
.{ .name = "windows-aarch64", .target = .{ .cpu_arch = .aarch64, .os_tag = .windows, .abi = .msvc } },
|
|
||||||
};
|
|
||||||
|
|
||||||
const release_step = b.step("release", "Build release binaries for all targets");
|
|
||||||
|
|
||||||
for (release_targets) |release_target| {
|
|
||||||
const resolved_target = b.resolveTargetQuery(release_target.target);
|
|
||||||
|
|
||||||
const release_mod = b.addModule(b.fmt("temporalz-{s}", .{release_target.name}), .{
|
|
||||||
.root_source_file = b.path("src/root.zig"),
|
|
||||||
.target = resolved_target,
|
|
||||||
});
|
|
||||||
release_mod.addObjectFile(b.path(getTemporalRsPath(resolved_target)));
|
|
||||||
release_mod.link_libc = true;
|
|
||||||
if (resolved_target.result.os.tag == .linux) release_mod.linkSystemLibrary("unwind", .{});
|
|
||||||
if (resolved_target.result.os.tag == .windows) {
|
|
||||||
release_mod.linkSystemLibrary("ws2_32", .{});
|
|
||||||
release_mod.linkSystemLibrary("bcrypt", .{});
|
|
||||||
release_mod.linkSystemLibrary("advapi32", .{});
|
|
||||||
release_mod.linkSystemLibrary("userenv", .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
const release_exe = b.addExecutable(.{
|
|
||||||
.name = "temporalz",
|
|
||||||
.root_module = b.createModule(.{
|
|
||||||
.root_source_file = b.path("src/main.zig"),
|
|
||||||
.target = resolved_target,
|
|
||||||
.optimize = .ReleaseSmall,
|
|
||||||
.imports = &.{
|
|
||||||
.{ .name = "temporalz", .module = release_mod },
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
release_exe.linkLibC();
|
|
||||||
if (resolved_target.result.os.tag == .windows) {
|
|
||||||
release_exe.linkSystemLibrary("ws2_32");
|
|
||||||
release_exe.linkSystemLibrary("bcrypt");
|
|
||||||
release_exe.linkSystemLibrary("advapi32");
|
|
||||||
release_exe.linkSystemLibrary("userenv");
|
|
||||||
}
|
|
||||||
|
|
||||||
const exe_ext = if (resolved_target.result.os.tag == .windows) ".exe" else "";
|
|
||||||
const install_release = b.addInstallArtifact(release_exe, .{
|
|
||||||
.dest_sub_path = b.fmt("release/temporalz-{s}{s}", .{ release_target.name, exe_ext }),
|
|
||||||
});
|
|
||||||
|
|
||||||
const target_step = b.step(
|
|
||||||
b.fmt("release-{s}", .{release_target.name}),
|
|
||||||
b.fmt("Build release binary for {s}", .{release_target.name}),
|
|
||||||
);
|
);
|
||||||
target_step.dependOn(&install_release.step);
|
|
||||||
release_step.dependOn(&install_release.step);
|
const install_lib = b.addInstallDirectory(.{
|
||||||
|
.source_dir = build_dir,
|
||||||
|
.install_dir = .{ .custom = "../lib" },
|
||||||
|
.install_subdir = p,
|
||||||
|
});
|
||||||
|
build_lib_step.dependOn(&install_lib.step);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Supported cross-compilation targets
|
const platforms = [_][]const u8{
|
||||||
const rust_targets = [_]struct { triple: []const u8 }{
|
"aarch64-macos",
|
||||||
.{ .triple = "aarch64-apple-darwin" },
|
"x86_64-macos",
|
||||||
.{ .triple = "x86_64-apple-darwin" },
|
"aarch64-linux-gnu",
|
||||||
.{ .triple = "x86_64-unknown-linux-gnu" },
|
"x86_64-linux-gnu",
|
||||||
.{ .triple = "aarch64-unknown-linux-gnu" },
|
"x86_64-windows-gnu",
|
||||||
.{ .triple = "x86_64-pc-windows-msvc" },
|
"aarch64-windows-gnu",
|
||||||
.{ .triple = "aarch64-pc-windows-msvc" },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Platform-specific Rust library path resolution
|
|
||||||
fn getTemporalRsPath(target: std.Build.ResolvedTarget) []const u8 {
|
|
||||||
const arch_tag = target.result.cpu.arch;
|
|
||||||
return switch (target.result.os.tag) {
|
|
||||||
.macos => switch (arch_tag) {
|
|
||||||
.aarch64 => "vendor/temporal/target/aarch64-apple-darwin/release/libtemporal.a",
|
|
||||||
.x86_64 => "vendor/temporal/target/x86_64-apple-darwin/release/libtemporal.a",
|
|
||||||
else => @panic("unsupported macOS architecture"),
|
|
||||||
},
|
|
||||||
.linux => switch (arch_tag) {
|
|
||||||
.x86_64 => "vendor/temporal/target/x86_64-unknown-linux-gnu/release/libtemporal.a",
|
|
||||||
.aarch64 => "vendor/temporal/target/aarch64-unknown-linux-gnu/release/libtemporal.a",
|
|
||||||
else => @panic("unsupported Linux architecture"),
|
|
||||||
},
|
|
||||||
.windows => switch (arch_tag) {
|
|
||||||
.x86_64 => "vendor/temporal/target/x86_64-pc-windows-msvc/release/temporal.lib",
|
|
||||||
.aarch64 => "vendor/temporal/target/aarch64-pc-windows-msvc/release/temporal.lib",
|
|
||||||
else => @panic("unsupported Windows architecture"),
|
|
||||||
},
|
|
||||||
else => @panic("unsupported OS"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,23 @@
|
||||||
.version = "0.0.0",
|
.version = "0.0.0",
|
||||||
.fingerprint = 0xd8d79d59acc4faae,
|
.fingerprint = 0xd8d79d59acc4faae,
|
||||||
.minimum_zig_version = "0.15.2",
|
.minimum_zig_version = "0.15.2",
|
||||||
.dependencies = .{},
|
.dependencies = .{
|
||||||
|
// .temporal_rs = .{
|
||||||
|
// .path = "./pkg/temporal_rs",
|
||||||
|
// },
|
||||||
|
.temporal_rs = .{
|
||||||
|
.url = "git+https://github.com/boa-dev/temporal#v0.1.2",
|
||||||
|
.hash = "N-V-__8AANlkNAB77Z946lqp-lgp2qSsOBDADValZC86PhB-",
|
||||||
|
},
|
||||||
|
.build_crab = .{
|
||||||
|
.url = "git+https://github.com/linusg/build.crab#7c8ace3739023b88f1fb95151df4f5b65bd7a311",
|
||||||
|
.hash = "build_crab-0.2.1-U0id_33BAAD3l81W7CBvgLU3OJSw7WI6FVLBSEHTnjTX",
|
||||||
|
},
|
||||||
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
"build.zig",
|
"build.zig",
|
||||||
"build.zig.zon",
|
"build.zig.zon",
|
||||||
"src",
|
"src",
|
||||||
"vendor",
|
"lib",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
27
example/build.zig
Normal file
27
example/build.zig
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn build(b: *std.Build) void {
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
|
const temporalz_dep = b.dependency("temporalz", .{ .target = target, .optimize = optimize });
|
||||||
|
const exe = b.addExecutable(.{
|
||||||
|
.name = "example",
|
||||||
|
.root_module = b.createModule(.{
|
||||||
|
.root_source_file = b.path("src/main.zig"),
|
||||||
|
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
.imports = &.{
|
||||||
|
.{ .name = "temporalz", .module = temporalz_dep.module("temporalz") },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
b.installArtifact(exe);
|
||||||
|
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
const run_cmd = b.addRunArtifact(exe);
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
if (b.args) |args| run_cmd.addArgs(args);
|
||||||
|
}
|
||||||
16
example/build.zig.zon
Normal file
16
example/build.zig.zon
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
.{
|
||||||
|
.name = .temporalz_example,
|
||||||
|
.version = "0.1.2",
|
||||||
|
.fingerprint = 0x686c9dfc777f9593,
|
||||||
|
.minimum_zig_version = "0.15.2",
|
||||||
|
.dependencies = .{
|
||||||
|
.temporalz = .{
|
||||||
|
.path = "../",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.paths = .{
|
||||||
|
"build.zig",
|
||||||
|
"build.zig.zon",
|
||||||
|
"src",
|
||||||
|
},
|
||||||
|
}
|
||||||
16
example/src/main.zig
Normal file
16
example/src/main.zig
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const Temporal = @import("temporalz");
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
const allocator = std.heap.page_allocator;
|
||||||
|
const result = try Temporal.Instant.init(1_704_067_200_000_000_000); // 2024-01-01 00:00:00 UTC
|
||||||
|
defer result.deinit();
|
||||||
|
|
||||||
|
std.debug.print("Instant.epoch_milliseconds: {}\n", .{result.epoch_milliseconds});
|
||||||
|
std.debug.print("Instant.epoch_nanoseconds: {}\n", .{result.epoch_nanoseconds});
|
||||||
|
const instant_str = try result.toString(allocator, .{});
|
||||||
|
std.debug.print("Instant.toString(): {s}\n", .{instant_str});
|
||||||
|
|
||||||
|
const dur = try Temporal.Duration.from("P1Y2M3DT4H5M6S");
|
||||||
|
defer dur.deinit();
|
||||||
|
}
|
||||||
418
src/Duration.zig
418
src/Duration.zig
|
|
@ -1,4 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const temporal_rs = @import("cabi.zig");
|
||||||
|
const c = temporal_rs.c;
|
||||||
|
|
||||||
/// The Zig implementation of `Temporal.Duration`.
|
/// The Zig implementation of `Temporal.Duration`.
|
||||||
///
|
///
|
||||||
|
|
@ -135,7 +137,7 @@ const std = @import("std");
|
||||||
/// [mdn-duration]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration
|
/// [mdn-duration]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal/Duration
|
||||||
const Duration = @This();
|
const Duration = @This();
|
||||||
|
|
||||||
_inner: *CDuration,
|
_inner: *c.Duration,
|
||||||
|
|
||||||
/// Construct a Duration from years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds.
|
/// Construct a Duration from years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, and nanoseconds.
|
||||||
/// Equivalent to `Temporal.Duration.from()` or the constructor.
|
/// Equivalent to `Temporal.Duration.from()` or the constructor.
|
||||||
|
|
@ -151,7 +153,7 @@ pub fn init(
|
||||||
microseconds_val: f64,
|
microseconds_val: f64,
|
||||||
nanoseconds_val: f64,
|
nanoseconds_val: f64,
|
||||||
) !Duration {
|
) !Duration {
|
||||||
return wrapDuration(temporal_rs_Duration_try_new(
|
return wrapDuration(c.temporal_rs_Duration_try_new(
|
||||||
years_val,
|
years_val,
|
||||||
months_val,
|
months_val,
|
||||||
weeks_val,
|
weeks_val,
|
||||||
|
|
@ -167,156 +169,156 @@ pub fn init(
|
||||||
|
|
||||||
/// Parse an ISO 8601 duration string (Temporal.Duration.from).
|
/// Parse an ISO 8601 duration string (Temporal.Duration.from).
|
||||||
pub fn from(text: []const u8) !Duration {
|
pub fn from(text: []const u8) !Duration {
|
||||||
const view = DiplomatStringView{ .data = text.ptr, .len = text.len };
|
const view = temporal_rs.toDiplomatStringView(text);
|
||||||
return wrapDuration(temporal_rs_Duration_from_utf8(view));
|
return wrapDuration(c.temporal_rs_Duration_from_utf8(view));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an ISO 8601 UTF-16 duration string.
|
/// Parse an ISO 8601 UTF-16 duration string.
|
||||||
fn fromUtf16(text: []const u16) !Duration {
|
fn fromUtf16(text: []const u16) !Duration {
|
||||||
const view = DiplomatString16View{ .data = text.ptr, .len = text.len };
|
const view = temporal_rs.toDiplomatString16View(text);
|
||||||
return wrapDuration(temporal_rs_Duration_from_utf16(view));
|
return wrapDuration(c.temporal_rs_Duration_from_utf16(view));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a Duration from a partial duration (where some fields may be omitted).
|
/// Create a Duration from a partial duration (where some fields may be omitted).
|
||||||
fn fromPartialDuration(partial: PartialDuration) !Duration {
|
fn fromPartialDuration(partial: PartialDuration) !Duration {
|
||||||
return wrapDuration(temporal_rs_Duration_from_partial_duration(partial));
|
return wrapDuration(c.temporal_rs_Duration_from_partial_duration(partial));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the time portion of the duration is within valid ranges.
|
/// Check if the time portion of the duration is within valid ranges.
|
||||||
fn isTimeWithinRange(self: Duration) bool {
|
fn isTimeWithinRange(self: Duration) bool {
|
||||||
return temporal_rs_Duration_is_time_within_range(self._inner);
|
return c.temporal_rs_Duration_is_time_within_range(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the years component of the duration.
|
/// Get the years component of the duration.
|
||||||
pub fn years(self: Duration) i64 {
|
pub fn years(self: Duration) i64 {
|
||||||
return temporal_rs_Duration_years(self._inner);
|
return c.temporal_rs_Duration_years(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the months component of the duration.
|
/// Get the months component of the duration.
|
||||||
pub fn months(self: Duration) i64 {
|
pub fn months(self: Duration) i64 {
|
||||||
return temporal_rs_Duration_months(self._inner);
|
return c.temporal_rs_Duration_months(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the weeks component of the duration.
|
/// Get the weeks component of the duration.
|
||||||
pub fn weeks(self: Duration) i64 {
|
pub fn weeks(self: Duration) i64 {
|
||||||
return temporal_rs_Duration_weeks(self._inner);
|
return c.temporal_rs_Duration_weeks(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the days component of the duration.
|
/// Get the days component of the duration.
|
||||||
pub fn days(self: Duration) i64 {
|
pub fn days(self: Duration) i64 {
|
||||||
return temporal_rs_Duration_days(self._inner);
|
return c.temporal_rs_Duration_days(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the hours component of the duration.
|
/// Get the hours component of the duration.
|
||||||
pub fn hours(self: Duration) i64 {
|
pub fn hours(self: Duration) i64 {
|
||||||
return temporal_rs_Duration_hours(self._inner);
|
return c.temporal_rs_Duration_hours(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the minutes component of the duration.
|
/// Get the minutes component of the duration.
|
||||||
pub fn minutes(self: Duration) i64 {
|
pub fn minutes(self: Duration) i64 {
|
||||||
return temporal_rs_Duration_minutes(self._inner);
|
return c.temporal_rs_Duration_minutes(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the seconds component of the duration.
|
/// Get the seconds component of the duration.
|
||||||
pub fn seconds(self: Duration) i64 {
|
pub fn seconds(self: Duration) i64 {
|
||||||
return temporal_rs_Duration_seconds(self._inner);
|
return c.temporal_rs_Duration_seconds(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the milliseconds component of the duration.
|
/// Get the milliseconds component of the duration.
|
||||||
pub fn milliseconds(self: Duration) i64 {
|
pub fn milliseconds(self: Duration) i64 {
|
||||||
return temporal_rs_Duration_milliseconds(self._inner);
|
return c.temporal_rs_Duration_milliseconds(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the microseconds component of the duration.
|
/// Get the microseconds component of the duration.
|
||||||
pub fn microseconds(self: Duration) f64 {
|
pub fn microseconds(self: Duration) f64 {
|
||||||
return temporal_rs_Duration_microseconds(self._inner);
|
return c.temporal_rs_Duration_microseconds(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the nanoseconds component of the duration.
|
/// Get the nanoseconds component of the duration.
|
||||||
pub fn nanoseconds(self: Duration) f64 {
|
pub fn nanoseconds(self: Duration) f64 {
|
||||||
return temporal_rs_Duration_nanoseconds(self._inner);
|
return c.temporal_rs_Duration_nanoseconds(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the sign of the duration: positive (1), zero (0), or negative (-1).
|
/// Get the sign of the duration: positive (1), zero (0), or negative (-1).
|
||||||
pub fn sign(self: Duration) Sign {
|
pub fn sign(self: Duration) Sign {
|
||||||
return temporal_rs_Duration_sign(self._inner);
|
return @as(Sign, @enumFromInt(c.temporal_rs_Duration_sign(self._inner)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the duration is zero (all fields are zero).
|
/// Check if the duration is zero (all fields are zero).
|
||||||
pub fn blank(self: Duration) bool {
|
pub fn blank(self: Duration) bool {
|
||||||
return temporal_rs_Duration_is_zero(self._inner);
|
return c.temporal_rs_Duration_is_zero(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new Duration with the absolute value (all components positive).
|
/// Returns a new Duration with the absolute value (all components positive).
|
||||||
pub fn abs(self: Duration) Duration {
|
pub fn abs(self: Duration) Duration {
|
||||||
const ptr = temporal_rs_Duration_abs(self._inner);
|
const ptr: *c.Duration = c.temporal_rs_Duration_abs(self._inner) orelse unreachable;
|
||||||
return .{ ._inner = ptr };
|
return .{ ._inner = ptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new Duration with all components negated.
|
/// Returns a new Duration with all components negated.
|
||||||
pub fn negated(self: Duration) Duration {
|
pub fn negated(self: Duration) Duration {
|
||||||
const ptr = temporal_rs_Duration_negated(self._inner);
|
const ptr: *c.Duration = c.temporal_rs_Duration_negated(self._inner) orelse unreachable;
|
||||||
return .{ ._inner = ptr };
|
return .{ ._inner = ptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add two durations together (Temporal.Duration.prototype.add).
|
/// Add two durations together (Temporal.Duration.prototype.add).
|
||||||
pub fn add(self: Duration, other: Duration) !Duration {
|
pub fn add(self: Duration, other: Duration) !Duration {
|
||||||
return wrapDuration(temporal_rs_Duration_add(self._inner, other._inner));
|
return wrapDuration(c.temporal_rs_Duration_add(self._inner, other._inner));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subtract another duration from this one (Temporal.Duration.prototype.subtract).
|
/// Subtract another duration from this one (Temporal.Duration.prototype.subtract).
|
||||||
pub fn subtract(self: Duration, other: Duration) !Duration {
|
pub fn subtract(self: Duration, other: Duration) !Duration {
|
||||||
return wrapDuration(temporal_rs_Duration_subtract(self._inner, other._inner));
|
return wrapDuration(c.temporal_rs_Duration_subtract(self._inner, other._inner));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Round the duration according to the specified options (Temporal.Duration.prototype.round).
|
/// Round the duration according to the specified options (Temporal.Duration.prototype.round).
|
||||||
pub fn round(self: Duration, options: RoundingOptions, relative_to: RelativeTo) !Duration {
|
pub fn round(self: Duration, options: RoundingOptions, relative_to: RelativeTo) !Duration {
|
||||||
return wrapDuration(temporal_rs_Duration_round(self._inner, options, relative_to));
|
return wrapDuration(c.temporal_rs_Duration_round(self._inner, options, relative_to));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Round the duration with an explicit provider.
|
/// Round the duration with an explicit provider.
|
||||||
fn roundWithProvider(self: Duration, options: RoundingOptions, relative_to: RelativeTo, provider: *const Provider) !Duration {
|
fn roundWithProvider(self: Duration, options: RoundingOptions, relative_to: RelativeTo, provider: *const c.Provider) !Duration {
|
||||||
return wrapDuration(temporal_rs_Duration_round_with_provider(self._inner, options, relative_to, provider));
|
return wrapDuration(c.temporal_rs_Duration_round_with_provider(self._inner, options, relative_to, provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare two durations (Temporal.Duration.compare).
|
/// Compare two durations (Temporal.Duration.compare).
|
||||||
pub fn compare(self: Duration, other: Duration, relative_to: RelativeTo) !i8 {
|
pub fn compare(self: Duration, other: Duration, relative_to: RelativeTo) !i8 {
|
||||||
const res = temporal_rs_Duration_compare(self._inner, other._inner, relative_to);
|
const res = c.temporal_rs_Duration_compare(self._inner, other._inner, relative_to);
|
||||||
if (!res.is_ok) return error.TemporalError;
|
if (!res.is_ok) return error.TemporalError;
|
||||||
return res.result.ok;
|
return res.unnamed_0.ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare two durations with an explicit provider.
|
/// Compare two durations with an explicit provider.
|
||||||
fn compareWithProvider(self: Duration, other: Duration, relative_to: RelativeTo, provider: *const Provider) !i8 {
|
fn compareWithProvider(self: Duration, other: Duration, relative_to: RelativeTo, provider: *const c.Provider) !i8 {
|
||||||
const res = temporal_rs_Duration_compare_with_provider(self._inner, other._inner, relative_to, provider);
|
const res = c.temporal_rs_Duration_compare_with_provider(self._inner, other._inner, relative_to, provider);
|
||||||
if (!res.is_ok) return error.TemporalError;
|
if (!res.is_ok) return error.TemporalError;
|
||||||
return res.result.ok;
|
return res.unnamed_0.ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the total value of the duration in the specified unit (Temporal.Duration.prototype.total).
|
/// Get the total value of the duration in the specified unit (Temporal.Duration.prototype.total).
|
||||||
pub fn total(self: Duration, unit: Unit, relative_to: RelativeTo) !f64 {
|
pub fn total(self: Duration, unit: Unit, relative_to: RelativeTo) !f64 {
|
||||||
const res = temporal_rs_Duration_total(self._inner, unit, relative_to);
|
const res = c.temporal_rs_Duration_total(self._inner, @intFromEnum(unit), relative_to);
|
||||||
if (!res.is_ok) return error.TemporalError;
|
if (!res.is_ok) return error.TemporalError;
|
||||||
return res.result.ok;
|
return res.unnamed_0.ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the total value of the duration with an explicit provider.
|
/// Get the total value of the duration with an explicit provider.
|
||||||
fn totalWithProvider(self: Duration, unit: Unit, relative_to: RelativeTo, provider: *const Provider) !f64 {
|
fn totalWithProvider(self: Duration, unit: Unit, relative_to: RelativeTo, provider: *const c.Provider) !f64 {
|
||||||
const res = temporal_rs_Duration_total_with_provider(self._inner, unit, relative_to, provider);
|
const res = c.temporal_rs_Duration_total_with_provider(self._inner, @intFromEnum(unit), relative_to, provider);
|
||||||
if (!res.is_ok) return error.TemporalError;
|
if (!res.is_ok) return error.TemporalError;
|
||||||
return res.result.ok;
|
return res.unnamed_0.ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to string (Temporal.Duration.prototype.toString); caller owns returned slice.
|
/// Convert to string (Temporal.Duration.prototype.toString); caller owns returned slice.
|
||||||
pub fn toString(self: Duration, allocator: std.mem.Allocator, options: ToStringRoundingOptions) ![]u8 {
|
pub fn toString(self: Duration, allocator: std.mem.Allocator, options: ToStringRoundingOptions) ![]u8 {
|
||||||
const writer = diplomat_buffer_write_create(128);
|
const writer = c.diplomat_buffer_write_create(128);
|
||||||
defer diplomat_buffer_write_destroy(writer);
|
defer c.diplomat_buffer_write_destroy(writer);
|
||||||
|
|
||||||
const res = temporal_rs_Duration_to_string(self._inner, options, writer);
|
const res = c.temporal_rs_Duration_to_string(self._inner, options, writer);
|
||||||
try handleVoidResult(res);
|
try handleVoidResult(res);
|
||||||
|
|
||||||
const len = diplomat_buffer_write_len(writer);
|
const len = c.diplomat_buffer_write_len(writer);
|
||||||
const source = diplomat_buffer_write_get_bytes(writer)[0..len];
|
const source = c.diplomat_buffer_write_get_bytes(writer)[0..len];
|
||||||
|
|
||||||
const out = try allocator.alloc(u8, len);
|
const out = try allocator.alloc(u8, len);
|
||||||
std.mem.copyForwards(u8, out, source);
|
std.mem.copyForwards(u8, out, source);
|
||||||
|
|
@ -335,32 +337,30 @@ pub fn toLocaleString(self: Duration, allocator: std.mem.Allocator) ![]u8 {
|
||||||
|
|
||||||
/// Clone the underlying duration.
|
/// Clone the underlying duration.
|
||||||
fn clone(self: Duration) Duration {
|
fn clone(self: Duration) Duration {
|
||||||
const ptr = temporal_rs_Duration_clone(self._inner);
|
const ptr: *c.Duration = c.temporal_rs_Duration_clone(self._inner) orelse unreachable;
|
||||||
return .{ ._inner = ptr };
|
return .{ ._inner = ptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Duration) void {
|
pub fn deinit(self: Duration) void {
|
||||||
temporal_rs_Duration_destroy(self._inner);
|
c.temporal_rs_Duration_destroy(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Helpers -----------------------------------------------------------------
|
// --- Helpers -----------------------------------------------------------------
|
||||||
|
|
||||||
fn wrapDuration(res: DurationResult) !Duration {
|
fn handleVoidResult(res: anytype) !void {
|
||||||
if (!res.is_ok) return error.TemporalError;
|
if (!res.is_ok) return error.TemporalError;
|
||||||
const ptr = res.result.ok orelse return error.TemporalError;
|
}
|
||||||
|
|
||||||
|
fn wrapDuration(res: anytype) !Duration {
|
||||||
|
if (!res.is_ok) return error.TemporalError;
|
||||||
|
const maybe_ptr = res.unnamed_0.ok;
|
||||||
|
if (maybe_ptr == null) return error.TemporalError;
|
||||||
|
const ptr: *c.Duration = maybe_ptr.?;
|
||||||
return .{ ._inner = ptr };
|
return .{ ._inner = ptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleVoidResult(res: VoidResult) !void {
|
|
||||||
if (!res.is_ok) return error.TemporalError;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn defaultToStringRoundingOptions() ToStringRoundingOptions {
|
fn defaultToStringRoundingOptions() ToStringRoundingOptions {
|
||||||
return .{
|
return temporal_rs.to_string_rounding_options_auto;
|
||||||
.precision = .{ .is_minute = false, .precision = OptionU8{ .ok = 0, .is_ok = false } },
|
|
||||||
.smallest_unit = Unit_option{ .ok = .auto, .is_ok = false },
|
|
||||||
.rounding_mode = RoundingMode_option{ .ok = .trunc, .is_ok = false },
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Public helper types -----------------------------------------------------
|
// --- Public helper types -----------------------------------------------------
|
||||||
|
|
@ -379,277 +379,71 @@ pub const ToStringOptions = struct {
|
||||||
smallest_unit: ?Unit = null,
|
smallest_unit: ?Unit = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A partial duration where some or all fields may be omitted.
|
pub const PartialDuration = c.PartialDuration;
|
||||||
pub const PartialDuration = extern struct {
|
|
||||||
years: OptionI64,
|
|
||||||
months: OptionI64,
|
|
||||||
weeks: OptionI64,
|
|
||||||
days: OptionI64,
|
|
||||||
hours: OptionI64,
|
|
||||||
minutes: OptionI64,
|
|
||||||
seconds: OptionI64,
|
|
||||||
milliseconds: OptionI64,
|
|
||||||
microseconds: OptionI128,
|
|
||||||
nanoseconds: OptionI128,
|
|
||||||
|
|
||||||
pub fn empty() PartialDuration {
|
|
||||||
return .{
|
|
||||||
.years = .{ .ok = 0, .is_ok = false },
|
|
||||||
.months = .{ .ok = 0, .is_ok = false },
|
|
||||||
.weeks = .{ .ok = 0, .is_ok = false },
|
|
||||||
.days = .{ .ok = 0, .is_ok = false },
|
|
||||||
.hours = .{ .ok = 0, .is_ok = false },
|
|
||||||
.minutes = .{ .ok = 0, .is_ok = false },
|
|
||||||
.seconds = .{ .ok = 0, .is_ok = false },
|
|
||||||
.milliseconds = .{ .ok = 0, .is_ok = false },
|
|
||||||
.microseconds = .{ .ok = 0, .is_ok = false },
|
|
||||||
.nanoseconds = .{ .ok = 0, .is_ok = false },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn withYears(self: PartialDuration, value: i64) PartialDuration {
|
|
||||||
var result = self;
|
|
||||||
result.years = .{ .ok = value, .is_ok = true };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn withMonths(self: PartialDuration, value: i64) PartialDuration {
|
|
||||||
var result = self;
|
|
||||||
result.months = .{ .ok = value, .is_ok = true };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn withWeeks(self: PartialDuration, value: i64) PartialDuration {
|
|
||||||
var result = self;
|
|
||||||
result.weeks = .{ .ok = value, .is_ok = true };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn withDays(self: PartialDuration, value: i64) PartialDuration {
|
|
||||||
var result = self;
|
|
||||||
result.days = .{ .ok = value, .is_ok = true };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn withHours(self: PartialDuration, value: i64) PartialDuration {
|
|
||||||
var result = self;
|
|
||||||
result.hours = .{ .ok = value, .is_ok = true };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn withMinutes(self: PartialDuration, value: i64) PartialDuration {
|
|
||||||
var result = self;
|
|
||||||
result.minutes = .{ .ok = value, .is_ok = true };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn withSeconds(self: PartialDuration, value: i64) PartialDuration {
|
|
||||||
var result = self;
|
|
||||||
result.seconds = .{ .ok = value, .is_ok = true };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn withMilliseconds(self: PartialDuration, value: i64) PartialDuration {
|
|
||||||
var result = self;
|
|
||||||
result.milliseconds = .{ .ok = value, .is_ok = true };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn withMicroseconds(self: PartialDuration, value: i128) PartialDuration {
|
|
||||||
var result = self;
|
|
||||||
result.microseconds = .{ .ok = value, .is_ok = true };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn withNanoseconds(self: PartialDuration, value: i128) PartialDuration {
|
|
||||||
var result = self;
|
|
||||||
result.nanoseconds = .{ .ok = value, .is_ok = true };
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Relative-to context for duration operations.
|
/// Relative-to context for duration operations.
|
||||||
pub const RelativeTo = extern struct {
|
pub const RelativeTo = extern struct {
|
||||||
plain_date: ?*PlainDate,
|
plain_date: ?*c.PlainDate,
|
||||||
zoned_date_time: ?*ZonedDateTime,
|
zoned_date_time: ?*c.ZonedDateTime,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Extern types ------------------------------------------------------------
|
// --- Public type aliases and enums ------------------------------------------
|
||||||
|
|
||||||
const CDuration = opaque {};
|
const OptionU8 = c.OptionU8;
|
||||||
const PlainDate = opaque {};
|
const OptionU32 = c.OptionU32;
|
||||||
const ZonedDateTime = opaque {};
|
const OptionI64 = c.OptionI64;
|
||||||
const Provider = opaque {};
|
const OptionF64 = c.OptionF64;
|
||||||
|
const Precision = c.Precision;
|
||||||
const DiplomatStringView = extern struct { data: [*c]const u8, len: usize };
|
const Unit_option = c.Unit_option;
|
||||||
const DiplomatString16View = extern struct { data: [*c]const u16, len: usize };
|
const RoundingMode_option = c.RoundingMode_option;
|
||||||
|
|
||||||
const OptionStringView = extern struct { ok: DiplomatStringView, is_ok: bool };
|
|
||||||
const OptionU8 = extern struct { ok: u8, is_ok: bool };
|
|
||||||
const OptionU32 = extern struct { ok: u32, is_ok: bool };
|
|
||||||
const OptionI64 = extern struct { ok: i64, is_ok: bool };
|
|
||||||
const OptionI128 = extern struct { ok: i128, is_ok: bool };
|
|
||||||
|
|
||||||
const DiplomatWrite = extern struct {
|
|
||||||
context: ?*anyopaque,
|
|
||||||
buf: [*c]u8,
|
|
||||||
len: usize,
|
|
||||||
cap: usize,
|
|
||||||
grow_failed: bool,
|
|
||||||
flush: ?*const fn (*DiplomatWrite) void,
|
|
||||||
grow: ?*const fn (*DiplomatWrite, usize) bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Precision = extern struct {
|
|
||||||
is_minute: bool,
|
|
||||||
precision: OptionU8,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Time unit for Temporal operations.
|
/// Time unit for Temporal operations.
|
||||||
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal
|
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal
|
||||||
pub const Unit = enum(c_int) {
|
pub const Unit = enum(c_uint) {
|
||||||
auto = 0,
|
auto = c.Unit_Auto,
|
||||||
nanosecond = 1,
|
nanosecond = c.Unit_Nanosecond,
|
||||||
microsecond = 2,
|
microsecond = c.Unit_Microsecond,
|
||||||
millisecond = 3,
|
millisecond = c.Unit_Millisecond,
|
||||||
second = 4,
|
second = c.Unit_Second,
|
||||||
minute = 5,
|
minute = c.Unit_Minute,
|
||||||
hour = 6,
|
hour = c.Unit_Hour,
|
||||||
day = 7,
|
day = c.Unit_Day,
|
||||||
week = 8,
|
week = c.Unit_Week,
|
||||||
month = 9,
|
month = c.Unit_Month,
|
||||||
year = 10,
|
year = c.Unit_Year,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Unit_option = extern struct { ok: Unit, is_ok: bool };
|
|
||||||
|
|
||||||
/// Rounding mode for Temporal operations.
|
/// Rounding mode for Temporal operations.
|
||||||
/// See: https://tc39.es/ecma402/#table-sanctioned-single-unit-identifiers
|
/// See: https://tc39.es/ecma402/#table-sanctioned-single-unit-identifiers
|
||||||
pub const RoundingMode = enum(c_int) {
|
pub const RoundingMode = enum(c_uint) {
|
||||||
/// Round toward positive infinity
|
/// Round toward positive infinity
|
||||||
ceil = 0,
|
ceil = c.RoundingMode_Ceil,
|
||||||
/// Round toward negative infinity
|
/// Round toward negative infinity
|
||||||
floor = 1,
|
floor = c.RoundingMode_Floor,
|
||||||
/// Round away from zero
|
/// Round away from zero
|
||||||
expand = 2,
|
expand = c.RoundingMode_Expand,
|
||||||
/// Round toward zero (truncate)
|
/// Round toward zero (truncate)
|
||||||
trunc = 3,
|
trunc = c.RoundingMode_Trunc,
|
||||||
/// Round half toward positive infinity
|
/// Round half toward positive infinity
|
||||||
half_ceil = 4,
|
half_ceil = c.RoundingMode_HalfCeil,
|
||||||
/// Round half toward negative infinity
|
/// Round half toward negative infinity
|
||||||
half_floor = 5,
|
half_floor = c.RoundingMode_HalfFloor,
|
||||||
/// Round half away from zero
|
/// Round half away from zero
|
||||||
half_expand = 6,
|
half_expand = c.RoundingMode_HalfExpand,
|
||||||
/// Round half toward zero
|
/// Round half toward zero
|
||||||
half_trunc = 7,
|
half_trunc = c.RoundingMode_HalfTrunc,
|
||||||
/// Round half to even (banker's rounding)
|
/// Round half to even (banker's rounding)
|
||||||
half_even = 8,
|
half_even = c.RoundingMode_HalfEven,
|
||||||
};
|
|
||||||
|
|
||||||
const RoundingMode_option = extern struct { ok: RoundingMode, is_ok: bool };
|
|
||||||
|
|
||||||
pub const RoundingOptions = extern struct {
|
|
||||||
largest_unit: Unit_option,
|
|
||||||
smallest_unit: Unit_option,
|
|
||||||
rounding_mode: RoundingMode_option,
|
|
||||||
increment: OptionU32,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const ToStringRoundingOptions = extern struct {
|
|
||||||
precision: Precision,
|
|
||||||
smallest_unit: Unit_option,
|
|
||||||
rounding_mode: RoundingMode_option,
|
|
||||||
};
|
|
||||||
|
|
||||||
const ErrorKind = enum(c_int) {
|
|
||||||
ErrorKind_Generic = 0,
|
|
||||||
ErrorKind_Type = 1,
|
|
||||||
ErrorKind_Range = 2,
|
|
||||||
ErrorKind_Syntax = 3,
|
|
||||||
ErrorKind_Assert = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
const TemporalError = extern struct {
|
|
||||||
kind: ErrorKind,
|
|
||||||
msg: OptionStringView,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Sign = enum(c_int) {
|
pub const Sign = enum(c_int) {
|
||||||
Sign_Positive = 1,
|
positive = c.Sign_Positive,
|
||||||
Sign_Zero = 0,
|
zero = c.Sign_Zero,
|
||||||
Sign_Negative = -1,
|
negative = c.Sign_Negative,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Result wrappers ---------------------------------------------------------
|
pub const RoundingOptions = c.RoundingOptions;
|
||||||
|
pub const ToStringRoundingOptions = c.ToStringRoundingOptions;
|
||||||
const DurationResult = extern struct {
|
|
||||||
result: extern union {
|
|
||||||
ok: ?*CDuration,
|
|
||||||
err: TemporalError,
|
|
||||||
},
|
|
||||||
is_ok: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const I8Result = extern struct {
|
|
||||||
result: extern union {
|
|
||||||
ok: i8,
|
|
||||||
err: TemporalError,
|
|
||||||
},
|
|
||||||
is_ok: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const F64Result = extern struct {
|
|
||||||
result: extern union {
|
|
||||||
ok: f64,
|
|
||||||
err: TemporalError,
|
|
||||||
},
|
|
||||||
is_ok: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VoidResult = extern struct {
|
|
||||||
result: extern union {
|
|
||||||
err: TemporalError,
|
|
||||||
},
|
|
||||||
is_ok: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- Extern functions -------------------------------------------------------
|
|
||||||
|
|
||||||
extern "c" fn temporal_rs_Duration_try_new(years: i64, months: i64, weeks: i64, days: i64, hours: i64, minutes: i64, seconds: i64, milliseconds: i64, microseconds: f64, nanoseconds: f64) DurationResult;
|
|
||||||
extern "c" fn temporal_rs_Duration_from_partial_duration(partial: PartialDuration) DurationResult;
|
|
||||||
extern "c" fn temporal_rs_Duration_from_utf8(s: DiplomatStringView) DurationResult;
|
|
||||||
extern "c" fn temporal_rs_Duration_from_utf16(s: DiplomatString16View) DurationResult;
|
|
||||||
extern "c" fn temporal_rs_Duration_is_time_within_range(self: *const CDuration) bool;
|
|
||||||
extern "c" fn temporal_rs_Duration_years(self: *const CDuration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_months(self: *const CDuration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_weeks(self: *const CDuration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_days(self: *const CDuration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_hours(self: *const CDuration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_minutes(self: *const CDuration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_seconds(self: *const CDuration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_milliseconds(self: *const CDuration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_microseconds(self: *const CDuration) f64;
|
|
||||||
extern "c" fn temporal_rs_Duration_nanoseconds(self: *const CDuration) f64;
|
|
||||||
extern "c" fn temporal_rs_Duration_sign(self: *const CDuration) Sign;
|
|
||||||
extern "c" fn temporal_rs_Duration_is_zero(self: *const CDuration) bool;
|
|
||||||
extern "c" fn temporal_rs_Duration_abs(self: *const CDuration) *CDuration;
|
|
||||||
extern "c" fn temporal_rs_Duration_negated(self: *const CDuration) *CDuration;
|
|
||||||
extern "c" fn temporal_rs_Duration_add(self: *const CDuration, other: *const CDuration) DurationResult;
|
|
||||||
extern "c" fn temporal_rs_Duration_subtract(self: *const CDuration, other: *const CDuration) DurationResult;
|
|
||||||
extern "c" fn temporal_rs_Duration_to_string(self: *const CDuration, options: ToStringRoundingOptions, write: *DiplomatWrite) VoidResult;
|
|
||||||
extern "c" fn temporal_rs_Duration_round(self: *const CDuration, options: RoundingOptions, relative_to: RelativeTo) DurationResult;
|
|
||||||
extern "c" fn temporal_rs_Duration_round_with_provider(self: *const CDuration, options: RoundingOptions, relative_to: RelativeTo, p: *const Provider) DurationResult;
|
|
||||||
extern "c" fn temporal_rs_Duration_compare(self: *const CDuration, other: *const CDuration, relative_to: RelativeTo) I8Result;
|
|
||||||
extern "c" fn temporal_rs_Duration_compare_with_provider(self: *const CDuration, other: *const CDuration, relative_to: RelativeTo, p: *const Provider) I8Result;
|
|
||||||
extern "c" fn temporal_rs_Duration_total(self: *const CDuration, unit: Unit, relative_to: RelativeTo) F64Result;
|
|
||||||
extern "c" fn temporal_rs_Duration_total_with_provider(self: *const CDuration, unit: Unit, relative_to: RelativeTo, p: *const Provider) F64Result;
|
|
||||||
extern "c" fn temporal_rs_Duration_clone(self: *const CDuration) *CDuration;
|
|
||||||
extern "c" fn temporal_rs_Duration_destroy(self: *CDuration) void;
|
|
||||||
|
|
||||||
extern "c" fn diplomat_buffer_write_create(cap: usize) *DiplomatWrite;
|
|
||||||
extern "c" fn diplomat_buffer_write_get_bytes(write: *DiplomatWrite) [*c]u8;
|
|
||||||
extern "c" fn diplomat_buffer_write_len(write: *DiplomatWrite) usize;
|
|
||||||
extern "c" fn diplomat_buffer_write_destroy(write: *DiplomatWrite) void;
|
|
||||||
|
|
||||||
// --- Tests -------------------------------------------------------------------
|
// --- Tests -------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -689,7 +483,7 @@ test from {
|
||||||
defer dur_negative.deinit();
|
defer dur_negative.deinit();
|
||||||
|
|
||||||
try std.testing.expectEqual(@as(i64, -1), dur_negative.days());
|
try std.testing.expectEqual(@as(i64, -1), dur_negative.days());
|
||||||
try std.testing.expectEqual(Sign.Sign_Negative, dur_negative.sign());
|
try std.testing.expectEqual(Sign.negative, dur_negative.sign());
|
||||||
}
|
}
|
||||||
|
|
||||||
test blank {
|
test blank {
|
||||||
|
|
@ -697,7 +491,7 @@ test blank {
|
||||||
defer dur.deinit();
|
defer dur.deinit();
|
||||||
|
|
||||||
try std.testing.expect(dur.blank());
|
try std.testing.expect(dur.blank());
|
||||||
try std.testing.expectEqual(Sign.Sign_Zero, dur.sign());
|
try std.testing.expectEqual(Sign.zero, dur.sign());
|
||||||
}
|
}
|
||||||
|
|
||||||
test add {
|
test add {
|
||||||
|
|
@ -735,7 +529,7 @@ test abs {
|
||||||
|
|
||||||
try std.testing.expectEqual(@as(i64, 1), abs_dur.hours());
|
try std.testing.expectEqual(@as(i64, 1), abs_dur.hours());
|
||||||
try std.testing.expectEqual(@as(i64, 30), abs_dur.minutes());
|
try std.testing.expectEqual(@as(i64, 30), abs_dur.minutes());
|
||||||
try std.testing.expectEqual(Sign.Sign_Positive, abs_dur.sign());
|
try std.testing.expectEqual(Sign.positive, abs_dur.sign());
|
||||||
}
|
}
|
||||||
|
|
||||||
test negated {
|
test negated {
|
||||||
|
|
@ -746,7 +540,7 @@ test negated {
|
||||||
defer neg.deinit();
|
defer neg.deinit();
|
||||||
|
|
||||||
try std.testing.expectEqual(@as(i64, -1), neg.hours());
|
try std.testing.expectEqual(@as(i64, -1), neg.hours());
|
||||||
try std.testing.expectEqual(Sign.Sign_Negative, neg.sign());
|
try std.testing.expectEqual(Sign.negative, neg.sign());
|
||||||
}
|
}
|
||||||
|
|
||||||
test toString {
|
test toString {
|
||||||
|
|
@ -762,9 +556,21 @@ test toString {
|
||||||
}
|
}
|
||||||
|
|
||||||
test fromPartialDuration {
|
test fromPartialDuration {
|
||||||
var partial = PartialDuration.empty();
|
const empty_i64 = temporal_rs.toOption(c.OptionI64, null);
|
||||||
partial = partial.withHours(3);
|
const empty_f64 = temporal_rs.toOption(c.OptionF64, null);
|
||||||
partial = partial.withMinutes(45);
|
|
||||||
|
const partial = c.PartialDuration{
|
||||||
|
.years = empty_i64,
|
||||||
|
.months = empty_i64,
|
||||||
|
.weeks = empty_i64,
|
||||||
|
.days = empty_i64,
|
||||||
|
.hours = .{ .is_ok = true, .unnamed_0 = .{ .ok = 3 } },
|
||||||
|
.minutes = .{ .is_ok = true, .unnamed_0 = .{ .ok = 45 } },
|
||||||
|
.seconds = empty_i64,
|
||||||
|
.milliseconds = empty_i64,
|
||||||
|
.microseconds = empty_f64,
|
||||||
|
.nanoseconds = empty_f64,
|
||||||
|
};
|
||||||
|
|
||||||
const dur = try Duration.fromPartialDuration(partial);
|
const dur = try Duration.fromPartialDuration(partial);
|
||||||
defer dur.deinit();
|
defer dur.deinit();
|
||||||
|
|
|
||||||
443
src/Instant.zig
443
src/Instant.zig
|
|
@ -1,11 +1,61 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const temporal_rs = @import("cabi.zig");
|
||||||
|
const c = temporal_rs.c;
|
||||||
|
|
||||||
const Instant = @This();
|
const Instant = @This();
|
||||||
|
|
||||||
_inner: *CInstant,
|
_inner: *c.Instant,
|
||||||
epoch_milliseconds: i64,
|
epoch_milliseconds: i64,
|
||||||
epoch_nanoseconds: i128,
|
epoch_nanoseconds: i128,
|
||||||
|
|
||||||
|
pub const Unit = enum(c_uint) {
|
||||||
|
auto = c.Unit_Auto,
|
||||||
|
nanosecond = c.Unit_Nanosecond,
|
||||||
|
microsecond = c.Unit_Microsecond,
|
||||||
|
millisecond = c.Unit_Millisecond,
|
||||||
|
second = c.Unit_Second,
|
||||||
|
minute = c.Unit_Minute,
|
||||||
|
hour = c.Unit_Hour,
|
||||||
|
day = c.Unit_Day,
|
||||||
|
week = c.Unit_Week,
|
||||||
|
month = c.Unit_Month,
|
||||||
|
year = c.Unit_Year,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const RoundingMode = enum(c_uint) {
|
||||||
|
ceil = c.RoundingMode_Ceil,
|
||||||
|
floor = c.RoundingMode_Floor,
|
||||||
|
expand = c.RoundingMode_Expand,
|
||||||
|
trunc = c.RoundingMode_Trunc,
|
||||||
|
half_ceil = c.RoundingMode_HalfCeil,
|
||||||
|
half_floor = c.RoundingMode_HalfFloor,
|
||||||
|
half_expand = c.RoundingMode_HalfExpand,
|
||||||
|
half_trunc = c.RoundingMode_HalfTrunc,
|
||||||
|
half_even = c.RoundingMode_HalfEven,
|
||||||
|
};
|
||||||
|
pub const Sign = enum(c_int) {
|
||||||
|
positive = c.Sign_Positive,
|
||||||
|
zero = c.Sign_Zero,
|
||||||
|
negative = c.Sign_Negative,
|
||||||
|
};
|
||||||
|
const TimeZone = c.TimeZone;
|
||||||
|
const TimeZone_option = c.TimeZone_option;
|
||||||
|
const Precision = c.Precision;
|
||||||
|
const Unit_option = c.Unit_option;
|
||||||
|
const RoundingMode_option = c.RoundingMode_option;
|
||||||
|
const DifferenceSettings = c.DifferenceSettings;
|
||||||
|
const RoundingOptions = c.RoundingOptions;
|
||||||
|
const ToStringRoundingOptions = c.ToStringRoundingOptions;
|
||||||
|
const OptionU8 = c.OptionU8;
|
||||||
|
const OptionU32 = c.OptionU32;
|
||||||
|
const TemporalError = c.TemporalError;
|
||||||
|
const DiplomatStringView = c.DiplomatStringView;
|
||||||
|
const DiplomatString16View = c.DiplomatString16View;
|
||||||
|
const DiplomatWrite = c.DiplomatWrite;
|
||||||
|
const Duration = c.Duration;
|
||||||
|
const ZonedDateTime = c.ZonedDateTime;
|
||||||
|
const Provider = c.Provider;
|
||||||
|
|
||||||
/// Construct from epoch nanoseconds (Temporal.Instant.fromEpochNanoseconds).
|
/// Construct from epoch nanoseconds (Temporal.Instant.fromEpochNanoseconds).
|
||||||
pub fn init(epoch_ns: i128) !Instant {
|
pub fn init(epoch_ns: i128) !Instant {
|
||||||
return fromEpochNanoseconds(epoch_ns);
|
return fromEpochNanoseconds(epoch_ns);
|
||||||
|
|
@ -13,79 +63,75 @@ pub fn init(epoch_ns: i128) !Instant {
|
||||||
|
|
||||||
/// Construct from epoch milliseconds.
|
/// Construct from epoch milliseconds.
|
||||||
pub fn fromEpochMilliseconds(epoch_ms: i64) !Instant {
|
pub fn fromEpochMilliseconds(epoch_ms: i64) !Instant {
|
||||||
return wrapInstant(temporal_rs_Instant_from_epoch_milliseconds(epoch_ms));
|
return wrapInstant(c.temporal_rs_Instant_from_epoch_milliseconds(epoch_ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct from epoch nanoseconds (Temporal.Instant.fromEpochNanoseconds).
|
/// Construct from epoch nanoseconds (Temporal.Instant.fromEpochNanoseconds).
|
||||||
pub fn fromEpochNanoseconds(epoch_ns: i128) !Instant {
|
pub fn fromEpochNanoseconds(epoch_ns: i128) !Instant {
|
||||||
const parts = i128ToParts(epoch_ns);
|
const parts = temporal_rs.toI128Nanoseconds(epoch_ns);
|
||||||
return wrapInstant(temporal_rs_Instant_try_new(parts));
|
return wrapInstant(c.temporal_rs_Instant_try_new(parts));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an ISO 8601 string (Temporal.Instant.from).
|
/// Parse an ISO 8601 string (Temporal.Instant.from).
|
||||||
pub fn from(text: []const u8) !Instant {
|
pub fn from(text: []const u8) !Instant {
|
||||||
const view = DiplomatStringView{ .data = text.ptr, .len = text.len };
|
const view = temporal_rs.toDiplomatStringView(text);
|
||||||
return wrapInstant(temporal_rs_Instant_from_utf8(view));
|
return wrapInstant(c.temporal_rs_Instant_from_utf8(view));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an ISO 8601 UTF-16 string (Temporal.Instant.from).
|
/// Parse an ISO 8601 UTF-16 string (Temporal.Instant.from).
|
||||||
fn fromUtf16(text: []const u16) !Instant {
|
fn fromUtf16(text: []const u16) !Instant {
|
||||||
const view = DiplomatString16View{ .data = text.ptr, .len = text.len };
|
const view = temporal_rs.toDiplomatString16View(text);
|
||||||
return wrapInstant(temporal_rs_Instant_from_utf16(view));
|
return wrapInstant(c.temporal_rs_Instant_from_utf16(view));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a Duration to this instant (Temporal.Instant.prototype.add).
|
/// Add a Duration to this instant (Temporal.Instant.prototype.add).
|
||||||
pub fn add(self: Instant, duration: *const Duration) !Instant {
|
pub fn add(self: Instant, duration: *const Duration) !Instant {
|
||||||
return wrapInstant(temporal_rs_Instant_add(self._inner, duration));
|
return wrapInstant(c.temporal_rs_Instant_add(self._inner, duration));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subtract a Duration from this instant (Temporal.Instant.prototype.subtract).
|
/// Subtract a Duration from this instant (Temporal.Instant.prototype.subtract).
|
||||||
pub fn subtract(self: Instant, duration: *const Duration) !Instant {
|
pub fn subtract(self: Instant, duration: *const Duration) !Instant {
|
||||||
return wrapInstant(temporal_rs_Instant_subtract(self._inner, duration));
|
return wrapInstant(c.temporal_rs_Instant_subtract(self._inner, duration));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Difference until another instant (Temporal.Instant.prototype.until).
|
/// Difference until another instant (Temporal.Instant.prototype.until).
|
||||||
pub fn until(self: Instant, other: Instant, settings: DifferenceSettings) !DurationHandle {
|
pub fn until(self: Instant, other: Instant, settings: DifferenceSettings) !DurationHandle {
|
||||||
return wrapDuration(temporal_rs_Instant_until(self._inner, other._inner, settings));
|
return wrapDuration(c.temporal_rs_Instant_until(self._inner, other._inner, settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Difference since another instant (Temporal.Instant.prototype.since).
|
/// Difference since another instant (Temporal.Instant.prototype.since).
|
||||||
pub fn since(self: Instant, other: Instant, settings: DifferenceSettings) !DurationHandle {
|
pub fn since(self: Instant, other: Instant, settings: DifferenceSettings) !DurationHandle {
|
||||||
return wrapDuration(temporal_rs_Instant_since(self._inner, other._inner, settings));
|
return wrapDuration(c.temporal_rs_Instant_since(self._inner, other._inner, settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Round this instant (Temporal.Instant.prototype.round).
|
/// Round this instant (Temporal.Instant.prototype.round).
|
||||||
pub fn round(self: Instant, options: RoundingOptions) !Instant {
|
pub fn round(self: Instant, options: RoundingOptions) !Instant {
|
||||||
return wrapInstant(temporal_rs_Instant_round(self._inner, options));
|
return wrapInstant(c.temporal_rs_Instant_round(self._inner, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compare two instants (Temporal.Instant.compare).
|
/// Compare two instants (Temporal.Instant.compare).
|
||||||
pub fn compare(a: Instant, b: Instant) i8 {
|
pub fn compare(a: Instant, b: Instant) i8 {
|
||||||
return temporal_rs_Instant_compare(a._inner, b._inner);
|
return c.temporal_rs_Instant_compare(a._inner, b._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equality check (Temporal.Instant.prototype.equals).
|
/// Equality check (Temporal.Instant.prototype.equals).
|
||||||
pub fn equals(a: Instant, b: Instant) bool {
|
pub fn equals(a: Instant, b: Instant) bool {
|
||||||
return temporal_rs_Instant_equals(a._inner, b._inner);
|
return c.temporal_rs_Instant_equals(a._inner, b._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to string using compiled TZ data; caller owns returned slice.
|
/// Convert to string using compiled TZ data; caller owns returned slice.
|
||||||
pub fn toString(self: Instant, allocator: std.mem.Allocator, opts: ToStringOptions) ![]u8 {
|
pub fn toString(self: Instant, allocator: std.mem.Allocator, opts: ToStringOptions) ![]u8 {
|
||||||
const zone_opt = if (opts.time_zone) |z|
|
const zone_opt = temporal_rs.toTimeZoneOption(opts.time_zone);
|
||||||
TimeZone_option{ .ok = z, .is_ok = true }
|
|
||||||
else
|
|
||||||
TimeZone_option{ .ok = undefined, .is_ok = false };
|
|
||||||
|
|
||||||
const rounding = optsToRounding(opts);
|
const rounding = optsToRounding(opts);
|
||||||
|
|
||||||
const writer = diplomat_buffer_write_create(128);
|
const writer = c.diplomat_buffer_write_create(128);
|
||||||
defer diplomat_buffer_write_destroy(writer);
|
defer c.diplomat_buffer_write_destroy(writer);
|
||||||
|
|
||||||
const res = temporal_rs_Instant_to_ixdtf_string_with_compiled_data(self._inner, zone_opt, rounding, writer);
|
const res = c.temporal_rs_Instant_to_ixdtf_string_with_compiled_data(self._inner, zone_opt, rounding, writer);
|
||||||
try handleVoidResult(res);
|
try handleVoidResult(res);
|
||||||
|
|
||||||
const len = diplomat_buffer_write_len(writer);
|
const len = c.diplomat_buffer_write_len(writer);
|
||||||
const source = diplomat_buffer_write_get_bytes(writer)[0..len];
|
const source = c.diplomat_buffer_write_get_bytes(writer)[0..len];
|
||||||
|
|
||||||
const out = try allocator.alloc(u8, len);
|
const out = try allocator.alloc(u8, len);
|
||||||
std.mem.copyForwards(u8, out, source);
|
std.mem.copyForwards(u8, out, source);
|
||||||
|
|
@ -94,21 +140,17 @@ pub fn toString(self: Instant, allocator: std.mem.Allocator, opts: ToStringOptio
|
||||||
|
|
||||||
/// Convert to string using an explicit provider.
|
/// Convert to string using an explicit provider.
|
||||||
fn toStringWithProvider(self: Instant, allocator: std.mem.Allocator, provider: *const Provider, opts: ToStringOptions) ![]u8 {
|
fn toStringWithProvider(self: Instant, allocator: std.mem.Allocator, provider: *const Provider, opts: ToStringOptions) ![]u8 {
|
||||||
const zone_opt = if (opts.time_zone) |z|
|
const zone_opt = temporal_rs.toTimeZoneOption(opts.time_zone);
|
||||||
TimeZone_option{ .ok = z, .is_ok = true }
|
|
||||||
else
|
|
||||||
TimeZone_option{ .ok = undefined, .is_ok = false };
|
|
||||||
|
|
||||||
const rounding = optsToRounding(opts);
|
const rounding = optsToRounding(opts);
|
||||||
|
|
||||||
const writer = diplomat_buffer_write_create(128);
|
const writer = c.diplomat_buffer_write_create(128);
|
||||||
defer diplomat_buffer_write_destroy(writer);
|
defer c.diplomat_buffer_write_destroy(writer);
|
||||||
|
|
||||||
const res = temporal_rs_Instant_to_ixdtf_string_with_provider(self._inner, zone_opt, rounding, provider, writer);
|
const res = c.temporal_rs_Instant_to_ixdtf_string_with_provider(self._inner, zone_opt, rounding, provider, writer);
|
||||||
try handleVoidResult(res);
|
try handleVoidResult(res);
|
||||||
|
|
||||||
const len = diplomat_buffer_write_len(writer);
|
const len = c.diplomat_buffer_write_len(writer);
|
||||||
const source = diplomat_buffer_write_get_bytes(writer)[0..len];
|
const source = c.diplomat_buffer_write_get_bytes(writer)[0..len];
|
||||||
|
|
||||||
const out = try allocator.alloc(u8, len);
|
const out = try allocator.alloc(u8, len);
|
||||||
std.mem.copyForwards(u8, out, source);
|
std.mem.copyForwards(u8, out, source);
|
||||||
|
|
@ -127,49 +169,49 @@ pub fn toLocaleString(self: Instant, allocator: std.mem.Allocator) ![]u8 {
|
||||||
|
|
||||||
/// Convert to ZonedDateTime using built-in provider (Temporal.Instant.prototype.toZonedDateTimeISO).
|
/// Convert to ZonedDateTime using built-in provider (Temporal.Instant.prototype.toZonedDateTimeISO).
|
||||||
pub fn toZonedDateTimeISO(self: Instant, zone: TimeZone) !ZonedDateTimeHandle {
|
pub fn toZonedDateTimeISO(self: Instant, zone: TimeZone) !ZonedDateTimeHandle {
|
||||||
return wrapZonedDateTime(temporal_rs_Instant_to_zoned_date_time_iso(self._inner, zone));
|
return wrapZonedDateTime(c.temporal_rs_Instant_to_zoned_date_time_iso(self._inner, zone));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to ZonedDateTime using an explicit provider.
|
/// Convert to ZonedDateTime using an explicit provider.
|
||||||
fn toZonedDateTimeIsoWithProvider(self: Instant, zone: TimeZone, provider: *const Provider) !ZonedDateTimeHandle {
|
fn toZonedDateTimeIsoWithProvider(self: Instant, zone: TimeZone, provider: *const Provider) !ZonedDateTimeHandle {
|
||||||
return wrapZonedDateTime(temporal_rs_Instant_to_zoned_date_time_iso_with_provider(self._inner, zone, provider));
|
return wrapZonedDateTime(c.temporal_rs_Instant_to_zoned_date_time_iso_with_provider(self._inner, zone, provider));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clone the underlying instant.
|
/// Clone the underlying instant.
|
||||||
fn clone(self: Instant) Instant {
|
fn clone(self: Instant) Instant {
|
||||||
const ptr = temporal_rs_Instant_clone(self._inner);
|
const ptr = c.temporal_rs_Instant_clone(self._inner) orelse unreachable;
|
||||||
return .{ ._inner = ptr, .epoch_milliseconds = temporal_rs_Instant_epoch_milliseconds(ptr), .epoch_nanoseconds = partsToI128(temporal_rs_Instant_epoch_nanoseconds(ptr)) };
|
return .{ ._inner = ptr, .epoch_milliseconds = c.temporal_rs_Instant_epoch_milliseconds(ptr), .epoch_nanoseconds = temporal_rs.fromI128Nanoseconds(c.temporal_rs_Instant_epoch_nanoseconds(ptr)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Instant) void {
|
pub fn deinit(self: Instant) void {
|
||||||
temporal_rs_Instant_destroy(self._inner);
|
c.temporal_rs_Instant_destroy(self._inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Helpers -----------------------------------------------------------------
|
// --- Helpers -----------------------------------------------------------------
|
||||||
|
|
||||||
fn wrapInstant(res: InstantResult) !Instant {
|
fn wrapInstant(res: anytype) !Instant {
|
||||||
if (!res.is_ok) return error.TemporalError;
|
if (!res.is_ok) return error.TemporalError;
|
||||||
const ptr = res.result.ok orelse return error.TemporalError;
|
const maybe_ptr = res.unnamed_0.ok;
|
||||||
return .{ ._inner = ptr, .epoch_milliseconds = temporal_rs_Instant_epoch_milliseconds(ptr), .epoch_nanoseconds = partsToI128(temporal_rs_Instant_epoch_nanoseconds(ptr)) };
|
if (maybe_ptr == null) return error.TemporalError;
|
||||||
|
const ptr: *c.Instant = maybe_ptr.?;
|
||||||
|
return .{ ._inner = ptr, .epoch_milliseconds = c.temporal_rs_Instant_epoch_milliseconds(ptr), .epoch_nanoseconds = temporal_rs.fromI128Nanoseconds(c.temporal_rs_Instant_epoch_nanoseconds(ptr)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrapDuration(res: DurationResult) !DurationHandle {
|
fn wrapDuration(res: anytype) !DurationHandle {
|
||||||
if (!res.is_ok) return error.TemporalError;
|
if (!res.is_ok) return error.TemporalError;
|
||||||
const ptr = res.result.ok orelse return error.TemporalError;
|
return .{ .ptr = res.unnamed_0.ok orelse return error.TemporalError };
|
||||||
return .{ .ptr = ptr };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrapZonedDateTime(res: ZonedDateTimeResult) !ZonedDateTimeHandle {
|
fn wrapZonedDateTime(res: anytype) !ZonedDateTimeHandle {
|
||||||
if (!res.is_ok) return error.TemporalError;
|
if (!res.is_ok) return error.TemporalError;
|
||||||
const ptr = res.result.ok orelse return error.TemporalError;
|
return .{ .ptr = res.unnamed_0.ok orelse return error.TemporalError };
|
||||||
return .{ .ptr = ptr };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleVoidResult(res: VoidResult) !void {
|
fn handleVoidResult(res: anytype) !void {
|
||||||
if (!res.is_ok) return error.TemporalError;
|
if (!res.is_ok) return error.TemporalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn i128ToParts(value: i128) I128Nanoseconds {
|
fn i128ToParts(value: i128) temporal_rs.c.I128Nanoseconds {
|
||||||
const is_neg = value < 0;
|
const is_neg = value < 0;
|
||||||
const mag: u128 = if (is_neg) @intCast(@as(u128, @intCast(-value))) else @intCast(value);
|
const mag: u128 = if (is_neg) @intCast(@as(u128, @intCast(-value))) else @intCast(value);
|
||||||
const mask: u64 = 1 << 63;
|
const mask: u64 = 1 << 63;
|
||||||
|
|
@ -179,7 +221,7 @@ fn i128ToParts(value: i128) I128Nanoseconds {
|
||||||
return .{ .high = high, .low = low };
|
return .{ .high = high, .low = low };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn partsToI128(value: I128Nanoseconds) i128 {
|
fn partsToI128(value: temporal_rs.c.I128Nanoseconds) i128 {
|
||||||
const mask: u64 = 1 << 63;
|
const mask: u64 = 1 << 63;
|
||||||
const is_neg = (value.high & mask) != 0;
|
const is_neg = (value.high & mask) != 0;
|
||||||
const mag: u128 = ((@as(u128, value.high & ~mask)) << 64) | value.low;
|
const mag: u128 = ((@as(u128, value.high & ~mask)) << 64) | value.low;
|
||||||
|
|
@ -188,48 +230,34 @@ fn partsToI128(value: I128Nanoseconds) i128 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn defaultPrecision() Precision {
|
fn defaultPrecision() Precision {
|
||||||
return .{ .is_minute = false, .precision = OptionU8{ .ok = 0, .is_ok = false } };
|
return .{ .is_minute = false, .precision = temporal_rs.toOption(c.OptionU8, null) };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn defaultToStringRoundingOptions() ToStringRoundingOptions {
|
fn defaultToStringRoundingOptions() ToStringRoundingOptions {
|
||||||
return .{
|
return temporal_rs.to_string_rounding_options_auto;
|
||||||
.precision = defaultPrecision(),
|
|
||||||
.smallest_unit = Unit_option{ .ok = .auto, .is_ok = false },
|
|
||||||
.rounding_mode = RoundingMode_option{ .ok = .trunc, .is_ok = false },
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert ToStringOptions to ToStringRoundingOptions for the C API
|
/// Convert ToStringOptions to ToStringRoundingOptions for the C API
|
||||||
fn optsToRounding(opts: ToStringOptions) ToStringRoundingOptions {
|
fn optsToRounding(opts: ToStringOptions) ToStringRoundingOptions {
|
||||||
// If smallest_unit is specified, use it; otherwise use fractional_second_digits for precision
|
// If smallest_unit is specified, use it; otherwise use fractional_second_digits for precision
|
||||||
const smallest_unit_opt = if (opts.smallest_unit) |unit|
|
|
||||||
Unit_option{ .ok = unit, .is_ok = true }
|
|
||||||
else
|
|
||||||
Unit_option{ .ok = .auto, .is_ok = false };
|
|
||||||
|
|
||||||
const precision = if (opts.fractional_second_digits) |digits|
|
const precision = if (opts.fractional_second_digits) |digits|
|
||||||
Precision{ .is_minute = false, .precision = OptionU8{ .ok = digits, .is_ok = true } }
|
Precision{ .is_minute = false, .precision = temporal_rs.toOption(c.OptionU8, digits) }
|
||||||
else
|
else
|
||||||
defaultPrecision();
|
defaultPrecision();
|
||||||
|
|
||||||
const rounding_mode_opt = if (opts.rounding_mode) |mode|
|
const smallest_unit = if (opts.smallest_unit) |unit| @intFromEnum(unit) else null;
|
||||||
RoundingMode_option{ .ok = mode, .is_ok = true }
|
const rounding_mode = if (opts.rounding_mode) |mode| @intFromEnum(mode) else null;
|
||||||
else
|
|
||||||
RoundingMode_option{ .ok = .trunc, .is_ok = false };
|
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.precision = precision,
|
.precision = precision,
|
||||||
.smallest_unit = smallest_unit_opt,
|
.smallest_unit = temporal_rs.toUnitOption(smallest_unit),
|
||||||
.rounding_mode = rounding_mode_opt,
|
.rounding_mode = temporal_rs.toRoundingModeOption(rounding_mode),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parseDuration(text: []const u8) !DurationHandle {
|
fn parseDuration(text: []const u8) !DurationHandle {
|
||||||
const view = DiplomatStringView{ .data = text.ptr, .len = text.len };
|
const view = temporal_rs.toDiplomatStringView(text);
|
||||||
const res = temporal_rs_Duration_from_utf8(view);
|
return wrapDuration(c.temporal_rs_Duration_from_utf8(view));
|
||||||
if (!res.is_ok) return error.TemporalError;
|
|
||||||
const ptr = res.result.ok orelse return error.TemporalError;
|
|
||||||
return .{ .ptr = ptr };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Public helper types -----------------------------------------------------
|
// --- Public helper types -----------------------------------------------------
|
||||||
|
|
@ -260,7 +288,7 @@ const DurationHandle = struct {
|
||||||
ptr: *Duration,
|
ptr: *Duration,
|
||||||
|
|
||||||
pub fn deinit(self: DurationHandle) void {
|
pub fn deinit(self: DurationHandle) void {
|
||||||
temporal_rs_Duration_destroy(self.ptr);
|
c.temporal_rs_Duration_destroy(self.ptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -268,215 +296,10 @@ const ZonedDateTimeHandle = struct {
|
||||||
ptr: *ZonedDateTime,
|
ptr: *ZonedDateTime,
|
||||||
|
|
||||||
pub fn deinit(self: ZonedDateTimeHandle) void {
|
pub fn deinit(self: ZonedDateTimeHandle) void {
|
||||||
temporal_rs_ZonedDateTime_destroy(self.ptr);
|
c.temporal_rs_ZonedDateTime_destroy(self.ptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Extern types ------------------------------------------------------------
|
|
||||||
|
|
||||||
const CInstant = opaque {};
|
|
||||||
const Duration = opaque {};
|
|
||||||
const ZonedDateTime = opaque {};
|
|
||||||
const Provider = opaque {};
|
|
||||||
|
|
||||||
const I128Nanoseconds = extern struct { high: u64, low: u64 };
|
|
||||||
const I128Nanoseconds_option = extern struct { ok: I128Nanoseconds, is_ok: bool };
|
|
||||||
|
|
||||||
const DiplomatStringView = extern struct { data: [*c]const u8, len: usize };
|
|
||||||
const DiplomatString16View = extern struct { data: [*c]const u16, len: usize };
|
|
||||||
|
|
||||||
const OptionStringView = extern struct { ok: DiplomatStringView, is_ok: bool };
|
|
||||||
const OptionU8 = extern struct { ok: u8, is_ok: bool };
|
|
||||||
const OptionU32 = extern struct { ok: u32, is_ok: bool };
|
|
||||||
|
|
||||||
const DiplomatWrite = extern struct {
|
|
||||||
context: ?*anyopaque,
|
|
||||||
buf: [*c]u8,
|
|
||||||
len: usize,
|
|
||||||
cap: usize,
|
|
||||||
grow_failed: bool,
|
|
||||||
flush: ?*const fn (*DiplomatWrite) void,
|
|
||||||
grow: ?*const fn (*DiplomatWrite, usize) bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const TimeZone = extern struct {
|
|
||||||
offset_minutes: i16,
|
|
||||||
resolved_id: usize,
|
|
||||||
normalized_id: usize,
|
|
||||||
is_iana_id: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const TimeZone_option = extern struct {
|
|
||||||
ok: TimeZone,
|
|
||||||
is_ok: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Precision = extern struct {
|
|
||||||
is_minute: bool,
|
|
||||||
precision: OptionU8,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Time unit for Temporal operations.
|
|
||||||
/// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal
|
|
||||||
pub const Unit = enum(c_int) {
|
|
||||||
auto = 0,
|
|
||||||
nanosecond = 1,
|
|
||||||
microsecond = 2,
|
|
||||||
millisecond = 3,
|
|
||||||
second = 4,
|
|
||||||
minute = 5,
|
|
||||||
hour = 6,
|
|
||||||
day = 7,
|
|
||||||
week = 8,
|
|
||||||
month = 9,
|
|
||||||
year = 10,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Unit_option = extern struct { ok: Unit, is_ok: bool };
|
|
||||||
|
|
||||||
/// Rounding mode for Temporal operations.
|
|
||||||
/// See: https://tc39.es/ecma402/#table-sanctioned-single-unit-identifiers
|
|
||||||
pub const RoundingMode = enum(c_int) {
|
|
||||||
/// Round toward positive infinity
|
|
||||||
ceil = 0,
|
|
||||||
/// Round toward negative infinity
|
|
||||||
floor = 1,
|
|
||||||
/// Round away from zero
|
|
||||||
expand = 2,
|
|
||||||
/// Round toward zero (truncate)
|
|
||||||
trunc = 3,
|
|
||||||
/// Round half toward positive infinity
|
|
||||||
half_ceil = 4,
|
|
||||||
/// Round half toward negative infinity
|
|
||||||
half_floor = 5,
|
|
||||||
/// Round half away from zero
|
|
||||||
half_expand = 6,
|
|
||||||
/// Round half toward zero
|
|
||||||
half_trunc = 7,
|
|
||||||
/// Round half to even (banker's rounding)
|
|
||||||
half_even = 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
const RoundingMode_option = extern struct { ok: RoundingMode, is_ok: bool };
|
|
||||||
|
|
||||||
const DifferenceSettings = extern struct {
|
|
||||||
largest_unit: Unit_option,
|
|
||||||
smallest_unit: Unit_option,
|
|
||||||
rounding_mode: RoundingMode_option,
|
|
||||||
increment: OptionU32,
|
|
||||||
};
|
|
||||||
|
|
||||||
const RoundingOptions = extern struct {
|
|
||||||
largest_unit: Unit_option,
|
|
||||||
smallest_unit: Unit_option,
|
|
||||||
rounding_mode: RoundingMode_option,
|
|
||||||
increment: OptionU32,
|
|
||||||
};
|
|
||||||
|
|
||||||
const ToStringRoundingOptions = extern struct {
|
|
||||||
precision: Precision,
|
|
||||||
smallest_unit: Unit_option,
|
|
||||||
rounding_mode: RoundingMode_option,
|
|
||||||
};
|
|
||||||
|
|
||||||
const ErrorKind = enum(c_int) {
|
|
||||||
ErrorKind_Generic = 0,
|
|
||||||
ErrorKind_Type = 1,
|
|
||||||
ErrorKind_Range = 2,
|
|
||||||
ErrorKind_Syntax = 3,
|
|
||||||
ErrorKind_Assert = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
const TemporalError = extern struct {
|
|
||||||
kind: ErrorKind,
|
|
||||||
msg: OptionStringView,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Sign = enum(c_int) {
|
|
||||||
Sign_Positive = 1,
|
|
||||||
Sign_Zero = 0,
|
|
||||||
Sign_Negative = -1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- Result wrappers ---------------------------------------------------------
|
|
||||||
|
|
||||||
const InstantResult = extern struct {
|
|
||||||
result: extern union {
|
|
||||||
ok: ?*CInstant,
|
|
||||||
err: TemporalError,
|
|
||||||
},
|
|
||||||
is_ok: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const DurationResult = extern struct {
|
|
||||||
result: extern union {
|
|
||||||
ok: ?*Duration,
|
|
||||||
err: TemporalError,
|
|
||||||
},
|
|
||||||
is_ok: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const DurationParseResult = extern struct {
|
|
||||||
result: extern union {
|
|
||||||
ok: ?*Duration,
|
|
||||||
err: TemporalError,
|
|
||||||
},
|
|
||||||
is_ok: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const ZonedDateTimeResult = extern struct {
|
|
||||||
result: extern union {
|
|
||||||
ok: ?*ZonedDateTime,
|
|
||||||
err: TemporalError,
|
|
||||||
},
|
|
||||||
is_ok: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const VoidResult = extern struct {
|
|
||||||
result: extern union {
|
|
||||||
err: TemporalError,
|
|
||||||
},
|
|
||||||
is_ok: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- Extern functions -------------------------------------------------------
|
|
||||||
|
|
||||||
extern "c" fn temporal_rs_Instant_try_new(ns: I128Nanoseconds) InstantResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_from_epoch_milliseconds(epoch_milliseconds: i64) InstantResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_from_utf8(s: DiplomatStringView) InstantResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_from_utf16(s: DiplomatString16View) InstantResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_add(self: *const CInstant, duration: *const Duration) InstantResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_subtract(self: *const CInstant, duration: *const Duration) InstantResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_since(self: *const CInstant, other: *const CInstant, settings: DifferenceSettings) DurationResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_until(self: *const CInstant, other: *const CInstant, settings: DifferenceSettings) DurationResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_round(self: *const CInstant, options: RoundingOptions) InstantResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_compare(self: *const CInstant, other: *const CInstant) i8;
|
|
||||||
extern "c" fn temporal_rs_Instant_equals(self: *const CInstant, other: *const CInstant) bool;
|
|
||||||
extern "c" fn temporal_rs_Instant_epoch_milliseconds(self: *const CInstant) i64;
|
|
||||||
extern "c" fn temporal_rs_Instant_epoch_nanoseconds(self: *const CInstant) I128Nanoseconds;
|
|
||||||
extern "c" fn temporal_rs_Instant_to_ixdtf_string_with_compiled_data(self: *const CInstant, zone: TimeZone_option, options: ToStringRoundingOptions, write: *DiplomatWrite) VoidResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_to_ixdtf_string_with_provider(self: *const CInstant, zone: TimeZone_option, options: ToStringRoundingOptions, p: *const Provider, write: *DiplomatWrite) VoidResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_to_zoned_date_time_iso(self: *const CInstant, zone: TimeZone) ZonedDateTimeResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_to_zoned_date_time_iso_with_provider(self: *const CInstant, zone: TimeZone, p: *const Provider) ZonedDateTimeResult;
|
|
||||||
extern "c" fn temporal_rs_Instant_clone(self: *const CInstant) *CInstant;
|
|
||||||
extern "c" fn temporal_rs_Instant_destroy(self: *CInstant) void;
|
|
||||||
|
|
||||||
extern "c" fn temporal_rs_Duration_destroy(self: *Duration) void;
|
|
||||||
extern "c" fn temporal_rs_Duration_from_utf8(s: DiplomatStringView) DurationParseResult;
|
|
||||||
extern "c" fn temporal_rs_Duration_hours(self: *const Duration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_minutes(self: *const Duration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_seconds(self: *const Duration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_milliseconds(self: *const Duration) i64;
|
|
||||||
extern "c" fn temporal_rs_Duration_microseconds(self: *const Duration) f64;
|
|
||||||
extern "c" fn temporal_rs_Duration_nanoseconds(self: *const Duration) f64;
|
|
||||||
extern "c" fn temporal_rs_Duration_sign(self: *const Duration) Sign;
|
|
||||||
extern "c" fn temporal_rs_ZonedDateTime_destroy(self: *ZonedDateTime) void;
|
|
||||||
|
|
||||||
extern "c" fn diplomat_buffer_write_create(cap: usize) *DiplomatWrite;
|
|
||||||
extern "c" fn diplomat_buffer_write_get_bytes(write: *DiplomatWrite) [*c]u8;
|
|
||||||
extern "c" fn diplomat_buffer_write_len(write: *DiplomatWrite) usize;
|
|
||||||
extern "c" fn diplomat_buffer_write_destroy(write: *DiplomatWrite) void;
|
|
||||||
|
|
||||||
// --- Tests -------------------------------------------------------------------
|
// --- Tests -------------------------------------------------------------------
|
||||||
|
|
||||||
test init {
|
test init {
|
||||||
|
|
@ -544,13 +367,13 @@ test compare {
|
||||||
defer a.deinit();
|
defer a.deinit();
|
||||||
const b = try Instant.fromEpochMilliseconds(0);
|
const b = try Instant.fromEpochMilliseconds(0);
|
||||||
defer b.deinit();
|
defer b.deinit();
|
||||||
const c = try Instant.fromEpochMilliseconds(1_000);
|
const cc = try Instant.fromEpochMilliseconds(1_000);
|
||||||
defer c.deinit();
|
defer cc.deinit();
|
||||||
|
|
||||||
try std.testing.expectEqual(@as(i8, 0), Instant.compare(a, b));
|
try std.testing.expectEqual(@as(i8, 0), Instant.compare(a, b));
|
||||||
try std.testing.expect(Instant.equals(a, b));
|
try std.testing.expect(Instant.equals(a, b));
|
||||||
try std.testing.expectEqual(@as(i8, -1), Instant.compare(a, c));
|
try std.testing.expectEqual(@as(i8, -1), Instant.compare(a, cc));
|
||||||
try std.testing.expectEqual(@as(i8, 1), Instant.compare(c, a));
|
try std.testing.expectEqual(@as(i8, 1), Instant.compare(cc, a));
|
||||||
}
|
}
|
||||||
|
|
||||||
test equals {
|
test equals {
|
||||||
|
|
@ -558,13 +381,13 @@ test equals {
|
||||||
defer a.deinit();
|
defer a.deinit();
|
||||||
const b = try Instant.fromEpochMilliseconds(0);
|
const b = try Instant.fromEpochMilliseconds(0);
|
||||||
defer b.deinit();
|
defer b.deinit();
|
||||||
const c = try Instant.fromEpochMilliseconds(1_000);
|
const cc = try Instant.fromEpochMilliseconds(1_000);
|
||||||
defer c.deinit();
|
defer cc.deinit();
|
||||||
|
|
||||||
try std.testing.expectEqual(@as(i8, 0), Instant.compare(a, b));
|
try std.testing.expectEqual(@as(i8, 0), Instant.compare(a, b));
|
||||||
try std.testing.expect(Instant.equals(a, b));
|
try std.testing.expect(Instant.equals(a, b));
|
||||||
try std.testing.expectEqual(@as(i8, -1), Instant.compare(a, c));
|
try std.testing.expectEqual(@as(i8, -1), Instant.compare(a, cc));
|
||||||
try std.testing.expectEqual(@as(i8, 1), Instant.compare(c, a));
|
try std.testing.expectEqual(@as(i8, 1), Instant.compare(cc, a));
|
||||||
}
|
}
|
||||||
|
|
||||||
test until {
|
test until {
|
||||||
|
|
@ -574,21 +397,21 @@ test until {
|
||||||
defer later.deinit();
|
defer later.deinit();
|
||||||
|
|
||||||
const settings = DifferenceSettings{
|
const settings = DifferenceSettings{
|
||||||
.largest_unit = Unit_option{ .ok = .hour, .is_ok = true },
|
.largest_unit = temporal_rs.toUnitOption(@intFromEnum(Unit.hour)),
|
||||||
.smallest_unit = Unit_option{ .ok = .second, .is_ok = true },
|
.smallest_unit = temporal_rs.toUnitOption(@intFromEnum(Unit.second)),
|
||||||
.rounding_mode = RoundingMode_option{ .ok = .trunc, .is_ok = true },
|
.rounding_mode = temporal_rs.toRoundingModeOption(@intFromEnum(RoundingMode.trunc)),
|
||||||
.increment = OptionU32{ .ok = 0, .is_ok = false },
|
.increment = temporal_rs.toOption(c.OptionU32, null),
|
||||||
};
|
};
|
||||||
|
|
||||||
var until_handle = try earlier.until(later, settings);
|
var until_handle = try earlier.until(later, settings);
|
||||||
defer until_handle.deinit();
|
defer until_handle.deinit();
|
||||||
try std.testing.expectEqual(Sign.Sign_Positive, temporal_rs_Duration_sign(until_handle.ptr));
|
try std.testing.expectEqual(Sign.positive, @as(Sign, @enumFromInt(temporal_rs.c.temporal_rs_Duration_sign(until_handle.ptr))));
|
||||||
try std.testing.expectEqual(@as(i64, 1), temporal_rs_Duration_hours(until_handle.ptr));
|
try std.testing.expectEqual(@as(i64, 1), temporal_rs.c.temporal_rs_Duration_hours(until_handle.ptr));
|
||||||
|
|
||||||
var since_handle = try later.since(earlier, settings);
|
var since_handle = try later.since(earlier, settings);
|
||||||
defer since_handle.deinit();
|
defer since_handle.deinit();
|
||||||
try std.testing.expectEqual(Sign.Sign_Positive, temporal_rs_Duration_sign(since_handle.ptr));
|
try std.testing.expectEqual(Sign.positive, @as(Sign, @enumFromInt(temporal_rs.c.temporal_rs_Duration_sign(since_handle.ptr))));
|
||||||
try std.testing.expectEqual(@as(i64, 1), temporal_rs_Duration_hours(since_handle.ptr));
|
try std.testing.expectEqual(@as(i64, 1), temporal_rs.c.temporal_rs_Duration_hours(since_handle.ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
test since {
|
test since {
|
||||||
|
|
@ -598,21 +421,21 @@ test since {
|
||||||
defer later.deinit();
|
defer later.deinit();
|
||||||
|
|
||||||
const settings = DifferenceSettings{
|
const settings = DifferenceSettings{
|
||||||
.largest_unit = Unit_option{ .ok = .hour, .is_ok = true },
|
.largest_unit = temporal_rs.toUnitOption(@intFromEnum(Unit.hour)),
|
||||||
.smallest_unit = Unit_option{ .ok = .second, .is_ok = true },
|
.smallest_unit = temporal_rs.toUnitOption(@intFromEnum(Unit.second)),
|
||||||
.rounding_mode = RoundingMode_option{ .ok = .trunc, .is_ok = true },
|
.rounding_mode = temporal_rs.toRoundingModeOption(@intFromEnum(RoundingMode.trunc)),
|
||||||
.increment = OptionU32{ .ok = 0, .is_ok = false },
|
.increment = temporal_rs.toOption(c.OptionU32, null),
|
||||||
};
|
};
|
||||||
|
|
||||||
var until_handle = try earlier.until(later, settings);
|
var until_handle = try earlier.until(later, settings);
|
||||||
defer until_handle.deinit();
|
defer until_handle.deinit();
|
||||||
try std.testing.expectEqual(Sign.Sign_Positive, temporal_rs_Duration_sign(until_handle.ptr));
|
try std.testing.expectEqual(Sign.positive, @as(Sign, @enumFromInt(temporal_rs.c.temporal_rs_Duration_sign(until_handle.ptr))));
|
||||||
try std.testing.expectEqual(@as(i64, 1), temporal_rs_Duration_hours(until_handle.ptr));
|
try std.testing.expectEqual(@as(i64, 1), temporal_rs.c.temporal_rs_Duration_hours(until_handle.ptr));
|
||||||
|
|
||||||
var since_handle = try later.since(earlier, settings);
|
var since_handle = try later.since(earlier, settings);
|
||||||
defer since_handle.deinit();
|
defer since_handle.deinit();
|
||||||
try std.testing.expectEqual(Sign.Sign_Positive, temporal_rs_Duration_sign(since_handle.ptr));
|
try std.testing.expectEqual(Sign.positive, @as(Sign, @enumFromInt(temporal_rs.c.temporal_rs_Duration_sign(since_handle.ptr))));
|
||||||
try std.testing.expectEqual(@as(i64, 1), temporal_rs_Duration_hours(since_handle.ptr));
|
try std.testing.expectEqual(@as(i64, 1), temporal_rs.c.temporal_rs_Duration_hours(since_handle.ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
test round {
|
test round {
|
||||||
|
|
@ -620,10 +443,10 @@ test round {
|
||||||
defer inst.deinit();
|
defer inst.deinit();
|
||||||
|
|
||||||
const opts = RoundingOptions{
|
const opts = RoundingOptions{
|
||||||
.largest_unit = Unit_option{ .ok = .auto, .is_ok = false },
|
.largest_unit = temporal_rs.toUnitOption(null),
|
||||||
.smallest_unit = Unit_option{ .ok = .second, .is_ok = true },
|
.smallest_unit = temporal_rs.toUnitOption(@intFromEnum(Unit.second)),
|
||||||
.rounding_mode = RoundingMode_option{ .ok = .half_expand, .is_ok = true },
|
.rounding_mode = temporal_rs.toRoundingModeOption(@intFromEnum(RoundingMode.half_expand)),
|
||||||
.increment = OptionU32{ .ok = 0, .is_ok = false },
|
.increment = temporal_rs.toOption(c.OptionU32, null),
|
||||||
};
|
};
|
||||||
|
|
||||||
const rounded = try inst.round(opts);
|
const rounded = try inst.round(opts);
|
||||||
|
|
|
||||||
263
src/cabi.zig
Normal file
263
src/cabi.zig
Normal file
|
|
@ -0,0 +1,263 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const c = @cImport({
|
||||||
|
@cInclude("AnyCalendarKind.h");
|
||||||
|
@cInclude("Calendar.h");
|
||||||
|
@cInclude("Duration.h");
|
||||||
|
@cInclude("ErrorKind.h");
|
||||||
|
@cInclude("I128Nanoseconds.h");
|
||||||
|
@cInclude("Instant.h");
|
||||||
|
@cInclude("OwnedRelativeTo.h");
|
||||||
|
@cInclude("ParsedDate.h");
|
||||||
|
@cInclude("ParsedDateTime.h");
|
||||||
|
@cInclude("ParsedZonedDateTime.h");
|
||||||
|
@cInclude("PlainDate.h");
|
||||||
|
@cInclude("PlainDateTime.h");
|
||||||
|
@cInclude("PlainMonthDay.h");
|
||||||
|
@cInclude("PlainTime.h");
|
||||||
|
@cInclude("PlainYearMonth.h");
|
||||||
|
@cInclude("RelativeTo.h");
|
||||||
|
@cInclude("TimeZone.h");
|
||||||
|
@cInclude("ZonedDateTime.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
pub const to_string_rounding_options_auto: c.ToStringRoundingOptions = .{
|
||||||
|
.precision = .{ .is_minute = false, .precision = toOption(c.OptionU8, null) },
|
||||||
|
.smallest_unit = toUnitOption(null),
|
||||||
|
.rounding_mode = toRoundingModeOption(null),
|
||||||
|
};
|
||||||
|
|
||||||
|
const u64_high_bit_mask: u64 = 1 << 63;
|
||||||
|
|
||||||
|
/// Covert a Rust `I128Nanoseconds` struct to a Zig `i128`.
|
||||||
|
///
|
||||||
|
/// Ported from temporal_rs's [`From<ffi::I128Nanoseconds>`](https://github.com/boa-dev/temporal/blob/89bfca1f5b918d00a19354664e1da11da51305ee/temporal_capi/src/instant.rs#L172-L186) trait for `i128`.
|
||||||
|
pub fn fromI128Nanoseconds(ns: c.I128Nanoseconds) i128 {
|
||||||
|
const is_neg = (ns.high & u64_high_bit_mask) != 0;
|
||||||
|
const ns_high: u128 = @intCast((ns.high & ~u64_high_bit_mask));
|
||||||
|
const total: i128 = @intCast((ns_high << 64) + ns.low);
|
||||||
|
return if (is_neg) -total else total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Covert a Zig `i128` to a Rust `I128Nanoseconds` struct.
|
||||||
|
///
|
||||||
|
/// Ported from temporal_rs's [`From<i128>`](https://github.com/boa-dev/temporal/blob/89bfca1f5b918d00a19354664e1da11da51305ee/temporal_capi/src/instant.rs#L188-L207) trait for `ffi::I128Nanoseconds`.
|
||||||
|
pub fn toI128Nanoseconds(ns: i128) c.I128Nanoseconds {
|
||||||
|
std.debug.assert(ns != std.math.minInt(i128));
|
||||||
|
const is_neg = ns < 0;
|
||||||
|
const ns_abs = @abs(ns);
|
||||||
|
const high: u64 = @intCast(ns_abs >> 64);
|
||||||
|
const low: u64 = @truncate(ns_abs);
|
||||||
|
return .{ .high = if (is_neg) high | u64_high_bit_mask else high, .low = low };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Rust `DiplomatStringView` to a Zig slice.
|
||||||
|
pub fn fromDiplomatStringView(sv: c.DiplomatStringView) []const u8 {
|
||||||
|
return sv.data[0..sv.len];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Zig slice to a Rust `DiplomatStringView`.
|
||||||
|
pub fn toDiplomatStringView(s: []const u8) c.DiplomatStringView {
|
||||||
|
return .{ .data = s.ptr, .len = s.len };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Zig slice to a Rust `DiplomatString16View`.
|
||||||
|
pub fn toDiplomatString16View(s: []const u16) c.DiplomatString16View {
|
||||||
|
return .{ .data = s.ptr, .len = s.len };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Rust `Option<T>` to a Zig `?T`.
|
||||||
|
pub fn fromOption(value: anytype) ?Success(@TypeOf(value)) {
|
||||||
|
return success(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Zig `?T` to a Rust `Option<T>`.
|
||||||
|
pub fn toOption(comptime T: type, maybe_value: ?Success(T)) T {
|
||||||
|
return if (maybe_value) |value|
|
||||||
|
.{ .is_ok = true, .unnamed_0 = .{ .ok = value } }
|
||||||
|
else
|
||||||
|
.{ .is_ok = false };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Zig `?ArithmeticOverflow` to a Rust `Option<ArithmeticOverflow>`.
|
||||||
|
pub fn toArithmeticOverflowOption(maybe_value: ?c.RoundingMode) c.ArithmeticOverflow_option {
|
||||||
|
return toOption(c.ArithmeticOverflow_option, maybe_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Zig `?Disambiguation` to a Rust `Option<Disambiguation>`.
|
||||||
|
pub fn toDisambiguationOption(maybe_value: ?c.Disambiguation) c.Disambiguation_option {
|
||||||
|
return toOption(c.Disambiguation_option, maybe_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Zig `?OffsetDisambiguation` to a Rust `Option<OffsetDisambiguation>`.
|
||||||
|
pub fn toOffsetDisambiguationOption(maybe_value: ?c.OffsetDisambiguation) c.OffsetDisambiguation_option {
|
||||||
|
return toOption(c.OffsetDisambiguation_option, maybe_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Zig `?PartialDate` to a Rust `Option<PartialDate>`.
|
||||||
|
pub fn toPartialDateOption(maybe_value: ?c.PartialDate) c.PartialDate_option {
|
||||||
|
return toOption(c.PartialDate_option, maybe_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Zig `?RoundingMode` to a Rust `Option<RoundingMode>`.
|
||||||
|
pub fn toRoundingModeOption(maybe_value: ?c.RoundingMode) c.RoundingMode_option {
|
||||||
|
return toOption(c.RoundingMode_option, maybe_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Zig `?TimeZone` to a Rust `Option<TimeZone>`.
|
||||||
|
pub fn toTimeZoneOption(maybe_value: ?c.TimeZone) c.TimeZone_option {
|
||||||
|
return toOption(c.TimeZone_option, maybe_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a Zig `?Unit` to a Rust `Option<Unit>`.
|
||||||
|
pub fn toUnitOption(maybe_value: ?c.Unit) c.Unit_option {
|
||||||
|
return toOption(c.Unit_option, maybe_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wraps values from a `c.RelativeTo` or `c.OwnedRelativeTo`.
|
||||||
|
pub const RelativeTo = union(enum) {
|
||||||
|
none,
|
||||||
|
owned_plain_date: *c.PlainDate,
|
||||||
|
owned_zoned_date_time: *c.ZonedDateTime,
|
||||||
|
borrowed_plain_date: *const c.PlainDate,
|
||||||
|
borrowed_zoned_date_time: *const c.ZonedDateTime,
|
||||||
|
|
||||||
|
pub fn fromOwned(owned: c.OwnedRelativeTo) RelativeTo {
|
||||||
|
if (owned.date) |plain_date| {
|
||||||
|
return .{ .owned_plain_date = plain_date };
|
||||||
|
} else if (owned.zoned) |zoned_date_time| {
|
||||||
|
return .{ .owned_zoned_date_time = zoned_date_time };
|
||||||
|
} else {
|
||||||
|
return .none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toRust(self: RelativeTo) c.RelativeTo {
|
||||||
|
return switch (self) {
|
||||||
|
.none => .{ .date = null, .zoned = null },
|
||||||
|
.owned_plain_date => |plain_date| .{ .date = plain_date, .zoned = null },
|
||||||
|
.owned_zoned_date_time => |zoned_date_time| .{ .date = null, .zoned = zoned_date_time },
|
||||||
|
.borrowed_plain_date => |plain_date| .{ .date = plain_date, .zoned = null },
|
||||||
|
.borrowed_zoned_date_time => |zoned_date_time| .{ .date = null, .zoned = zoned_date_time },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: RelativeTo) void {
|
||||||
|
switch (self) {
|
||||||
|
.owned_plain_date => |plain_date| c.temporal_rs_PlainDate_destroy(plain_date),
|
||||||
|
.owned_zoned_date_time => |zoned_date_time| c.temporal_rs_ZonedDateTime_destroy(zoned_date_time),
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DiplomatWrite = struct {
|
||||||
|
gpa: std.mem.Allocator,
|
||||||
|
array_list: std.ArrayList(u8),
|
||||||
|
inner: c.DiplomatWrite,
|
||||||
|
|
||||||
|
pub fn init(gpa: std.mem.Allocator) DiplomatWrite {
|
||||||
|
return .{
|
||||||
|
.gpa = gpa,
|
||||||
|
.array_list = .empty,
|
||||||
|
.inner = .{
|
||||||
|
// NOTE: We use `@fieldParentPtr()` on the `inner` struct field to get to the other
|
||||||
|
// fields instead of creating a context externally and storing a pointer.
|
||||||
|
.context = null,
|
||||||
|
.buf = undefined,
|
||||||
|
.len = 0,
|
||||||
|
.cap = 0,
|
||||||
|
.grow_failed = false,
|
||||||
|
.flush = flush,
|
||||||
|
.grow = grow,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *DiplomatWrite) void {
|
||||||
|
self.array_list.deinit(self.gpa);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toOwnedSlice(self: *DiplomatWrite) std.mem.Allocator.Error![]u8 {
|
||||||
|
if (self.inner.grow_failed) return error.OutOfMemory;
|
||||||
|
self.inner = undefined; // Invalidate the inner struct to prevent further writes
|
||||||
|
return self.array_list.toOwnedSlice(self.gpa);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(inner: ?*c.DiplomatWrite) callconv(.c) void {
|
||||||
|
const self: *DiplomatWrite = @fieldParentPtr("inner", inner.?);
|
||||||
|
self.array_list.items.len = inner.?.len;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn grow(inner: ?*c.DiplomatWrite, size: usize) callconv(.c) bool {
|
||||||
|
const self: *DiplomatWrite = @fieldParentPtr("inner", inner.?);
|
||||||
|
self.array_list.ensureTotalCapacity(self.gpa, size) catch return false;
|
||||||
|
inner.?.buf = self.array_list.items.ptr;
|
||||||
|
inner.?.cap = self.array_list.capacity;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
test DiplomatWrite {
|
||||||
|
const gpa = std.testing.allocator;
|
||||||
|
var write = DiplomatWrite.init(gpa);
|
||||||
|
defer write.deinit();
|
||||||
|
|
||||||
|
const WriteImpl = struct {
|
||||||
|
inner: *c.DiplomatWrite,
|
||||||
|
|
||||||
|
// https://github.com/rust-diplomat/diplomat/blob/2b903255187976779798fc89df3fee7298641c80/runtime/src/write.rs#L70-L73
|
||||||
|
pub fn flush(self: @This()) void {
|
||||||
|
self.inner.flush.?(self.inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/rust-diplomat/diplomat/blob/2b903255187976779798fc89df3fee7298641c80/runtime/src/write.rs#L76-L94
|
||||||
|
pub fn writeStr(self: @This(), s: []const u8) void {
|
||||||
|
if (self.inner.grow_failed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const needed_len = self.inner.len + s.len;
|
||||||
|
if (needed_len > self.inner.cap) {
|
||||||
|
const success_ = self.inner.grow.?(self.inner, needed_len);
|
||||||
|
if (!success_) {
|
||||||
|
self.inner.grow_failed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std.debug.assert(needed_len <= self.inner.cap);
|
||||||
|
@memcpy(self.inner.buf[self.inner.len..][0..s.len], s);
|
||||||
|
self.inner.len = needed_len;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var write_impl: WriteImpl = .{ .inner = &write.inner };
|
||||||
|
write_impl.writeStr("Hello World");
|
||||||
|
write_impl.flush();
|
||||||
|
|
||||||
|
try std.testing.expectEqual(write.array_list.items.ptr, write.inner.buf);
|
||||||
|
try std.testing.expectEqual(write.array_list.items.len, write.inner.len);
|
||||||
|
try std.testing.expectEqual(write.array_list.capacity, write.inner.cap);
|
||||||
|
try std.testing.expectEqual(false, write.inner.grow_failed);
|
||||||
|
try std.testing.expectEqualSlices(u8, "Hello World", write.array_list.items);
|
||||||
|
|
||||||
|
const slice = try write.toOwnedSlice();
|
||||||
|
defer gpa.free(slice);
|
||||||
|
try std.testing.expectEqualSlices(u8, "Hello World", slice);
|
||||||
|
try std.testing.expectEqualSlices(u8, &.{}, write.array_list.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a "result" value to its "success" type, or returns `null` if the value is an error.
|
||||||
|
/// This is `inline` to prevent binary bloat, because each instantiation is expected to be called
|
||||||
|
/// only once.
|
||||||
|
pub inline fn success(result: anytype) ?Success(@TypeOf(result)) {
|
||||||
|
if (!result.is_ok) return null;
|
||||||
|
if (Success(@TypeOf(result)) == void) return;
|
||||||
|
return result.unnamed_0.ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given the C API representation of a `Result<T, E>`, returns the type 'T'.
|
||||||
|
pub fn Success(comptime Result: type) type {
|
||||||
|
const Union = @FieldType(Result, "unnamed_0");
|
||||||
|
if (!@hasField(Union, "ok")) return void;
|
||||||
|
return @FieldType(Union, "ok");
|
||||||
|
}
|
||||||
1
src/lib.rs
Normal file
1
src/lib.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
extern crate temporal_capi;
|
||||||
|
|
@ -13,6 +13,4 @@ pub fn main() !void {
|
||||||
|
|
||||||
const dur = try Temporal.Duration.from("P1Y2M3DT4H5M6S");
|
const dur = try Temporal.Duration.from("P1Y2M3DT4H5M6S");
|
||||||
defer dur.deinit();
|
defer dur.deinit();
|
||||||
// const dur_str = try dur.toString(allocator, .{});
|
|
||||||
// std.debug.print("Duration String: {s}\n", .{dur_str});
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ test "Temporal.Instant" {
|
||||||
"ToStringOptions",
|
"ToStringOptions",
|
||||||
"Unit",
|
"Unit",
|
||||||
"RoundingMode",
|
"RoundingMode",
|
||||||
|
"Sign",
|
||||||
};
|
};
|
||||||
|
|
||||||
try assertDecls(Instant, checks);
|
try assertDecls(Instant, checks);
|
||||||
|
|
|
||||||
29
src/unwind_stubs.zig
Normal file
29
src/unwind_stubs.zig
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
//! Provides unwind symbols because apparently Rust still might include these when using panic=abort.
|
||||||
|
//!
|
||||||
|
//! See:
|
||||||
|
//! - https://github.com/rust-lang/rust/issues/47493
|
||||||
|
//! - https://code.videolan.org/videolan/vlc/-/merge_requests/2878
|
||||||
|
|
||||||
|
export fn _Unwind_Backtrace() void {}
|
||||||
|
export fn _Unwind_DeleteException() void {}
|
||||||
|
export fn _Unwind_GetDataRelBase() void {}
|
||||||
|
export fn _Unwind_GetIP() void {}
|
||||||
|
export fn _Unwind_GetIPInfo() void {}
|
||||||
|
export fn _Unwind_GetLanguageSpecificData() void {}
|
||||||
|
export fn _Unwind_GetRegionStart() void {}
|
||||||
|
export fn _Unwind_GetTextRelBase() void {}
|
||||||
|
export fn _Unwind_RaiseException() void {}
|
||||||
|
export fn _Unwind_Resume() void {}
|
||||||
|
export fn _Unwind_SetGR() void {}
|
||||||
|
export fn _Unwind_SetIP() void {}
|
||||||
|
// These appear when building for riscv64
|
||||||
|
export fn _Unwind_FindEnclosingFunction() void {}
|
||||||
|
export fn _Unwind_GetCFA() void {}
|
||||||
|
// These appear when building for arm
|
||||||
|
export fn _Unwind_VRS_Get() void {}
|
||||||
|
export fn _Unwind_VRS_Set() void {}
|
||||||
|
export fn __gnu_unwind_frame() void {}
|
||||||
|
// This appears when building for s390x
|
||||||
|
export fn _Unwind_GetGR() void {}
|
||||||
|
// This appears when building for x86_64-windows
|
||||||
|
export fn _GCC_specific_handler() void {}
|
||||||
Loading…
Add table
Reference in a new issue