rl-core 1.18.0

Core logic for a token-bucket rate-limiter.
Documentation
fn is_default(v: &(impl Default + PartialEq)) -> bool {
	v == &Default::default()
}

#[derive(Debug)]
#[derive(serde::Deserialize,serde::Serialize)]
struct Serialized<T> {
	#[serde(rename="s")]
	#[serde(skip_serializing_if="Option::is_none")]
	empty_at: Option<T>,

	#[serde(rename="o")]
	#[serde(default)]
	#[serde(skip_serializing_if="is_default")]
	overfull: u32,

	#[serde(rename="u")]
	#[serde(default)]
	#[serde(skip_serializing_if="is_default")]
	unlimited: bool,
}

impl<T: crate::TimeSerde> serde::Serialize for crate::Tracker<T> {
	fn serialize<S: serde::Serializer>(&self, serializer: S)
	-> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error> {
		match self {
			crate::Tracker::Filling{empty_at} => {
				Serialized{
					empty_at: Some(empty_at.serialize()),
					overfull: 0,
					unlimited: false,
				}.serialize(serializer)
			}
			crate::Tracker::Full{overfull} => {
				Serialized{
					empty_at: None::<T::Ser<'_>>,
					overfull: *overfull,
					unlimited: false,
				}.serialize(serializer)
			}
			crate::Tracker::Unlimited => {
				Serialized{
					empty_at: None::<T::Ser<'_>>,
					overfull: 0,
					unlimited: true,
				}.serialize(serializer)
			}
		}
	}
}

impl<'de, T: crate::TimeSerde> serde::Deserialize<'de> for crate::Tracker<T> {
	fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, <D as serde::Deserializer<'de>>::Error> {
		let Serialized{
			empty_at,
			overfull,
			unlimited,
		} = serde::Deserialize::deserialize(deserializer)?;

		Ok(if let Some(empty_at) = empty_at {
			crate::Tracker::Filling{
				empty_at: T::deserialize(empty_at),
			}
		} else if unlimited {
			crate::Tracker::Unlimited
		} else {
			crate::Tracker::Full{
				overfull
			}
		})
	}
}