Skip to content

Commit b1e68f7

Browse files
authored
Merge branch 'main' into add-derive-impls
2 parents a7f5fd1 + 1501955 commit b1e68f7

9 files changed

+1084
-4
lines changed

Diff for: temporal_capi/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ exclude.workspace = true
1212
[dependencies]
1313
diplomat = "0.9.0"
1414
diplomat-runtime = "0.9.0"
15-
temporal_rs = { version = "0.0.4", path = ".." }
15+
temporal_rs = { version = "0.0.4", path = "..", default-features = false }
1616
icu_calendar = { version = "2.0.0-beta1", default-features = false}

Diff for: temporal_capi/src/duration.rs

+290
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
use crate::error::ffi::TemporalError;
2+
3+
#[diplomat::bridge]
4+
#[diplomat::abi_rename = "temporal_rs_{0}"]
5+
#[diplomat::attr(auto, namespace = "temporal_rs")]
6+
pub mod ffi {
7+
use crate::error::ffi::TemporalError;
8+
use diplomat_runtime::DiplomatOption;
9+
10+
#[diplomat::opaque]
11+
pub struct Duration(pub(crate) temporal_rs::Duration);
12+
13+
#[diplomat::opaque]
14+
#[diplomat::transparent_convert]
15+
pub struct TimeDuration(pub(crate) temporal_rs::TimeDuration);
16+
17+
#[diplomat::opaque]
18+
#[diplomat::transparent_convert]
19+
pub struct DateDuration(pub(crate) temporal_rs::DateDuration);
20+
21+
pub struct PartialDuration {
22+
pub years: DiplomatOption<f64>,
23+
pub months: DiplomatOption<f64>,
24+
pub weeks: DiplomatOption<f64>,
25+
pub days: DiplomatOption<f64>,
26+
pub hours: DiplomatOption<f64>,
27+
pub minutes: DiplomatOption<f64>,
28+
pub seconds: DiplomatOption<f64>,
29+
pub milliseconds: DiplomatOption<f64>,
30+
pub microseconds: DiplomatOption<f64>,
31+
pub nanoseconds: DiplomatOption<f64>,
32+
}
33+
34+
#[diplomat::enum_convert(temporal_rs::Sign)]
35+
pub enum Sign {
36+
Positive = 1,
37+
Zero = 0,
38+
Negative = -1,
39+
}
40+
41+
impl PartialDuration {
42+
pub fn is_empty(self) -> bool {
43+
temporal_rs::partial::PartialDuration::try_from(self)
44+
.map(|p| p.is_empty())
45+
.unwrap_or(false)
46+
}
47+
}
48+
49+
impl TimeDuration {
50+
pub fn new(
51+
hours: f64,
52+
minutes: f64,
53+
seconds: f64,
54+
milliseconds: f64,
55+
microseconds: f64,
56+
nanoseconds: f64,
57+
) -> Result<Box<Self>, TemporalError> {
58+
temporal_rs::TimeDuration::new(
59+
hours.try_into()?,
60+
minutes.try_into()?,
61+
seconds.try_into()?,
62+
milliseconds.try_into()?,
63+
microseconds.try_into()?,
64+
nanoseconds.try_into()?,
65+
)
66+
.map(|x| Box::new(TimeDuration(x)))
67+
.map_err(Into::into)
68+
}
69+
70+
pub fn abs(&self) -> Box<Self> {
71+
Box::new(Self(self.0.abs()))
72+
}
73+
pub fn negated(&self) -> Box<Self> {
74+
Box::new(Self(self.0.negated()))
75+
}
76+
77+
pub fn is_within_range(&self) -> bool {
78+
self.0.is_within_range()
79+
}
80+
pub fn sign(&self) -> Sign {
81+
self.0.sign().into()
82+
}
83+
}
84+
85+
impl DateDuration {
86+
pub fn new(
87+
years: f64,
88+
months: f64,
89+
weeks: f64,
90+
days: f64,
91+
) -> Result<Box<Self>, TemporalError> {
92+
temporal_rs::DateDuration::new(
93+
years.try_into()?,
94+
months.try_into()?,
95+
weeks.try_into()?,
96+
days.try_into()?,
97+
)
98+
.map(|x| Box::new(DateDuration(x)))
99+
.map_err(Into::into)
100+
}
101+
102+
pub fn abs(&self) -> Box<Self> {
103+
Box::new(Self(self.0.abs()))
104+
}
105+
pub fn negated(&self) -> Box<Self> {
106+
Box::new(Self(self.0.negated()))
107+
}
108+
109+
pub fn sign(&self) -> Sign {
110+
self.0.sign().into()
111+
}
112+
}
113+
impl Duration {
114+
pub fn create(
115+
years: f64,
116+
months: f64,
117+
weeks: f64,
118+
days: f64,
119+
hours: f64,
120+
minutes: f64,
121+
seconds: f64,
122+
milliseconds: f64,
123+
microseconds: f64,
124+
nanoseconds: f64,
125+
) -> Result<Box<Self>, TemporalError> {
126+
temporal_rs::Duration::new(
127+
years.try_into()?,
128+
months.try_into()?,
129+
weeks.try_into()?,
130+
days.try_into()?,
131+
hours.try_into()?,
132+
minutes.try_into()?,
133+
seconds.try_into()?,
134+
milliseconds.try_into()?,
135+
microseconds.try_into()?,
136+
nanoseconds.try_into()?,
137+
)
138+
.map(|x| Box::new(Duration(x)))
139+
.map_err(Into::into)
140+
}
141+
142+
pub fn from_day_and_time(
143+
day: f64,
144+
time: &TimeDuration,
145+
) -> Result<Box<Self>, TemporalError> {
146+
Ok(Box::new(Duration(
147+
temporal_rs::Duration::from_day_and_time(day.try_into()?, &time.0),
148+
)))
149+
}
150+
pub fn from_partial_duration(partial: PartialDuration) -> Result<Box<Self>, TemporalError> {
151+
temporal_rs::Duration::from_partial_duration(partial.try_into()?)
152+
.map(|x| Box::new(Duration(x)))
153+
.map_err(Into::into)
154+
}
155+
pub fn is_time_within_range(&self) -> bool {
156+
self.0.is_time_within_range()
157+
}
158+
159+
pub fn time<'a>(&'a self) -> &'a TimeDuration {
160+
TimeDuration::transparent_convert(self.0.time())
161+
}
162+
pub fn date<'a>(&'a self) -> &'a DateDuration {
163+
DateDuration::transparent_convert(self.0.date())
164+
}
165+
166+
// set_time_duration is NOT safe to expose over FFI if the date()/time() methods are available
167+
// Diplomat plans to make this a hard error.
168+
// If needed, implement it as with_time_duration(&self, TimeDuration) -> Self
169+
170+
pub fn years(&self) -> f64 {
171+
self.0.years().as_inner()
172+
}
173+
pub fn months(&self) -> f64 {
174+
self.0.months().as_inner()
175+
}
176+
pub fn weeks(&self) -> f64 {
177+
self.0.weeks().as_inner()
178+
}
179+
pub fn days(&self) -> f64 {
180+
self.0.days().as_inner()
181+
}
182+
pub fn hours(&self) -> f64 {
183+
self.0.hours().as_inner()
184+
}
185+
pub fn minutes(&self) -> f64 {
186+
self.0.minutes().as_inner()
187+
}
188+
pub fn seconds(&self) -> f64 {
189+
self.0.seconds().as_inner()
190+
}
191+
pub fn milliseconds(&self) -> f64 {
192+
self.0.milliseconds().as_inner()
193+
}
194+
pub fn microseconds(&self) -> f64 {
195+
self.0.microseconds().as_inner()
196+
}
197+
pub fn nanoseconds(&self) -> f64 {
198+
self.0.nanoseconds().as_inner()
199+
}
200+
201+
pub fn sign(&self) -> Sign {
202+
self.0.sign().into()
203+
}
204+
205+
pub fn is_zero(&self) -> bool {
206+
self.0.is_zero()
207+
}
208+
209+
pub fn abs(&self) -> Box<Self> {
210+
Box::new(Self(self.0.abs()))
211+
}
212+
pub fn negated(&self) -> Box<Self> {
213+
Box::new(Self(self.0.negated()))
214+
}
215+
216+
pub fn add(&self, other: &Self) -> Result<Box<Self>, TemporalError> {
217+
self.0
218+
.add(&other.0)
219+
.map(|x| Box::new(Duration(x)))
220+
.map_err(Into::into)
221+
}
222+
223+
pub fn subtract(&self, other: &Self) -> Result<Box<Self>, TemporalError> {
224+
self.0
225+
.subtract(&other.0)
226+
.map(|x| Box::new(Duration(x)))
227+
.map_err(Into::into)
228+
}
229+
230+
// TODO round_with_provider (needs time zone stuff)
231+
}
232+
}
233+
234+
impl TryFrom<ffi::PartialDuration> for temporal_rs::partial::PartialDuration {
235+
type Error = TemporalError;
236+
fn try_from(other: ffi::PartialDuration) -> Result<Self, TemporalError> {
237+
Ok(Self {
238+
years: other
239+
.years
240+
.into_option()
241+
.map(TryFrom::try_from)
242+
.transpose()?,
243+
months: other
244+
.months
245+
.into_option()
246+
.map(TryFrom::try_from)
247+
.transpose()?,
248+
weeks: other
249+
.weeks
250+
.into_option()
251+
.map(TryFrom::try_from)
252+
.transpose()?,
253+
days: other
254+
.days
255+
.into_option()
256+
.map(TryFrom::try_from)
257+
.transpose()?,
258+
hours: other
259+
.hours
260+
.into_option()
261+
.map(TryFrom::try_from)
262+
.transpose()?,
263+
minutes: other
264+
.minutes
265+
.into_option()
266+
.map(TryFrom::try_from)
267+
.transpose()?,
268+
seconds: other
269+
.seconds
270+
.into_option()
271+
.map(TryFrom::try_from)
272+
.transpose()?,
273+
milliseconds: other
274+
.milliseconds
275+
.into_option()
276+
.map(TryFrom::try_from)
277+
.transpose()?,
278+
microseconds: other
279+
.microseconds
280+
.into_option()
281+
.map(TryFrom::try_from)
282+
.transpose()?,
283+
nanoseconds: other
284+
.nanoseconds
285+
.into_option()
286+
.map(TryFrom::try_from)
287+
.transpose()?,
288+
})
289+
}
290+
}

Diff for: temporal_capi/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
#![allow(unused)] // Until we add all the APIs
2+
#![warn(unused_imports)] // But we want to clean up imports
23
#![allow(clippy::needless_lifetimes)] // Diplomat requires explicit lifetimes at times
4+
#![allow(clippy::too_many_arguments)] // We're mapping APIs with the same argument size
5+
#![allow(clippy::wrong_self_convention)] // Diplomat forces self conventions that may not always be ideal
36

47
mod calendar;
8+
mod duration;
59
mod error;
610
mod options;
711

812
mod plain_date;
13+
mod plain_date_time;
14+
mod plain_month_day;
15+
mod plain_time;
16+
mod plain_year_month;

0 commit comments

Comments
 (0)