urandom 0.2.2

Produce and consume randomness, to convert them to useful types and distributions, and some randomness-related algorithms.
Documentation
use core::fmt;

const CONSTANT: [u32; 4] = [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574];

#[derive(Clone)]
#[repr(C)]
pub struct ChaChaCore {
	seed: [u32; 8],
	counter: [u32; 2],
	stream: [u32; 2],
}

unsafe impl dataview::Pod for ChaChaCore {}

impl ChaChaCore {
	#[inline]
	pub fn new(seed: [u32; 8], counter: u64, stream: u64) -> ChaChaCore {
		ChaChaCore {
			seed,
			counter: [counter as u32, (counter >> 32) as u32],
			stream: [stream as u32, (stream >> 32) as u32],
		}
	}
	#[inline]
	pub fn get_state(&self) -> [[u32; 4]; 4] {
		[
			CONSTANT,
			[self.seed[0], self.seed[1], self.seed[2], self.seed[3]],
			[self.seed[4], self.seed[5], self.seed[6], self.seed[7]],
			[self.counter[0], self.counter[1], self.stream[0], self.stream[1]],
		]
	}
	#[inline]
	pub fn get_counter(&self) -> u64 {
		(self.counter[1] as u64) << 32 | self.counter[0] as u64
	}
	#[inline]
	pub fn set_counter(&mut self, counter: u64) {
		self.counter[0] = counter as u32;
		self.counter[1] = (counter >> 32) as u32;
	}
	#[inline]
	pub fn add_counter(&self, counter: u64) -> ChaChaCore {
		let mut this = self.clone();
		this.set_counter(self.get_counter().wrapping_add(counter));
		this
	}
	#[inline]
	pub fn get_stream(&self) -> u64 {
		(self.stream[1] as u64) << 32 | self.stream[0] as u64
	}
	#[inline]
	pub fn set_stream(&mut self, stream: u64) {
		self.stream[0] = stream as u32;
		self.stream[1] = (stream >> 32) as u32;
	}
}

impl fmt::Debug for ChaChaCore {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		f.debug_struct("ChaChaCore")
			.field("seed", &format_args!("{:x?}", self.seed))
			.field("counter", &self.get_counter())
			.field("stream", &self.get_stream())
			.finish()
	}
}

#[cfg(feature = "serde")]
impl serde::Serialize for ChaChaCore {
	fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
		[
			self.seed[0], self.seed[1], self.seed[2], self.seed[3],
			self.seed[4], self.seed[5], self.seed[6], self.seed[7],
			self.counter[0], self.counter[1], self.stream[0], self.stream[1],
		].serialize(serializer)
	}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for ChaChaCore {
	fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
		let values = <[u32; 12]>::deserialize(deserializer)?;
		Ok(ChaChaCore {
			seed: [values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7]],
			counter: [values[8], values[9]],
			stream: [values[10], values[11]],
		})
	}
}