1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
#![cfg_attr(feature = "dev", allow(unstable_features))] #![cfg_attr(feature = "dev", feature(plugin))] #![cfg_attr(feature = "dev", plugin(clippy))] use std::time::{Duration, Instant}; use std::thread::sleep; pub struct Lim { last: Instant, npi: u64, } fn ips2npi(ips: u64) -> u64 { if ips > 0 { (1000.0*1000.0*1000.0 / ips as f64) as u64 } else { 0 } } impl Lim { pub fn new(ips: u64) -> Lim { Lim { last: Instant::now(), npi: ips2npi(ips), } } pub fn limit(&mut self) { let left = Instant::now() - self.last; let nanoleft = left.as_secs() * 1000*1000*1000 + left.subsec_nanos() as u64; if self.npi > nanoleft { let sleeptime = self.npi - nanoleft; let sleeptime = Duration::new(sleeptime / 1000000000, (sleeptime % 1000000000) as u32); sleep(sleeptime); } self.last = Instant::now(); } } #[cfg(test)] mod tests { use super::Lim; use std::time::Instant; #[test] fn basic() { let mut lim = Lim::new(15); let begin = Instant::now(); for _ in 0..60 { lim.limit(); } let end = Instant::now(); let elaps = end - begin; assert!(elaps.as_secs() >= 3); assert!(elaps.as_secs() <= 5); } #[test] fn edge() { let mut lim = Lim::new(0); let begin = Instant::now(); for _ in 0..60 { lim.limit(); } let end = Instant::now(); let elaps = end - begin; assert!(elaps.as_secs() <= 0); } }