hsmtool/util/attribute/
date.rs1use cryptoki::types;
6use cryptoki_sys::*;
7use std::convert::TryFrom;
8
9use crate::util::attribute::{AttrData, AttributeError};
10
11pub struct Date(pub String);
12
13fn parse(s: &[u8]) -> u32 {
14 let mut result = 0;
15 for &byte in s.iter() {
16 let ch = byte as char;
17 if ch.is_ascii_whitespace() || ch == '\0' {
18 } else if ch.is_ascii_digit() {
20 result *= 10;
21 result += (byte - b'0') as u32;
22 } else {
23 panic!("Expected digit or whitespace in {:?}", s);
24 }
25 }
26 result
27}
28
29impl From<types::Date> for Date {
30 fn from(val: types::Date) -> Self {
31 let val = CK_DATE::from(val);
32 let year = parse(&val.year);
33 let month = parse(&val.month);
34 let day = parse(&val.day);
35 Date(format!("{:04}-{:02}-{:02}", year, month, day))
36 }
37}
38
39impl From<&str> for Date {
40 fn from(val: &str) -> Self {
41 Date(val.to_string())
42 }
43}
44
45impl From<Date> for String {
46 fn from(val: Date) -> Self {
47 val.0
48 }
49}
50
51impl TryFrom<Date> for types::Date {
52 type Error = cryptoki::error::Error;
53 fn try_from(val: Date) -> Result<Self, Self::Error> {
54 if val.0.len() == 8 {
55 types::Date::new_from_str_slice(&val.0[0..4], &val.0[4..6], &val.0[6..8])
57 } else if val.0.len() == 10 {
58 types::Date::new_from_str_slice(&val.0[0..4], &val.0[5..7], &val.0[8..10])
60 } else {
61 Err(cryptoki::error::Error::InvalidValue)
62 }
63 }
64}
65
66impl TryFrom<&AttrData> for Date {
67 type Error = AttributeError;
68 fn try_from(val: &AttrData) -> Result<Self, Self::Error> {
69 Ok(Self::from(val.try_str()?))
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use anyhow::Result;
77
78 #[test]
79 fn test_convert_to_cryptoki_date() -> Result<()> {
80 let d = Date::from("2023-02-01");
81 let k = types::Date::try_from(d)?;
82 assert_eq!(k.to_string(), "Month: 02\nDay: 01\nYear: 2023");
83
84 let d = Date::from("20230504");
85 let k = types::Date::try_from(d)?;
86 assert_eq!(k.to_string(), "Month: 05\nDay: 04\nYear: 2023");
87
88 let d = Date::from("1234");
89 assert!(types::Date::try_from(d).is_err());
90 Ok(())
91 }
92
93 #[test]
94 fn test_convert_from_cryptoki_date() -> Result<()> {
95 let k = types::Date::from(CK_DATE {
96 year: *b"2023",
97 month: *b"02",
98 day: *b"01",
99 });
100 let d = Date::from(k);
101 assert_eq!(String::from(d), "2023-02-01");
102
103 let k = types::Date::from(CK_DATE {
104 year: *b"2023",
105 month: *b" 5",
106 day: *b"4 ",
107 });
108 let d = Date::from(k);
109 assert_eq!(String::from(d), "2023-05-04");
110
111 Ok(())
112 }
113}