Skip to content

Commit 5b54663

Browse files
s-arashArash Sahebolamri
andauthored
Make x509::Time more useful (#331)
Co-authored-by: Arash Sahebolamri <[email protected]>
1 parent 847011e commit 5b54663

File tree

6 files changed

+85
-10
lines changed

6 files changed

+85
-10
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.cargo
22
target/
3-
venv/
3+
venv/
4+
.vscode

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,7 @@ crypto (or PKI) only library.
7878
* **time** Enable time support in mbedtls-sys.
7979
* *zlib* Enable zlib support in mbedtls-sys.
8080
* *async-rt* Enable async support for SSL.
81-
82-
PRs adding new features are encouraged.
81+
* *chrono* Enable [`chrono`](https://docs.rs/chrono/) support (e.g., implementation of conversion traits between `x509::Time` and `chrono` types)
8382

8483
# mbedtls-sys-auto
8584

ci.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ case "$TRAVIS_RUST_VERSION" in
5353
if [ "$TARGET" != "x86_64-fortanix-unknown-sgx" ]; then
5454
cargo nextest run --test async_session --features=async-rt,ssl --target $TARGET
5555
cargo nextest run --test async_session --features=async-rt,ssl,legacy_protocols --target $TARGET
56+
cargo nextest run chrono --features=chrono,ssl,x509 --target $TARGET
5657

5758
# If zlib is installed, test the zlib feature
5859
if [ -n "$ZLIB_INSTALLED" ]; then

mbedtls/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ cbc = { version = "0.1.2", optional = true }
3131
rc2 = { version = "0.8.1", optional = true }
3232
cfg-if = "1.0.0"
3333
tokio = { version = "1.16.1", optional = true }
34+
chrono = { version = "0.4", optional = true }
3435

3536
[target.x86_64-fortanix-unknown-sgx.dependencies]
3637
rs-libc = "0.2.0"

mbedtls/src/x509/mod.rs

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,19 +196,19 @@ impl Time {
196196
pub fn new(year: u16, month: u8, day: u8, hour: u8, minute: u8, second: u8) -> Option<Time> {
197197
if year < 10000 && month >= 1 && month <= 12 && day >= 1 && day <= 31 && hour < 24 && minute < 60 && second < 60 {
198198
Some(Time {
199-
year: year,
200-
month: month,
201-
day: day,
202-
hour: hour,
203-
minute: minute,
204-
second: second,
199+
year,
200+
month,
201+
day,
202+
hour,
203+
minute,
204+
second,
205205
})
206206
} else {
207207
None
208208
}
209209
}
210210

211-
fn to_x509_time(&self) -> [u8; 15] {
211+
pub fn to_x509_time(&self) -> [u8; 15] {
212212
let mut writer = TimeWriter { buf: [0; 15], idx: 0 };
213213
write!(
214214
writer,
@@ -219,4 +219,76 @@ impl Time {
219219
assert!(writer.idx == 14);
220220
writer.buf
221221
}
222+
223+
pub fn year(&self) -> u16 {
224+
self.year
225+
}
226+
pub fn month(&self) -> u8 {
227+
self.month
228+
}
229+
pub fn day(&self) -> u8 {
230+
self.day
231+
}
232+
pub fn hour(&self) -> u8 {
233+
self.hour
234+
}
235+
pub fn minute(&self) -> u8 {
236+
self.minute
237+
}
238+
pub fn second(&self) -> u8 {
239+
self.second
240+
}
241+
}
242+
243+
#[cfg(feature = "chrono")]
244+
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
245+
pub struct InvalidTimeError;
246+
247+
#[cfg(feature = "chrono")]
248+
mod chrono_time {
249+
use chrono::{Datelike, NaiveDate, NaiveDateTime, Timelike};
250+
use core::convert::{TryFrom, TryInto};
251+
252+
use super::{InvalidTimeError, Time};
253+
254+
impl TryFrom<Time> for NaiveDateTime {
255+
type Error = InvalidTimeError;
256+
257+
fn try_from(value: Time) -> Result<Self, Self::Error> {
258+
let res = NaiveDate::from_ymd_opt(value.year.into(), value.month.into(), value.day.into())
259+
.and_then(|date| date.and_hms_opt(value.hour.into(), value.minute.into(), value.second.into()))
260+
.ok_or(InvalidTimeError)?;
261+
Ok(res)
262+
}
263+
}
264+
265+
impl TryFrom<NaiveDateTime> for Time {
266+
type Error = InvalidTimeError;
267+
268+
fn try_from(value: NaiveDateTime) -> Result<Self, Self::Error> {
269+
let res = Time::new(
270+
value.year().try_into().map_err(|_| InvalidTimeError)?,
271+
value.month().try_into().map_err(|_| InvalidTimeError)?,
272+
value.day().try_into().map_err(|_| InvalidTimeError)?,
273+
value.hour().try_into().map_err(|_| InvalidTimeError)?,
274+
value.minute().try_into().map_err(|_| InvalidTimeError)?,
275+
value.second().try_into().map_err(|_| InvalidTimeError)?,
276+
);
277+
res.ok_or(InvalidTimeError)
278+
}
279+
}
280+
281+
#[test]
282+
fn time_naive_date_time_conversion() {
283+
let time = Time::new(2077, 12, 13, 10, 20, 30).unwrap();
284+
let naive_date_time: NaiveDateTime = time.try_into().unwrap();
285+
286+
let expected = NaiveDate::from_ymd_opt(2077, 12, 13)
287+
.unwrap()
288+
.and_hms_opt(10, 20, 30)
289+
.unwrap();
290+
assert_eq!(naive_date_time, expected);
291+
292+
assert_eq!(time, Time::try_from(naive_date_time).unwrap());
293+
}
222294
}

0 commit comments

Comments
 (0)