<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::AttrBinding;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::Node;
use dom::window::Window;
use dom::virtualmethods::vtable_for;

use devtools_traits::AttrInfo;
use servo_util::str::{DOMString, split_html_space_chars};
use std::cell::{Ref, RefCell};
use std::mem;
use std::slice::Items;
use string_cache::{Atom, Namespace};

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[deriving(PartialEq, Clone)]
#[jstraceable]
pub enum AttrValue {
    StringAttrValue(DOMString),
    TokenListAttrValue(DOMString, Vec<Atom>),
    UIntAttrValue(DOMString, u32),
    AtomAttrValue(Atom),
}

impl AttrValue {
    pub fn from_tokenlist(tokens: DOMString) -> AttrValue {
        let atoms = split_html_space_chars(tokens.as_slice())
            .map(|token| Atom::from_slice(token)).collect();
        TokenListAttrValue(tokens, atoms)
    }

    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        let result: u32 = from_str(string.as_slice()).unwrap_or(default);
        UIntAttrValue(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(string.as_slice());
        AtomAttrValue(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<Items<'a, Atom>> {
        match *self {
            TokenListAttrValue(_, ref tokens) => Some(tokens.iter()),
            _ => None
        }
    }
}

impl Str for AttrValue {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self {
            StringAttrValue(ref value) |
            TokenListAttrValue(ref value, _) |
            UIntAttrValue(ref value, _) => value.as_slice(),
            AtomAttrValue(ref value) => value.as_slice(),
        }
    }
}

#[jstraceable]
#[must_root]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: Traceable<RefCell<AttrValue>>,
    pub name: Atom,
    pub namespace: Namespace,
    pub prefix: Option<DOMString>,

    /// the element that owns this attribute.
    owner: JS<Element>,
}

impl Reflectable for Attr {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue,
                     name: Atom, namespace: Namespace,
                     prefix: Option<DOMString>, owner: JSRef<Element>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: Traceable::new(RefCell::new(value)),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: JS::from_rooted(owner),
        }
    }

    pub fn new(window: JSRef<Window>, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<DOMString>, owner: JSRef<Element>) -> Temporary<Attr> {
        reflect_dom_object(box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
                           &global::Window(window), AttrBinding::Wrap)
    }
}

impl<'a> AttrMethods for JSRef<'a, Attr> {
    fn LocalName(self) -> DOMString {
        self.local_name().as_slice().to_string()
    }

    fn Value(self) -> DOMString {
        self.value().as_slice().to_string()
    }

    fn SetValue(self, value: DOMString) {
        let owner = self.owner.root();
        let value = owner.deref().parse_attribute(&self.namespace, self.local_name(), value);
        self.set_value(ReplacedAttr, value);
    }

    fn Name(self) -> DOMString {
        self.name.as_slice().to_string()
    }

    fn GetNamespaceURI(self) -> Option<DOMString> {
        let Namespace(ref atom) = self.namespace;
        match atom.as_slice() {
            "" => None,
            url => Some(url.to_string()),
        }
    }

    fn GetPrefix(self) -> Option<DOMString> {
        self.prefix.clone()
    }
}

pub trait AttrHelpers<'a> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue);
    fn value(self) -> Ref<'a, AttrValue>;
    fn local_name(self) -> &'a Atom;
    fn summarize(self) -> AttrInfo;
}

impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue) {
        let owner = self.owner.root();
        let node: JSRef<Node> = NodeCast::from_ref(*owner);
        let namespace_is_null = self.namespace == ns!("");

        match set_type {
            ReplacedAttr => {
                if namespace_is_null {
                    vtable_for(&node).before_remove_attr(
                        self.local_name(),
                        self.value().as_slice().to_string())
                }
            }
            FirstSetAttr => {}
        }

        *self.value.deref().borrow_mut() = value;

        if namespace_is_null {
            vtable_for(&node).after_set_attr(
                self.local_name(),
                self.value().as_slice().to_string())
        }
    }

    fn value(self) -> Ref<'a, AttrValue> {
        self.extended_deref().value.borrow()
    }

    fn local_name(self) -> &'a Atom {
        &self.extended_deref().local_name
    }

    fn summarize(self) -> AttrInfo {
        let Namespace(ref ns) = self.namespace;
        AttrInfo {
            namespace: ns.as_slice().to_string(),
            name: self.Name(),
            value: self.Value(),
        }
    }
}

pub trait AttrHelpersForLayout {
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
    unsafe fn value_tokens_forever(&self) -> Option<Items<Atom>>;
    unsafe fn local_name_atom_forever(&self) -> Atom;
}

impl AttrHelpersForLayout for Attr {
    unsafe fn value_ref_forever(&self) -> &'static str {
        // cast to point to T in RefCell<T> directly
        let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref());
        value.as_slice()
    }

    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        // cast to point to T in RefCell<T> directly
        let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref());
        match *value {
            AtomAttrValue(ref val) => Some(val.clone()),
            _ => None,
        }
    }

    unsafe fn value_tokens_forever(&self) -> Option<Items<Atom>> {
        // cast to point to T in RefCell<T> directly
        let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref());
        match *value {
            TokenListAttrValue(_, ref tokens) => Some(tokens.iter()),
            _ => None,
        }
    }

    unsafe fn local_name_atom_forever(&self) -> Atom {
        self.local_name.clone()
    }
}
<commit_msg>Remove Traceable from attr.rs<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::AttrBinding;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::Node;
use dom::window::Window;
use dom::virtualmethods::vtable_for;

use devtools_traits::AttrInfo;
use servo_util::str::{DOMString, split_html_space_chars};
use std::cell::{Ref, RefCell};
use std::mem;
use std::slice::Items;
use string_cache::{Atom, Namespace};

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[deriving(PartialEq, Clone)]
#[jstraceable]
pub enum AttrValue {
    StringAttrValue(DOMString),
    TokenListAttrValue(DOMString, Vec<Atom>),
    UIntAttrValue(DOMString, u32),
    AtomAttrValue(Atom),
}

impl AttrValue {
    pub fn from_tokenlist(tokens: DOMString) -> AttrValue {
        let atoms = split_html_space_chars(tokens.as_slice())
            .map(|token| Atom::from_slice(token)).collect();
        TokenListAttrValue(tokens, atoms)
    }

    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        let result: u32 = from_str(string.as_slice()).unwrap_or(default);
        UIntAttrValue(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(string.as_slice());
        AtomAttrValue(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<Items<'a, Atom>> {
        match *self {
            TokenListAttrValue(_, ref tokens) => Some(tokens.iter()),
            _ => None
        }
    }
}

impl Str for AttrValue {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self {
            StringAttrValue(ref value) |
            TokenListAttrValue(ref value, _) |
            UIntAttrValue(ref value, _) => value.as_slice(),
            AtomAttrValue(ref value) => value.as_slice(),
        }
    }
}

#[jstraceable]
#[must_root]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: RefCell<AttrValue>,
    pub name: Atom,
    pub namespace: Namespace,
    pub prefix: Option<DOMString>,

    /// the element that owns this attribute.
    owner: JS<Element>,
}

impl Reflectable for Attr {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue,
                     name: Atom, namespace: Namespace,
                     prefix: Option<DOMString>, owner: JSRef<Element>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: RefCell::new(value),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: JS::from_rooted(owner),
        }
    }

    pub fn new(window: JSRef<Window>, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<DOMString>, owner: JSRef<Element>) -> Temporary<Attr> {
        reflect_dom_object(box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
                           &global::Window(window), AttrBinding::Wrap)
    }
}

impl<'a> AttrMethods for JSRef<'a, Attr> {
    fn LocalName(self) -> DOMString {
        self.local_name().as_slice().to_string()
    }

    fn Value(self) -> DOMString {
        self.value().as_slice().to_string()
    }

    fn SetValue(self, value: DOMString) {
        let owner = self.owner.root();
        let value = owner.deref().parse_attribute(&self.namespace, self.local_name(), value);
        self.set_value(ReplacedAttr, value);
    }

    fn Name(self) -> DOMString {
        self.name.as_slice().to_string()
    }

    fn GetNamespaceURI(self) -> Option<DOMString> {
        let Namespace(ref atom) = self.namespace;
        match atom.as_slice() {
            "" => None,
            url => Some(url.to_string()),
        }
    }

    fn GetPrefix(self) -> Option<DOMString> {
        self.prefix.clone()
    }
}

pub trait AttrHelpers<'a> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue);
    fn value(self) -> Ref<'a, AttrValue>;
    fn local_name(self) -> &'a Atom;
    fn summarize(self) -> AttrInfo;
}

impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue) {
        let owner = self.owner.root();
        let node: JSRef<Node> = NodeCast::from_ref(*owner);
        let namespace_is_null = self.namespace == ns!("");

        match set_type {
            ReplacedAttr => {
                if namespace_is_null {
                    vtable_for(&node).before_remove_attr(
                        self.local_name(),
                        self.value().as_slice().to_string())
                }
            }
            FirstSetAttr => {}
        }

        *self.value.borrow_mut() = value;

        if namespace_is_null {
            vtable_for(&node).after_set_attr(
                self.local_name(),
                self.value().as_slice().to_string())
        }
    }

    fn value(self) -> Ref<'a, AttrValue> {
        self.extended_deref().value.borrow()
    }

    fn local_name(self) -> &'a Atom {
        &self.extended_deref().local_name
    }

    fn summarize(self) -> AttrInfo {
        let Namespace(ref ns) = self.namespace;
        AttrInfo {
            namespace: ns.as_slice().to_string(),
            name: self.Name(),
            value: self.Value(),
        }
    }
}

pub trait AttrHelpersForLayout {
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
    unsafe fn value_tokens_forever(&self) -> Option<Items<Atom>>;
    unsafe fn local_name_atom_forever(&self) -> Atom;
}

impl AttrHelpersForLayout for Attr {
    unsafe fn value_ref_forever(&self) -> &'static str {
        // cast to point to T in RefCell<T> directly
        let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(&self.value);
        value.as_slice()
    }

    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        // cast to point to T in RefCell<T> directly
        let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(&self.value);
        match *value {
            AtomAttrValue(ref val) => Some(val.clone()),
            _ => None,
        }
    }

    unsafe fn value_tokens_forever(&self) -> Option<Items<Atom>> {
        // cast to point to T in RefCell<T> directly
        let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(&self.value);
        match *value {
            TokenListAttrValue(_, ref tokens) => Some(tokens.iter()),
            _ => None,
        }
    }

    unsafe fn local_name_atom_forever(&self) -> Atom {
        self.local_name.clone()
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::net::Ipv6Addr;

use fcp_cryptoauth::{publickey_to_ipv6addr, PublicKey};

use operation::{BackwardPath, Director, ForwardPath};
use packets::control::ControlPacket;
use packets::data::DataPacket;
use packets::data::Payload as DataPayload;
use packets::data::DATAPACKET_VERSION;
use packets::route::RoutePacket;
use packets::switch::Payload as SwitchPayload;
use packets::switch::SwitchPacket;
use passive_switch::PassiveSwitch;
use session_manager::MySessionHandle;
use session_manager::SessionManager;
use utils::new_from_raw_content;

pub struct Ip6Content {
    pub addr: Ipv6Addr,
    pub next_header: u8,
    pub content: Vec<u8>,
}

pub trait RouterTrait {
    /// Called when a RoutePacket is received from the network.
    /// Optionally returns RoutePackets to send back.
    fn on_route_packet(
        &mut self,
        packet: &RoutePacket,
        path: BackwardPath,
        handle: MySessionHandle,
        pk: PublicKey,
    ) -> Vec<RoutePacket>;
}

pub trait NetworkAdapterTrait {
    fn send_to(&mut self, to: Director, packet: &SwitchPacket);
    fn recv_from(&mut self) -> Option<(Director, Vec<SwitchPacket>)>;

    fn directors(&self) -> Vec<Director>;
    fn get_pk(&self, dir: Director) -> Option<&PublicKey>;
}

pub struct Plumbing<Router: RouterTrait, NetworkAdapter: NetworkAdapterTrait> {
    pub router: Router,
    pub network_adapter: NetworkAdapter,
    pub switch: PassiveSwitch,
    pub session_manager: SessionManager,
    /// If not `None`, holds a list of the opaque data received in Pong
    /// packets. Use only when debugging, as it is a DoS vulnerability.
    pub pongs: Option<VecDeque<Vec<u8>>>,
    /// Received "content" packets.
    pub rx_buffer: VecDeque<Ip6Content>,
}

impl<Router: RouterTrait, NetworkAdapter: NetworkAdapterTrait> Plumbing<Router, NetworkAdapter> {
    fn on_control_packet(&mut self, packet: ControlPacket, path: BackwardPath) {
        match packet {
            ControlPacket::Ping { opaque_data, .. } => {
                // If it is a ping packet, just reply to it.
                let control_response = ControlPacket::Pong {
                    version: 18,
                    opaque_data: opaque_data,
                };
                let packet_response =
                    SwitchPacket::new(path.reverse(), SwitchPayload::Control(control_response));
                self.dispatch(packet_response, 0b001);
            }
            ControlPacket::Pong { opaque_data, .. } => {
                if let Some(ref mut pongs) = self.pongs {
                    pongs.push_back(opaque_data);
                }
            }
            _ => panic!("Can only handle Pings and Pongs."),
        }
    }

    /// Called when a switch packet is sent to the self interface
    fn on_self_interface_switch_packet(
        &mut self,
        switch_packet: &SwitchPacket,
    ) -> Option<(MySessionHandle, Vec<DataPacket>)> {
        match switch_packet.payload() {
            Some(SwitchPayload::Control(control_packet)) => {
                self.on_control_packet(control_packet, switch_packet.label().into());
                None
            }
            Some(SwitchPayload::CryptoAuthHello(handshake)) => {
                // If it is a CryptoAuth handshake Hello packet (ie. if someone is
                // connecting to us), create a new session for this node.
                let (handle, inner_packet) =
                    self.session_manager.on_hello(handshake, switch_packet);
                if inner_packet.len() > 0 {
                    let inner_packet = DataPacket::new_from_raw(inner_packet)
                        .expect("Could not decode data packet");
                    Some((handle, vec![inner_packet]))
                } else {
                    Some((handle, vec![]))
                }
            }
            Some(SwitchPayload::CryptoAuthKey(handshake)) => {
                // If it is a CryptoAuth handshake Key packet (ie. if someone is
                // replies to our connection attempt), find its session and
                // update it.
                Some(self.session_manager.on_key(handshake, switch_packet))
            }
            Some(SwitchPayload::CryptoAuthData(handle, ca_message)) => {
                // If it is a CryptoAuth data packet, first read the session
                // handle to know which CryptoAuth session to use to
                // decrypt it.
                let handle = MySessionHandle(handle);
                let inner_packets = self.session_manager.unwrap_message(handle, ca_message);
                Some((handle, inner_packets))
            }
            _ => panic!("Can only handle Pings, Pongs, and CA."),
        }
    }

    /// Called when a CryptoAuth-wrapped message is received through an end-to-end
    /// session.
    fn on_data_packet(
        &mut self,
        data_packet: &DataPacket,
        handle: MySessionHandle,
        path: BackwardPath,
    ) {
        let mut responses = Vec::new();
        {
            let session = self.session_manager.get_session(handle).unwrap();

            let route_packets = match data_packet.payload().unwrap() {
                DataPayload::Ip6Content(next_header, ref content) => {
                    let their_pk = session.conn.their_pk();
                    let their_ipv6_addr = publickey_to_ipv6addr(their_pk);
                    self.rx_buffer.push_back(Ip6Content {
                        addr: their_ipv6_addr,
                        next_header,
                        content: content.clone(), // TODO: do not clone
                    });
                    Vec::new()
                }
                DataPayload::RoutePacket(route_packet) => self.router.on_route_packet(
                    &route_packet,
                    path,
                    handle,
                    session.conn.their_pk().clone(),
                ),
            };
            for route_packet in route_packets.into_iter() {
                responses.extend(session.wrap_route_packet(path.reverse(), route_packet));
            }
        }
        for response in responses {
            self.dispatch(response, 0b001);
        }
    }

    pub fn dispatch(
        &mut self,
        packet: SwitchPacket,
        from_interface: Director,
    ) -> Option<(MySessionHandle, Vec<DataPacket>)> {
        let path = BackwardPath::from(packet.label());
        let (to_self, forward) = self.switch.forward(packet, from_interface);
        for (interface, packet) in forward {
            self.network_adapter.send_to(interface, &packet)
        }

        to_self
            .and_then(|packet| self.on_self_interface_switch_packet(&packet))
            .map(|(handle, packets)| {
                for packet in packets.iter() {
                    self.on_data_packet(&packet, handle, path)
                }
                (handle, packets)
            })
    }

    pub fn upkeep(&mut self) -> Vec<(MySessionHandle, Vec<DataPacket>)> {
        let mut to_self = Vec::new();
        if let Some((director, messages)) = self.network_adapter.recv_from() {
            for message in messages.into_iter() {
                if let Some(pkts) = self.dispatch(message, director) {
                    to_self.push(pkts);
                }
            }
        }
        self.upkeep2();
        to_self
    }

    fn upkeep2(&mut self) {
        for message in self.session_manager.upkeep() {
            let to_self = self.dispatch(message, 0b001);
            assert!(to_self.is_none());
        }
    }

    pub fn send_hello(&mut self, path: ForwardPath, pk: PublicKey) {
        let _my_handle = self.session_manager.add_outgoing(Some(path), pk);
        self.upkeep2();
    }

    pub fn send_content_to_path(
        &mut self,
        path: ForwardPath,
        pk: PublicKey,
        ip6_next_header: u8,
        content: Vec<u8>,
        immediately: bool,
    ) {
        let (their_handle, messages) = {
            let session = self.session_manager.get_or_make_session_for_pk(pk);
            let data_payload = DataPayload::Ip6Content(ip6_next_header, content);
            let data_packet = DataPacket::new(DATAPACKET_VERSION, &data_payload);
            let messages = if immediately {
                session.conn.wrap_message_immediately(&data_packet.raw())
            } else {
                session.conn.wrap_message(&data_packet.raw())
            };
            (session.their_handle(), messages)
        };

        for message in messages {
            let switch_packet = new_from_raw_content(path, message, their_handle);
            println!("{:?}", switch_packet);
            self.dispatch(switch_packet, 0b001);
        }
    }

    pub fn send_content(&mut self, _ip6_content: &Ip6Content) {
        unimplemented!("send_content");
    }
}
<commit_msg>Make Plumbing::dispatch give the post-switch path, instead of pre-switch.<commit_after>use std::collections::VecDeque;
use std::net::Ipv6Addr;

use fcp_cryptoauth::{publickey_to_ipv6addr, PublicKey};

use operation::{BackwardPath, Director, ForwardPath};
use packets::control::ControlPacket;
use packets::data::DataPacket;
use packets::data::Payload as DataPayload;
use packets::data::DATAPACKET_VERSION;
use packets::route::RoutePacket;
use packets::switch::Payload as SwitchPayload;
use packets::switch::SwitchPacket;
use passive_switch::PassiveSwitch;
use session_manager::MySessionHandle;
use session_manager::SessionManager;
use utils::new_from_raw_content;

pub struct Ip6Content {
    pub addr: Ipv6Addr,
    pub next_header: u8,
    pub content: Vec<u8>,
}

pub trait RouterTrait {
    /// Called when a RoutePacket is received from the network.
    /// Optionally returns RoutePackets to send back.
    fn on_route_packet(
        &mut self,
        packet: &RoutePacket,
        path: BackwardPath,
        handle: MySessionHandle,
        pk: PublicKey,
    ) -> Vec<RoutePacket>;
}

pub trait NetworkAdapterTrait {
    fn send_to(&mut self, to: Director, packet: &SwitchPacket);
    fn recv_from(&mut self) -> Option<(Director, Vec<SwitchPacket>)>;

    fn directors(&self) -> Vec<Director>;
    fn get_pk(&self, dir: Director) -> Option<&PublicKey>;
}

pub struct Plumbing<Router: RouterTrait, NetworkAdapter: NetworkAdapterTrait> {
    pub router: Router,
    pub network_adapter: NetworkAdapter,
    pub switch: PassiveSwitch,
    pub session_manager: SessionManager,
    /// If not `None`, holds a list of the opaque data received in Pong
    /// packets. Use only when debugging, as it is a DoS vulnerability.
    pub pongs: Option<VecDeque<Vec<u8>>>,
    /// Received "content" packets.
    pub rx_buffer: VecDeque<Ip6Content>,
}

impl<Router: RouterTrait, NetworkAdapter: NetworkAdapterTrait> Plumbing<Router, NetworkAdapter> {
    fn on_control_packet(&mut self, packet: ControlPacket, path: BackwardPath) {
        match packet {
            ControlPacket::Ping { opaque_data, .. } => {
                // If it is a ping packet, just reply to it.
                let control_response = ControlPacket::Pong {
                    version: 18,
                    opaque_data: opaque_data,
                };
                let packet_response =
                    SwitchPacket::new(path.reverse(), SwitchPayload::Control(control_response));
                self.dispatch(packet_response, 0b001);
            }
            ControlPacket::Pong { opaque_data, .. } => {
                if let Some(ref mut pongs) = self.pongs {
                    pongs.push_back(opaque_data);
                }
            }
            _ => panic!("Can only handle Pings and Pongs."),
        }
    }

    /// Called when a switch packet is sent to the self interface
    fn on_self_interface_switch_packet(
        &mut self,
        switch_packet: &SwitchPacket,
    ) -> Option<(MySessionHandle, Vec<DataPacket>)> {
        match switch_packet.payload() {
            Some(SwitchPayload::Control(control_packet)) => {
                self.on_control_packet(control_packet, switch_packet.label().into());
                None
            }
            Some(SwitchPayload::CryptoAuthHello(handshake)) => {
                // If it is a CryptoAuth handshake Hello packet (ie. if someone is
                // connecting to us), create a new session for this node.
                let (handle, inner_packet) =
                    self.session_manager.on_hello(handshake, switch_packet);
                if inner_packet.len() > 0 {
                    let inner_packet = DataPacket::new_from_raw(inner_packet)
                        .expect("Could not decode data packet");
                    Some((handle, vec![inner_packet]))
                } else {
                    Some((handle, vec![]))
                }
            }
            Some(SwitchPayload::CryptoAuthKey(handshake)) => {
                // If it is a CryptoAuth handshake Key packet (ie. if someone is
                // replies to our connection attempt), find its session and
                // update it.
                Some(self.session_manager.on_key(handshake, switch_packet))
            }
            Some(SwitchPayload::CryptoAuthData(handle, ca_message)) => {
                // If it is a CryptoAuth data packet, first read the session
                // handle to know which CryptoAuth session to use to
                // decrypt it.
                let handle = MySessionHandle(handle);
                let inner_packets = self.session_manager.unwrap_message(handle, ca_message);
                Some((handle, inner_packets))
            }
            _ => panic!("Can only handle Pings, Pongs, and CA."),
        }
    }

    /// Called when a CryptoAuth-wrapped message is received through an end-to-end
    /// session.
    fn on_data_packet(
        &mut self,
        data_packet: &DataPacket,
        handle: MySessionHandle,
        path: BackwardPath,
    ) {
        let mut responses = Vec::new();
        {
            let session = self.session_manager.get_session(handle).unwrap();

            let route_packets = match data_packet.payload().unwrap() {
                DataPayload::Ip6Content(next_header, ref content) => {
                    let their_pk = session.conn.their_pk();
                    let their_ipv6_addr = publickey_to_ipv6addr(their_pk);
                    self.rx_buffer.push_back(Ip6Content {
                        addr: their_ipv6_addr,
                        next_header,
                        content: content.clone(), // TODO: do not clone
                    });
                    Vec::new()
                }
                DataPayload::RoutePacket(route_packet) => self.router.on_route_packet(
                    &route_packet,
                    path,
                    handle,
                    session.conn.their_pk().clone(),
                ),
            };
            for route_packet in route_packets.into_iter() {
                responses.extend(session.wrap_route_packet(path.reverse(), route_packet));
            }
        }
        for response in responses {
            self.dispatch(response, 0b001);
        }
    }

    pub fn dispatch(
        &mut self,
        packet: SwitchPacket,
        from_interface: Director,
    ) -> Option<(MySessionHandle, Vec<DataPacket>)> {
        let (to_self, forward) = self.switch.forward(packet, from_interface);
        for (interface, packet) in forward {
            self.network_adapter.send_to(interface, &packet)
        }

        if let Some(packet) = to_self.as_ref() {
            let switched_path = BackwardPath(packet.label());

            if let Some((handle, packets)) = self.on_self_interface_switch_packet(&packet) {
                for packet in packets.iter() {
                    self.on_data_packet(&packet, handle, switched_path)
                }
                Some((handle, packets))
            } else {
                None
            }
        } else {
            None
        }
    }

    pub fn upkeep(&mut self) -> Vec<(MySessionHandle, Vec<DataPacket>)> {
        let mut to_self = Vec::new();
        if let Some((director, messages)) = self.network_adapter.recv_from() {
            for message in messages.into_iter() {
                if let Some(pkts) = self.dispatch(message, director) {
                    to_self.push(pkts);
                }
            }
        }
        self.upkeep2();
        to_self
    }

    fn upkeep2(&mut self) {
        for message in self.session_manager.upkeep() {
            let to_self = self.dispatch(message, 0b001);
            assert!(to_self.is_none());
        }
    }

    pub fn send_hello(&mut self, path: ForwardPath, pk: PublicKey) {
        let _my_handle = self.session_manager.add_outgoing(Some(path), pk);
        self.upkeep2();
    }

    pub fn send_content_to_path(
        &mut self,
        path: ForwardPath,
        pk: PublicKey,
        ip6_next_header: u8,
        content: Vec<u8>,
        immediately: bool,
    ) {
        let (their_handle, messages) = {
            let session = self.session_manager.get_or_make_session_for_pk(pk);
            let data_payload = DataPayload::Ip6Content(ip6_next_header, content);
            let data_packet = DataPacket::new(DATAPACKET_VERSION, &data_payload);
            let messages = if immediately {
                session.conn.wrap_message_immediately(&data_packet.raw())
            } else {
                session.conn.wrap_message(&data_packet.raw())
            };
            (session.their_handle(), messages)
        };

        for message in messages {
            let switch_packet = new_from_raw_content(path, message, their_handle);
            println!("{:?}", switch_packet);
            self.dispatch(switch_packet, 0b001);
        }
    }

    pub fn send_content(&mut self, _ip6_content: &Ip6Content) {
        unimplemented!("send_content");
    }
}
<|endoftext|>


<commit_before>/// Implement ncurses-compatible database discovery

use core::os::getenv;
use core::str;
use path = core::path::PosixPath;

/// Return path to database entry for `term`
pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
    if term.len() == 0 {
        return None;
    }

    let mut dirs_to_search = ~[];
    let first_char = term.substr(0, 1);

    // Find search directory
    match getenv(~"TERMINFO") {
        Some(dir) => dirs_to_search.push(path(dir)),
        None => {
            match getenv(~"TERMINFO_DIRS") {
                Some(dirs) => for str::each_split_char(dirs, ':') |i| {
                    if i == ~"" {
                        dirs_to_search.push(path(~"/usr/share/terminfo"));
                    } else {
                        dirs_to_search.push(path(i.to_owned()));
                    }
                },
                // Found nothing, use the default path
                None => dirs_to_search.push(path(~"/usr/share/terminfo"))
            }
        }
    };

    // Look for the terminal in all of the search directories
    for dirs_to_search.each |p| {
        let newp = ~p.push_many(&[first_char.to_owned(), term.to_owned()]);
        if os::path_exists(p) && os::path_exists(newp) {
            return Some(newp);
        }
    }
    None
}

#[test]
fn test_get_dbpath_for_term() {
    // woefully inadequate test coverage
    use core::os::{setenv, unsetenv};
    fn x(t: &str) -> ~str { get_dbpath_for_term(t).expect("no terminfo entry found").to_str() };
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    assert!(get_dbpath_for_term("") == None);
    setenv("TERMINFO_DIRS", ":");
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    unsetenv("TERMINFO_DIRS");
}
<commit_msg>Add utility function to open db entry<commit_after>/// Implement ncurses-compatible database discovery

use core::os::getenv;
use core::str;
use core::io::{file_reader, Reader};
use path = core::path::PosixPath;

/// Return path to database entry for `term`
pub fn get_dbpath_for_term(term: &str) -> Option<~path> {
    if term.len() == 0 {
        return None;
    }

    let mut dirs_to_search = ~[];
    let first_char = term.substr(0, 1);

    // Find search directory
    match getenv(~"TERMINFO") {
        Some(dir) => dirs_to_search.push(path(dir)),
        None => {
            match getenv(~"TERMINFO_DIRS") {
                Some(dirs) => for str::each_split_char(dirs, ':') |i| {
                    if i == ~"" {
                        dirs_to_search.push(path(~"/usr/share/terminfo"));
                    } else {
                        dirs_to_search.push(path(i.to_owned()));
                    }
                },
                // Found nothing, use the default path
                None => dirs_to_search.push(path(~"/usr/share/terminfo"))
            }
        }
    };

    // Look for the terminal in all of the search directories
    for dirs_to_search.each |p| {
        let newp = ~p.push_many(&[first_char.to_owned(), term.to_owned()]);
        if os::path_exists(p) && os::path_exists(newp) {
            return Some(newp);
        }
    }
    None
}

/// Return open file for `term`
fn open(term: &str) -> Result<@Reader, ~str> {
    match get_dbpath_for_term(term) {
        Some(x) => file_reader(x),
        None => Err(fmt!("could not find terminfo entry for %s", term))
    }
}

#[test]
fn test_get_dbpath_for_term() {
    // woefully inadequate test coverage
    use core::os::{setenv, unsetenv};
    fn x(t: &str) -> ~str { get_dbpath_for_term(t).expect("no terminfo entry found").to_str() };
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    assert!(get_dbpath_for_term("") == None);
    setenv("TERMINFO_DIRS", ":");
    assert!(x("screen") == ~"/usr/share/terminfo/s/screen");
    unsetenv("TERMINFO_DIRS");
}

#[test]
fn test_open() {
    open("screen");
    let t = open("nonexistent terminal that hopefully does not exist");
    assert!(t.is_err());
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::cmp;

#[derive(Debug, PartialEq)]
enum ProgressState {
    Probe,
    Replicate,
    Snapshot,
}

struct Progress {
    matched: u64,
    next_idx: u64,
    // When in ProgressStateProbe, leader sends at most one replication message
    // per heartbeat interval. It also probes actual progress of the follower.
    //
    // When in ProgressStateReplicate, leader optimistically increases next
    // to the latest entry sent after sending replication message. This is
    // an optimized state for fast replicating log entries to the follower.
    //
    // When in ProgressStateSnapshot, leader should have sent out snapshot
    // before and stops sending any replication message.
    state: ProgressState,
    // Paused is used in ProgressStateProbe.
    // When Paused is true, raft should pause sending replication message to this peer.
    paused: bool,
    // pending_snapshot is used in ProgressStateSnapshot.
    // If there is a pending snapshot, the pendingSnapshot will be set to the
    // index of the snapshot. If pendingSnapshot is set, the replication process of
    // this Progress will be paused. raft will not resend snapshot until the pending one
    // is reported to be failed.
    pending_snapshot: u64,

    // recent_active is true if the progress is recently active. Receiving any messages
    // from the corresponding follower indicates the progress is active.
    // RecentActive can be reset to false after an election timeout.
    recent_active: bool,

    // Inflights is a sliding window for the inflight messages.
    // When inflights is full, no more message should be sent.
    // When a leader sends out a message, the index of the last
    // entry should be added to inflights. The index MUST be added
    // into inflights in order.
    // When a leader receives a reply, the previous inflights should
    // be freed by calling inflights.freeTo.
    ins: Inflights,
}

impl Progress {
    pub fn reset_state(&mut self, state: ProgressState) {
        self.paused = false;
        self.recent_active = false;
        self.pending_snapshot = 0;
        self.state = state;
        self.ins.reset();
    }

    pub fn become_probe(&mut self) {
        // If the original state is ProgressStateSnapshot, progress knows that
        // the pending snapshot has been sent to this peer successfully, then
        // probes from pendingSnapshot + 1.
        if self.state == ProgressState::Snapshot {
            let pending_snapshot = self.pending_snapshot;
            self.reset_state(ProgressState::Probe);
            self.next_idx = cmp::max(self.matched + 1, pending_snapshot + 1);
        } else {
            self.reset_state(ProgressState::Probe);
            self.next_idx = self.matched + 1;
        }
    }

    pub fn become_replicate(&mut self) {
        self.reset_state(ProgressState::Replicate);
        self.next_idx = self.matched + 1;
    }

    pub fn become_snapshot(&mut self, snapshot_idx: u64) {
        self.reset_state(ProgressState::Snapshot);
        self.pending_snapshot = snapshot_idx;
    }

    // maybeUpdate returns false if the given n index comes from an outdated message.
    // Otherwise it updates the progress and returns true.
    pub fn maybe_update(&mut self, n: u64) -> bool {
        let mut updated = false;
        if self.matched < n {
            self.matched = n;
            updated = true;
            self.resume()
        }

        if self.next_idx < n + 1 {
            self.next_idx = n + 1
        }

        updated
    }

    pub fn optimistic_update(&mut self, n: u64) {
        self.next_idx = n + 1;
    }

    // maybeDecrTo returns false if the given to index comes from an out of order message.
    // Otherwise it decreases the progress next index to min(rejected, last) and returns true.
    pub fn maybe_dec_to(&mut self, rejected: u64, last: u64) -> bool {
        if self.state == ProgressState::Replicate {
            // the rejection must be stale if the progress has matched and "rejected"
            // is smaller than "match".
            if rejected <= self.matched {
                return false;
            }
            self.next_idx = self.matched + 1;
            return true;
        }

        // the rejection must be stale if "rejected" does not match next - 1
        if self.next_idx - 1 != rejected {
            return false;
        }

        self.next_idx = cmp::min(rejected, last + 1);
        if self.next_idx < 1 {
            self.next_idx = 1;
        }
        self.resume();
        true
    }

    pub fn is_paused(&self) -> bool {
        match self.state {
            ProgressState::Probe => self.paused,
            ProgressState::Replicate => self.ins.full(),
            ProgressState::Snapshot => true,
        }
    }

    pub fn resume(&mut self) {
        self.paused = false;
    }

    pub fn pause(&mut self) {
        self.paused = true;
    }
}

#[derive(Debug, Default)]
struct Inflights {
    // the starting index in the buffer
    start: u64,
    // number of inflights in the buffer
    count: u64,

    // ring buffer
    buffer: Vec<u64>,
}

impl Inflights {
    pub fn new(cap: usize) -> Inflights {
        Inflights { buffer: Vec::with_capacity(cap), ..Default::default() }
    }

    pub fn full(&self) -> bool {
        self.count == self.cap()
    }

    pub fn cap(&self) -> u64 {
        self.buffer.capacity() as u64
    }

    // add adds an inflight into inflights
    pub fn add(&mut self, inflight: u64) {
        if self.full() {
            panic!("cannot add into a full inflights")
        }

        let mut next = self.start + self.count;
        if next >= self.cap() {
            next -= self.cap();
        }
        self.buffer[next as usize] = inflight;
        self.count += 1;
    }

    // free_to frees the inflights smaller or equal to the given `to` flight.
    pub fn free_to(&mut self, to: u64) {
        if self.count == 0 || to < self.buffer[self.start as usize] {
            // out of the left side of the window
            return;
        }

        let mut i = 0u64;
        let mut idx = self.start as usize;
        while i < self.count {
            if to < self.buffer[idx] {
                // found the first large inflight
                break;
            }

            // increase index and maybe rotate
            idx += 1;
            if idx >= self.cap() as usize {
                idx -= self.cap() as usize;
            }

            i += 1;
        }

        self.count -= i;
        self.start = idx as u64;
    }

    pub fn free_first_one(&mut self) {
        let start = self.start;
        self.free_to(start);
    }

    pub fn reset(&mut self) {
        self.count = 0;
        self.start = 0;
    }
}
<commit_msg>Add more comments and misc methods<commit_after>#![allow(dead_code)]

use std::cmp;

#[derive(Debug, PartialEq)]
enum ProgressState {
    Probe,
    Replicate,
    Snapshot,
}

struct Progress {
    matched: u64,
    next_idx: u64,
    // When in ProgressStateProbe, leader sends at most one replication message
    // per heartbeat interval. It also probes actual progress of the follower.
    //
    // When in ProgressStateReplicate, leader optimistically increases next
    // to the latest entry sent after sending replication message. This is
    // an optimized state for fast replicating log entries to the follower.
    //
    // When in ProgressStateSnapshot, leader should have sent out snapshot
    // before and stops sending any replication message.
    state: ProgressState,
    // Paused is used in ProgressStateProbe.
    // When Paused is true, raft should pause sending replication message to this peer.
    paused: bool,
    // pending_snapshot is used in ProgressStateSnapshot.
    // If there is a pending snapshot, the pendingSnapshot will be set to the
    // index of the snapshot. If pendingSnapshot is set, the replication process of
    // this Progress will be paused. raft will not resend snapshot until the pending one
    // is reported to be failed.
    pending_snapshot: u64,

    // recent_active is true if the progress is recently active. Receiving any messages
    // from the corresponding follower indicates the progress is active.
    // RecentActive can be reset to false after an election timeout.
    recent_active: bool,

    // Inflights is a sliding window for the inflight messages.
    // When inflights is full, no more message should be sent.
    // When a leader sends out a message, the index of the last
    // entry should be added to inflights. The index MUST be added
    // into inflights in order.
    // When a leader receives a reply, the previous inflights should
    // be freed by calling inflights.freeTo.
    ins: Inflights,
}

impl Progress {
    pub fn reset_state(&mut self, state: ProgressState) {
        self.paused = false;
        self.recent_active = false;
        self.pending_snapshot = 0;
        self.state = state;
        self.ins.reset();
    }

    pub fn become_probe(&mut self) {
        // If the original state is ProgressStateSnapshot, progress knows that
        // the pending snapshot has been sent to this peer successfully, then
        // probes from pendingSnapshot + 1.
        if self.state == ProgressState::Snapshot {
            let pending_snapshot = self.pending_snapshot;
            self.reset_state(ProgressState::Probe);
            self.next_idx = cmp::max(self.matched + 1, pending_snapshot + 1);
        } else {
            self.reset_state(ProgressState::Probe);
            self.next_idx = self.matched + 1;
        }
    }

    pub fn become_replicate(&mut self) {
        self.reset_state(ProgressState::Replicate);
        self.next_idx = self.matched + 1;
    }

    pub fn become_snapshot(&mut self, snapshot_idx: u64) {
        self.reset_state(ProgressState::Snapshot);
        self.pending_snapshot = snapshot_idx;
    }

    pub fn snapshot_failure(&self) -> bool {
        self.pending_snapshot == 0
    }

    // maybeSnapshotAbort unsets pendingSnapshot if Match is equal or higher than
    // the pendingSnapshot
    pub fn maybe_snapshot_abort(&self) -> bool {
        self.state == ProgressState::Snapshot && self.matched >= self.pending_snapshot
    }

    // maybeUpdate returns false if the given n index comes from an outdated message.
    // Otherwise it updates the progress and returns true.
    pub fn maybe_update(&mut self, n: u64) -> bool {
        let mut updated = false;
        if self.matched < n {
            self.matched = n;
            updated = true;
            self.resume()
        }

        if self.next_idx < n + 1 {
            self.next_idx = n + 1
        }

        updated
    }

    pub fn optimistic_update(&mut self, n: u64) {
        self.next_idx = n + 1;
    }

    // maybeDecrTo returns false if the given to index comes from an out of order message.
    // Otherwise it decreases the progress next index to min(rejected, last) and returns true.
    pub fn maybe_dec_to(&mut self, rejected: u64, last: u64) -> bool {
        if self.state == ProgressState::Replicate {
            // the rejection must be stale if the progress has matched and "rejected"
            // is smaller than "match".
            if rejected <= self.matched {
                return false;
            }
            self.next_idx = self.matched + 1;
            return true;
        }

        // the rejection must be stale if "rejected" does not match next - 1
        if self.next_idx - 1 != rejected {
            return false;
        }

        self.next_idx = cmp::min(rejected, last + 1);
        if self.next_idx < 1 {
            self.next_idx = 1;
        }
        self.resume();
        true
    }

    pub fn is_paused(&self) -> bool {
        match self.state {
            ProgressState::Probe => self.paused,
            ProgressState::Replicate => self.ins.full(),
            ProgressState::Snapshot => true,
        }
    }

    pub fn resume(&mut self) {
        self.paused = false;
    }

    pub fn pause(&mut self) {
        self.paused = true;
    }
}

#[derive(Debug, Default)]
struct Inflights {
    // the starting index in the buffer
    start: u64,
    // number of inflights in the buffer
    count: u64,

    // ring buffer
    buffer: Vec<u64>,
}

impl Inflights {
    pub fn new(cap: usize) -> Inflights {
        Inflights { buffer: Vec::with_capacity(cap), ..Default::default() }
    }

    // full returns true if the inflights is full.
    pub fn full(&self) -> bool {
        self.count == self.cap()
    }

    pub fn cap(&self) -> u64 {
        self.buffer.capacity() as u64
    }

    // add adds an inflight into inflights
    pub fn add(&mut self, inflight: u64) {
        if self.full() {
            panic!("cannot add into a full inflights")
        }

        let mut next = self.start + self.count;
        if next >= self.cap() {
            next -= self.cap();
        }
        self.buffer[next as usize] = inflight;
        self.count += 1;
    }

    // free_to frees the inflights smaller or equal to the given `to` flight.
    pub fn free_to(&mut self, to: u64) {
        if self.count == 0 || to < self.buffer[self.start as usize] {
            // out of the left side of the window
            return;
        }

        let mut i = 0u64;
        let mut idx = self.start as usize;
        while i < self.count {
            if to < self.buffer[idx] {
                // found the first large inflight
                break;
            }

            // increase index and maybe rotate
            idx += 1;
            if idx >= self.cap() as usize {
                idx -= self.cap() as usize;
            }

            i += 1;
        }

        // free i inflights and set new start index
        self.count -= i;
        self.start = idx as u64;
    }

    pub fn free_first_one(&mut self) {
        let start = self.start;
        self.free_to(start);
    }

    // resets frees all inflights.
    pub fn reset(&mut self) {
        self.count = 0;
        self.start = 0;
    }
}
<|endoftext|>


<commit_before>
/// A payload to reply to commands with
include!(concat!(env!("OUT_DIR"), "/rep.rs"));

impl Response {
    /// returned a response which will displayed for the user that issued the command
    /// for formatting rules see [this doc](https://api.slack.com/docs/formatting)
    pub fn ephemeral<T>(text: T) -> Response
        where T: Into<String>
    {
        Response {
            text: text.into(),
            response_type: "ephemeral".to_owned(),
        }
    }
    /// return a response which will be displayed for anyone in the channel
    /// for formatting rules see [this doc](https://api.slack.com/docs/formatting)
    pub fn in_channel<T>(text: T) -> Response
        where T: Into<String>
    {
        Response {
            text: text.into(),
            response_type: "in_channel".to_owned(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::serde_json;

    #[test]
    fn test_ephemeral_response() {
        match serde_json::to_string(&Response::ephemeral("test")) {
            Ok(json) => assert_eq!(json, r#"{"text":"test","response_type":"ephemeral"}"#),
            _ => assert!(false, "failed to serialize json"),
        }
    }

    #[test]
    fn test_in_channel_response() {
        match serde_json::to_string(&Response::in_channel("test")) {
            Ok(json) => assert_eq!(json, r#"{"text":"test","response_type":"in_channel"}"#),
            _ => assert!(false, "failed to serialize json"),
        }
    }
}
<commit_msg>update file ref<commit_after>
/// A payload to reply to commands with
include!(concat!(env!("OUT_DIR"), "/response.rs"));

impl Response {
    /// returned a response which will displayed for the user that issued the command
    /// for formatting rules see [this doc](https://api.slack.com/docs/formatting)
    pub fn ephemeral<T>(text: T) -> Response
        where T: Into<String>
    {
        Response {
            text: text.into(),
            response_type: "ephemeral".to_owned(),
        }
    }
    /// return a response which will be displayed for anyone in the channel
    /// for formatting rules see [this doc](https://api.slack.com/docs/formatting)
    pub fn in_channel<T>(text: T) -> Response
        where T: Into<String>
    {
        Response {
            text: text.into(),
            response_type: "in_channel".to_owned(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::serde_json;

    #[test]
    fn test_ephemeral_response() {
        match serde_json::to_string(&Response::ephemeral("test")) {
            Ok(json) => assert_eq!(json, r#"{"text":"test","response_type":"ephemeral"}"#),
            _ => assert!(false, "failed to serialize json"),
        }
    }

    #[test]
    fn test_in_channel_response() {
        match serde_json::to_string(&Response::in_channel("test")) {
            Ok(json) => assert_eq!(json, r#"{"text":"test","response_type":"in_channel"}"#),
            _ => assert!(false, "failed to serialize json"),
        }
    }
}
<|endoftext|>


<commit_before>pub use ::reqwest::StatusCode;

pub type ResponseResult = Result<OkResponse, ErrResponse>;
type Body = ::serde::json::Value;
type ReqwestResponse = ::reqwest::Response;

pub trait Response {
    fn from(&mut Option<&mut ReqwestResponse>) -> Self;
    fn body(&self) -> &Body;
    fn status_code(&self) -> StatusCode;
}

impl Response for ResponseResult {
    fn from(maybe_response: &mut Option<&mut ReqwestResponse>) -> Self {
        let error: bool;
        if let Some(ref response) = *maybe_response {
            error = !is_ok(response.status());
        } else {
            error = true;
        }

        match *maybe_response {
            Some(_) => {
                if !error {
                    Ok(<OkResponse as Response>::from(maybe_response))
                } else {
                    Err(<ErrResponse as Response>::from(maybe_response))
                }
            },
            None => Err(<ErrResponse as Response>::from(&mut None)),
        }
    }

    fn body(&self) -> &Body {
        match *self {
            Ok(ref s) => <OkResponse as Response>::body(&s),
            Err(ref s) => <ErrResponse as Response>::body(&s),
        }
    }

    fn status_code(&self) -> StatusCode {
        match *self {
            Ok(ref s) => <OkResponse as Response>::status_code(&s),
            Err(ref s) => <ErrResponse as Response>::status_code(&s),
        }
    }
}

pub fn is_ok(status: &StatusCode) -> bool {
    status.is_success()
        || status.is_informational()
        || status.is_redirection()
}

#[allow(private_in_public)]
struct OkResponse {
    body: Body,
    status_code: StatusCode,
}

impl Response for OkResponse {
    fn from(mut maybe_response: &mut Option<&mut ReqwestResponse>) -> Self {
        let status_code: StatusCode;

        if let Some(ref response) = *maybe_response {
            status_code = *response.status();
            assert!(is_ok(&status_code));
        } else {
            panic!("OkResponse requires Some response.")
        }

        Self {
            body: deser_body(&mut maybe_response),
            status_code,
        }
    }

    fn body(&self) -> &Body {
        &self.body
    }

    fn status_code(&self) -> StatusCode {
        self.status_code
    }
}

#[allow(private_in_public)]
struct ErrResponse {
    body: Body,
    status_code: StatusCode,
}

impl Response for ErrResponse {
    fn from(maybe_response: &mut Option<&mut ReqwestResponse>) -> Self {
        let status_code = match *maybe_response {
            Some(ref response) => deser_status(&Some(response)),
            None => deser_status(&None),
        };

        match *maybe_response {
            Some(_) => {
                assert!(!is_ok(&status_code));
                Self {
                    body: deser_body(maybe_response),
                    status_code,
                }
            },
            None => Self {
                body: deser_body(&mut None),
                status_code: deser_status(&None),
            },
        }
    }

    fn body(&self) -> &Body {
        &self.body
    }

    fn status_code(&self) -> StatusCode {
        self.status_code
    }
}

fn deser_body(response: &mut Option<&mut ::reqwest::Response>) -> Body {
    match *response {
        Some(ref mut r) => r.json().expect("Malformed JSON response."),
        None => ::serde::json::Value::Null,
    }
}

fn deser_status(response: &Option<&::reqwest::Response>) -> StatusCode {
    match *response {
        Some(r) => *r.status(),
        None => StatusCode::from_u16(520),
    }
}
<commit_msg>Refactor OkResponse constructor<commit_after>pub use ::reqwest::StatusCode;

pub type ResponseResult = Result<OkResponse, ErrResponse>;
type Body = ::serde::json::Value;
type ReqwestResponse = ::reqwest::Response;

pub trait Response {
    fn from(&mut Option<&mut ReqwestResponse>) -> Self;
    fn body(&self) -> &Body;
    fn status_code(&self) -> StatusCode;
}

impl Response for ResponseResult {
    fn from(maybe_response: &mut Option<&mut ReqwestResponse>) -> Self {
        let error: bool;
        if let Some(ref response) = *maybe_response {
            error = !is_ok(response.status());
        } else {
            error = true;
        }

        match *maybe_response {
            Some(_) => {
                if !error {
                    Ok(<OkResponse as Response>::from(maybe_response))
                } else {
                    Err(<ErrResponse as Response>::from(maybe_response))
                }
            },
            None => Err(<ErrResponse as Response>::from(&mut None)),
        }
    }

    fn body(&self) -> &Body {
        match *self {
            Ok(ref s) => <OkResponse as Response>::body(&s),
            Err(ref s) => <ErrResponse as Response>::body(&s),
        }
    }

    fn status_code(&self) -> StatusCode {
        match *self {
            Ok(ref s) => <OkResponse as Response>::status_code(&s),
            Err(ref s) => <ErrResponse as Response>::status_code(&s),
        }
    }
}

pub fn is_ok(status: &StatusCode) -> bool {
    status.is_success()
        || status.is_informational()
        || status.is_redirection()
}

#[allow(private_in_public)]
struct OkResponse {
    body: Body,
    status_code: StatusCode,
}

impl Response for OkResponse {
    fn from(mut maybe_response: &mut Option<&mut ReqwestResponse>) -> Self {
        let status_code = match *maybe_response {
            Some(ref response) => deser_status(&Some(response)),
            None => panic!("OkResponse requires Some response."),
        };

        assert!(is_ok(&status_code));

        Self {
            body: deser_body(&mut maybe_response),
            status_code,
        }
    }

    fn body(&self) -> &Body {
        &self.body
    }

    fn status_code(&self) -> StatusCode {
        self.status_code
    }
}

#[allow(private_in_public)]
struct ErrResponse {
    body: Body,
    status_code: StatusCode,
}

impl Response for ErrResponse {
    fn from(maybe_response: &mut Option<&mut ReqwestResponse>) -> Self {
        let status_code = match *maybe_response {
            Some(ref response) => deser_status(&Some(response)),
            None => deser_status(&None),
        };

        match *maybe_response {
            Some(_) => {
                assert!(!is_ok(&status_code));
                Self {
                    body: deser_body(maybe_response),
                    status_code,
                }
            },
            None => Self {
                body: deser_body(&mut None),
                status_code: deser_status(&None),
            },
        }
    }

    fn body(&self) -> &Body {
        &self.body
    }

    fn status_code(&self) -> StatusCode {
        self.status_code
    }
}

fn deser_body(response: &mut Option<&mut ::reqwest::Response>) -> Body {
    match *response {
        Some(ref mut r) => r.json().expect("Malformed JSON response."),
        None => ::serde::json::Value::Null,
    }
}

fn deser_status(response: &Option<&::reqwest::Response>) -> StatusCode {
    match *response {
        Some(r) => *r.status(),
        None => StatusCode::from_u16(520),
    }
}
<|endoftext|>


<commit_before>use super::RdxSort;

use core::ptr;

use std::cmp;
use std::mem;

/// Generic Radix Sort implementation
///
/// Works by splitting the work in rounds. During every round, the data is sorted into buckets and
/// is then collected again. Rounds are count from `0` to (exclusive) `cfg_nrounds()`.
///
/// The number of buckets is fixed for all rounds. That does not mean that the template has to use
/// all of them, since unused buckets are just empty and have no effect on the collected results.
/// Same hold for the number of rounds. Over-booking one or both of them wastes resources of
/// course.
///
/// **WARNING: The result returned from `get_bucket()` is not checked. Wrong implementations may
/// crash the program, or destroy the world, or both!!!**
pub trait RdxSortTemplate {
    /// Sets the number of buckets used by the generic implementation.
    fn cfg_nbuckets() -> usize;

    /// Sets the number of rounds scheduled by the generic implementation.
    fn cfg_nrounds() -> usize;

    /// Returns the bucket, depending on the round.
    ///
    /// This should respect the radix, e.g.:
    ///
    /// - if the number of buckets is `2` and the type is an unsigned integer, then the result is
    ///   the bit starting with the least significant one.
    /// - if the number of buckets is `8` and the type is an unsigned integer, then the result is
    ///   the byte starting with the least significant one.
    ///
    /// **Never** return a bucker greater or equal the number of buckets. See warning above!
    fn get_bucket(&self, round: usize) -> usize;

    /// Describes the fact that the content of a bucket should be copied back in reverse order
    /// after a certain round.
    fn reverse(round: usize, bucket: usize) -> bool;
}

#[inline]
fn helper_bucket<T, I>(buckets_b: &mut Vec<Vec<T>>, iter: I, cfg_nbuckets: usize, round: usize)
    where T: RdxSortTemplate,
          I: Iterator<Item = T>
{
    for x in iter {
        let b = x.get_bucket(round);
        assert!(b < cfg_nbuckets,
                "Your RdxSortTemplate implementation returns a bucket >= cfg_nbuckets()!");
        unsafe {
            buckets_b.get_unchecked_mut(b).push(x);
        }
    }
}

impl<T> RdxSort for [T] where T: RdxSortTemplate + Clone
{
    fn rdxsort(&mut self) {
        // config
        let cfg_nbuckets = T::cfg_nbuckets();
        let cfg_nrounds = T::cfg_nrounds();

        let n = self.len();
        let presize = cmp::max(16, (n << 2) / cfg_nbuckets);  // TODO: justify the presize value
        let mut buckets_a: Vec<Vec<T>> = Vec::with_capacity(cfg_nbuckets);
        let mut buckets_b: Vec<Vec<T>> = Vec::with_capacity(cfg_nbuckets);
        for _ in 0..cfg_nbuckets {
            buckets_a.push(Vec::with_capacity(presize));
            buckets_b.push(Vec::with_capacity(presize));
        }

        for x in self.iter().cloned() {
            let b = x.get_bucket(0);
            assert!(b < cfg_nbuckets,
                    "Your RdxSortTemplate implementation returns a bucket >= cfg_nbuckets()!");
            unsafe {
                buckets_a.get_unchecked_mut(b).push(x);
            }
        }

        for round in 1..cfg_nrounds {
            for bucket in &mut buckets_b {
                bucket.clear();
            }
            for (i, bucket) in buckets_a.iter().enumerate() {
                if T::reverse(round - 1, i) {
                    helper_bucket(&mut buckets_b,
                                  bucket.iter().rev().cloned(),
                                  cfg_nbuckets,
                                  round);
                } else {
                    helper_bucket(&mut buckets_b, bucket.iter().cloned(), cfg_nbuckets, round);
                }
            }
            mem::swap(&mut buckets_a, &mut buckets_b);
        }

        let mut pos = 0;
        for (i, bucket) in buckets_a.iter_mut().enumerate() {
            assert!(pos + bucket.len() <= self.len(),
                    "bug: a buckets got oversized");

            if T::reverse(cfg_nrounds - 1, i) {
                for x in bucket.iter().rev().cloned() {
                    unsafe {
                        *self.get_unchecked_mut(pos) = x;
                    }
                    pos += 1;
                }
            } else {
                unsafe {
                    ptr::copy_nonoverlapping(bucket.as_ptr(),
                                             self.get_unchecked_mut(pos),
                                             bucket.len());
                }
                pos += bucket.len();
            }
        }

        assert!(pos == self.len(), "bug: bucket size does not sum up");
    }
}

impl<T> RdxSort for Vec<T> where [T]: RdxSort
{
    fn rdxsort(&mut self) {
        self.as_mut_slice().rdxsort();
    }
}
<commit_msg>fix template handling when 0 rounds are configured<commit_after>use super::RdxSort;

use core::ptr;

use std::cmp;
use std::mem;

/// Generic Radix Sort implementation
///
/// Works by splitting the work in rounds. During every round, the data is sorted into buckets and
/// is then collected again. Rounds are count from `0` to (exclusive) `cfg_nrounds()`.
///
/// The number of buckets is fixed for all rounds. That does not mean that the template has to use
/// all of them, since unused buckets are just empty and have no effect on the collected results.
/// Same hold for the number of rounds. Over-booking one or both of them wastes resources of
/// course.
///
/// **WARNING: The result returned from `get_bucket()` is not checked. Wrong implementations may
/// crash the program, or destroy the world, or both!!!**
pub trait RdxSortTemplate {
    /// Sets the number of buckets used by the generic implementation.
    fn cfg_nbuckets() -> usize;

    /// Sets the number of rounds scheduled by the generic implementation.
    fn cfg_nrounds() -> usize;

    /// Returns the bucket, depending on the round.
    ///
    /// This should respect the radix, e.g.:
    ///
    /// - if the number of buckets is `2` and the type is an unsigned integer, then the result is
    ///   the bit starting with the least significant one.
    /// - if the number of buckets is `8` and the type is an unsigned integer, then the result is
    ///   the byte starting with the least significant one.
    ///
    /// **Never** return a bucker greater or equal the number of buckets. See warning above!
    fn get_bucket(&self, round: usize) -> usize;

    /// Describes the fact that the content of a bucket should be copied back in reverse order
    /// after a certain round.
    fn reverse(round: usize, bucket: usize) -> bool;
}

#[inline]
fn helper_bucket<T, I>(buckets_b: &mut Vec<Vec<T>>, iter: I, cfg_nbuckets: usize, round: usize)
    where T: RdxSortTemplate,
          I: Iterator<Item = T>
{
    for x in iter {
        let b = x.get_bucket(round);
        assert!(b < cfg_nbuckets,
                "Your RdxSortTemplate implementation returns a bucket >= cfg_nbuckets()!");
        unsafe {
            buckets_b.get_unchecked_mut(b).push(x);
        }
    }
}

impl<T> RdxSort for [T] where T: RdxSortTemplate + Clone
{
    fn rdxsort(&mut self) {
        // config
        let cfg_nbuckets = T::cfg_nbuckets();
        let cfg_nrounds = T::cfg_nrounds();

        // early return
        if cfg_nrounds == 0 {
            return;
        }

        let n = self.len();
        let presize = cmp::max(16, (n << 2) / cfg_nbuckets);  // TODO: justify the presize value
        let mut buckets_a: Vec<Vec<T>> = Vec::with_capacity(cfg_nbuckets);
        let mut buckets_b: Vec<Vec<T>> = Vec::with_capacity(cfg_nbuckets);
        for _ in 0..cfg_nbuckets {
            buckets_a.push(Vec::with_capacity(presize));
            buckets_b.push(Vec::with_capacity(presize));
        }

        for x in self.iter().cloned() {
            let b = x.get_bucket(0);
            assert!(b < cfg_nbuckets,
                    "Your RdxSortTemplate implementation returns a bucket >= cfg_nbuckets()!");
            unsafe {
                buckets_a.get_unchecked_mut(b).push(x);
            }
        }

        for round in 1..cfg_nrounds {
            for bucket in &mut buckets_b {
                bucket.clear();
            }
            for (i, bucket) in buckets_a.iter().enumerate() {
                if T::reverse(round - 1, i) {
                    helper_bucket(&mut buckets_b,
                                  bucket.iter().rev().cloned(),
                                  cfg_nbuckets,
                                  round);
                } else {
                    helper_bucket(&mut buckets_b, bucket.iter().cloned(), cfg_nbuckets, round);
                }
            }
            mem::swap(&mut buckets_a, &mut buckets_b);
        }

        let mut pos = 0;
        for (i, bucket) in buckets_a.iter_mut().enumerate() {
            assert!(pos + bucket.len() <= self.len(),
                    "bug: a buckets got oversized");

            if T::reverse(cfg_nrounds - 1, i) {
                for x in bucket.iter().rev().cloned() {
                    unsafe {
                        *self.get_unchecked_mut(pos) = x;
                    }
                    pos += 1;
                }
            } else {
                unsafe {
                    ptr::copy_nonoverlapping(bucket.as_ptr(),
                                             self.get_unchecked_mut(pos),
                                             bucket.len());
                }
                pos += bucket.len();
            }
        }

        assert!(pos == self.len(), "bug: bucket size does not sum up");
    }
}

impl<T> RdxSort for Vec<T> where [T]: RdxSort
{
    fn rdxsort(&mut self) {
        self.as_mut_slice().rdxsort();
    }
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate sdl2_image;

use std::path::Path;
use sdl2::EventPump;
use sdl2::event::Event;
use sdl2::Sdl;
use sdl2::pixels;
use sdl2::rect::Rect;
use sdl2::render::Renderer;
use sdl2_image::{LoadTexture, INIT_PNG};

use sprites::SpriteSheet;
use colors::Color;

struct Cell {
    glyph: char,
    fg: Color,
    bg: Color,
}

pub struct FontDefinition {
    pub image_path: &'static str,
    pub width: u32,
    pub height: u32,
    pub padding: u32,
    pub transparent: bool,
}

pub struct Terminal {
    sprite_sheet: SpriteSheet,
    grid: Vec<Cell>,
    renderer: Renderer<'static>,
    sdl_context: Sdl,
    font: FontDefinition,

    pub event_pump: EventPump,
    pub columns: u32,
    pub rows: u32,
    pub quit: bool,
}

impl Terminal {
    pub fn new(columns: u32, rows: u32, font: FontDefinition) -> Self {
        let sdl_context = sdl2::init().unwrap();
        let _image_context = sdl2_image::init(INIT_PNG).unwrap();
        let video_subsystem = sdl_context.video().unwrap();
        let window = video_subsystem.window("davokar-rl",
                    (columns * font.width) as u32,
                    (rows * font.height) as u32)
            .position_centered()
            .opengl()
            .build()
            .unwrap();
        let renderer = window.renderer()
            .accelerated()
            .present_vsync()
            .build()
            .unwrap();

        let sprite_sheet = Terminal::load_font_sheet(&font, &renderer).unwrap();

        let mut grid = vec![];

        let total_cells = columns * rows;
        for _ in 0..total_cells {
            grid.push(Cell {
                glyph: ' ',
                fg: Color {
                    r: 255,
                    g: 255,
                    b: 255,
                    a: 255,
                },
                bg: Color {
                    r: 0,
                    g: 0,
                    b: 0,
                    a: 255,
                },
            });
        }

        let event = sdl_context.event_pump().unwrap();

        Terminal {
            columns: columns,
            rows: rows,
            sprite_sheet: sprite_sheet,
            sdl_context: sdl_context,
            renderer: renderer,
            grid: grid,
            font: font,
            event_pump: event,
            quit: false,
        }
    }

    fn load_font_sheet(font: &FontDefinition,
                       renderer: &Renderer)
                       -> Result<SpriteSheet, &'static str> {
        let texture_result = renderer.load_texture(Path::new(font.image_path));

        match texture_result {
            Ok(texture) => Ok(SpriteSheet::new(texture, font.width, font.height, font.padding)),
            Err(_) => Err("failed to load font texture"),
        }

    }

    pub fn set_cell(&mut self, x: i32, y: i32, c: char, fg: Color, bg: Color) {
        let index = self.columns as i32 * y + x;
        if x >= 0 && y >= 0 && x < self.columns as i32 && y < self.rows as i32 {
            self.grid[index as usize] = Cell {
                glyph: c,
                fg: fg,
                bg: bg,
            }
        }
    }

    pub fn print(&mut self, x: i32, y: i32, text: &str, fg: Color, bg: Color) {
        let mut string_chars = text.chars();
        for i in 0..text.len() {
            let c = string_chars.next().unwrap();
            self.set_cell(x + i as i32, y, c, fg, bg);
        }
    }

    pub fn print_center(&mut self, y: i32, text: &str, fg: Color, bg: Color) {
        let center_x = self.columns / 2;
        let str_len_mid = text.len() / 2;
        let target_x = center_x - str_len_mid as u32;
        self.print(target_x as i32, y, text, fg, bg);
    }

    pub fn draw(&mut self) {

        for event in self.event_pump.poll_iter() {
            match event {
                Event::Quit { .. } => self.quit = true,
                _ => {}
            }
        }

        self.renderer.clear();

        let total_cells = self.columns * self.rows;
        for i in 0..total_cells {
            let cell = &self.grid[i as usize];

            self.sprite_sheet.texture.set_color_mod(cell.fg.r, cell.fg.g, cell.fg.b);
            let sprite = self.sprite_sheet.get_sprite((cell.glyph as u8) as usize);

            let x = i % self.columns;
            let y = i / self.columns;
            let px = x * self.font.width;
            let py = y * self.font.height;

            // draw the background for the cell
            self.renderer
                .set_draw_color(pixels::Color::RGBA(cell.bg.r, cell.bg.g, cell.bg.b, cell.bg.a));
            let _t = self.renderer
                .fill_rect(Rect::new(px as i32,
                                     py as i32,
                                     sprite.size.width(),
                                     sprite.size.height()));

            // draw the actual character
            sprite.draw(px as i32, py as i32, &mut self.renderer);
        }
        self.renderer.present();
    }
}
<commit_msg>disabled vsync for now<commit_after>extern crate sdl2;
extern crate sdl2_image;

use std::path::Path;
use sdl2::EventPump;
use sdl2::event::Event;
use sdl2::Sdl;
use sdl2::pixels;
use sdl2::rect::Rect;
use sdl2::render::Renderer;
use sdl2_image::{LoadTexture, INIT_PNG};

use sprites::SpriteSheet;
use colors::Color;

struct Cell {
    glyph: char,
    fg: Color,
    bg: Color,
}

pub struct FontDefinition {
    pub image_path: &'static str,
    pub width: u32,
    pub height: u32,
    pub padding: u32,
    pub transparent: bool,
}

pub struct Terminal {
    sprite_sheet: SpriteSheet,
    grid: Vec<Cell>,
    renderer: Renderer<'static>,
    sdl_context: Sdl,
    font: FontDefinition,

    pub event_pump: EventPump,
    pub columns: u32,
    pub rows: u32,
    pub quit: bool,
}

impl Terminal {
    pub fn new(columns: u32, rows: u32, font: FontDefinition) -> Self {
        let sdl_context = sdl2::init().unwrap();
        let _image_context = sdl2_image::init(INIT_PNG).unwrap();
        let video_subsystem = sdl_context.video().unwrap();
        let window = video_subsystem.window("davokar-rl",
                    (columns * font.width) as u32,
                    (rows * font.height) as u32)
            .position_centered()
            .opengl()
            .build()
            .unwrap();
        let renderer = window.renderer()
            .accelerated()
            // .present_vsync()
            .build()
            .unwrap();

        let sprite_sheet = Terminal::load_font_sheet(&font, &renderer).unwrap();

        let mut grid = vec![];

        let total_cells = columns * rows;
        for _ in 0..total_cells {
            grid.push(Cell {
                glyph: ' ',
                fg: Color {
                    r: 255,
                    g: 255,
                    b: 255,
                    a: 255,
                },
                bg: Color {
                    r: 0,
                    g: 0,
                    b: 0,
                    a: 255,
                },
            });
        }

        let event = sdl_context.event_pump().unwrap();

        Terminal {
            columns: columns,
            rows: rows,
            sprite_sheet: sprite_sheet,
            sdl_context: sdl_context,
            renderer: renderer,
            grid: grid,
            font: font,
            event_pump: event,
            quit: false,
        }
    }

    fn load_font_sheet(font: &FontDefinition,
                       renderer: &Renderer)
                       -> Result<SpriteSheet, &'static str> {
        let texture_result = renderer.load_texture(Path::new(font.image_path));

        match texture_result {
            Ok(texture) => Ok(SpriteSheet::new(texture, font.width, font.height, font.padding)),
            Err(_) => Err("failed to load font texture"),
        }

    }

    pub fn set_cell(&mut self, x: i32, y: i32, c: char, fg: Color, bg: Color) {
        let index = self.columns as i32 * y + x;
        if x >= 0 && y >= 0 && x < self.columns as i32 && y < self.rows as i32 {
            self.grid[index as usize] = Cell {
                glyph: c,
                fg: fg,
                bg: bg,
            }
        }
    }

    pub fn print(&mut self, x: i32, y: i32, text: &str, fg: Color, bg: Color) {
        let mut string_chars = text.chars();
        for i in 0..text.len() {
            let c = string_chars.next().unwrap();
            self.set_cell(x + i as i32, y, c, fg, bg);
        }
    }

    pub fn print_center(&mut self, y: i32, text: &str, fg: Color, bg: Color) {
        let center_x = self.columns / 2;
        let str_len_mid = text.len() / 2;
        let target_x = center_x - str_len_mid as u32;
        self.print(target_x as i32, y, text, fg, bg);
    }

    pub fn draw(&mut self) {

        for event in self.event_pump.poll_iter() {
            match event {
                Event::Quit { .. } => self.quit = true,
                _ => {}
            }
        }

        self.renderer.clear();

        let total_cells = self.columns * self.rows;
        for i in 0..total_cells {
            let cell = &self.grid[i as usize];

            self.sprite_sheet.texture.set_color_mod(cell.fg.r, cell.fg.g, cell.fg.b);
            let sprite = self.sprite_sheet.get_sprite((cell.glyph as u8) as usize);

            let x = i % self.columns;
            let y = i / self.columns;
            let px = x * self.font.width;
            let py = y * self.font.height;

            // draw the background for the cell
            self.renderer
                .set_draw_color(pixels::Color::RGBA(cell.bg.r, cell.bg.g, cell.bg.b, cell.bg.a));
            let _t = self.renderer
                .fill_rect(Rect::new(px as i32,
                                     py as i32,
                                     sprite.size.width(),
                                     sprite.size.height()));

            // draw the actual character
            sprite.draw(px as i32, py as i32, &mut self.renderer);
        }
        self.renderer.present();
    }
}
<|endoftext|>


<commit_before>use std::default:: { Default };
use std::collections:: { HashMap };
use branch:: { BranchUnit };

type LineNumber = u32;
type ExecutionCount = u32;
type FunctionName = String;

#[derive(Clone)]
pub struct TestSum {
    line: HashMap<LineNumber, ExecutionCount>,
    func: HashMap<FunctionName, ExecutionCount>,
    branch: HashMap<LineNumber, HashMap<BranchUnit, ExecutionCount>>
}

impl TestSum {
    pub fn new() -> Self {
        TestSum {
            line: HashMap::new(),
            branch: HashMap::new(),
            func: HashMap::new()
        }
    }

    /// Add the number of times of execution of the line
    ///
    /// # Examples
    ///
    /// ```
    /// use lcov_merge::TestSum;
    ///
    /// let mut sum = TestSum::default();
    /// sum.add_line_count(&1, &1);
    /// sum.add_line_count(&1, &2);
    ///
    /// assert_eq!(sum.get_line_count(&1), Some(&3));
    /// ```
    pub fn add_line_count(&mut self, line_number: &u32, exec_count: &u32) {
        let mut line_count = self.line.entry(line_number.clone())
            .or_insert(0);
        *line_count += *exec_count;
    }

    pub fn get_line_count(&self, line_number: &u32) -> Option<&u32> {
        self.line.get(line_number)
    }

    pub fn add_func_count(&mut self, func_name: &String, exec_count: &u32) {
        let mut func_count = self.func.entry(func_name.clone())
            .or_insert(0);
        *func_count += *exec_count;
    }

    pub fn get_func_count(&self, func_name: &String) -> Option<&u32> {
        self.func.get(func_name)
    }

    /// Add the number of times of execution of the branch
    ///
    /// # Examples
    ///
    /// ```
    /// use lcov_merge:: { TestSum, BranchUnit };
    ///
    /// let mut sum = TestSum::default();
    /// sum.add_branch_count(&1, &BranchUnit::new(1, 1), &1);
    /// sum.add_branch_count(&1, &BranchUnit::new(1, 1), &2);
    ///
    /// let branch = sum.get_branch_count(&1);
    /// let branch_count = branch.unwrap().get(&BranchUnit::new(1, 1));
    ///
    /// assert_eq!(branch_count, Some(&3));
    /// ```
    pub fn add_branch_count(&mut self, line_number: &u32, unit: &BranchUnit, exec_count: &u32) {
        let mut branch = self.branch.entry(line_number.clone())
            .or_insert(HashMap::new());

        let mut branch_count = branch.entry(unit.clone())
            .or_insert(0);

        *branch_count += *exec_count;
    }

    pub fn get_branch_count(&mut self, line_number: &u32) -> Option<&HashMap<BranchUnit, u32>> {
        self.branch.get(line_number)
    }
}

impl Default for TestSum {
    fn default() -> Self {
        TestSum {
            line: HashMap::new(),
            branch: HashMap::new(),
            func: HashMap::new()
        }
    }
}
<commit_msg>add AddAssign impl<commit_after>use std::default:: { Default };
use std::collections:: { HashMap };
use std::ops::AddAssign;
use branch:: { BranchUnit };
use lcov_parser:: { LineData, FunctionData, BranchData };

type LineNumber = u32;
type ExecutionCount = u32;
type FunctionName = String;

#[derive(Clone)]
pub struct TestSum {
    line: HashMap<LineNumber, ExecutionCount>,
    func: HashMap<FunctionName, ExecutionCount>,
    branch: HashMap<LineNumber, HashMap<BranchUnit, ExecutionCount>>
}

impl TestSum {
    pub fn new() -> Self {
        TestSum {
            line: HashMap::new(),
            branch: HashMap::new(),
            func: HashMap::new()
        }
    }

    /// Add the number of times of execution of the line
    ///
    /// # Examples
    ///
    /// ```
    /// use lcov_merge::TestSum;
    ///
    /// let mut sum = TestSum::default();
    /// sum.add_line_count(&1, &1);
    /// sum.add_line_count(&1, &2);
    ///
    /// assert_eq!(sum.get_line_count(&1), Some(&3));
    /// ```
    pub fn add_line_count(&mut self, line_number: &u32, exec_count: &u32) {
        let mut line_count = self.line.entry(line_number.clone())
            .or_insert(0);
        *line_count += *exec_count;
    }

    pub fn get_line_count(&self, line_number: &u32) -> Option<&u32> {
        self.line.get(line_number)
    }

    pub fn add_func_count(&mut self, func_name: &String, exec_count: &u32) {
        let mut func_count = self.func.entry(func_name.clone())
            .or_insert(0);
        *func_count += *exec_count;
    }

    pub fn get_func_count(&self, func_name: &String) -> Option<&u32> {
        self.func.get(func_name)
    }

    /// Add the number of times of execution of the branch
    ///
    /// # Examples
    ///
    /// ```
    /// use lcov_merge:: { TestSum, BranchUnit };
    ///
    /// let mut sum = TestSum::default();
    /// sum.add_branch_count(&1, &BranchUnit::new(1, 1), &1);
    /// sum.add_branch_count(&1, &BranchUnit::new(1, 1), &2);
    ///
    /// let branch = sum.get_branch_count(&1);
    /// let branch_count = branch.unwrap().get(&BranchUnit::new(1, 1));
    ///
    /// assert_eq!(branch_count, Some(&3));
    /// ```
    pub fn add_branch_count(&mut self, line_number: &u32, unit: &BranchUnit, exec_count: &u32) {
        let mut branch = self.branch.entry(line_number.clone())
            .or_insert(HashMap::new());

        let mut branch_count = branch.entry(unit.clone())
            .or_insert(0);

        *branch_count += *exec_count;
    }

    pub fn get_branch_count(&mut self, line_number: &u32) -> Option<&HashMap<BranchUnit, u32>> {
        self.branch.get(line_number)
    }
}

impl Default for TestSum {
    fn default() -> Self {
        TestSum {
            line: HashMap::new(),
            branch: HashMap::new(),
            func: HashMap::new()
        }
    }
}

impl<'a> AddAssign<&'a LineData> for TestSum {
    fn add_assign(&mut self, data: &'a LineData) {
        let mut line_count = self.line.entry(data.line)
            .or_insert(0);
        *line_count += data.count;
    }
}

impl<'a> AddAssign<&'a FunctionData> for TestSum {
    fn add_assign(&mut self, data: &'a FunctionData) {
        let mut func_count = self.func.entry(data.name.clone())
            .or_insert(0);
        *func_count += data.count;
    }
}

impl<'a> AddAssign<&'a BranchData> for TestSum {
    fn add_assign(&mut self, data: &'a BranchData) {
        let unit = BranchUnit::new(data.block, data.branch);

        let mut branch = self.branch.entry(data.line)
            .or_insert(HashMap::new());

        let mut branch_count = branch.entry(unit)
            .or_insert(0);

        *branch_count += data.taken;
    }
}

#[cfg(test)]
mod tests {
    use std::collections:: { HashMap };
    use test_sum:: { TestSum };
    use branch:: { BranchUnit };
    use lcov_parser:: { LineData, FunctionData, BranchData };

    #[test]
    fn add_line_data() {
        let mut test = TestSum::new();

        test += &LineData { line: 1, count: 1, checksum: None };
        assert_eq!( test.get_line_count(&1), Some(&1u32) );

        test += &LineData { line: 1, count: 1, checksum: None };
        assert_eq!( test.get_line_count(&1), Some(&2u32) );
    }

    #[test]
    fn add_func_data() {
        let mut test = TestSum::new();

        test += &FunctionData { name: "main".to_string(), count: 1 };
        assert_eq!( test.get_func_count(&"main".to_string()), Some(&1u32) );

        test += &FunctionData { name: "main".to_string(), count: 1 };
        assert_eq!( test.get_func_count(&"main".to_string()), Some(&2u32) );
    }

    #[test]
    fn add_branch_data() {
        let mut test = TestSum::new();

        test += &BranchData { line: 1, block: 1, branch: 1, taken: 1 };

        let mut first_branch_count = HashMap::new();
        first_branch_count.insert(BranchUnit::new(1, 1), 1);

        assert_eq!( test.get_branch_count(&1), Some(&first_branch_count) );

        test += &BranchData { line: 1, block: 1, branch: 1, taken: 1 };

        let mut second_branch_count = HashMap::new();
        second_branch_count.insert(BranchUnit::new(1, 1), 2);

        assert_eq!( test.get_branch_count(&1), Some(&second_branch_count) );
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib_sys;
use std::mem;

pub use glib_sys::GTimeVal as TimeVal;

pub fn get_current_time() -> TimeVal {
    unsafe {
        let mut ret = mem::uninitialized();
        glib_sys::g_get_current_time(&mut ret);
        ret
    }
}
<commit_msg>Add missing traits<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use glib_sys;
use std::mem;
use translate::{StashMut, ToGlibPtrMut, Uninitialized};

pub use glib_sys::GTimeVal as TimeVal;

pub fn get_current_time() -> TimeVal {
    unsafe {
        let mut ret = mem::uninitialized();
        glib_sys::g_get_current_time(&mut ret);
        ret
    }
}

#[doc(hidden)]
impl<'a> ToGlibPtrMut<'a, *mut glib_sys::GTimeVal> for TimeVal {
    type Storage = &'a mut Self;

    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut glib_sys::GTimeVal, Self> {
        StashMut(self as *mut _, self)
    }
}

impl Uninitialized for TimeVal {
    unsafe fn uninitialized() -> TimeVal {
        mem::uninitialized()
    }
}
<|endoftext|>