ethanlin01x commented on code in PR #3891: URL: https://github.com/apache/iggy/pull/3891#discussion_r3821852262
########## core/common/src/utils/non_zero_duration.rs: ########## @@ -0,0 +1,255 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use crate::IggyDuration; +use serde::de::{Error as DeError, Visitor}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::{ + error::Error, + fmt::{Display, Formatter}, + str::FromStr, + time::Duration, +}; + +/// A duration that is guaranteed to be greater than zero. +/// +/// Intervals that pace a loop - heartbeats, reconnection and retry delays - turn into +/// a busy loop or a `tokio::time::interval` panic when they are zero. Such fields hold +/// this type so the zero is rejected where the value is built, not where it is awaited. +/// +/// `IggyDuration::from_str` maps `0`, `none`, `disabled` and `unlimited` to the same +/// zero, so all four are rejected here. +/// +/// # Example +/// +/// ``` +/// use iggy_common::{IggyDuration, NonZeroIggyDuration, NonZeroDurationError}; +/// use std::str::FromStr; +/// +/// let interval = NonZeroIggyDuration::from_str("1s").unwrap(); +/// assert_eq!(1, interval.as_secs()); +/// assert_eq!("1s", format!("{}", interval)); +/// +/// assert_eq!(Err(NonZeroDurationError::Zero), NonZeroIggyDuration::from_str("none")); +/// assert_eq!( +/// Err(NonZeroDurationError::Zero), +/// NonZeroIggyDuration::try_from(IggyDuration::from(0_u64)), +/// ); +/// ``` +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub struct NonZeroIggyDuration { + duration: IggyDuration, +} + +/// The reason a value could not become a `NonZeroIggyDuration`. +#[derive(Debug, Clone, PartialEq)] +pub enum NonZeroDurationError { + /// The value parsed or converted to zero. + Zero, + /// The text is not a duration `humantime` understands. + InvalidFormat(humantime::DurationError), +} + +impl NonZeroIggyDuration { + pub const ONE_SECOND: NonZeroIggyDuration = NonZeroIggyDuration { + duration: IggyDuration::ONE_SECOND, + }; + + pub fn get(&self) -> IggyDuration { + self.duration + } + + pub fn get_duration(&self) -> Duration { + self.duration.get_duration() + } + + pub fn as_human_time_string(&self) -> String { + self.duration.as_human_time_string() + } + + pub fn as_secs(&self) -> u32 { + self.duration.as_secs() + } + + pub fn as_micros(&self) -> u64 { + self.duration.as_micros() + } +} + +impl Display for NonZeroDurationError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + NonZeroDurationError::Zero => write!(f, "duration must be greater than zero"), + NonZeroDurationError::InvalidFormat(error) => write!(f, "invalid duration: {error}"), + } + } +} + +impl Error for NonZeroDurationError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + NonZeroDurationError::Zero => None, + NonZeroDurationError::InvalidFormat(error) => Some(error), + } + } +} + +impl From<humantime::DurationError> for NonZeroDurationError { + fn from(error: humantime::DurationError) -> Self { + NonZeroDurationError::InvalidFormat(error) + } +} + +impl TryFrom<IggyDuration> for NonZeroIggyDuration { Review Comment: Added in 71f3484 -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
