<commit_before>use irc;
use matrix;
use irc::protocol::{Command,Message};
use mio;
use mio::{EventLoop,Handler,Token,EventSet,PollOpt,Sender};
use std::thread;
use std::collections::HashMap;

const CLIENT: Token = Token(0);

#[derive(Debug)]
pub enum Event {
    EndPoll,
    Matrix(matrix::events::Event)
}

pub struct Bridge {
    client: irc::streams::Client,
    matrix: matrix::client::Client,
    rooms: HashMap<matrix::events::RoomID, Room>,
    seen_events: Vec<matrix::events::EventID>,
}

impl Handler for Bridge {
    type Timeout = ();
    type Message = Event;

    fn ready(&mut self, event_loop: &mut EventLoop<Bridge>, token: Token, _: EventSet) {
        match token {
            CLIENT =>
                self.handle_client(event_loop),
            _ => unreachable!()
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Bridge>, msg: Self::Message) {
        match msg {
            Event::EndPoll => {
                self.poll_matrix(event_loop.channel());
            },
            Event::Matrix(e) =>
                self.handle_matrix(e)
        };
    }
}

unsafe impl Sync for Bridge{}

struct Room {
    id: matrix::events::RoomID,
    canonical_alias: Option<String>,
    join_rules: Option<String>,
    members: Vec<matrix::events::UserID>,
    pending_events: Vec<matrix::events::RoomEvent>
}

impl Room {
    fn new(id: matrix::events::RoomID) -> Self {
        Room {
            id: id,
            canonical_alias: None,
            join_rules: None,
            members: vec![],
            pending_events: vec![]
        }
    }

    fn run_pending<F>(&mut self, mut callback: &mut F)
            where F: FnMut(irc::protocol::Message) {
        while let Some(evt) = self.pending_events.pop() {
            self.handle_with_alias(evt, callback);
        }
    }

    fn handle_with_alias<F>(&mut self, evt: matrix::events::RoomEvent, mut callback: &mut F)
            where F: FnMut(irc::protocol::Message) {
        if self.canonical_alias != None {
            match evt {
                matrix::events::RoomEvent::Membership(user, matrix::events::MembershipAction::Join) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Join,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: None
                    });
                    self.members.push(user);
                },
                matrix::events::RoomEvent::Membership(user, matrix::events::MembershipAction::Leave) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Part,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: None
                    });
                    self.members.push(user);
                },
                matrix::events::RoomEvent::Membership(_, _) => (),
                matrix::events::RoomEvent::Message(user, text) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Privmsg,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: Some(text)
                    });
                },
                matrix::events::RoomEvent::Topic(user, topic) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}@{}", user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Topic,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: Some(topic.clone())
                    });
                },
                matrix::events::RoomEvent::CanonicalAlias(_) => unreachable!(),
                _ => {
                    warn!("Unhandled event {:?}", evt)
                }
            }
        } else {
            self.pending_events.push(evt);
        }
    }

    fn handle_event<F>(&mut self, evt: matrix::events::RoomEvent, mut callback: F)
            where F: FnMut(irc::protocol::Message) {
        match evt {
            matrix::events::RoomEvent::CanonicalAlias(name) => {
                let was_empty = self.canonical_alias == None;
                self.canonical_alias = Some(name.clone());
                if was_empty {
                    self.run_pending(&mut callback);
                }
            },
            matrix::events::RoomEvent::JoinRules(rules) =>
                self.join_rules = Some(rules.clone()),
            matrix::events::RoomEvent::Create => (),
            matrix::events::RoomEvent::Aliases(aliases) => {
                let is_empty = self.canonical_alias == None;
                if is_empty {
                    self.canonical_alias = Some(aliases[0].clone());
                    self.run_pending(&mut callback);
                }
            },
            matrix::events::RoomEvent::PowerLevels => (),
            matrix::events::RoomEvent::HistoryVisibility(_) => (),
            matrix::events::RoomEvent::Name(_, _) => (),
            matrix::events::RoomEvent::Avatar(_, _) => (),
            matrix::events::RoomEvent::Unknown(unknown_type, json) => {
                warn!("Unknown room event {}", unknown_type);
                trace!("raw event: {:?}", json);
            }
            _ => self.handle_with_alias(evt, &mut callback)
        };
    }
}

impl Bridge {
    pub fn room_from_matrix(&mut self, id: &matrix::events::RoomID) -> &mut Room {
        if !self.rooms.contains_key(id) {
            self.rooms.insert(id.clone(), Room::new(id.clone()));
        }
        match self.rooms.get_mut(id) {
            Some(room) => room,
            None => unreachable!()
        }
    }

    pub fn room_from_irc(&mut self, id: &String) -> &mut Room {
        let mut room_id: Option<matrix::events::RoomID> = None;
        for (_, r) in self.rooms.iter_mut() {
            if let Some(ref alias) = r.canonical_alias {
                if alias == id {
                    room_id = Some(r.id.clone())
                }
            }
        }
        self.room_from_matrix(&room_id.unwrap())
    }

    pub fn new(client: irc::streams::Client, url: &str) -> Self {
        Bridge {
            client: client,
            matrix: matrix::client::Client::new(url),
            rooms: HashMap::new(),
            seen_events: vec![]
        }
    }

    pub fn run(&mut self) {
        let mut events = EventLoop::new().unwrap();
        events.register(self.client.stream().get_ref(), CLIENT, EventSet::all(), PollOpt::edge()).unwrap();
        events.run(self).unwrap();
    }

    fn handle_matrix(&mut self, evt: matrix::events::Event) {
        let duplicate = match evt.id {
            Some(ref id) =>
                self.seen_events.contains(id),
            _ => false
        };
        if !duplicate {
            let mut messages: Vec<irc::protocol::Message> = vec![];
            {
                let append_msg = |msg: irc::protocol::Message| {
                    messages.push(msg);
                };
                match evt.data {
                    matrix::events::EventData::Room(room_id, room_event) => {
                        self.room_from_matrix(&room_id).handle_event(room_event, append_msg);
                    },
                    matrix::events::EventData::Typing(_) => (),
                    _ => warn!("Unhandled {}", evt.data.type_str())
                }
            }
            match evt.id {
                Some(id) =>
                    self.seen_events.push(id),
                None => ()
            };
            for ref msg in messages {
                self.client.send(msg).unwrap();
            }
        }
    }

    fn poll_matrix(&mut self, channel: mio::Sender<Event>) ->
        thread::JoinHandle<matrix::client::Result> {
        let poll = self.matrix.poll_async();
        thread::spawn(move|| {
            poll.send().and_then(|evts| {
                for evt in evts {
                    channel.send(Event::Matrix(evt)).unwrap();
                };
                channel.send(Event::EndPoll).unwrap();
                Ok(())
            })
        })
    }

    fn start_matrix(&mut self, channel: mio::Sender<Event>) ->
        matrix::client::Result {
        self.matrix.sync().and_then(|events| {
            for e in events {
                self.handle_matrix(e);
            }
            self.poll_matrix(channel);
            Ok(())
        })
    }

    fn handle_client(&mut self, events: &mut EventLoop<Bridge>) {
        loop {
            match self.client.read_message() {
                None => return,
                Some(message) => {
                    match message.command {
                        Command::Pass => {
                            self.client.auth.set_password(message.args[0].clone())
                        }
                        Command::Nick => {
                            self.client.set_nickname(message.args[0].clone());
                        },
                        Command::User => {
                            self.client.auth.set_username(message.args[0].clone());
                            let auth = self.client.auth.consume();
                            match (auth.username, auth.password) {
                                (Some(username), Some(password)) => {
                                    self.matrix.login(username.trim(), password.trim())
                                        .and_then(|_| {
                                            self.start_matrix(events.channel())
                                        })
                                        .and_then(|_| {
                                            self.client.welcome(username.trim()).unwrap();
                                            debug!("Logged in a user");
                                            Ok(())
                                        }).expect("Could not login!");
                                },
                                _ => panic!("Username and/or password missing")
                            };
                        },
                        Command::Join => {
                            self.client.join(&message.args[0]).expect("Could not send JOIN");
                        },
                        Command::Ping => {
                            self.client.pong().expect("Could not send PONG");
                        },
                        Command::Quit => {
                            // FIXME: Logout of matrix and exit thread
                            return;
                        },
                        Command::Privmsg => {
                            let evt = {
                                let id = self.matrix.uid.clone().unwrap();
                                let room = self.room_from_irc(&message.args[0]);
                                matrix::events::EventData::Room(
                                    room.id.clone(),
                                    matrix::events::RoomEvent::Message(
                                        id, message.suffix.unwrap()))
                            };
                            self.seen_events.push(self.matrix.send(evt).expect("Could not send event"));
                        },
                        _ =>
                            warn!("unhandled {:?}", message)
                    }
                }
            }
        }
    }
}

<commit_msg>bridge: fix up syntax of IRC user tuples<commit_after>use irc;
use matrix;
use irc::protocol::{Command,Message};
use mio;
use mio::{EventLoop,Handler,Token,EventSet,PollOpt,Sender};
use std::thread;
use std::collections::HashMap;

const CLIENT: Token = Token(0);

#[derive(Debug)]
pub enum Event {
    EndPoll,
    Matrix(matrix::events::Event)
}

pub struct Bridge {
    client: irc::streams::Client,
    matrix: matrix::client::Client,
    rooms: HashMap<matrix::events::RoomID, Room>,
    seen_events: Vec<matrix::events::EventID>,
}

impl Handler for Bridge {
    type Timeout = ();
    type Message = Event;

    fn ready(&mut self, event_loop: &mut EventLoop<Bridge>, token: Token, _: EventSet) {
        match token {
            CLIENT =>
                self.handle_client(event_loop),
            _ => unreachable!()
        }
    }

    fn notify(&mut self, event_loop: &mut EventLoop<Bridge>, msg: Self::Message) {
        match msg {
            Event::EndPoll => {
                self.poll_matrix(event_loop.channel());
            },
            Event::Matrix(e) =>
                self.handle_matrix(e)
        };
    }
}

unsafe impl Sync for Bridge{}

struct Room {
    id: matrix::events::RoomID,
    canonical_alias: Option<String>,
    join_rules: Option<String>,
    members: Vec<matrix::events::UserID>,
    pending_events: Vec<matrix::events::RoomEvent>
}

impl Room {
    fn new(id: matrix::events::RoomID) -> Self {
        Room {
            id: id,
            canonical_alias: None,
            join_rules: None,
            members: vec![],
            pending_events: vec![]
        }
    }

    fn run_pending<F>(&mut self, mut callback: &mut F)
            where F: FnMut(irc::protocol::Message) {
        while let Some(evt) = self.pending_events.pop() {
            self.handle_with_alias(evt, callback);
        }
    }

    fn handle_with_alias<F>(&mut self, evt: matrix::events::RoomEvent, mut callback: &mut F)
            where F: FnMut(irc::protocol::Message) {
        if self.canonical_alias != None {
            match evt {
                matrix::events::RoomEvent::Membership(user, matrix::events::MembershipAction::Join) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}!{}@{}", user.nickname, user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Join,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: None
                    });
                    self.members.push(user);
                },
                matrix::events::RoomEvent::Membership(user, matrix::events::MembershipAction::Leave) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}!{}@{}", user.nickname, user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Part,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: None
                    });
                    self.members.push(user);
                },
                matrix::events::RoomEvent::Membership(_, _) => (),
                matrix::events::RoomEvent::Message(user, text) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}!{}@{}", user.nickname, user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Privmsg,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: Some(text)
                    });
                },
                matrix::events::RoomEvent::Topic(user, topic) => {
                    callback(irc::protocol::Message {
                        prefix: Some(format!("{}!{}@{}", user.nickname, user.nickname, user.homeserver)),
                        command: irc::protocol::Command::Topic,
                        args: vec![self.canonical_alias.clone().unwrap()],
                        suffix: Some(topic.clone())
                    });
                },
                matrix::events::RoomEvent::CanonicalAlias(_) => unreachable!(),
                _ => {
                    warn!("Unhandled event {:?}", evt)
                }
            }
        } else {
            self.pending_events.push(evt);
        }
    }

    fn handle_event<F>(&mut self, evt: matrix::events::RoomEvent, mut callback: F)
            where F: FnMut(irc::protocol::Message) {
        match evt {
            matrix::events::RoomEvent::CanonicalAlias(name) => {
                let was_empty = self.canonical_alias == None;
                self.canonical_alias = Some(name.clone());
                if was_empty {
                    self.run_pending(&mut callback);
                }
            },
            matrix::events::RoomEvent::JoinRules(rules) =>
                self.join_rules = Some(rules.clone()),
            matrix::events::RoomEvent::Create => (),
            matrix::events::RoomEvent::Aliases(aliases) => {
                let is_empty = self.canonical_alias == None;
                if is_empty {
                    self.canonical_alias = Some(aliases[0].clone());
                    self.run_pending(&mut callback);
                }
            },
            matrix::events::RoomEvent::PowerLevels => (),
            matrix::events::RoomEvent::HistoryVisibility(_) => (),
            matrix::events::RoomEvent::Name(_, _) => (),
            matrix::events::RoomEvent::Avatar(_, _) => (),
            matrix::events::RoomEvent::Unknown(unknown_type, json) => {
                warn!("Unknown room event {}", unknown_type);
                trace!("raw event: {:?}", json);
            }
            _ => self.handle_with_alias(evt, &mut callback)
        };
    }
}

impl Bridge {
    pub fn room_from_matrix(&mut self, id: &matrix::events::RoomID) -> &mut Room {
        if !self.rooms.contains_key(id) {
            self.rooms.insert(id.clone(), Room::new(id.clone()));
        }
        match self.rooms.get_mut(id) {
            Some(room) => room,
            None => unreachable!()
        }
    }

    pub fn room_from_irc(&mut self, id: &String) -> &mut Room {
        let mut room_id: Option<matrix::events::RoomID> = None;
        for (_, r) in self.rooms.iter_mut() {
            if let Some(ref alias) = r.canonical_alias {
                if alias == id {
                    room_id = Some(r.id.clone())
                }
            }
        }
        self.room_from_matrix(&room_id.unwrap())
    }

    pub fn new(client: irc::streams::Client, url: &str) -> Self {
        Bridge {
            client: client,
            matrix: matrix::client::Client::new(url),
            rooms: HashMap::new(),
            seen_events: vec![]
        }
    }

    pub fn run(&mut self) {
        let mut events = EventLoop::new().unwrap();
        events.register(self.client.stream().get_ref(), CLIENT, EventSet::all(), PollOpt::edge()).unwrap();
        events.run(self).unwrap();
    }

    fn handle_matrix(&mut self, evt: matrix::events::Event) {
        let duplicate = match evt.id {
            Some(ref id) =>
                self.seen_events.contains(id),
            _ => false
        };
        if !duplicate {
            let mut messages: Vec<irc::protocol::Message> = vec![];
            {
                let append_msg = |msg: irc::protocol::Message| {
                    messages.push(msg);
                };
                match evt.data {
                    matrix::events::EventData::Room(room_id, room_event) => {
                        self.room_from_matrix(&room_id).handle_event(room_event, append_msg);
                    },
                    matrix::events::EventData::Typing(_) => (),
                    _ => warn!("Unhandled {}", evt.data.type_str())
                }
            }
            match evt.id {
                Some(id) =>
                    self.seen_events.push(id),
                None => ()
            };
            for ref msg in messages {
                self.client.send(msg).unwrap();
            }
        }
    }

    fn poll_matrix(&mut self, channel: mio::Sender<Event>) ->
        thread::JoinHandle<matrix::client::Result> {
        let poll = self.matrix.poll_async();
        thread::spawn(move|| {
            poll.send().and_then(|evts| {
                for evt in evts {
                    channel.send(Event::Matrix(evt)).unwrap();
                };
                channel.send(Event::EndPoll).unwrap();
                Ok(())
            })
        })
    }

    fn start_matrix(&mut self, channel: mio::Sender<Event>) ->
        matrix::client::Result {
        self.matrix.sync().and_then(|events| {
            for e in events {
                self.handle_matrix(e);
            }
            self.poll_matrix(channel);
            Ok(())
        })
    }

    fn handle_client(&mut self, events: &mut EventLoop<Bridge>) {
        loop {
            match self.client.read_message() {
                None => return,
                Some(message) => {
                    match message.command {
                        Command::Pass => {
                            self.client.auth.set_password(message.args[0].clone())
                        }
                        Command::Nick => {
                            self.client.set_nickname(message.args[0].clone());
                        },
                        Command::User => {
                            self.client.auth.set_username(message.args[0].clone());
                            let auth = self.client.auth.consume();
                            match (auth.username, auth.password) {
                                (Some(username), Some(password)) => {
                                    self.matrix.login(username.trim(), password.trim())
                                        .and_then(|_| {
                                            self.start_matrix(events.channel())
                                        })
                                        .and_then(|_| {
                                            self.client.welcome(username.trim()).unwrap();
                                            debug!("Logged in a user");
                                            Ok(())
                                        }).expect("Could not login!");
                                },
                                _ => panic!("Username and/or password missing")
                            };
                        },
                        Command::Join => {
                            self.client.join(&message.args[0]).expect("Could not send JOIN");
                        },
                        Command::Ping => {
                            self.client.pong().expect("Could not send PONG");
                        },
                        Command::Quit => {
                            // FIXME: Logout of matrix and exit thread
                            return;
                        },
                        Command::Privmsg => {
                            let evt = {
                                let id = self.matrix.uid.clone().unwrap();
                                let room = self.room_from_irc(&message.args[0]);
                                matrix::events::EventData::Room(
                                    room.id.clone(),
                                    matrix::events::RoomEvent::Message(
                                        id, message.suffix.unwrap()))
                            };
                            self.seen_events.push(self.matrix.send(evt).expect("Could not send event"));
                        },
                        _ =>
                            warn!("unhandled {:?}", message)
                    }
                }
            }
        }
    }
}

<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! This module defines physical storage schema for LedgerInfoWithSignatures structure.
//!
//! Serialized LedgerInfoWithSignatures identified by `epoch_num`.
//! ```text
//! |<---key--->|<---------------value------------->|
//! | epoch_num | ledger_info_with_signatures bytes |
//! ```
//!
//! `epoch_num` is serialized in big endian so that records in RocksDB will be in order of it's
//! numeric value.

use crate::schema::ensure_slice_len_eq;
use byteorder::{BigEndian, ReadBytesExt};
use failure::prelude::*;
use libra_types::crypto_proxies::LedgerInfoWithSignatures;
use prost::Message;
use prost_ext::MessageExt;
use schemadb::{
    define_schema,
    schema::{KeyCodec, ValueCodec},
    DEFAULT_CF_NAME,
};
use std::convert::TryInto;
use std::mem::size_of;

define_schema!(
    LedgerInfoSchema,
    u64, /* epoch num */
    LedgerInfoWithSignatures,
    DEFAULT_CF_NAME
);

impl KeyCodec<LedgerInfoSchema> for u64 {
    fn encode_key(&self) -> Result<Vec<u8>> {
        Ok(self.to_be_bytes().to_vec())
    }

    fn decode_key(data: &[u8]) -> Result<Self> {
        ensure_slice_len_eq(data, size_of::<Self>())?;
        Ok((&data[..]).read_u64::<BigEndian>()?)
    }
}

impl ValueCodec<LedgerInfoSchema> for LedgerInfoWithSignatures {
    fn encode_value(&self) -> Result<Vec<u8>> {
        let event: libra_types::proto::types::LedgerInfoWithSignatures = self.clone().into();
        Ok(event.to_vec()?)
    }

    fn decode_value(data: &[u8]) -> Result<Self> {
        libra_types::proto::types::LedgerInfoWithSignatures::decode(data)?.try_into()
    }
}

#[cfg(test)]
mod test;
<commit_msg>[Storage] Fix typo<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! This module defines physical storage schema for LedgerInfoWithSignatures structure.
//!
//! Serialized LedgerInfoWithSignatures identified by `epoch_num`.
//! ```text
//! |<---key--->|<---------------value------------->|
//! | epoch_num | ledger_info_with_signatures bytes |
//! ```
//!
//! `epoch_num` is serialized in big endian so that records in RocksDB will be in order of their
//! numeric value.

use crate::schema::ensure_slice_len_eq;
use byteorder::{BigEndian, ReadBytesExt};
use failure::prelude::*;
use libra_types::crypto_proxies::LedgerInfoWithSignatures;
use prost::Message;
use prost_ext::MessageExt;
use schemadb::{
    define_schema,
    schema::{KeyCodec, ValueCodec},
    DEFAULT_CF_NAME,
};
use std::convert::TryInto;
use std::mem::size_of;

define_schema!(
    LedgerInfoSchema,
    u64, /* epoch num */
    LedgerInfoWithSignatures,
    DEFAULT_CF_NAME
);

impl KeyCodec<LedgerInfoSchema> for u64 {
    fn encode_key(&self) -> Result<Vec<u8>> {
        Ok(self.to_be_bytes().to_vec())
    }

    fn decode_key(data: &[u8]) -> Result<Self> {
        ensure_slice_len_eq(data, size_of::<Self>())?;
        Ok((&data[..]).read_u64::<BigEndian>()?)
    }
}

impl ValueCodec<LedgerInfoSchema> for LedgerInfoWithSignatures {
    fn encode_value(&self) -> Result<Vec<u8>> {
        let event: libra_types::proto::types::LedgerInfoWithSignatures = self.clone().into();
        Ok(event.to_vec()?)
    }

    fn decode_value(data: &[u8]) -> Result<Self> {
        libra_types::proto::types::LedgerInfoWithSignatures::decode(data)?.try_into()
    }
}

#[cfg(test)]
mod test;
<|endoftext|>


<commit_before>// Copyright 2016 Alexander Reece
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

///
/// Define getters and setters for a struct.
///
/// # FAQ
///
/// Error: "only traits may use parentheses" or "undefined or not in scope"
///
/// Ensure you are using commas
///
///
/// # Examples
///
/// By-value copy types (doesn't return a reference, no get_mut())
///
/// ```
/// struct TestCopy { val}
///
/// impl TestCopy {
///     impl_properties!(
///         (val, set_val) -> u8,
///     )
/// }
/// ```
///
/// By-reference values (owned structs)
///
/// ```
/// struct Member;
/// struct TestRef { member: Member }
///
/// impl TestRef {
///     impl_properties!(
///         (member, member_mut, set_member) -> &Member
///     )
/// }
/// ```
///
/// By-reference `Option`s (owned options)
///
/// ```
/// struct Member;
/// struct TestRef { member: Option<Member> }
///
/// impl TestRef {
///     impl_properties!(
///         (member, member_mut, set_member) -> Option<&Member>
///     )
/// }
/// ```
///
/// `Cow`s (where ToOwned::Target == Self)
/// ```
/// #[derive(Clone)]
/// struct Cloneable;
/// struct TestRef { member: Cow<'a, Member> }
///
/// // currently only works with 'a
/// impl TestRef<'a> {
///     impl_properties!(
///         (member, member_mut, set_member) -> Cow<Member>
///     )
/// }
/// ```
///
/// `Cow`s (where ToOwned::Target != Self)
/// ```
/// #[derive(Clone)]
/// struct Cloneable;
/// struct TestRef { member: Cow<'a, Member> }
///
/// // currently only works with 'a
/// impl TestRef<'a> {
///     impl_properties!(
///         (member, member_mut -> Owned, set_member) -> Cow<Borrowed>
///     )
/// }
/// ```
///
/// `Option<Cow<_>>`'s (add -> Owned if ToOwned::Target != Self
///
///
///
#[macro_export]
macro_rules! impl_properties {
    () => {};

    // Option<Cow<_>> (different owned type)
    (($property:ident, $mutator:ident -> $owned:ty, $setter:ident, $take:ident) -> Option< Cow<$ty:ty> >) => {
        pub fn $property(&self) -> Option<&$ty> {
            self.$property.as_ref().map(|v| &**v)
        }

        pub fn $setter<O, V>(&mut self, value: O)
            where O: Into<Option<V>>,
                  V: Into<::std::borrow::Cow<'a, $ty>>
        {
            self.$property = value.into().map(|v| v.into());
        }

        pub fn $mutator(&mut self) -> Option<&mut $owned> {
            self.$property.as_mut()
                .map(|v| v.to_mut())
        }

        pub fn $take(&mut self) -> Option<::std::borrow::Cow<'a, $ty>> {
            self.$property.take()
        }
    };
    (($property:ident, $mutator:ident -> $owned:ty, $setter:ident, $take:ident) -> Option< Cow<$ty:ty> >, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> $owned, $setter, $take) -> Option< Cow< $ty> >);
        impl_properties!($($rest)*);
    };

    // Option<Cow<[_]>> (automatically notes that owned type is Vec<_>
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<[$ty:ty]> >) => {
        impl_properties!(($property, $mutator -> Vec<$ty>, $setter, $take) -> Option< Cow<[$ty]> >);
    };
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<[$ty:ty]> >, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> Vec<$ty>, $setter, $take) -> Option< Cow<[$ty]> >);
        impl_properties!($($rest)*);
    };

    // Option<Cow<str>> (automatically notes that owned type is String
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<str> >) => {
        impl_properties!(($property, $mutator -> ::std::string::String, $setter, $take) -> Option< Cow<str> >);
    };
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<str> >, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> ::std::string::String, $setter, $take) -> Option< Cow<str> >);
        impl_properties!($($rest)*);
    };

    // Option<Cow<_>> same owned type
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<$ty:ty> >) => {
        impl_properties!(($property, $mutator -> $ty, $setter, $take) -> Option< Cow<$ty> >);
    };
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<$ty:ty> >, $($rest:tt)*) => {
        impl_properties!(($property, $mutator, $setter, $take) -> Option< Cow< $ty> >);
        impl_properties!($($rest)*);
    };

    // Cow<_> (different owned type)
    (($property:ident, $mutator:ident -> $owned:ty, $setter:ident) -> Cow<$ty:ty>) => {
        pub fn $property(&self) -> &$ty {
            &*self.$property
        }

        pub fn $setter<V>(&mut self, value: V)
            where V: Into<::std::borrow::Cow<'a, $ty>>
        {
            self.$property = value.into()
        }

        pub fn $mutator(&mut self) -> &mut $owned {
            self.$property.to_mut()
        }
    };
    (($property:ident, $mutator:ident -> $owned:ty, $setter:ident) -> Cow<$ty:ty>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> $owned, $setter) -> Cow<$ty>);
        impl_properties!($($rest)*);
    };

    // Cow<[_]> (automatically notes that owned type is Vec<_>
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<[$ty:ty]>) => {
        impl_properties!(($property, $mutator -> Vec<$ty>, $setter) -> Cow<[$ty]>);
    };
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<[$ty:ty]>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> Vec<$ty>, $setter) -> Cow<[$ty]>);
        impl_properties!($($rest)*);
    };

    // Cow<str> (automatically notes that owned type is String
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<str>) => {
        impl_properties!(($property, $mutator -> ::std::string::String, $setter) -> Cow<str>);
    };
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<str>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> ::std::string::String, $setter) -> Cow<str>);
        impl_properties!($($rest)*);
    };

    // Cow<_> same owned type
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<$ty:ty>) => {
        impl_properties!(($property, $mutator -> $ty, $setter) -> Cow<$ty>);
    };
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<$ty:ty>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> $ty, $setter) -> Cow<$ty>);
        impl_properties!($($rest)*);
    };

    // Option
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option<&$ty:ty>) => {
        pub fn $property(&self) -> Option<&$ty> {
            self.$property.as_ref()
        }

        pub fn $setter<O>(&mut self, value: O)
            where O: Into<Option<$ty>>
        {
            self.$property = value.into();
        }

        pub fn $mutator(&mut self) -> Option<&mut $ty> {
            self.$property.as_mut()
        }

        pub fn $take(&mut self) -> Option<$ty> {
            self.$property.take()
        }
    };
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option<&$ty:ty>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator, $setter, $take) -> Option<&$ty>);
        impl_properties!($($rest)*);
    };

    // by reference
    (($property:ident, $mutator:ident, $setter:ident) -> &$ty:ty) => {
        pub fn $property(&self) -> &$ty {
            &self.$property
        }
        pub fn $mutator(&mut self) -> &mut $ty {
            &mut self.$property
        }
        pub fn $setter(&mut self, value: $ty) {
            self.$property = value;
        }
    };
    (($property:ident, $mutator:ident, $setter:ident) -> &$ty:ty, $($rest:tt)*) => {
        impl_properties!(($property, $mutator, $setter) -> &$ty);
        impl_properties!($($rest)*);
    };

    // option by value
    (($property:ident, $mutator:ident, $setter:ident, $taker:ident) -> Option<$ty:ty>) => {
        pub fn $property(&self) -> Option<$ty> {
            self.$property
        }

        pub fn $setter<O>(&mut self, value: O)
            where O: Into<Option<$ty>>
        {
            self.$property = value.into();
        }

        pub fn $mutator(&mut self) -> Option<&mut $ty> {
            self.$property.as_mut()
        }

        pub fn $taker(&mut self) -> Option<$ty> {
            self.$property.take()
        }
    };
    (($property:ident, $mutator:ident, $setter:ident, $taker:ident) -> Option<$ty:ty>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator, $setter, $taker) -> Option<$ty>);
        impl_properties!($($rest)*);
    };

    // by value
    (($property:ident, $setter:ident) -> $ty:ty) => {
        pub fn $property(&self) -> $ty {
            self.$property
        }
        pub fn $setter(&mut self, value: $ty) {
            self.$property = value;
        }
    };
    (($property:ident, $setter:ident) -> $ty:ty, $($rest:tt)*) => {
        impl_properties!(($property, $setter) -> $ty);
        impl_properties!($($rest)*);
    };
}<commit_msg>[primitives] Clean up documentation for impl_properties! and fix its tests.<commit_after>// Copyright 2016 Alexander Reece
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

///
/// Define getters and setters for a struct. Non-stable until lifetime support is added
/// (currently only supports 'a)
///
/// Expects to be given the name of functions, and the return value, e.g:
///
/// `([list of function names`] -> ReturnType
///
/// The number of functions names needed varies, depending on the return type.
///
/// * For copy types `(name|getter, setter) -> Ty`
/// * Borrowed types require a mutator method: `(name|getter, mutator, setters) -> &Ty`
/// * Cow types are detected, don't need a lifetime: `(...) -> Cow<SomeType>`
/// * Option types may require spacing, and also require a taker name: `(name|getter, mutator, setters, taker) -> Option<&Ty>`
/// * Option types that don't return a reference still require a mutator:  `(name|getter, mutator, setters, taker) -> Option<u8>`
/// * Option may require spacing: `(...) -> Option< Cow<SomeType> >`
///
/// # Examples
///
/// By-value copy types (doesn't return a reference, no get_mut())
///
/// ```
/// #[macro_use]
/// extern crate amqp0_primitives;
///
/// use std::borrow::Cow;
///
/// #[derive(Clone)]
/// struct Member;
///
/// struct TestCopy<'a> {
///     val: u8,
///     option_val: Option<u8>,
///     member: Member,
///     option_member: Option<Member>,
///     cow: Cow<'a, Member>,
///     option_cow: Option<Cow<'a, Member>>,
/// }
///
/// impl<'a> TestCopy<'a> {
///     impl_properties! {
///         // copy-values (no reference)
///         (val, set_val) -> u8,
///         // optional copy-values
///         (option_val, mutate_option_val, set_option_val, take_option_val) -> Option<u8>,
///         // reference
///         (member, member_mut, set_member) -> &Member,
///         // optional reference
///         (option_member, option_member_mut, set_option_member, take_option_member) -> Option<&Member>,
///         // Cow
///         (cow, cow_mut, set_cow) -> Cow<Member>,
///         // Optional Cow -- note the spacing around the `Option` <>
///         (option_cow, option_cow_mut, set_option_cow, take_option_cow_mut) -> Option< Cow<Member> >
///     }
/// }
///
/// fn main() {}
/// ```
///
/// # Cow notes
///
/// `Cow`s that return a different type for their mutable reference will need to make note on the
/// mutator method. This is automatically done for `str and `slices` e.g:
///
/// Cow<str> and Cow<Vec<_>> are special cases -- mutable references are different and owned. They
/// should be detected automatically, e.g:
///
/// ```
/// #[macro_use]
/// extern crate amqp0_primitives;
///
/// use std::borrow::{Borrow, Cow};
///
/// struct Borrowed(u8);
/// struct Owned(Borrowed);
///
/// impl Borrow<Borrowed> for Owned {
///     fn borrow(&self) -> &Borrowed {
///         &self.0
///     }
/// }
///
/// impl ToOwned for Borrowed {
/// type Owned = Owned;
///     fn to_owned(&self) -> Owned {
///         Owned(Borrowed(self.0))
///     }
/// }
///
/// struct TestCow<'a> {
///     string: Cow<'a, str>,
///     bytes: Cow<'a, [u8]>,
///     borrow: Cow<'a, Borrowed>,
/// }
///
/// impl<'a> TestCow<'a> {
///     impl_properties! {
///         // strings and slices are automatically detected, no need to do -> String or -> Vec<_>
///         (string, string_mut, set_string) -> Cow<str>,
///         (bytes, bytes_mut, set_bytes) -> Cow<[u8]>,
///         // other types require it to be set
///         (borrow, borrow_mut -> Owned, set_borrow) -> Cow<Borrowed>
///     }
/// }
///
/// fn main() {}
/// ```
///
/// # FAQ
///
/// Error: "only traits may use parentheses" or "undefined or not in scope"
///
/// Ensure you are using commas
///
#[macro_export]
macro_rules! impl_properties {
    () => {};

    // Option<Cow<_>> (different owned type)
    (($property:ident, $mutator:ident -> $owned:ty, $setter:ident, $take:ident) -> Option< Cow<$ty:ty> >) => {
        pub fn $property(&self) -> Option<&$ty> {
            self.$property.as_ref().map(|v| &**v)
        }

        pub fn $setter<O, V>(&mut self, value: O)
            where O: Into<Option<V>>,
                  V: Into<::std::borrow::Cow<'a, $ty>>
        {
            self.$property = value.into().map(|v| v.into());
        }

        pub fn $mutator(&mut self) -> Option<&mut $owned> {
            self.$property.as_mut()
                .map(|v| v.to_mut())
        }

        pub fn $take(&mut self) -> Option<::std::borrow::Cow<'a, $ty>> {
            self.$property.take()
        }
    };
    (($property:ident, $mutator:ident -> $owned:ty, $setter:ident, $take:ident) -> Option< Cow<$ty:ty> >, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> $owned, $setter, $take) -> Option< Cow< $ty> >);
        impl_properties!($($rest)*);
    };

    // Option<Cow<[_]>> (automatically notes that owned type is Vec<_>
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<[$ty:ty]> >) => {
        impl_properties!(($property, $mutator -> Vec<$ty>, $setter, $take) -> Option< Cow<[$ty]> >);
    };
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<[$ty:ty]> >, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> Vec<$ty>, $setter, $take) -> Option< Cow<[$ty]> >);
        impl_properties!($($rest)*);
    };

    // Option<Cow<str>> (automatically notes that owned type is String
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<str> >) => {
        impl_properties!(($property, $mutator -> ::std::string::String, $setter, $take) -> Option< Cow<str> >);
    };
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<str> >, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> ::std::string::String, $setter, $take) -> Option< Cow<str> >);
        impl_properties!($($rest)*);
    };

    // Option<Cow<_>> same owned type
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<$ty:ty> >) => {
        impl_properties!(($property, $mutator -> $ty, $setter, $take) -> Option< Cow<$ty> >);
    };
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option< Cow<$ty:ty> >, $($rest:tt)*) => {
        impl_properties!(($property, $mutator, $setter, $take) -> Option< Cow< $ty> >);
        impl_properties!($($rest)*);
    };

    // Cow<_> (different owned type)
    (($property:ident, $mutator:ident -> $owned:ty, $setter:ident) -> Cow<$ty:ty>) => {
        pub fn $property(&self) -> &$ty {
            &*self.$property
        }

        pub fn $setter<V>(&mut self, value: V)
            where V: Into<::std::borrow::Cow<'a, $ty>>
        {
            self.$property = value.into()
        }

        pub fn $mutator(&mut self) -> &mut $owned {
            self.$property.to_mut()
        }
    };
    (($property:ident, $mutator:ident -> $owned:ty, $setter:ident) -> Cow<$ty:ty>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> $owned, $setter) -> Cow<$ty>);
        impl_properties!($($rest)*);
    };

    // Cow<[_]> (automatically notes that owned type is Vec<_>
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<[$ty:ty]>) => {
        impl_properties!(($property, $mutator -> Vec<$ty>, $setter) -> Cow<[$ty]>);
    };
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<[$ty:ty]>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> Vec<$ty>, $setter) -> Cow<[$ty]>);
        impl_properties!($($rest)*);
    };

    // Cow<str> (automatically notes that owned type is String
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<str>) => {
        impl_properties!(($property, $mutator -> ::std::string::String, $setter) -> Cow<str>);
    };
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<str>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> ::std::string::String, $setter) -> Cow<str>);
        impl_properties!($($rest)*);
    };

    // Cow<_> same owned type
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<$ty:ty>) => {
        impl_properties!(($property, $mutator -> $ty, $setter) -> Cow<$ty>);
    };
    (($property:ident, $mutator:ident, $setter:ident) -> Cow<$ty:ty>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator -> $ty, $setter) -> Cow<$ty>);
        impl_properties!($($rest)*);
    };

    // Option
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option<&$ty:ty>) => {
        pub fn $property(&self) -> Option<&$ty> {
            self.$property.as_ref()
        }

        pub fn $setter<O>(&mut self, value: O)
            where O: Into<Option<$ty>>
        {
            self.$property = value.into();
        }

        pub fn $mutator(&mut self) -> Option<&mut $ty> {
            self.$property.as_mut()
        }

        pub fn $take(&mut self) -> Option<$ty> {
            self.$property.take()
        }
    };
    (($property:ident, $mutator:ident, $setter:ident, $take:ident) -> Option<&$ty:ty>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator, $setter, $take) -> Option<&$ty>);
        impl_properties!($($rest)*);
    };

    // by reference
    (($property:ident, $mutator:ident, $setter:ident) -> &$ty:ty) => {
        pub fn $property(&self) -> &$ty {
            &self.$property
        }
        pub fn $mutator(&mut self) -> &mut $ty {
            &mut self.$property
        }
        pub fn $setter(&mut self, value: $ty) {
            self.$property = value;
        }
    };
    (($property:ident, $mutator:ident, $setter:ident) -> &$ty:ty, $($rest:tt)*) => {
        impl_properties!(($property, $mutator, $setter) -> &$ty);
        impl_properties!($($rest)*);
    };

    // option by value
    (($property:ident, $mutator:ident, $setter:ident, $taker:ident) -> Option<$ty:ty>) => {
        pub fn $property(&self) -> Option<$ty> {
            self.$property
        }

        pub fn $setter<O>(&mut self, value: O)
            where O: Into<Option<$ty>>
        {
            self.$property = value.into();
        }

        pub fn $mutator(&mut self) -> Option<&mut $ty> {
            self.$property.as_mut()
        }

        pub fn $taker(&mut self) -> Option<$ty> {
            self.$property.take()
        }
    };
    (($property:ident, $mutator:ident, $setter:ident, $taker:ident) -> Option<$ty:ty>, $($rest:tt)*) => {
        impl_properties!(($property, $mutator, $setter, $taker) -> Option<$ty>);
        impl_properties!($($rest)*);
    };

    // by value
    (($property:ident, $setter:ident) -> $ty:ty) => {
        pub fn $property(&self) -> $ty {
            self.$property
        }
        pub fn $setter(&mut self, value: $ty) {
            self.$property = value;
        }
    };
    (($property:ident, $setter:ident) -> $ty:ty, $($rest:tt)*) => {
        impl_properties!(($property, $setter) -> $ty);
        impl_properties!($($rest)*);
    };
}<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The ChaCha random number generator.

use std::num::Wrapping as w;
use {Rng, SeedableRng, Rand, w32};

const KEY_WORDS    : usize =  8; // 8 words for the 256-bit key
const STATE_WORDS  : usize = 16;
const CHACHA_ROUNDS: u32 = 20; // Cryptographically secure from 8 upwards as of this writing

/// A random number generator that uses the ChaCha20 algorithm [1].
///
/// The ChaCha algorithm is widely accepted as suitable for
/// cryptographic purposes, but this implementation has not been
/// verified as such. Prefer a generator like `OsRng` that defers to
/// the operating system for cases that need high security.
///
/// [1]: D. J. Bernstein, [*ChaCha, a variant of
/// Salsa20*](http://cr.yp.to/chacha.html)
#[derive(Copy, Clone)]
pub struct ChaChaRng {
    buffer:  [w32; STATE_WORDS], // Internal buffer of output
    state:   [w32; STATE_WORDS], // Initial state
    index:   usize,                 // Index into state
}

static EMPTY: ChaChaRng = ChaChaRng {
    buffer:  [w(0); STATE_WORDS],
    state:   [w(0); STATE_WORDS],
    index:   STATE_WORDS
};

macro_rules! quarter_round{
    ($a: expr, $b: expr, $c: expr, $d: expr) => {{
        $a = $a + $b; $d = $d ^ $a; $d = w($d.0.rotate_left(16));
        $c = $c + $d; $b = $b ^ $c; $b = w($b.0.rotate_left(12));
        $a = $a + $b; $d = $d ^ $a; $d = w($d.0.rotate_left( 8));
        $c = $c + $d; $b = $b ^ $c; $b = w($b.0.rotate_left( 7));
    }}
}

macro_rules! double_round{
    ($x: expr) => {{
        // Column round
        quarter_round!($x[ 0], $x[ 4], $x[ 8], $x[12]);
        quarter_round!($x[ 1], $x[ 5], $x[ 9], $x[13]);
        quarter_round!($x[ 2], $x[ 6], $x[10], $x[14]);
        quarter_round!($x[ 3], $x[ 7], $x[11], $x[15]);
        // Diagonal round
        quarter_round!($x[ 0], $x[ 5], $x[10], $x[15]);
        quarter_round!($x[ 1], $x[ 6], $x[11], $x[12]);
        quarter_round!($x[ 2], $x[ 7], $x[ 8], $x[13]);
        quarter_round!($x[ 3], $x[ 4], $x[ 9], $x[14]);
    }}
}

#[inline]
fn core(output: &mut [w32; STATE_WORDS], input: &[w32; STATE_WORDS]) {
    *output = *input;

    for _ in 0..CHACHA_ROUNDS / 2 {
        double_round!(output);
    }

    for i in 0..STATE_WORDS {
        output[i] = output[i] + input[i];
    }
}

impl ChaChaRng {

    /// Create an ChaCha random number generator using the default
    /// fixed key of 8 zero words.
    pub fn new_unseeded() -> ChaChaRng {
        let mut rng = EMPTY;
        rng.init(&[0; KEY_WORDS]);
        rng
    }

    /// Sets the internal 128-bit ChaCha counter to
    /// a user-provided value. This permits jumping
    /// arbitrarily ahead (or backwards) in the pseudorandom stream.
    ///
    /// Since the nonce words are used to extend the counter to 128 bits,
    /// users wishing to obtain the conventional ChaCha pseudorandom stream
    /// associated with a particular nonce can call this function with
    /// arguments `0, desired_nonce`.
    pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) {
        self.state[12] = w((counter_low >>  0) as u32);
        self.state[13] = w((counter_low >> 32) as u32);
        self.state[14] = w((counter_high >>  0) as u32);
        self.state[15] = w((counter_high >> 32) as u32);
        self.index = STATE_WORDS; // force recomputation
    }

    /// Initializes `self.state` with the appropriate key and constants
    ///
    /// We deviate slightly from the ChaCha specification regarding
    /// the nonce, which is used to extend the counter to 128 bits.
    /// This is provably as strong as the original cipher, though,
    /// since any distinguishing attack on our variant also works
    /// against ChaCha with a chosen-nonce. See the XSalsa20 [1]
    /// security proof for a more involved example of this.
    ///
    /// The modified word layout is:
    /// ```text
    /// constant constant constant constant
    /// key      key      key      key
    /// key      key      key      key
    /// counter  counter  counter  counter
    /// ```
    /// [1]: Daniel J. Bernstein. [*Extending the Salsa20
    /// nonce.*](http://cr.yp.to/papers.html#xsalsa)
    fn init(&mut self, key: &[u32; KEY_WORDS]) {
        self.state[0] = w(0x61707865);
        self.state[1] = w(0x3320646E);
        self.state[2] = w(0x79622D32);
        self.state[3] = w(0x6B206574);

        for i in 0..KEY_WORDS {
            self.state[4+i] = w(key[i]);
        }

        self.state[12] = w(0);
        self.state[13] = w(0);
        self.state[14] = w(0);
        self.state[15] = w(0);

        self.index = STATE_WORDS;
    }

    /// Refill the internal output buffer (`self.buffer`)
    fn update(&mut self) {
        core(&mut self.buffer, &self.state);
        self.index = 0;
        // update 128-bit counter
        self.state[12] = self.state[12] + w(1);
        if self.state[12] != w(0) { return };
        self.state[13] = self.state[13] + w(1);
        if self.state[13] != w(0) { return };
        self.state[14] = self.state[14] + w(1);
        if self.state[14] != w(0) { return };
        self.state[15] = self.state[15] + w(1);
    }
}

impl Rng for ChaChaRng {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        if self.index == STATE_WORDS {
            self.update();
        }

        let value = self.buffer[self.index % STATE_WORDS];
        self.index += 1;
        value.0
    }
}

impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {

    fn reseed(&mut self, seed: &'a [u32]) {
        // reset state
        self.init(&[0u32; KEY_WORDS]);
        // set key in place
        let key = &mut self.state[4 .. 4+KEY_WORDS];
        for (k, s) in key.iter_mut().zip(seed.iter()) {
            *k = w(*s);
        }
    }

    /// Create a ChaCha generator from a seed,
    /// obtained from a variable-length u32 array.
    /// Only up to 8 words are used; if less than 8
    /// words are used, the remaining are set to zero.
    fn from_seed(seed: &'a [u32]) -> ChaChaRng {
        let mut rng = EMPTY;
        rng.reseed(seed);
        rng
    }
}

impl Rand for ChaChaRng {
    fn rand<R: Rng>(other: &mut R) -> ChaChaRng {
        let mut key : [u32; KEY_WORDS] = [0; KEY_WORDS];
        for word in key.iter_mut() {
            *word = other.gen();
        }
        SeedableRng::from_seed(&key[..])
    }
}

#[cfg(test)]
mod test {
    use {Rng, SeedableRng};
    use super::ChaChaRng;

    #[test]
    fn test_rng_rand_seeded() {
        let s = ::test::rng().gen_iter::<u32>().take(8).collect::<Vec<u32>>();
        let mut ra: ChaChaRng = SeedableRng::from_seed(&s[..]);
        let mut rb: ChaChaRng = SeedableRng::from_seed(&s[..]);
        assert!(::test::iter_eq(ra.gen_ascii_chars().take(100),
                                rb.gen_ascii_chars().take(100)));
    }

    #[test]
    fn test_rng_seeded() {
        let seed : &[_] = &[0,1,2,3,4,5,6,7];
        let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
        let mut rb: ChaChaRng = SeedableRng::from_seed(seed);
        assert!(::test::iter_eq(ra.gen_ascii_chars().take(100),
                                rb.gen_ascii_chars().take(100)));
    }

    #[test]
    fn test_rng_reseed() {
        let s = ::test::rng().gen_iter::<u32>().take(8).collect::<Vec<u32>>();
        let mut r: ChaChaRng = SeedableRng::from_seed(&s[..]);
        let string1: String = r.gen_ascii_chars().take(100).collect();

        r.reseed(&s);

        let string2: String = r.gen_ascii_chars().take(100).collect();
        assert_eq!(string1, string2);
    }

    #[test]
    fn test_rng_true_values() {
        // Test vectors 1 and 2 from
        // http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04
        let seed : &[_] = &[0u32; 8];
        let mut ra: ChaChaRng = SeedableRng::from_seed(seed);

        let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>();
        assert_eq!(v,
                   vec!(0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653,
                        0xb819d2bd, 0x1aed8da0, 0xccef36a8, 0xc70d778b,
                        0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8,
                        0xf4b8436a, 0x1ca11815, 0x69b687c3, 0x8665eeb2));

        let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>();
        assert_eq!(v,
                   vec!(0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73,
                        0xa0290fcb, 0x6965e348, 0x3e53c612, 0xed7aee32,
                        0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874,
                        0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b));

        let seed : &[_] = &[0,1,2,3,4,5,6,7];
        let mut ra: ChaChaRng = SeedableRng::from_seed(seed);

        // Store the 17*i-th 32-bit word,
        // i.e., the i-th word of the i-th 16-word block
        let mut v : Vec<u32> = Vec::new();
        for _ in 0..16 {
            v.push(ra.next_u32());
            for _ in 0..16 {
                ra.next_u32();
            }
        }

        assert_eq!(v,
                   vec!(0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036,
                        0x49884684, 0x64efec72, 0x4be2d186, 0x3615b384,
                        0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530,
                        0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4));
    }

    #[test]
    fn test_rng_clone() {
        let seed : &[_] = &[0u32; 8];
        let mut rng: ChaChaRng = SeedableRng::from_seed(seed);
        let mut clone = rng.clone();
        for _ in 0..16 {
            assert_eq!(rng.next_u64(), clone.next_u64());
        }
    }
}
<commit_msg>Adding examples to ChaChaRng<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The ChaCha random number generator.

use std::num::Wrapping as w;
use {Rng, SeedableRng, Rand, w32};

const KEY_WORDS    : usize =  8; // 8 words for the 256-bit key
const STATE_WORDS  : usize = 16;
const CHACHA_ROUNDS: u32 = 20; // Cryptographically secure from 8 upwards as of this writing

/// A random number generator that uses the ChaCha20 algorithm [1].
///
/// The ChaCha algorithm is widely accepted as suitable for
/// cryptographic purposes, but this implementation has not been
/// verified as such. Prefer a generator like `OsRng` that defers to
/// the operating system for cases that need high security.
///
/// [1]: D. J. Bernstein, [*ChaCha, a variant of
/// Salsa20*](http://cr.yp.to/chacha.html)
#[derive(Copy, Clone)]
pub struct ChaChaRng {
    buffer:  [w32; STATE_WORDS], // Internal buffer of output
    state:   [w32; STATE_WORDS], // Initial state
    index:   usize,                 // Index into state
}

static EMPTY: ChaChaRng = ChaChaRng {
    buffer:  [w(0); STATE_WORDS],
    state:   [w(0); STATE_WORDS],
    index:   STATE_WORDS
};

macro_rules! quarter_round{
    ($a: expr, $b: expr, $c: expr, $d: expr) => {{
        $a = $a + $b; $d = $d ^ $a; $d = w($d.0.rotate_left(16));
        $c = $c + $d; $b = $b ^ $c; $b = w($b.0.rotate_left(12));
        $a = $a + $b; $d = $d ^ $a; $d = w($d.0.rotate_left( 8));
        $c = $c + $d; $b = $b ^ $c; $b = w($b.0.rotate_left( 7));
    }}
}

macro_rules! double_round{
    ($x: expr) => {{
        // Column round
        quarter_round!($x[ 0], $x[ 4], $x[ 8], $x[12]);
        quarter_round!($x[ 1], $x[ 5], $x[ 9], $x[13]);
        quarter_round!($x[ 2], $x[ 6], $x[10], $x[14]);
        quarter_round!($x[ 3], $x[ 7], $x[11], $x[15]);
        // Diagonal round
        quarter_round!($x[ 0], $x[ 5], $x[10], $x[15]);
        quarter_round!($x[ 1], $x[ 6], $x[11], $x[12]);
        quarter_round!($x[ 2], $x[ 7], $x[ 8], $x[13]);
        quarter_round!($x[ 3], $x[ 4], $x[ 9], $x[14]);
    }}
}

#[inline]
fn core(output: &mut [w32; STATE_WORDS], input: &[w32; STATE_WORDS]) {
    *output = *input;

    for _ in 0..CHACHA_ROUNDS / 2 {
        double_round!(output);
    }

    for i in 0..STATE_WORDS {
        output[i] = output[i] + input[i];
    }
}

impl ChaChaRng {

    /// Create an ChaCha random number generator using the default
    /// fixed key of 8 zero words.
    ///
    /// # Examples
    ///
    /// ```rust
    /// use rand::{Rng, ChaChaRng};
    ///
    /// let mut ra = ChaChaRng::new_unseeded();
    /// println!("{:?}", ra.next_u32());
    /// println!("{:?}", ra.next_u32());
    /// ```
    ///
    /// Since this equivalent to a RNG with a fixed seed, repeated executions
    /// of an unseeded RNG will produce the same result. This code sample will
    /// consistently produce:
    /// - 2917185654
    /// - 2419978656
    pub fn new_unseeded() -> ChaChaRng {
        let mut rng = EMPTY;
        rng.init(&[0; KEY_WORDS]);
        rng
    }

    /// Sets the internal 128-bit ChaCha counter to
    /// a user-provided value. This permits jumping
    /// arbitrarily ahead (or backwards) in the pseudorandom stream.
    ///
    /// Since the nonce words are used to extend the counter to 128 bits,
    /// users wishing to obtain the conventional ChaCha pseudorandom stream
    /// associated with a particular nonce can call this function with
    /// arguments `0, desired_nonce`.
    ///
    /// # Examples
    ///
    /// ```
    /// use rand::{Rng, ChaChaRng};
    ///
    /// let mut ra = ChaChaRng::new_unseeded();
    /// ra.set_counter(0u64, 1234567890u64);
    /// println!("{:?}", ra.next_u32());
    /// println!("{:?}", ra.next_u32());
    /// ```
    pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) {
        self.state[12] = w((counter_low >>  0) as u32);
        self.state[13] = w((counter_low >> 32) as u32);
        self.state[14] = w((counter_high >>  0) as u32);
        self.state[15] = w((counter_high >> 32) as u32);
        self.index = STATE_WORDS; // force recomputation
    }

    /// Initializes `self.state` with the appropriate key and constants
    ///
    /// We deviate slightly from the ChaCha specification regarding
    /// the nonce, which is used to extend the counter to 128 bits.
    /// This is provably as strong as the original cipher, though,
    /// since any distinguishing attack on our variant also works
    /// against ChaCha with a chosen-nonce. See the XSalsa20 [1]
    /// security proof for a more involved example of this.
    ///
    /// The modified word layout is:
    /// ```text
    /// constant constant constant constant
    /// key      key      key      key
    /// key      key      key      key
    /// counter  counter  counter  counter
    /// ```
    /// [1]: Daniel J. Bernstein. [*Extending the Salsa20
    /// nonce.*](http://cr.yp.to/papers.html#xsalsa)
    fn init(&mut self, key: &[u32; KEY_WORDS]) {
        self.state[0] = w(0x61707865);
        self.state[1] = w(0x3320646E);
        self.state[2] = w(0x79622D32);
        self.state[3] = w(0x6B206574);

        for i in 0..KEY_WORDS {
            self.state[4+i] = w(key[i]);
        }

        self.state[12] = w(0);
        self.state[13] = w(0);
        self.state[14] = w(0);
        self.state[15] = w(0);

        self.index = STATE_WORDS;
    }

    /// Refill the internal output buffer (`self.buffer`)
    fn update(&mut self) {
        core(&mut self.buffer, &self.state);
        self.index = 0;
        // update 128-bit counter
        self.state[12] = self.state[12] + w(1);
        if self.state[12] != w(0) { return };
        self.state[13] = self.state[13] + w(1);
        if self.state[13] != w(0) { return };
        self.state[14] = self.state[14] + w(1);
        if self.state[14] != w(0) { return };
        self.state[15] = self.state[15] + w(1);
    }
}

impl Rng for ChaChaRng {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        if self.index == STATE_WORDS {
            self.update();
        }

        let value = self.buffer[self.index % STATE_WORDS];
        self.index += 1;
        value.0
    }
}

impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {

    fn reseed(&mut self, seed: &'a [u32]) {
        // reset state
        self.init(&[0u32; KEY_WORDS]);
        // set key in place
        let key = &mut self.state[4 .. 4+KEY_WORDS];
        for (k, s) in key.iter_mut().zip(seed.iter()) {
            *k = w(*s);
        }
    }

    /// Create a ChaCha generator from a seed,
    /// obtained from a variable-length u32 array.
    /// Only up to 8 words are used; if less than 8
    /// words are used, the remaining are set to zero.
    fn from_seed(seed: &'a [u32]) -> ChaChaRng {
        let mut rng = EMPTY;
        rng.reseed(seed);
        rng
    }
}

impl Rand for ChaChaRng {
    fn rand<R: Rng>(other: &mut R) -> ChaChaRng {
        let mut key : [u32; KEY_WORDS] = [0; KEY_WORDS];
        for word in key.iter_mut() {
            *word = other.gen();
        }
        SeedableRng::from_seed(&key[..])
    }
}

#[cfg(test)]
mod test {
    use {Rng, SeedableRng};
    use super::ChaChaRng;

    #[test]
    fn test_rng_rand_seeded() {
        let s = ::test::rng().gen_iter::<u32>().take(8).collect::<Vec<u32>>();
        let mut ra: ChaChaRng = SeedableRng::from_seed(&s[..]);
        let mut rb: ChaChaRng = SeedableRng::from_seed(&s[..]);
        assert!(::test::iter_eq(ra.gen_ascii_chars().take(100),
                                rb.gen_ascii_chars().take(100)));
    }

    #[test]
    fn test_rng_seeded() {
        let seed : &[_] = &[0,1,2,3,4,5,6,7];
        let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
        let mut rb: ChaChaRng = SeedableRng::from_seed(seed);
        assert!(::test::iter_eq(ra.gen_ascii_chars().take(100),
                                rb.gen_ascii_chars().take(100)));
    }

    #[test]
    fn test_rng_reseed() {
        let s = ::test::rng().gen_iter::<u32>().take(8).collect::<Vec<u32>>();
        let mut r: ChaChaRng = SeedableRng::from_seed(&s[..]);
        let string1: String = r.gen_ascii_chars().take(100).collect();

        r.reseed(&s);

        let string2: String = r.gen_ascii_chars().take(100).collect();
        assert_eq!(string1, string2);
    }

    #[test]
    fn test_rng_true_values() {
        // Test vectors 1 and 2 from
        // http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04
        let seed : &[_] = &[0u32; 8];
        let mut ra: ChaChaRng = SeedableRng::from_seed(seed);

        let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>();
        assert_eq!(v,
                   vec!(0xade0b876, 0x903df1a0, 0xe56a5d40, 0x28bd8653,
                        0xb819d2bd, 0x1aed8da0, 0xccef36a8, 0xc70d778b,
                        0x7c5941da, 0x8d485751, 0x3fe02477, 0x374ad8b8,
                        0xf4b8436a, 0x1ca11815, 0x69b687c3, 0x8665eeb2));

        let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>();
        assert_eq!(v,
                   vec!(0xbee7079f, 0x7a385155, 0x7c97ba98, 0x0d082d73,
                        0xa0290fcb, 0x6965e348, 0x3e53c612, 0xed7aee32,
                        0x7621b729, 0x434ee69c, 0xb03371d5, 0xd539d874,
                        0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b));

        let seed : &[_] = &[0,1,2,3,4,5,6,7];
        let mut ra: ChaChaRng = SeedableRng::from_seed(seed);

        // Store the 17*i-th 32-bit word,
        // i.e., the i-th word of the i-th 16-word block
        let mut v : Vec<u32> = Vec::new();
        for _ in 0..16 {
            v.push(ra.next_u32());
            for _ in 0..16 {
                ra.next_u32();
            }
        }

        assert_eq!(v,
                   vec!(0xf225c81a, 0x6ab1be57, 0x04d42951, 0x70858036,
                        0x49884684, 0x64efec72, 0x4be2d186, 0x3615b384,
                        0x11cfa18e, 0xd3c50049, 0x75c775f6, 0x434c6530,
                        0x2c5bad8f, 0x898881dc, 0x5f1c86d9, 0xc1f8e7f4));
    }

    #[test]
    fn test_rng_clone() {
        let seed : &[_] = &[0u32; 8];
        let mut rng: ChaChaRng = SeedableRng::from_seed(seed);
        let mut clone = rng.clone();
        for _ in 0..16 {
            assert_eq!(rng.next_u64(), clone.next_u64());
        }
    }
}
<|endoftext|>


<commit_before>use authoritative::AuthoritativeServer;
use std::io::Result;
use std::io;
use std::io::prelude::*;
use mio::{Token, EventLoop, EventSet, PollOpt, TryRead};
use mio::tcp::{TcpStream};
use byteorder::{ByteOrder, BigEndian, LittleEndian};

pub struct GameClient{
    socket: TcpStream,
    token: Token
}

impl GameClient{
    pub fn new(socket: TcpStream, token: Token) -> GameClient{
        GameClient {
            socket: socket,
            token: token,
        }
    }

    pub fn register(&mut self, event_loop: &mut EventLoop<AuthoritativeServer>) -> Result<()>{
        println!("Registering token {:?}", self.token);

        event_loop.register(
            &self.socket,
            self.token,
            EventSet::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).and_then(|(),|{
            Ok(())
        }).or_else(|e|{
            println!("Failed to register {:?}, {:?}", self.token, e);
            Err(e)
        })
    }

    pub fn reregister(&mut self, event_loop: &mut EventLoop<AuthoritativeServer>) -> Result<()>{
        println!("Reregistering token {:?}", self.token);

        event_loop.reregister(
            &self.socket,
            self.token,
            EventSet::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).and_then(|(),|{
            Ok(())
        }).or_else(|e|{
            println!("Failed to reregister {:?}, {:?}", self.token, e);
            Err(e)
        })
    }

    pub fn read(&mut self) -> Result<Option<u64>>{
        println!("Fuck yeah!");

        let mut buf = [0u8; 12];

        let bytes_read = match self.socket.try_read(&mut buf){
            Ok(None) => { return Ok(None); },
            Ok(Some(n)) => n,
            Err(e) => { return Err(e); }
        };

        println!("Received: {:?}, {} bytes", buf, bytes_read);

        let some_fucking_value = BigEndian::read_u16(buf[0..2].as_ref());

        println!("Read {}", some_fucking_value);

        let mut recv_buf : Vec<u8> = Vec::with_capacity(8);

        let read_socket = <TcpStream as Read>::by_ref(&mut self.socket);

        match read_socket.take(8).try_read_buf(&mut recv_buf){
            Ok(None) => {},
            Ok(Some(n)) => {},
            Err(e) => {}
        };

        while let Some(b) = read_socket.take(1).try_read_buf(&mut recv_buf).ok(){
            match b{
                None => { break; },
                Some(bytes) => { println!("Read {:?} bytes", bytes); },
            };
        }

        Ok(None)
    }
}
<commit_msg>yey, messages are actually reading!<commit_after>use authoritative::AuthoritativeServer;
use std::io::Result;
use std::io;
use std::io::prelude::*;
use mio::{Token, EventLoop, EventSet, PollOpt, TryRead};
use mio::tcp::{TcpStream};
use byteorder::{ByteOrder, BigEndian, LittleEndian};

pub struct GameClient{
    socket: TcpStream,
    token: Token
}

impl GameClient{
    pub fn new(socket: TcpStream, token: Token) -> GameClient{
        GameClient {
            socket: socket,
            token: token,
        }
    }

    pub fn register(&mut self, event_loop: &mut EventLoop<AuthoritativeServer>) -> Result<()>{
        println!("Registering token {:?}", self.token);

        event_loop.register(
            &self.socket,
            self.token,
            EventSet::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).and_then(|(),|{
            Ok(())
        }).or_else(|e|{
            println!("Failed to register {:?}, {:?}", self.token, e);
            Err(e)
        })
    }

    pub fn reregister(&mut self, event_loop: &mut EventLoop<AuthoritativeServer>) -> Result<()>{
        println!("Reregistering token {:?}", self.token);

        event_loop.reregister(
            &self.socket,
            self.token,
            EventSet::readable(),
            PollOpt::edge() | PollOpt::oneshot()
        ).and_then(|(),|{
            Ok(())
        }).or_else(|e|{
            println!("Failed to reregister {:?}, {:?}", self.token, e);
            Err(e)
        })
    }

    pub fn read(&mut self) -> Result<Option<u64>>{
        //println!("Fuck yeah!");

        // let mut buf = [0u8; 12];

        // let bytes_read = match self.socket.try_read(&mut buf){
            // Ok(None) => { return Ok(None); },
            // Ok(Some(n)) => n,
            // Err(e) => { return Err(e); }
        // };

        //let some_fucking_value = BigEndian::read_u16(buf[0..2].as_ref());

        //println!("Read {}", some_fucking_value);

        let mut recv_buf : Vec<u8> = Vec::with_capacity(8);

        let read_socket = <TcpStream as Read>::by_ref(&mut self.socket);

        // match read_socket.take(8).try_read_buf(&mut recv_buf){
        //     Ok(None) => {},
        //     Ok(Some(n)) => {},
        //     Err(e) => {}
        // };

        let mut total_bytes = 0;
        while let Some(b) = read_socket.take(8).try_read_buf(&mut recv_buf).ok(){
            match b{
                None => { break; },
                Some(bytes) => {
                    total_bytes += bytes;
                },
            };
        }

        recv_buf.truncate(total_bytes);

        //println!("Received: {:?}, {} bytes", recv_buf, total_bytes);

        let message : String = String::from_utf8(recv_buf).expect("Failed to read message!");

        println!("Received message: {}", message);

        Ok(None)
    }
}
<|endoftext|>


<commit_before>use std::io::{TcpStream, BufferedReader, BufferedWriter};
use std::io::{IoResult};
use std::io::net::ip::{Ipv4Addr, Ipv6Addr};
use std::rc::{Rc, Weak};
//use std::sync::{Arc, Weak};
use std::cell::{RefCell};
use std::rand::{random};
use std::fmt::{Show, Formatter, FormatError};

use message::{RawMessage};
use cmd::{Command, REPLY, ResponseCode};

use server::{Event, ClientConnected, MessageReceived};

pub type SharedClient = Rc<RefCell<Client>>;
pub type WeaklySharedClient = Weak<RefCell<Client>>;

/// Unique client id
#[deriving(Hash)]
pub struct ClientId {
    id: [u64, ..2]
}

impl ClientId {
    /// The client id is losely inspired by SILC but the silc
    /// method of using the nickname is not applicable to IRC
    fn new(stream: &mut TcpStream) -> ClientId {
        ClientId {
            id: [
                match stream.socket_name().unwrap().ip {
                    Ipv4Addr(a, b, c, d) => a as u32 <<24 | b as u32<<16 | c as u32<<8 | d as u32,
                    Ipv6Addr(_, _, _, _, _, _, a, b) => a as u32 << 16 | b as u32
                } as u64 << 32
                | match stream.peer_name().unwrap().ip {
                    Ipv4Addr(a, b, c, d) => a as u32 <<24 | b as u32 <<16 | c as u32 <<8 | d as u32,
                    Ipv6Addr(_, _, _, _, _, _, a, b) => a as u32  << 16 | b as u32
                } as u64,
                random()
            ]
        }
    }
}

impl PartialEq for ClientId {
    #[inline]
    fn eq(&self, other: &ClientId) -> bool {
        self.id == other.id
    }
}

impl Eq for ClientId {}

impl Show for ClientId {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatError> {
        write!(fmt, "{:x}{:x}", self.id[0], self.id[1])
    }
}

impl Clone for ClientId {
    fn clone(&self) -> ClientId {
        ClientId { id: [ self.id[0], self.id[1] ] }
    }
}

/// Proxy that forwards a message to a client
pub struct ClientProxy {
    tx: Sender<RawMessage>
}

impl ClientProxy {
    fn new(tx: Sender<RawMessage>) -> ClientProxy {
        ClientProxy {
            tx: tx
        }
    }
    pub fn send_msg(&self, msg: RawMessage) {
        self.tx.send(msg)
    }
}

pub struct Client {
    id: ClientId,
    msg_tx: Sender<RawMessage>,
    stream: TcpStream,
    server_host: String,
    hostname: String,
    pub ip: String,
    pub nickname: String,
    pub username: String,
    pub realname: String,
}

impl Client {
    /// Spawns two threads for communication with the client
    /// Returns a SharedClient instance.
    /// TODO handle failures
    pub fn listen(host: String, mut stream: TcpStream,
                         tx: Sender<Event>) -> IoResult<()> {
        let (msg_tx, rx) = channel();
        let peer_name = stream.peer_name().unwrap();
        let this = Client {
            id: ClientId::new(&mut stream),
            msg_tx: msg_tx,
            stream: stream.clone(),
            server_host: host,
            hostname: self::net::get_nameinfo(peer_name),
            ip: format!("{}", peer_name.ip),
            nickname: "".to_string(),
            username: "".to_string(),
            realname: "".to_string()
        };
        debug!("hostname of client is {}", this.hostname)
        let receiving_stream = stream.clone();
        let id = this.id;
        // this has to be sended first otherwise we have a nice race conditions
        tx.send(ClientConnected(this));
        spawn(proc() {
            // TODO: write a proper 510 char line iterator
            for line in BufferedReader::new(receiving_stream).lines() {
                let message = RawMessage::parse(line.unwrap().as_slice().trim_right().as_bytes()).unwrap();
                debug!("received message {}", message.to_string());
                tx.send(MessageReceived(id, message))
            }
        });
        spawn(proc() {
            // TODO: socket timeout
            // implement when pings are send out
            let mut output_stream = BufferedWriter::new(stream);
            for message in rx.iter() {
                debug!("sending message {}", message.to_string());
                output_stream.write(message.as_slice()).unwrap();
                output_stream.write(b"\r\n").unwrap();
                output_stream.flush().unwrap();
            }
        });
        Ok(())
    }

    /// Converts the Client to a shared client
    pub fn as_shared(self) -> SharedClient {
        Rc::new(RefCell::new(self))
    }

    /// Sends a numeric response code to the client.
    /// Returns immediately.
    pub fn send_response<'a>(&'a self, response: ResponseCode,
                         origin: Option<&'a str>, reason: Option<&'a str>) {
        let mut params: Vec<&'a str> = Vec::with_capacity(2);
        if self.nickname.len() == 0 {
            // TODO follow rust-dev
            // this static lifetime made all lifetime annotations necessary
            params.push("*")
        } else {
            params.push(self.nickname.as_slice())
        }
        if origin.is_some() {
            params.push(origin.unwrap())
        }
        if reason.is_some() {
            params.push(reason.unwrap())
        }
        self.send_msg(RawMessage::new(REPLY(response),
            params.as_slice(), Some(self.server_host.as_slice())))
    }

    /// Sends constructs a message and sends it the client
    pub fn send(&self, command: Command, params: &[&str], prefix: Option<&str>) {
        // Note mem::transmute is safe in this case, since &[&str] is just &[&[u8].
        self.send_msg(RawMessage::new(
            command, params, prefix
        ))
    }

    /// Sends a message to the client.
    /// Returns immediately.
    pub fn send_msg(&self, message: RawMessage) {
        self.msg_tx.send(message)
    }

    /// Closes the connection to the client
    pub fn close_connection(&mut self) {
        let _ = self.stream.close_read();
        let _ = self.stream.close_write();
    }

    /// Accessor for the client id
    #[inline]
    pub fn id(&self) -> ClientId {
        self.id
    }

    /// Returns a proxy to the current client
    pub fn proxy(&self) -> ClientProxy {
        ClientProxy::new(self.msg_tx.clone())
    }
}

impl PartialEq for Client {
    #[inline]
    fn eq(&self, other: &Client) -> bool {
        self.id == other.id
    }
}

impl Eq for Client {}

mod net {

    use std::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
    use libc::{malloc, sockaddr, sockaddr_in, sockaddr_in6, in_addr, in6_addr, c_int, c_char, socklen_t, AF_INET, AF_INET6};
    use std::mem::{size_of, transmute};
    use std::string;

    /*
     const char *
         inet_ntop(int af, const void * restrict src, char * restrict dst,
             socklen_t size);
    */
    extern {
        fn getnameinfo(sa: *const sockaddr, salen: socklen_t,
                       host: *mut c_char, hostlen: socklen_t,
                       serv: *mut c_char, servlen: socklen_t,
                       flags: c_int) -> c_int;
    }

    //static NI_NUMERICHOST: c_int = 0x00000002;
    //static NI_NAMEREQD: c_int = 0x00000004;

    /// Returns the hostname for an ip address
    /// TODO: make this safe, see manpage
    pub fn get_nameinfo(peer_socket: SocketAddr) -> String {
        let SocketAddr { ip: ip, port: port } = peer_socket;
        let buf: *mut i8;
        let _ = unsafe {
            let hostlen = 80;
            buf = transmute(malloc(hostlen as u64 + 1));
            match ip {
                Ipv4Addr(a, b, c, d) => {
                    let addr = in_addr {
                        s_addr: a as u32 << 24
                              | b as u32 << 16
                              | c as u32 << 8
                              | d as u32
                    };
                    let sockaddr = sockaddr_in {
                        sin_len: size_of::<sockaddr_in>() as u8,
                        sin_family: AF_INET as u8,
                        sin_port: port,
                        sin_addr: addr,
                        sin_zero: [0, ..8]
                    };
                    getnameinfo(transmute(&sockaddr), size_of::<sockaddr_in>() as i32,
                                buf, hostlen, transmute(0u), 0, 0)
                },
                Ipv6Addr(a, b, c, d, e, f, g, h) => {
                    let sockaddr = sockaddr_in6 {
                        sin6_len: size_of::<sockaddr_in6>() as u8,
                        sin6_family: AF_INET6 as u8,
                        sin6_port: port,
                        sin6_flowinfo: 0,
                        sin6_addr: in6_addr {
                            s6_addr: [a, b, c, d, e, f, g, h]
                        },
                        sin6_scope_id: 0,
                    };
                    getnameinfo(transmute(&sockaddr), size_of::<sockaddr_in6>() as i32,
                                buf, hostlen, transmute(0u), 0, 0)
                },
            }

        };
        unsafe {string::raw::from_buf(transmute(buf))}

    }
}<commit_msg>prevent failure of main task<commit_after>use std::io::{TcpStream, BufferedReader, BufferedWriter};
use std::io::{IoResult};
use std::io::net::ip::{Ipv4Addr, Ipv6Addr};
use std::rc::{Rc, Weak};
//use std::sync::{Arc, Weak};
use std::cell::{RefCell};
use std::rand::{random};
use std::fmt::{Show, Formatter, FormatError};

use message::{RawMessage};
use cmd::{Command, REPLY, ResponseCode};

use server::{Event, ClientConnected, MessageReceived};

pub type SharedClient = Rc<RefCell<Client>>;
pub type WeaklySharedClient = Weak<RefCell<Client>>;

/// Unique client id
#[deriving(Hash)]
pub struct ClientId {
    id: [u64, ..2]
}

impl ClientId {
    /// The client id is losely inspired by SILC but the silc
    /// method of using the nickname is not applicable to IRC
    fn new(stream: &mut TcpStream) -> ClientId {
        ClientId {
            id: [
                match stream.socket_name().unwrap().ip {
                    Ipv4Addr(a, b, c, d) => a as u32 <<24 | b as u32<<16 | c as u32<<8 | d as u32,
                    Ipv6Addr(_, _, _, _, _, _, a, b) => a as u32 << 16 | b as u32
                } as u64 << 32
                | match stream.peer_name().unwrap().ip {
                    Ipv4Addr(a, b, c, d) => a as u32 <<24 | b as u32 <<16 | c as u32 <<8 | d as u32,
                    Ipv6Addr(_, _, _, _, _, _, a, b) => a as u32  << 16 | b as u32
                } as u64,
                random()
            ]
        }
    }
}

impl PartialEq for ClientId {
    #[inline]
    fn eq(&self, other: &ClientId) -> bool {
        self.id == other.id
    }
}

impl Eq for ClientId {}

impl Show for ClientId {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), FormatError> {
        write!(fmt, "{:x}{:x}", self.id[0], self.id[1])
    }
}

impl Clone for ClientId {
    fn clone(&self) -> ClientId {
        ClientId { id: [ self.id[0], self.id[1] ] }
    }
}

/// Proxy that forwards a message to a client
pub struct ClientProxy {
    tx: Sender<RawMessage>
}

impl ClientProxy {
    fn new(tx: Sender<RawMessage>) -> ClientProxy {
        ClientProxy {
            tx: tx
        }
    }
    pub fn send_msg(&self, msg: RawMessage) {
        let _ = self.tx.send_opt(msg);
    }
}

pub struct Client {
    id: ClientId,
    msg_tx: Sender<RawMessage>,
    stream: TcpStream,
    server_host: String,
    hostname: String,
    pub ip: String,
    pub nickname: String,
    pub username: String,
    pub realname: String,
}

impl Client {
    /// Spawns two threads for communication with the client
    /// Returns a SharedClient instance.
    /// TODO handle failures
    pub fn listen(host: String, mut stream: TcpStream,
                         tx: Sender<Event>) -> IoResult<()> {
        let (msg_tx, rx) = channel();
        let peer_name = stream.peer_name().unwrap();
        let this = Client {
            id: ClientId::new(&mut stream),
            msg_tx: msg_tx,
            stream: stream.clone(),
            server_host: host,
            hostname: self::net::get_nameinfo(peer_name),
            ip: format!("{}", peer_name.ip),
            nickname: "".to_string(),
            username: "".to_string(),
            realname: "".to_string()
        };
        debug!("hostname of client is {}", this.hostname)
        let receiving_stream = stream.clone();
        let id = this.id;
        // this has to be sended first otherwise we have a nice race conditions
        tx.send(ClientConnected(this));
        spawn(proc() {
            // TODO: write a proper 510 char line iterator
            for line in BufferedReader::new(receiving_stream).lines() {
                let message = RawMessage::parse(line.unwrap().as_slice().trim_right().as_bytes()).unwrap();
                debug!("received message {}", message.to_string());
                tx.send(MessageReceived(id, message))
            }
        });
        spawn(proc() {
            // TODO: socket timeout
            // implement when pings are send out
            let mut output_stream = BufferedWriter::new(stream);
            for message in rx.iter() {
                debug!("sending message {}", message.to_string());
                output_stream.write(message.as_slice()).unwrap();
                output_stream.write(b"\r\n").unwrap();
                output_stream.flush().unwrap();
            }
        });
        Ok(())
    }

    /// Converts the Client to a shared client
    pub fn as_shared(self) -> SharedClient {
        Rc::new(RefCell::new(self))
    }

    /// Sends a numeric response code to the client.
    /// Returns immediately.
    pub fn send_response<'a>(&'a self, response: ResponseCode,
                         origin: Option<&'a str>, reason: Option<&'a str>) {
        let mut params: Vec<&'a str> = Vec::with_capacity(2);
        if self.nickname.len() == 0 {
            // TODO follow rust-dev
            // this static lifetime made all lifetime annotations necessary
            params.push("*")
        } else {
            params.push(self.nickname.as_slice())
        }
        if origin.is_some() {
            params.push(origin.unwrap())
        }
        if reason.is_some() {
            params.push(reason.unwrap())
        }
        self.send_msg(RawMessage::new(REPLY(response),
            params.as_slice(), Some(self.server_host.as_slice())))
    }

    /// Sends constructs a message and sends it the client
    pub fn send(&self, command: Command, params: &[&str], prefix: Option<&str>) {
        // Note mem::transmute is safe in this case, since &[&str] is just &[&[u8].
        self.send_msg(RawMessage::new(
            command, params, prefix
        ))
    }

    /// Sends a message to the client.
    /// Returns immediately.
    pub fn send_msg(&self, message: RawMessage) {
        let _ = self.msg_tx.send(message);
    }

    /// Closes the connection to the client
    pub fn close_connection(&mut self) {
        let _ = self.stream.close_read();
        let _ = self.stream.close_write();
    }

    /// Accessor for the client id
    #[inline]
    pub fn id(&self) -> ClientId {
        self.id
    }

    /// Returns a proxy to the current client
    pub fn proxy(&self) -> ClientProxy {
        ClientProxy::new(self.msg_tx.clone())
    }
}

impl PartialEq for Client {
    #[inline]
    fn eq(&self, other: &Client) -> bool {
        self.id == other.id
    }
}

impl Eq for Client {}

mod net {

    use std::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
    use libc::{malloc, sockaddr, sockaddr_in, sockaddr_in6, in_addr, in6_addr, c_int, c_char, socklen_t, AF_INET, AF_INET6};
    use std::mem::{size_of, transmute};
    use std::string;

    /*
     const char *
         inet_ntop(int af, const void * restrict src, char * restrict dst,
             socklen_t size);
    */
    extern {
        fn getnameinfo(sa: *const sockaddr, salen: socklen_t,
                       host: *mut c_char, hostlen: socklen_t,
                       serv: *mut c_char, servlen: socklen_t,
                       flags: c_int) -> c_int;
    }

    //static NI_NUMERICHOST: c_int = 0x00000002;
    //static NI_NAMEREQD: c_int = 0x00000004;

    /// Returns the hostname for an ip address
    /// TODO: make this safe, see manpage
    pub fn get_nameinfo(peer_socket: SocketAddr) -> String {
        let SocketAddr { ip: ip, port: port } = peer_socket;
        let buf: *mut i8;
        let _ = unsafe {
            let hostlen = 80;
            buf = transmute(malloc(hostlen as u64 + 1));
            match ip {
                Ipv4Addr(a, b, c, d) => {
                    let addr = in_addr {
                        s_addr: a as u32 << 24
                              | b as u32 << 16
                              | c as u32 << 8
                              | d as u32
                    };
                    let sockaddr = sockaddr_in {
                        sin_len: size_of::<sockaddr_in>() as u8,
                        sin_family: AF_INET as u8,
                        sin_port: port,
                        sin_addr: addr,
                        sin_zero: [0, ..8]
                    };
                    getnameinfo(transmute(&sockaddr), size_of::<sockaddr_in>() as i32,
                                buf, hostlen, transmute(0u), 0, 0)
                },
                Ipv6Addr(a, b, c, d, e, f, g, h) => {
                    let sockaddr = sockaddr_in6 {
                        sin6_len: size_of::<sockaddr_in6>() as u8,
                        sin6_family: AF_INET6 as u8,
                        sin6_port: port,
                        sin6_flowinfo: 0,
                        sin6_addr: in6_addr {
                            s6_addr: [a, b, c, d, e, f, g, h]
                        },
                        sin6_scope_id: 0,
                    };
                    getnameinfo(transmute(&sockaddr), size_of::<sockaddr_in6>() as i32,
                                buf, hostlen, transmute(0u), 0, 0)
                },
            }

        };
        unsafe {string::raw::from_buf(transmute(buf))}

    }
}<|endoftext|>