<commit_before>use crate::algo::{
    deserialize, serialize, DefaultUComputer, LoginResult, ServerHandshake, UComputer, SRP,
};
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::marker::PhantomData;

use rand;
use rand::Rng;

use crate::communication::Communicate;

use failure::{err_msg, Error};

use bignum::NumBigInt as BigNum;

struct SimplifiedUComputer;

impl UComputer for SimplifiedUComputer {
    fn compute_u<T: Communicate>(_: &BigNum, _: &BigNum, stream: &mut T) -> Result<BigNum, Error> {
        let mut rng = rand::thread_rng();
        let u: Vec<u8> = rng.gen_iter::<u8>().take(128).collect();
        stream.send(&u)?;
        Ok(deserialize(&u))
    }
}

struct ServerBase<U: UComputer> {
    params: SRP,
    user_database: HashMap<Vec<u8>, (Vec<u8>, BigNum)>,
    computer: PhantomData<U>,
}

impl<U: UComputer> ServerBase<U> {
    fn new(params: SRP) -> Self {
        ServerBase {
            params,
            user_database: HashMap::new(),
            computer: PhantomData,
        }
    }

    fn handle_client<T: Communicate>(&mut self, stream: &mut T) -> Result<(), Error> {
        let user_name = stream.receive()?.ok_or_else(|| err_msg("user name"))?;

        // TODO Rewrite once NLL has landed
        match self.user_database.entry(user_name) {
            Entry::Occupied(o) => Self::authenticate_client(&self.params, stream, o.get()),
            Entry::Vacant(v) => {
                let password = stream.receive()?.ok_or_else(|| err_msg("password"))?;
                v.insert(self.params.password_to_verifier(&password));
                Ok(())
            }
        }
    }

    fn authenticate_client<T: Communicate>(
        params: &SRP,
        stream: &mut T,
        &(ref salt, ref v): &(Vec<u8>, BigNum),
    ) -> Result<(), Error> {
        let state = ServerHandshake::new(params, salt, v);
        let A = deserialize(&stream.receive()?.ok_or_else(|| err_msg("A"))?);
        let B = state.B();
        stream.send(salt)?;
        stream.send(&serialize(B))?;
        let u = U::compute_u::<T>(&A, &B, stream)?;
        let server_secret = state.compute_hashed_secret(&A, &u);
        let client_secret = stream.receive()?.ok_or_else(|| err_msg("client secret"))?;

        let login_result = if server_secret == client_secret {
            LoginResult::Success
        } else {
            LoginResult::Failure
        };
        stream.send(&[login_result as u8])?;
        Ok(())
    }
}

pub trait ClientHandler: Send + 'static {
    fn handle_client<T: Communicate>(&mut self, stream: &mut T) -> Result<(), Error>;
}

pub struct Server {
    base: ServerBase<DefaultUComputer>,
}

impl Default for Server {
    fn default() -> Self {
        Server {
            base: ServerBase::new(SRP::default()),
        }
    }
}

impl ClientHandler for Server {
    fn handle_client<T: Communicate>(&mut self, stream: &mut T) -> Result<(), Error> {
        self.base.handle_client(stream)
    }
}

pub struct SimplifiedServer {
    base: ServerBase<SimplifiedUComputer>,
}

impl Default for SimplifiedServer {
    fn default() -> Self {
        SimplifiedServer {
            base: ServerBase::new(SRP::new_with_k(0)),
        }
    }
}

impl ClientHandler for SimplifiedServer {
    fn handle_client<T: Communicate>(&mut self, stream: &mut T) -> Result<(), Error> {
        self.base.handle_client(stream)
    }
}
<commit_msg>Make first use of NLL :)<commit_after>use crate::algo::{
    deserialize, serialize, DefaultUComputer, LoginResult, ServerHandshake, UComputer, SRP,
};
use std::collections::HashMap;
use std::marker::PhantomData;

use rand;
use rand::Rng;

use crate::communication::Communicate;

use failure::{err_msg, Error};

use bignum::NumBigInt as BigNum;

struct SimplifiedUComputer;

impl UComputer for SimplifiedUComputer {
    fn compute_u<T: Communicate>(_: &BigNum, _: &BigNum, stream: &mut T) -> Result<BigNum, Error> {
        let mut rng = rand::thread_rng();
        let u: Vec<u8> = rng.gen_iter::<u8>().take(128).collect();
        stream.send(&u)?;
        Ok(deserialize(&u))
    }
}

struct ServerBase<U: UComputer> {
    params: SRP,
    user_database: HashMap<Vec<u8>, (Vec<u8>, BigNum)>,
    computer: PhantomData<U>,
}

impl<U: UComputer> ServerBase<U> {
    fn new(params: SRP) -> Self {
        ServerBase {
            params,
            user_database: HashMap::new(),
            computer: PhantomData,
        }
    }

    fn handle_client<T: Communicate>(&mut self, stream: &mut T) -> Result<(), Error> {
        let user_name = stream.receive()?.ok_or_else(|| err_msg("user name"))?;

        match self.user_database.get(&user_name) {
            Some(user_data) => Self::authenticate_client(&self.params, stream, user_data),
            None => {
                let password = stream.receive()?.ok_or_else(|| err_msg("password"))?;
                let user_data = self.params.password_to_verifier(&password);
                self.user_database.insert(user_name, user_data);
                Ok(())
            }
        }
    }

    fn authenticate_client<T: Communicate>(
        params: &SRP,
        stream: &mut T,
        &(ref salt, ref v): &(Vec<u8>, BigNum),
    ) -> Result<(), Error> {
        let state = ServerHandshake::new(params, salt, v);
        let A = deserialize(&stream.receive()?.ok_or_else(|| err_msg("A"))?);
        let B = state.B();
        stream.send(salt)?;
        stream.send(&serialize(B))?;
        let u = U::compute_u::<T>(&A, &B, stream)?;
        let server_secret = state.compute_hashed_secret(&A, &u);
        let client_secret = stream.receive()?.ok_or_else(|| err_msg("client secret"))?;

        let login_result = if server_secret == client_secret {
            LoginResult::Success
        } else {
            LoginResult::Failure
        };
        stream.send(&[login_result as u8])?;
        Ok(())
    }
}

pub trait ClientHandler: Send + 'static {
    fn handle_client<T: Communicate>(&mut self, stream: &mut T) -> Result<(), Error>;
}

pub struct Server {
    base: ServerBase<DefaultUComputer>,
}

impl Default for Server {
    fn default() -> Self {
        Server {
            base: ServerBase::new(SRP::default()),
        }
    }
}

impl ClientHandler for Server {
    fn handle_client<T: Communicate>(&mut self, stream: &mut T) -> Result<(), Error> {
        self.base.handle_client(stream)
    }
}

pub struct SimplifiedServer {
    base: ServerBase<SimplifiedUComputer>,
}

impl Default for SimplifiedServer {
    fn default() -> Self {
        SimplifiedServer {
            base: ServerBase::new(SRP::new_with_k(0)),
        }
    }
}

impl ClientHandler for SimplifiedServer {
    fn handle_client<T: Communicate>(&mut self, stream: &mut T) -> Result<(), Error> {
        self.base.handle_client(stream)
    }
}

{'fraction_non_alphanumeric': 0.15037483463178009, 'fraction_numerical': 0.0029398794649419372, 'mean_word_length': 2.7842046718576197, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '304119', 'n_tokens_mistral': 2233, 'n_tokens_neox': 2198, 'n_words': 479}