Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use byteorder::{ReadBytesExt, WriteBytesExt, LE};
- use crc::{crc64,Hasher64};
- use rand::{Rng, SeedableRng};
- use rand_chacha::ChaChaRng;
- use std::io::{self, Read, Write};
- use std::hash::Hasher;
- #[derive(Debug)]
- pub struct EncodedString<F>
- where
- F: FnMut(u64, &mut [u8]) -> (),
- {
- seed: u64,
- length: u64,
- check : u64,
- data: Vec<u8>,
- encode_function: F,
- }
- impl<F> EncodedString<F>
- where
- F: FnMut(u64, &mut [u8]) -> (),
- {
- pub fn new(source: String, mut encode_function: F) -> Self {
- let seed = rand::random();
- let mut data = source.into_bytes();
- encode_function(seed, &mut data);
- let check = Self::generate_crc(seed, &data);
- EncodedString {
- seed,
- length: (data.len() as u64) ^ seed ^ 0x32DF9B0617010FED,
- check,
- data,
- encode_function,
- }
- }
- pub fn decode(mut self) -> Result<String, std::string::FromUtf8Error> {
- (self.encode_function)(self.seed, &mut self.data); // Decoding is the same as encoding
- String::from_utf8(self.data)
- }
- pub fn write<T>(&self, writer: &mut T) -> io::Result<()>
- where
- T: Write,
- {
- writer.write_u64::<LE>(self.seed)?;
- writer.write_u64::<LE>(self.length)?;
- writer.write_u64::<LE>(Self::generate_crc(self.seed, &self.data))?;
- writer.write_all(&self.data)
- }
- pub fn read<T>(reader: &mut T, encode_function: F) -> io::Result<Self>
- where
- T: Read,
- {
- let seed = reader.read_u64::<LE>()?;
- let length = reader.read_u64::<LE>()? ^ seed ^ 0x32DF9B0617010FED;
- let check = reader.read_u64::<LE>()?;
- let mut data = vec![0; length as usize];
- reader.read_exact(&mut data)?;
- if check == Self::generate_crc(seed, &data){
- Ok(EncodedString {
- seed,
- length,
- check,
- data,
- encode_function,
- })
- }
- else{
- Err(io::Error::new(io::ErrorKind::Other,"Data is corrupt"))
- }
- }
- #[inline]
- fn generate_crc(seed : u64, data : &[u8]) -> u64{
- let mut check = crc64::Digest::new(crc64::ECMA);
- check.write_u64(seed);
- check.write_u64(data.len() as u64);
- Hasher::write(&mut check, data);
- check.sum64()
- }
- }
- fn generic_encode<F>(data: &mut [u8], mut generator: F)
- where
- F: FnMut() -> u8,
- {
- for n in data {
- *n ^= generator();
- }
- }
- pub fn random_encode(seed: u64, data: &mut [u8]) {
- let mut rng = ChaChaRng::seed_from_u64(seed);
- generic_encode(data, || rng.gen());
- }
Add Comment
Please, Sign In to add comment