diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bc4edd..8b10b70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] -... +### Changed +- [breaking-change] Return `Error::InvalidDeviceState` if it was not possible to read the + date and/or time from the device because the state of the device corresponds to + an invalid date and/or time. ## [0.3.2] - 2021-02-22 diff --git a/src/ds323x/datetime.rs b/src/ds323x/datetime.rs index 2f7a902..acbd79d 100644 --- a/src/ds323x/datetime.rs +++ b/src/ds323x/datetime.rs @@ -1,6 +1,8 @@ //! Common implementation -use super::{decimal_to_packed_bcd, hours_to_register, packed_bcd_to_decimal}; +use super::{ + decimal_to_packed_bcd, hours_to_register, packed_bcd_to_decimal, some_or_invalid_error, +}; use crate::{ interface::{ReadData, WriteData}, BitFlags, Datelike, Ds323x, Error, Hours, NaiveDate, NaiveDateTime, NaiveTime, Register, Rtcc, @@ -33,11 +35,8 @@ where let minute = packed_bcd_to_decimal(data[Register::MINUTES as usize + 1]); let second = packed_bcd_to_decimal(data[Register::SECONDS as usize + 1]); - Ok(NaiveTime::from_hms( - get_h24(hour).into(), - minute.into(), - second.into(), - )) + let time = NaiveTime::from_hms_opt(get_h24(hour).into(), minute.into(), second.into()); + some_or_invalid_error(time) } fn get_weekday(&mut self) -> Result { @@ -74,7 +73,8 @@ where let month = packed_bcd_to_decimal(data[Register::MONTH as usize + 1 - offset] & !BitFlags::CENTURY); let day = packed_bcd_to_decimal(data[Register::DOM as usize + 1 - offset]); - Ok(NaiveDate::from_ymd(year.into(), month.into(), day.into())) + let date = NaiveDate::from_ymd_opt(year.into(), month.into(), day.into()); + some_or_invalid_error(date) } fn get_datetime(&mut self) -> Result { @@ -91,13 +91,10 @@ where let minute = packed_bcd_to_decimal(data[Register::MINUTES as usize + 1]); let second = packed_bcd_to_decimal(data[Register::SECONDS as usize + 1]); - Ok( - rtcc::NaiveDate::from_ymd(year.into(), month.into(), day.into()).and_hms( - get_h24(hour).into(), - minute.into(), - second.into(), - ), - ) + let date = NaiveDate::from_ymd_opt(year.into(), month.into(), day.into()); + let date = some_or_invalid_error(date)?; + let datetime = date.and_hms_opt(get_h24(hour).into(), minute.into(), second.into()); + some_or_invalid_error(datetime) } fn set_seconds(&mut self, seconds: u8) -> Result<(), Self::Error> { diff --git a/src/ds323x/mod.rs b/src/ds323x/mod.rs index 1a8ea3c..b0c7729 100644 --- a/src/ds323x/mod.rs +++ b/src/ds323x/mod.rs @@ -28,10 +28,34 @@ fn hours_to_register(hours: Hours) -> Result } } +fn some_or_invalid_error(data: Option) -> Result> { + if let Some(data) = data { + Ok(data) + } else { + Err(Error::InvalidDeviceState) + } +} + #[cfg(test)] mod tests { use super::*; + #[test] + fn if_some_then_get_inner() { + match some_or_invalid_error::(Some(1)) { + Ok(1) => (), + _ => panic!(), + } + } + + #[test] + fn if_none_then_error() { + match some_or_invalid_error::(None) { + Err(Error::InvalidDeviceState) => (), + _ => panic!(), + } + } + #[test] fn can_convert_packed_bcd_to_decimal() { assert_eq!(0, packed_bcd_to_decimal(0b0000_0000)); diff --git a/src/lib.rs b/src/lib.rs index 90c61ce..ad2c580 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -408,6 +408,11 @@ pub enum Error { Pin(PinE), /// Invalid input data provided InvalidInputData, + /// Internal device state is invalid. + /// + /// It was not possible to read a valid date and/or time. + /// The device is probably missing initialization. + InvalidDeviceState, } /// Square-wave output frequency