1 use super::NaiveTime; 2 use core::fmt; 3 use serde::{de, ser}; 4 5 // TODO not very optimized for space (binary formats would want something better) 6 // TODO round-trip for general leap seconds (not just those with second = 60) 7 8 impl ser::Serialize for NaiveTime { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: ser::Serializer,9 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 10 where 11 S: ser::Serializer, 12 { 13 serializer.collect_str(&self) 14 } 15 } 16 17 struct NaiveTimeVisitor; 18 19 impl de::Visitor<'_> for NaiveTimeVisitor { 20 type Value = NaiveTime; 21 expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result22 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 23 formatter.write_str("a formatted time string") 24 } 25 visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: de::Error,26 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> 27 where 28 E: de::Error, 29 { 30 value.parse().map_err(E::custom) 31 } 32 } 33 34 impl<'de> de::Deserialize<'de> for NaiveTime { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: de::Deserializer<'de>,35 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 36 where 37 D: de::Deserializer<'de>, 38 { 39 deserializer.deserialize_str(NaiveTimeVisitor) 40 } 41 } 42 43 #[cfg(test)] 44 mod tests { 45 use crate::NaiveTime; 46 47 #[test] test_serde_serialize()48 fn test_serde_serialize() { 49 assert_eq!( 50 serde_json::to_string(&NaiveTime::from_hms_opt(0, 0, 0).unwrap()).ok(), 51 Some(r#""00:00:00""#.into()) 52 ); 53 assert_eq!( 54 serde_json::to_string(&NaiveTime::from_hms_milli_opt(0, 0, 0, 950).unwrap()).ok(), 55 Some(r#""00:00:00.950""#.into()) 56 ); 57 assert_eq!( 58 serde_json::to_string(&NaiveTime::from_hms_milli_opt(0, 0, 59, 1_000).unwrap()).ok(), 59 Some(r#""00:00:60""#.into()) 60 ); 61 assert_eq!( 62 serde_json::to_string(&NaiveTime::from_hms_opt(0, 1, 2).unwrap()).ok(), 63 Some(r#""00:01:02""#.into()) 64 ); 65 assert_eq!( 66 serde_json::to_string(&NaiveTime::from_hms_nano_opt(3, 5, 7, 98765432).unwrap()).ok(), 67 Some(r#""03:05:07.098765432""#.into()) 68 ); 69 assert_eq!( 70 serde_json::to_string(&NaiveTime::from_hms_opt(7, 8, 9).unwrap()).ok(), 71 Some(r#""07:08:09""#.into()) 72 ); 73 assert_eq!( 74 serde_json::to_string(&NaiveTime::from_hms_micro_opt(12, 34, 56, 789).unwrap()).ok(), 75 Some(r#""12:34:56.000789""#.into()) 76 ); 77 let leap = NaiveTime::from_hms_nano_opt(23, 59, 59, 1_999_999_999).unwrap(); 78 assert_eq!(serde_json::to_string(&leap).ok(), Some(r#""23:59:60.999999999""#.into())); 79 } 80 81 #[test] test_serde_deserialize()82 fn test_serde_deserialize() { 83 let from_str = serde_json::from_str::<NaiveTime>; 84 85 assert_eq!(from_str(r#""00:00:00""#).ok(), Some(NaiveTime::from_hms_opt(0, 0, 0).unwrap())); 86 assert_eq!(from_str(r#""0:0:0""#).ok(), Some(NaiveTime::from_hms_opt(0, 0, 0).unwrap())); 87 assert_eq!( 88 from_str(r#""00:00:00.950""#).ok(), 89 Some(NaiveTime::from_hms_milli_opt(0, 0, 0, 950).unwrap()) 90 ); 91 assert_eq!( 92 from_str(r#""0:0:0.95""#).ok(), 93 Some(NaiveTime::from_hms_milli_opt(0, 0, 0, 950).unwrap()) 94 ); 95 assert_eq!( 96 from_str(r#""00:00:60""#).ok(), 97 Some(NaiveTime::from_hms_milli_opt(0, 0, 59, 1_000).unwrap()) 98 ); 99 assert_eq!(from_str(r#""00:01:02""#).ok(), Some(NaiveTime::from_hms_opt(0, 1, 2).unwrap())); 100 assert_eq!( 101 from_str(r#""03:05:07.098765432""#).ok(), 102 Some(NaiveTime::from_hms_nano_opt(3, 5, 7, 98765432).unwrap()) 103 ); 104 assert_eq!(from_str(r#""07:08:09""#).ok(), Some(NaiveTime::from_hms_opt(7, 8, 9).unwrap())); 105 assert_eq!( 106 from_str(r#""12:34:56.000789""#).ok(), 107 Some(NaiveTime::from_hms_micro_opt(12, 34, 56, 789).unwrap()) 108 ); 109 assert_eq!( 110 from_str(r#""23:59:60.999999999""#).ok(), 111 Some(NaiveTime::from_hms_nano_opt(23, 59, 59, 1_999_999_999).unwrap()) 112 ); 113 assert_eq!( 114 from_str(r#""23:59:60.9999999999997""#).ok(), // excess digits are ignored 115 Some(NaiveTime::from_hms_nano_opt(23, 59, 59, 1_999_999_999).unwrap()) 116 ); 117 118 // bad formats 119 assert!(from_str(r#""""#).is_err()); 120 assert!(from_str(r#""000000""#).is_err()); 121 assert!(from_str(r#""00:00:61""#).is_err()); 122 assert!(from_str(r#""00:60:00""#).is_err()); 123 assert!(from_str(r#""24:00:00""#).is_err()); 124 assert!(from_str(r#""23:59:59,1""#).is_err()); 125 assert!(from_str(r#""012:34:56""#).is_err()); 126 assert!(from_str(r#""hh:mm:ss""#).is_err()); 127 assert!(from_str(r#"0"#).is_err()); 128 assert!(from_str(r#"86399"#).is_err()); 129 assert!(from_str(r#"{}"#).is_err()); 130 } 131 132 #[test] test_serde_bincode()133 fn test_serde_bincode() { 134 // Bincode is relevant to test separately from JSON because 135 // it is not self-describing. 136 use bincode::{deserialize, serialize}; 137 138 let t = NaiveTime::from_hms_nano_opt(3, 5, 7, 98765432).unwrap(); 139 let encoded = serialize(&t).unwrap(); 140 let decoded: NaiveTime = deserialize(&encoded).unwrap(); 141 assert_eq!(t, decoded); 142 } 143 } 144