use std::io;
use std::time;
extern crate byteorder;
extern crate rand;
use byteorder::{ReadBytesExt, WriteBytesExt};
mod errors;
pub use errors::*;
pub fn gen<R: rand::Rng>(rng: &mut R) -> Result<i64, IdError> {
let now = match time::SystemTime::now().duration_since(time::UNIX_EPOCH) {
Ok(v) => v,
Err(e) => return Err(IdError::Time(e)),
};
let mut v_time_sec: Vec<u8> = Vec::with_capacity(8);
match v_time_sec.write_u64::<byteorder::BigEndian>(now.as_secs()) {
Ok(_) => (),
Err(e) => return Err(IdError::Io(e)),
}
let mut v_time_nsec: Vec<u8> = Vec::with_capacity(4);
match v_time_nsec.write_u32::<byteorder::BigEndian>(now.subsec_nanos()) {
Ok(_) => (),
Err(e) => return Err(IdError::Io(e)),
}
let mut v_rand: Vec<u8> = Vec::with_capacity(4);
match v_rand.write_u32::<byteorder::BigEndian>(rng.gen()) {
Ok(_) => (),
Err(e) => return Err(IdError::Io(e)),
}
let array: [u8; 8] = [v_time_sec[4],
v_time_sec[5],
v_time_sec[6],
v_time_sec[7],
v_time_nsec[0],
v_rand[0],
v_rand[1],
v_rand[2]];
let mut rd = io::Cursor::new(array);
match rd.read_i64::<byteorder::BigEndian>() {
Ok(v) => Ok(v),
Err(e) => return Err(IdError::Io(e)),
}
}
pub fn gen_timeid() -> Result<i64, IdError> {
let now = match time::UNIX_EPOCH.elapsed() {
Ok(v) => v,
Err(e) => return Err(IdError::Time(e)),
};
let mut v_time_sec: Vec<u8> = Vec::with_capacity(8);
match v_time_sec.write_u64::<byteorder::BigEndian>(now.as_secs()) {
Ok(_) => (),
Err(e) => return Err(IdError::Io(e)),
}
let mut v_time_nsec: Vec<u8> = Vec::with_capacity(4);
match v_time_nsec.write_u32::<byteorder::BigEndian>(now.subsec_nanos()) {
Ok(_) => (),
Err(e) => return Err(IdError::Io(e)),
}
let array: [u8; 8] = [v_time_sec[4],
v_time_sec[5],
v_time_sec[6],
v_time_sec[7],
v_time_nsec[0],
v_time_nsec[1],
v_time_nsec[2],
v_time_nsec[3]];
let mut rdr = io::Cursor::new(array);
match rdr.read_i64::<byteorder::BigEndian>() {
Ok(v) => Ok(v),
Err(e) => return Err(IdError::Io(e)),
}
}
pub struct Generator<T> {
rng: T,
}
impl<T: rand::Rng> Generator<T> {
pub fn new(rng: T) -> Generator<T> {
Generator { rng: rng }
}
}
impl<T: rand::Rng> Iterator for Generator<T> {
type Item = Result<i64, IdError>;
fn next(&mut self) -> Option<Result<i64, IdError>> {
match gen(&mut self.rng) {
Ok(v) => Some(Ok(v)),
Err(e) => Some(Err(e)),
}
}
}
pub struct TimeGenerator {}
impl Iterator for TimeGenerator {
type Item = Result<i64, IdError>;
fn next(&mut self) -> Option<Result<i64, IdError>> {
match gen_timeid() {
Ok(v) => Some(Ok(v)),
Err(e) => Some(Err(e)),
}
}
}
#[cfg(test)]
mod tests {
use std::time;
use byteorder::{BigEndian, WriteBytesExt};
use rand;
use super::*;
#[test]
fn check_bytes_time() {
let now = time::UNIX_EPOCH.elapsed().unwrap();
let mut v_time_sec: Vec<u8> = Vec::with_capacity(8);
v_time_sec.write_u64::<BigEndian>(now.as_secs()).unwrap();
assert_eq!(v_time_sec[3], 0);
}
#[test]
fn generators() {
let mut rng = rand::thread_rng();
let id = gen(&mut rng).unwrap();
assert!(id > 0);
let id = gen_timeid().unwrap();
assert!(id > 0);
}
#[test]
fn iterators() {
let mut rng = rand::thread_rng();
let mut gen = Generator::new(&mut rng);
let mut result: Result<i64, IdError>;
print!("\n== Generating Combids\n");
for _ in 0..5 {
result = gen.next().unwrap();
println!("{:?}", result);
}
print!("\n== Generating time ids\n");
let mut gen_time = TimeGenerator {};
for _ in 0..5 {
result = gen_time.next().unwrap();
println!("{:?}", result);
}
println!("");
}
}