parent
eeea6a13b1
commit
1212bfdb12
@ -0,0 +1,65 @@
|
||||
use super::*;
|
||||
use std::collections::HashMap;
|
||||
use tokio::time::{
|
||||
DelayQueue,
|
||||
delay_queue,
|
||||
};
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Cache
|
||||
{
|
||||
//TODO: HashMap and DelayQueue of mapping public keys to user IDs, etc.
|
||||
pkey_maps: HashMap<String, (UserID, delay_queue::Key)>,
|
||||
pkey_rems: DelayQueue<String>,
|
||||
}
|
||||
|
||||
impl Cache
|
||||
{
|
||||
/// Create a new empty cache
|
||||
pub fn new() -> Self
|
||||
{
|
||||
Self {
|
||||
pkey_maps: HashMap::new(),
|
||||
pkey_rems: DelayQueue::new(),
|
||||
}
|
||||
}
|
||||
|
||||
//how tf do we get this to run concurrently with insertions??? it holds `&mut self` forever!
|
||||
//redesign required. maybe using Arc and RwLock or Mutex and interrupting the purge task when something needs to be inserted. i.e: give this task a stream that it can `select!` along with calling `next()`, if the other future completes first, we return? but wouldn't that lose us an item in `next()`? is there a `select with priority` in `futures`? i think there is. eh...
|
||||
/// Run a purge on this cache.
|
||||
pub async fn purge(&mut self) -> eyre::Result<()>
|
||||
{
|
||||
let mut errors = Vec::default();
|
||||
while let Some(entry) = self.pkey_rems.next().await
|
||||
{
|
||||
match entry {
|
||||
Ok(entry) => {
|
||||
self.pkey_maps.remove(entry.get_ref());
|
||||
},
|
||||
Err(err) => {
|
||||
errors.push(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
if errors.len() > 0 {
|
||||
let mut err = Err(eyre!("One or more removals failed"))
|
||||
.with_note(|| errors.len().to_string().header("Number of failed removals"));
|
||||
for e in errors.into_iter()
|
||||
{
|
||||
err = err.with_error(move || e);
|
||||
}
|
||||
return err;
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
/// Purge all values available to be purged now.
|
||||
pub fn purge_now(&mut self) -> eyre::Result<()>
|
||||
{
|
||||
match self.purge().now_or_never() {
|
||||
Some(x) => x,
|
||||
None => Ok(())
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,207 @@
|
||||
use std::fmt;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
/// Represents a semver version number of the order `major.minor.bugfix`.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] //TODO: Make these impls instead of derives, because safe packed borrows.
|
||||
#[repr(C, packed)]
|
||||
pub struct Version(u8,u8,u16);
|
||||
|
||||
impl fmt::Display for Version
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
|
||||
{
|
||||
write!(f, "{}.{}.{}", self.major(), self.minor(), self.bugfix())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Version
|
||||
{
|
||||
#[inline] fn from(from: u32) -> Self
|
||||
{
|
||||
Self::from_u32(from)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Version> for u32
|
||||
{
|
||||
fn from(from: Version) -> Self
|
||||
{
|
||||
from.to_u32()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Version> for u32
|
||||
{
|
||||
#[inline] fn eq(&self, other: &Version) -> bool
|
||||
{
|
||||
*self == other.to_u32()
|
||||
}
|
||||
}
|
||||
impl PartialEq<u32> for Version
|
||||
{
|
||||
#[inline] fn eq(&self, other: &u32) -> bool
|
||||
{
|
||||
self.to_u32() == *other
|
||||
}
|
||||
}
|
||||
impl PartialOrd<u32> for Version
|
||||
{
|
||||
#[inline] fn partial_cmp(&self, other: &u32) -> Option<Ordering> {
|
||||
self.to_u32().partial_cmp(other)
|
||||
}
|
||||
}
|
||||
impl PartialOrd<Version> for u32
|
||||
{
|
||||
#[inline] fn partial_cmp(&self, other: &Version) -> Option<Ordering> {
|
||||
self.partial_cmp(&other.to_u32())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<()> for Version
|
||||
{
|
||||
#[inline] fn from(from: ()) -> Self
|
||||
{
|
||||
Self(0,0,0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<(usize,)> for Version
|
||||
{
|
||||
#[inline] fn from(from: (usize,)) -> Self
|
||||
{
|
||||
Self::new(from.0,0,0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<(usize, usize)> for Version
|
||||
{
|
||||
#[inline] fn from((ma, mi): (usize, usize)) -> Self
|
||||
{
|
||||
Self::new(ma, mi, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl From<(usize, usize, usize)> for Version
|
||||
{
|
||||
#[inline] fn from((ma,mi,bu): (usize, usize, usize)) -> Self
|
||||
{
|
||||
Self::new(ma,mi,bu)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(u8, u8, u16)> for Version
|
||||
{
|
||||
#[inline] fn from((ma, mi, bu): (u8, u8, u16)) -> Self
|
||||
{
|
||||
Self(ma,mi,bu)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Version> for (u8, u8, u16)
|
||||
{
|
||||
#[inline] fn from(from: Version) -> Self
|
||||
{
|
||||
(from.0, from.1, from.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Version> for (usize, usize, usize)
|
||||
{
|
||||
#[inline] fn from(from: Version) -> Self
|
||||
{
|
||||
(from.major(), from.minor(), from.bugfix())
|
||||
}
|
||||
}
|
||||
|
||||
impl Version
|
||||
{
|
||||
/// The major component of this `Version`.
|
||||
#[inline] pub const fn major(self) -> usize
|
||||
{
|
||||
self.0 as usize
|
||||
}
|
||||
/// The minor component of this `Version`.
|
||||
#[inline] pub const fn minor(self) -> usize
|
||||
{
|
||||
self.1 as usize
|
||||
}
|
||||
/// The bugfix component of this `Version`.
|
||||
#[inline] pub const fn bugfix(self) -> usize
|
||||
{
|
||||
self.2 as usize
|
||||
}
|
||||
|
||||
/// Convert to a 32 bit integer representation
|
||||
#[inline] pub const fn to_u32(self) -> u32
|
||||
{
|
||||
let mb = self.2.to_be_bytes();
|
||||
u32::from_be_bytes([
|
||||
self.0,
|
||||
self.1,
|
||||
mb[0],
|
||||
mb[1],
|
||||
])
|
||||
}
|
||||
/// Convert to a 32 bit integer representation
|
||||
#[inline] pub const fn from_u32(from: u32) -> Self
|
||||
{
|
||||
let bytes = from.to_be_bytes();
|
||||
Self(
|
||||
bytes[0],
|
||||
bytes[1],
|
||||
u16::from_be_bytes([bytes[2], bytes[3]]),
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new version object
|
||||
#[inline] pub const fn new_exact(major: u8, minor: u8, bugfix: u16) -> Self
|
||||
{
|
||||
Self(major,minor,bugfix)
|
||||
}
|
||||
|
||||
/// Create a new version object
|
||||
///
|
||||
/// # Panics
|
||||
/// If any of the components do not fit within their bounds.
|
||||
#[inline] pub fn new(major: usize, minor: usize, bugfix: usize) -> Self
|
||||
{
|
||||
use std::convert::TryInto;
|
||||
Self::new_exact(major.try_into().expect("Major exceeded limit of u8"),
|
||||
minor.try_into().expect("Minor exceeded limit of u8"),
|
||||
bugfix.try_into().expect("Bugfix exceeded limit of u16"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export] macro_rules! version {
|
||||
($maj:expr, $min:expr, $bfx:expr) => ($crate::version::Version::new_exact($maj as u8, $min as u8, $bfx as u16));
|
||||
($maj:expr, $min:expr) => ($crate::version::Version::new_exact($maj as u8, $min as u8, 0));
|
||||
($maj:expr) => ($crate::version::Version::new_exact($maj as u8, 0, 0));
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests
|
||||
{
|
||||
use super::*;
|
||||
#[test]
|
||||
fn ordinal()
|
||||
{
|
||||
assert!( version!(1) > version!(0, 9, 1));
|
||||
assert!( version!(2) > version!(1, 9, 300));
|
||||
assert!( (version!(1)..version!(1, 9)).contains(&version!(1, 8)));
|
||||
assert!( !(version!(1)..version!(2)).contains(&version!(2, 10, 432)));
|
||||
|
||||
println!("{}: {}", version!(1), version!(1).to_u32());
|
||||
println!("{}: {}", version!(0,9,1), version!(0,9,1).to_u32());
|
||||
|
||||
assert!( version!(1).to_u32() > version!(0, 9, 1).to_u32());
|
||||
assert!( version!(2).to_u32() > version!(1, 9, 300).to_u32());
|
||||
assert!( (version!(1).to_u32()..version!(1, 9).to_u32()).contains(&version!(1, 8).to_u32()));
|
||||
assert!( !(version!(1).to_u32()..version!(2).to_u32()).contains(&version!(2, 10, 432).to_u32()));
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in new issue