Skip to content

Commit 6544ed4

Browse files
committed
jiff-icu: add crate for converting to-and-from icu_calendar
This adds a new crate, `jiff-icu`, with `ConvertFrom` and `ConvertInto` traits. These mirror the `TryFrom` and `TryInto` traits from `std`. I took this approach for conversions specifically because it avoids needing to define wrapper types for everything. It does means we can't use the standard traits, but I think just importing one trait and having that add conversion routines on to the types in `jiff` and `icu_calendar` is an overall lighter weight solution. One thing I'm slightly unsure about is whether I want `jiff-icu` to just encompass _everything_ that makes sense to convert between inside of `icu`, or whether it should actually be `jiff-icu-calendar`. And then maybe down the road add `jiff-icu-timezone` or something? I'm partial to just adding everything in `icu` to `jiff-icu` that makes sense to add, and perhaps exposing some features (that are turned on by default) to opt out of `icu` crates that you don't need. I also think this will set the template for other crates I'd like to add, like `jiff-chrono`. With that said, I think `jiff-icu` is of particular importance, because it will enable an easier on-ramp to locale and non-Gregorian support. That is, presumably, `jiff-chrono` and `jiff-time` (if I do those) will be things that you wouldn't _ideally_ use, but `jiff-icu` will likely be part of intended and recommended workflows for users. Ref #50
1 parent 80255fe commit 6544ed4

File tree

10 files changed

+770
-3
lines changed

10 files changed

+770
-3
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ jobs:
5959
- run: cargo build --verbose
6060
- run: cargo doc --features serde --verbose
6161
- run: cargo test --verbose --all
62-
- run: cargo test --verbose -p jiff-cli
6362
# Skip on Windows because it takes freaking forever.
6463
- if: matrix.build != 'win-msvc'
6564
run: cargo test --verbose --lib --profile testrelease
@@ -110,8 +109,14 @@ jobs:
110109
run: cargo build -p jiff-tzdb-platform --verbose
111110
- name: Build docs
112111
run: cargo doc --features serde --verbose
113-
# We don't really care much about adding dev dependencies, and they can
114-
# move quite a bit faster. So unfortunately don't run tests on MSRV. We
112+
# NOTE: We currently don't track some ecosystem integration crates
113+
# like `jiff-icu`. They don't support Jiff's MSRV at time of writing
114+
# (2025-02-02), and I think these sorts of integration crates are at very
115+
# low risk of being more aggressive with respect to MSRV than the crates
116+
# they depend on. So for now, we just don't test them here.
117+
#
118+
# NOTE: We don't really care much about adding dev dependencies, and they
119+
# can move quite a bit faster. So unfortunately don't run tests on MSRV. We
115120
# could fix this by adding a `Carg.msrv.lock` or some such, but it doesn't
116121
# seem worth it.
117122
# - name: Run library tests

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ include = [
3131
[workspace]
3232
members = [
3333
"crates/jiff-cli",
34+
"crates/jiff-icu",
3435
"crates/jiff-tzdb",
3536
"crates/jiff-tzdb-platform",
3637
"examples/*",

crates/jiff-icu/COPYING

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This project is dual-licensed under the Unlicense and MIT licenses.
2+
3+
You may use this code under the terms of either license.

crates/jiff-icu/Cargo.toml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[package]
2+
name = "jiff-icu"
3+
version = "0.0.1" #:version
4+
authors = ["Andrew Gallant <[email protected]>"]
5+
license = "Unlicense OR MIT"
6+
homepage = "https://github.com/BurntSushi/jiff/tree/master/crates/jiff-icu"
7+
repository = "https://github.com/BurntSushi/jiff"
8+
documentation = "https://docs.rs/jiff-icu"
9+
description = "The entire Time Zone Database embedded into your binary."
10+
categories = ["date-and-time"]
11+
keywords = ["date", "time", "temporal", "zone", "iana"]
12+
workspace = "../.."
13+
edition = "2021"
14+
rust-version = "1.70"
15+
include = ["/*.rs", "/*.dat", "COPYING", "LICENSE-MIT", "UNLICENSE"]
16+
17+
[lib]
18+
name = "jiff_icu"
19+
bench = false
20+
path = "src/lib.rs"
21+
22+
[features]
23+
default = ["std"]
24+
std = ["alloc", "icu_calendar/std", "jiff/std"]
25+
alloc = ["jiff/alloc"]
26+
27+
[dependencies]
28+
jiff = { path = "../..", default-features = false }
29+
icu_calendar = { version = "1.5.2", default-features = false }
30+
31+
[dev-dependencies]
32+
jiff = { path = "../..", default-features = true }
33+
icu = { version = "1.5.0", features = ["std"] }

crates/jiff-icu/LICENSE-MIT

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2015 Andrew Gallant
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

crates/jiff-icu/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
jiff-icu
2+
========
3+
WIP
4+
5+
### Documentation
6+
7+
https://docs.rs/jiff-icu

crates/jiff-icu/UNLICENSE

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
This is free and unencumbered software released into the public domain.
2+
3+
Anyone is free to copy, modify, publish, use, compile, sell, or
4+
distribute this software, either in source code form or as a compiled
5+
binary, for any purpose, commercial or non-commercial, and by any
6+
means.
7+
8+
In jurisdictions that recognize copyright laws, the author or authors
9+
of this software dedicate any and all copyright interest in the
10+
software to the public domain. We make this dedication for the benefit
11+
of the public at large and to the detriment of our heirs and
12+
successors. We intend this dedication to be an overt act of
13+
relinquishment in perpetuity of all present and future rights to this
14+
software under copyright law.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22+
OTHER DEALINGS IN THE SOFTWARE.
23+
24+
For more information, please refer to <http://unlicense.org/>

crates/jiff-icu/src/error.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/// Creates a new ad hoc error via `format_args!`.
2+
macro_rules! err {
3+
($($tt:tt)*) => {{
4+
crate::error::Error::adhoc_from_args(format_args!($($tt)*))
5+
}}
6+
}
7+
8+
pub(crate) use err;
9+
10+
/// An error that can occur when converting between types in this crate.
11+
#[derive(Clone, Debug)]
12+
pub struct Error {
13+
kind: ErrorKind,
14+
}
15+
16+
impl Error {
17+
/// Creates an error from an arbitrary `core::fmt::Arguments`.
18+
///
19+
/// When `alloc` isn't enabled, then `Arguments::as_str()` is used to
20+
/// find an error message. Otherwise, a generic error message is emitted.
21+
pub(crate) fn adhoc_from_args<'a>(
22+
message: core::fmt::Arguments<'a>,
23+
) -> Error {
24+
let kind = ErrorKind::Adhoc(AdhocError::from_args(message));
25+
Error { kind }
26+
}
27+
}
28+
29+
#[derive(Clone, Debug)]
30+
enum ErrorKind {
31+
Adhoc(AdhocError),
32+
Jiff(jiff::Error),
33+
}
34+
35+
impl core::fmt::Display for Error {
36+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
37+
match self.kind {
38+
ErrorKind::Adhoc(ref err) => {
39+
core::fmt::Display::fmt(&err.message, f)
40+
}
41+
ErrorKind::Jiff(ref err) => err.fmt(f),
42+
}
43+
}
44+
}
45+
46+
#[cfg(feature = "std")]
47+
impl std::error::Error for Error {
48+
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
49+
match self.kind {
50+
ErrorKind::Adhoc(_) => None,
51+
ErrorKind::Jiff(ref err) => Some(err),
52+
}
53+
}
54+
}
55+
56+
impl From<jiff::Error> for Error {
57+
fn from(e: jiff::Error) -> Error {
58+
Error { kind: ErrorKind::Jiff(e) }
59+
}
60+
}
61+
62+
/// A generic error message.
63+
#[derive(Clone, Debug)]
64+
struct AdhocError {
65+
#[cfg(feature = "alloc")]
66+
message: alloc::boxed::Box<str>,
67+
#[cfg(not(feature = "alloc"))]
68+
message: &'static str,
69+
}
70+
71+
impl AdhocError {
72+
fn from_args<'a>(message: core::fmt::Arguments<'a>) -> AdhocError {
73+
#[cfg(feature = "alloc")]
74+
{
75+
AdhocError::from_display(message)
76+
}
77+
#[cfg(not(feature = "alloc"))]
78+
{
79+
let message = message.as_str().unwrap_or(
80+
"unknown `jiff-icu` error (better error messages require \
81+
enabling the `alloc` feature for the `jiff-icu` crate)",
82+
);
83+
AdhocError::from_static_str(message)
84+
}
85+
}
86+
87+
#[cfg(feature = "alloc")]
88+
fn from_display<'a>(message: impl core::fmt::Display + 'a) -> AdhocError {
89+
use alloc::string::ToString;
90+
91+
let message = message.to_string().into_boxed_str();
92+
AdhocError { message }
93+
}
94+
95+
#[cfg(not(feature = "alloc"))]
96+
fn from_static_str(message: &'static str) -> AdhocError {
97+
AdhocError { message }
98+
}
99+
}

0 commit comments

Comments
 (0)