<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::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::WebSocketBinding;
use dom::bindings::codegen::Bindings::WebSocketBinding::WebSocketMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::codegen::InheritTypes::EventCast;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::error::Error::{InvalidAccess, Syntax};
use dom::bindings::global::{GlobalField, GlobalRef};
use dom::bindings::js::Root;
use dom::bindings::refcounted::Trusted;
use dom::bindings::str::USVString;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::reflect_dom_object;
use dom::closeevent::CloseEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use script_task::Runnable;
use script_task::ScriptMsg;
use std::cell::{Cell, RefCell};
use std::borrow::ToOwned;
use util::str::DOMString;

use hyper::header::Host;
use websocket::Message;
use websocket::ws::sender::Sender as Sender_Object;
use websocket::client::sender::Sender;
use websocket::client::receiver::Receiver;
use websocket::stream::WebSocketStream;
use websocket::client::request::Url;
use websocket::Client;
use websocket::header::Origin;
use websocket::result::WebSocketResult;
use websocket::ws::util::url::parse_url;

#[derive(JSTraceable, PartialEq, Copy, Clone)]
enum WebSocketRequestState {
    Connecting = 0,
    Open = 1,
    Closing = 2,
    Closed = 3,
}

no_jsmanaged_fields!(Sender<WebSocketStream>);

#[dom_struct]
pub struct WebSocket {
    eventtarget: EventTarget,
    url: Url,
    global: GlobalField,
    ready_state: Cell<WebSocketRequestState>,
    sender: RefCell<Option<Sender<WebSocketStream>>>,
    failed: Cell<bool>, //Flag to tell if websocket was closed due to failure
    full: Cell<bool>, //Flag to tell if websocket queue is full
    clean_close: Cell<bool>, //Flag to tell if the websocket closed cleanly (not due to full or fail)
    code: Cell<u16>, //Closing code
    reason: DOMRefCell<DOMString>, //Closing reason
    data: DOMRefCell<DOMString>, //Data from send - TODO: Remove after buffer is added.
}

/// *Establish a WebSocket Connection* as defined in RFC 6455.
fn establish_a_websocket_connection(url: (Host, String, bool), origin: String)
    -> WebSocketResult<(Sender<WebSocketStream>, Receiver<WebSocketStream>)> {
    let mut request = try!(Client::connect(url));
    request.headers.set(Origin(origin));

    let response = try!(request.send());
    try!(response.validate());

    Ok(response.begin().split())
}

impl WebSocket {
    pub fn new_inherited(global: GlobalRef, url: Url) -> WebSocket {
        WebSocket {
            eventtarget: EventTarget::new_inherited(EventTargetTypeId::WebSocket),
            url: url,
            global: GlobalField::from_rooted(&global),
            ready_state: Cell::new(WebSocketRequestState::Connecting),
            failed: Cell::new(false),
            sender: RefCell::new(None),
            full: Cell::new(false),
            clean_close: Cell::new(true),
            code: Cell::new(0),
            reason: DOMRefCell::new("".to_owned()),
            data: DOMRefCell::new("".to_owned()),
        }

    }

    pub fn new(global: GlobalRef,
               url: DOMString,
               protocols: Option<DOMString>)
               -> Fallible<Root<WebSocket>> {
        // Step 1.
        let parsed_url = try!(Url::parse(&url).map_err(|_| Error::Syntax));
        let url = try!(parse_url(&parsed_url).map_err(|_| Error::Syntax));

        // Step 4.
        let protocols = protocols.as_slice();

        // Step 5.
        for (i, protocol) in protocols.iter().enumerate() {
            // https://tools.ietf.org/html/rfc6455#section-4.1
            // Handshake requirements, step 10
            if protocol.is_empty() {
                return Err(Syntax);
            }

            if protocols[i+1..].iter().any(|p| p == protocol) {
                return Err(Syntax);
            }

            if protocol.chars().any(|c| c < '\u{0021}' || c > '\u{007E}') {
                return Err(Syntax);
            }
        }

        /*TODO: This constructor is only a prototype, it does not accomplish the specs
          defined here:
          http://html.spec.whatwg.org
          The remaining 8 items must be satisfied.
          TODO: This constructor should be responsible for spawning a thread for the
          receive loop after ws.r().Open() - See comment
        */
        let ws = reflect_dom_object(box WebSocket::new_inherited(global, parsed_url),
                                    global,
                                    WebSocketBinding::Wrap);

        let channel = establish_a_websocket_connection(url, global.get_url().serialize());
        let (temp_sender, _temp_receiver) = match channel {
            Ok(channel) => channel,
            Err(e) => {
                debug!("Failed to establish a WebSocket connection: {:?}", e);
                let global_root = ws.r().global.root();
                let address = Trusted::new(global_root.r().get_cx(), ws.r(), global_root.r().script_chan().clone());
                let task = box CloseTask {
                    addr: address,
                };
                global_root.r().script_chan().send(ScriptMsg::RunnableMsg(task)).unwrap();
                return Ok(ws);
            }
        };

        //Create everything necessary for starting the open asynchronous task, then begin the task.
        let global_root = ws.r().global.root();
        let addr: Trusted<WebSocket> =
            Trusted::new(global_root.r().get_cx(), ws.r(), global_root.r().script_chan().clone());
        let open_task = box ConnectionEstablishedTask {
            addr: addr,
            sender: temp_sender,
        };
        global_root.r().script_chan().send(ScriptMsg::RunnableMsg(open_task)).unwrap();
        //TODO: Spawn thread here for receive loop
        /*TODO: Add receive loop here and make new thread run this
          Receive is an infinite loop "similiar" the one shown here:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: The receive loop however does need to follow the spec. These are outlined here
          under "WebSocket message has been received" items 1-5:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: The receive loop also needs to dispatch an asynchronous event as stated here:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: When the receive loop receives a close message from the server,
          it confirms the websocket is now closed. This requires the close event
          to be fired (dispatch_close fires the close event - see implementation below)
        */
        Ok(ws)
    }

    pub fn Constructor(global: GlobalRef,
                       url: DOMString,
                       protocols: Option<DOMString>)
                       -> Fallible<Root<WebSocket>> {
        WebSocket::new(global, url, protocols)
    }
}

impl<'a> WebSocketMethods for &'a WebSocket {
    event_handler!(open, GetOnopen, SetOnopen);
    event_handler!(close, GetOnclose, SetOnclose);
    event_handler!(error, GetOnerror, SetOnerror);

    fn Url(self) -> DOMString {
        self.url.serialize()
    }

    fn ReadyState(self) -> u16 {
        self.ready_state.get() as u16
    }

    fn Send(self, data: Option<USVString>) -> Fallible<()> {
        match self.ready_state.get() {
            WebSocketRequestState::Connecting => {
                return Err(Error::InvalidState);
            },
            WebSocketRequestState::Open => (),
            WebSocketRequestState::Closing | WebSocketRequestState::Closed => {
                // TODO: Update bufferedAmount.
                return Ok(());
            }
        }

        /*TODO: This is not up to spec see http://html.spec.whatwg.org/multipage/comms.html search for
                "If argument is a string"
          TODO: Need to buffer data
          TODO: bufferedAmount attribute returns the size of the buffer in bytes -
                this is a required attribute defined in the websocket.webidl file
          TODO: The send function needs to flag when full by using the following
          self.full.set(true). This needs to be done when the buffer is full
        */
        let mut other_sender = self.sender.borrow_mut();
        let my_sender = other_sender.as_mut().unwrap();
        let _ = my_sender.send_message(Message::Text(data.unwrap().0));
        return Ok(())
    }

    fn Close(self, code: Option<u16>, reason: Option<USVString>) -> Fallible<()>{
        fn send_close(this: &WebSocket) {
            this.ready_state.set(WebSocketRequestState::Closing);

            let mut sender = this.sender.borrow_mut();
            //TODO: Also check if the buffer is full
            if let Some(sender) = sender.as_mut() {
                let _ = sender.send_message(Message::Close(None));
            }
        }

        if let Some(code) = code {
            //Check code is NOT 1000 NOR in the range of 3000-4999 (inclusive)
            if  code != 1000 && (code < 3000 || code > 4999) {
                return Err(Error::InvalidAccess);
            }
        }
        if let Some(ref reason) = reason {
            if reason.0.as_bytes().len() > 123 { //reason cannot be larger than 123 bytes
                return Err(Error::Syntax);
            }
        }

        match self.ready_state.get() {
            WebSocketRequestState::Closing | WebSocketRequestState::Closed  => {} //Do nothing
            WebSocketRequestState::Connecting => { //Connection is not yet established
                /*By setting the state to closing, the open function
                  will abort connecting the websocket*/
                self.failed.set(true);
                send_close(self);
                //Note: After sending the close message, the receive loop confirms a close message from the server and
                //      must fire a close event
            }
            WebSocketRequestState::Open => {
                //Closing handshake not started - still in open
                //Start the closing by setting the code and reason if they exist
                if let Some(code) = code {
                    self.code.set(code);
                }
                if let Some(reason) = reason {
                    *self.reason.borrow_mut() = reason.0;
                }
                send_close(self);
                //Note: After sending the close message, the receive loop confirms a close message from the server and
                //      must fire a close event
            }
        }
        Ok(()) //Return Ok
    }
}

/// Task queued when *the WebSocket connection is established*.
struct ConnectionEstablishedTask {
    addr: Trusted<WebSocket>,
    sender: Sender<WebSocketStream>,
}

impl Runnable for ConnectionEstablishedTask {
    fn handler(self: Box<Self>) {
        let ws = self.addr.root();

        *ws.r().sender.borrow_mut() = Some(self.sender);

        // Step 1: Protocols.

        // Step 2.
        ws.ready_state.set(WebSocketRequestState::Open);

        // Step 3: Extensions.
        // Step 4: Protocols.
        // Step 5: Cookies.

        // Step 6.
        let global = ws.global.root();
        let event = Event::new(global.r(), "open".to_owned(),
                               EventBubbles::DoesNotBubble,
                               EventCancelable::NotCancelable);
        event.fire(EventTargetCast::from_ref(ws.r()));
    }
}

struct CloseTask {
    addr: Trusted<WebSocket>,
}

impl Runnable for CloseTask {
    fn handler(self: Box<Self>) {
        let ws = self.addr.root();
        let ws = ws.r();
        let global = ws.global.root();
        ws.ready_state.set(WebSocketRequestState::Closed);
        //If failed or full, fire error event
        if ws.failed.get() || ws.full.get() {
            ws.failed.set(false);
            ws.full.set(false);
            //A Bad close
            ws.clean_close.set(false);
            let event = Event::new(global.r(),
                                   "error".to_owned(),
                                   EventBubbles::DoesNotBubble,
                                   EventCancelable::Cancelable);
            let target = EventTargetCast::from_ref(ws);
            event.r().fire(target);
        }
        let rsn = ws.reason.borrow();
        let rsn_clone = rsn.clone();
        /*In addition, we also have to fire a close even if error event fired
         https://html.spec.whatwg.org/multipage/#closeWebSocket
        */
        let close_event = CloseEvent::new(global.r(),
                                          "close".to_owned(),
                                          EventBubbles::DoesNotBubble,
                                          EventCancelable::NotCancelable,
                                          ws.clean_close.get(),
                                          ws.code.get(),
                                          rsn_clone);
        let target = EventTargetCast::from_ref(ws);
        let event = EventCast::from_ref(close_event.r());
        event.fire(target);
    }
}
<commit_msg>Spawn a thread for WebSocket messages.<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::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::WebSocketBinding;
use dom::bindings::codegen::Bindings::WebSocketBinding::WebSocketMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::codegen::InheritTypes::EventCast;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::error::Error::{InvalidAccess, Syntax};
use dom::bindings::global::{GlobalField, GlobalRef};
use dom::bindings::js::Root;
use dom::bindings::refcounted::Trusted;
use dom::bindings::str::USVString;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::reflect_dom_object;
use dom::closeevent::CloseEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use script_task::Runnable;
use script_task::ScriptMsg;
use std::cell::{Cell, RefCell};
use std::borrow::ToOwned;
use util::str::DOMString;
use util::task::spawn_named;

use hyper::header::Host;
use websocket::Message;
use websocket::ws::sender::Sender as Sender_Object;
use websocket::client::sender::Sender;
use websocket::client::receiver::Receiver;
use websocket::stream::WebSocketStream;
use websocket::client::request::Url;
use websocket::Client;
use websocket::header::Origin;
use websocket::result::WebSocketResult;
use websocket::ws::util::url::parse_url;

#[derive(JSTraceable, PartialEq, Copy, Clone)]
enum WebSocketRequestState {
    Connecting = 0,
    Open = 1,
    Closing = 2,
    Closed = 3,
}

no_jsmanaged_fields!(Sender<WebSocketStream>);

#[dom_struct]
pub struct WebSocket {
    eventtarget: EventTarget,
    url: Url,
    global: GlobalField,
    ready_state: Cell<WebSocketRequestState>,
    sender: RefCell<Option<Sender<WebSocketStream>>>,
    failed: Cell<bool>, //Flag to tell if websocket was closed due to failure
    full: Cell<bool>, //Flag to tell if websocket queue is full
    clean_close: Cell<bool>, //Flag to tell if the websocket closed cleanly (not due to full or fail)
    code: Cell<u16>, //Closing code
    reason: DOMRefCell<DOMString>, //Closing reason
    data: DOMRefCell<DOMString>, //Data from send - TODO: Remove after buffer is added.
}

/// *Establish a WebSocket Connection* as defined in RFC 6455.
fn establish_a_websocket_connection(url: (Host, String, bool), origin: String)
    -> WebSocketResult<(Sender<WebSocketStream>, Receiver<WebSocketStream>)> {
    let mut request = try!(Client::connect(url));
    request.headers.set(Origin(origin));

    let response = try!(request.send());
    try!(response.validate());

    Ok(response.begin().split())
}

impl WebSocket {
    pub fn new_inherited(global: GlobalRef, url: Url) -> WebSocket {
        WebSocket {
            eventtarget: EventTarget::new_inherited(EventTargetTypeId::WebSocket),
            url: url,
            global: GlobalField::from_rooted(&global),
            ready_state: Cell::new(WebSocketRequestState::Connecting),
            failed: Cell::new(false),
            sender: RefCell::new(None),
            full: Cell::new(false),
            clean_close: Cell::new(true),
            code: Cell::new(0),
            reason: DOMRefCell::new("".to_owned()),
            data: DOMRefCell::new("".to_owned()),
        }

    }

    pub fn new(global: GlobalRef,
               url: DOMString,
               protocols: Option<DOMString>)
               -> Fallible<Root<WebSocket>> {
        // Step 1.
        let parsed_url = try!(Url::parse(&url).map_err(|_| Error::Syntax));
        let url = try!(parse_url(&parsed_url).map_err(|_| Error::Syntax));

        // Step 2: Disallow https -> ws connections.
        // Step 3: Potentially block access to some ports.

        // Step 4.
        let protocols = protocols.as_slice();

        // Step 5.
        for (i, protocol) in protocols.iter().enumerate() {
            // https://tools.ietf.org/html/rfc6455#section-4.1
            // Handshake requirements, step 10
            if protocol.is_empty() {
                return Err(Syntax);
            }

            if protocols[i+1..].iter().any(|p| p == protocol) {
                return Err(Syntax);
            }

            if protocol.chars().any(|c| c < '\u{0021}' || c > '\u{007E}') {
                return Err(Syntax);
            }
        }

        // Step 6: Origin.

        // Step 7.
        let ws = reflect_dom_object(box WebSocket::new_inherited(global, parsed_url),
                                    global,
                                    WebSocketBinding::Wrap);
        let address = Trusted::new(global.get_cx(), ws.r(), global.script_chan());

        let origin = global.get_url().serialize();
        let sender = global.script_chan();
        spawn_named(format!("WebSocket connection to {}", ws.Url()), move || {
            // Step 8: Protocols.

            // Step 9.
            let channel = establish_a_websocket_connection(url, origin);
            let (temp_sender, _temp_receiver) = match channel {
                Ok(channel) => channel,
                Err(e) => {
                    debug!("Failed to establish a WebSocket connection: {:?}", e);
                    let task = box CloseTask {
                        addr: address,
                    };
                    sender.send(ScriptMsg::RunnableMsg(task)).unwrap();
                    return;
                }
            };

            let open_task = box ConnectionEstablishedTask {
                addr: address,
                sender: temp_sender,
            };
            sender.send(ScriptMsg::RunnableMsg(open_task)).unwrap();
        });

        // Step 7.
        Ok(ws)
    }

    pub fn Constructor(global: GlobalRef,
                       url: DOMString,
                       protocols: Option<DOMString>)
                       -> Fallible<Root<WebSocket>> {
        WebSocket::new(global, url, protocols)
    }
}

impl<'a> WebSocketMethods for &'a WebSocket {
    event_handler!(open, GetOnopen, SetOnopen);
    event_handler!(close, GetOnclose, SetOnclose);
    event_handler!(error, GetOnerror, SetOnerror);

    fn Url(self) -> DOMString {
        self.url.serialize()
    }

    fn ReadyState(self) -> u16 {
        self.ready_state.get() as u16
    }

    fn Send(self, data: Option<USVString>) -> Fallible<()> {
        match self.ready_state.get() {
            WebSocketRequestState::Connecting => {
                return Err(Error::InvalidState);
            },
            WebSocketRequestState::Open => (),
            WebSocketRequestState::Closing | WebSocketRequestState::Closed => {
                // TODO: Update bufferedAmount.
                return Ok(());
            }
        }

        /*TODO: This is not up to spec see http://html.spec.whatwg.org/multipage/comms.html search for
                "If argument is a string"
          TODO: Need to buffer data
          TODO: bufferedAmount attribute returns the size of the buffer in bytes -
                this is a required attribute defined in the websocket.webidl file
          TODO: The send function needs to flag when full by using the following
          self.full.set(true). This needs to be done when the buffer is full
        */
        let mut other_sender = self.sender.borrow_mut();
        let my_sender = other_sender.as_mut().unwrap();
        let _ = my_sender.send_message(Message::Text(data.unwrap().0));
        return Ok(())
    }

    fn Close(self, code: Option<u16>, reason: Option<USVString>) -> Fallible<()>{
        fn send_close(this: &WebSocket) {
            this.ready_state.set(WebSocketRequestState::Closing);

            let mut sender = this.sender.borrow_mut();
            //TODO: Also check if the buffer is full
            if let Some(sender) = sender.as_mut() {
                let _ = sender.send_message(Message::Close(None));
            }
        }

        if let Some(code) = code {
            //Check code is NOT 1000 NOR in the range of 3000-4999 (inclusive)
            if  code != 1000 && (code < 3000 || code > 4999) {
                return Err(Error::InvalidAccess);
            }
        }
        if let Some(ref reason) = reason {
            if reason.0.as_bytes().len() > 123 { //reason cannot be larger than 123 bytes
                return Err(Error::Syntax);
            }
        }

        match self.ready_state.get() {
            WebSocketRequestState::Closing | WebSocketRequestState::Closed  => {} //Do nothing
            WebSocketRequestState::Connecting => { //Connection is not yet established
                /*By setting the state to closing, the open function
                  will abort connecting the websocket*/
                self.failed.set(true);
                send_close(self);
                //Note: After sending the close message, the receive loop confirms a close message from the server and
                //      must fire a close event
            }
            WebSocketRequestState::Open => {
                //Closing handshake not started - still in open
                //Start the closing by setting the code and reason if they exist
                if let Some(code) = code {
                    self.code.set(code);
                }
                if let Some(reason) = reason {
                    *self.reason.borrow_mut() = reason.0;
                }
                send_close(self);
                //Note: After sending the close message, the receive loop confirms a close message from the server and
                //      must fire a close event
            }
        }
        Ok(()) //Return Ok
    }
}

/// Task queued when *the WebSocket connection is established*.
struct ConnectionEstablishedTask {
    addr: Trusted<WebSocket>,
    sender: Sender<WebSocketStream>,
}

impl Runnable for ConnectionEstablishedTask {
    fn handler(self: Box<Self>) {
        let ws = self.addr.root();

        *ws.r().sender.borrow_mut() = Some(self.sender);

        // Step 1: Protocols.

        // Step 2.
        ws.ready_state.set(WebSocketRequestState::Open);

        // Step 3: Extensions.
        // Step 4: Protocols.
        // Step 5: Cookies.

        // Step 6.
        let global = ws.global.root();
        let event = Event::new(global.r(), "open".to_owned(),
                               EventBubbles::DoesNotBubble,
                               EventCancelable::NotCancelable);
        event.fire(EventTargetCast::from_ref(ws.r()));
    }
}

struct CloseTask {
    addr: Trusted<WebSocket>,
}

impl Runnable for CloseTask {
    fn handler(self: Box<Self>) {
        let ws = self.addr.root();
        let ws = ws.r();
        let global = ws.global.root();
        ws.ready_state.set(WebSocketRequestState::Closed);
        //If failed or full, fire error event
        if ws.failed.get() || ws.full.get() {
            ws.failed.set(false);
            ws.full.set(false);
            //A Bad close
            ws.clean_close.set(false);
            let event = Event::new(global.r(),
                                   "error".to_owned(),
                                   EventBubbles::DoesNotBubble,
                                   EventCancelable::Cancelable);
            let target = EventTargetCast::from_ref(ws);
            event.r().fire(target);
        }
        let rsn = ws.reason.borrow();
        let rsn_clone = rsn.clone();
        /*In addition, we also have to fire a close even if error event fired
         https://html.spec.whatwg.org/multipage/#closeWebSocket
        */
        let close_event = CloseEvent::new(global.r(),
                                          "close".to_owned(),
                                          EventBubbles::DoesNotBubble,
                                          EventCancelable::NotCancelable,
                                          ws.clean_close.get(),
                                          ws.code.get(),
                                          rsn_clone);
        let target = EventTargetCast::from_ref(ws);
        let event = EventCast::from_ref(close_event.r());
        event.fire(target);
    }
}
<|endoftext|>


<commit_before>use super::pokemon_model::PokemonModel;
use super::determinant_values::Dv;
use super::enums;
use super::natures;

/// Contains the main stats for every Pokemon.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Stats {
    hp: u16,
    attack: u16,
    defense: u16,
    special_attack: u16,
    special_defense: u16,
    speed: u16,
    accuracy: u16,
    evasion: u16,
}

impl Stats {
    /// Is used to calculate the stat when converting a Pokemon Model in a Pokemon Token.
    pub fn calculate_stats(model: PokemonModel,
                           dv: Dv,
                           nature: natures::Nature,
                           level: u16)
                           -> Stats {
        let hp = ((((2.0 * model.get_stats().get_stat(&enums::Stats::Hp) as f32 +
                     (dv.get_dv(enums::Stats::Hp) as f32 /
                      4.0)) as f32 * level as f32) / 100.0) + level as f32 +
                  10.0) as u16;

        fn stat_formula(base: u16,
                        stat: enums::Stats,
                        dv: u8,
                        level: u16,
                        nature: natures::Nature)
                        -> u16 {
            let mut nature_modifier = 1.0;
            if nature.get_stats().0 == stat {
                nature_modifier = nature_modifier - 0.1;
            }
            if nature.get_stats().1 == stat {
                nature_modifier = nature_modifier + 0.1;
            }
            ((((2.0 * base as f32 + (dv as f32 / 4.0)) * level as f32) / 100.0 + 5.0) *
             nature_modifier) as u16
        }
        println!("{:?}", hp);

        Stats {
            hp: hp,
            attack: {
                stat_formula(model.get_stats().get_stat(&enums::Stats::Attack),
                             enums::Stats::Attack,
                             dv.get_dv(enums::Stats::Attack),
                             level,
                             nature.clone())
            },
            defense: {
                stat_formula(model.get_stats().get_stat(&enums::Stats::Defense),
                             enums::Stats::Defense,
                             dv.get_dv(enums::Stats::Defense),
                             level,
                             nature.clone())
            },
            speed: {
                stat_formula(model.get_stats().get_stat(&enums::Stats::Speed),
                             enums::Stats::Speed,
                             dv.get_dv(enums::Stats::Speed),
                             level,
                             nature.clone())
            },
            special_attack: {
                stat_formula(model.get_stats().get_stat(&enums::Stats::SpecialAttack),
                             enums::Stats::SpecialAttack,
                             dv.get_dv(enums::Stats::SpecialAttack),
                             level,
                             nature.clone())
            },
            special_defense: {
                stat_formula(model.get_stats().get_stat(&enums::Stats::SpecialDefense),
                             enums::Stats::SpecialDefense,
                             dv.get_dv(enums::Stats::SpecialDefense),
                             level,
                             nature)
            },
            accuracy: 100,
            evasion: 100,
        }
    }
    // Getter methods
    //
    /// Gets the stat value of the given stat
    pub fn get_stat(&self, stat: &enums::Stats) -> u16 {
        match stat {
            &enums::Stats::Hp => self.hp,
            &enums::Stats::Attack => self.attack,
            &enums::Stats::Defense => self.defense,
            &enums::Stats::SpecialAttack => self.special_attack,
            &enums::Stats::SpecialDefense => self.special_defense,
            &enums::Stats::Speed => self.speed,
            &enums::Stats::Evasion => self.evasion,
            &enums::Stats::Accuracy => self.accuracy,
            _ => 0,
        }
    }
    // Setter methods
    //
    /// Sets the stat value of the given stat
    pub fn set_stats(&mut self, stat: enums::Stats, value: u16) {
        match stat {
            enums::Stats::Hp => self.hp = value,
            enums::Stats::Attack => self.attack = value,
            enums::Stats::Defense => self.defense = value,
            enums::Stats::SpecialAttack => self.special_attack = value,
            enums::Stats::SpecialDefense => self.special_defense = value,
            enums::Stats::Speed => self.speed = value,
            enums::Stats::Evasion => self.evasion = value,
            enums::Stats::Accuracy => self.accuracy = value,
            _ => {}
        }
    }

    // Provides a default Stat struct with all Values set to 0
    pub fn default() -> Stats {
        Stats {
            hp: 0,
            attack: 0,
            defense: 0,
            special_attack: 0,
            special_defense: 0,
            speed: 0,
            accuracy: 0,
            evasion: 0,
        }
    }
}
<commit_msg>Fixed formatting<commit_after>use super::pokemon_model::PokemonModel;
use super::determinant_values::Dv;
use super::enums;
use super::natures;

/// Contains the main stats for every Pokemon.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Stats {
    hp: u16,
    attack: u16,
    defense: u16,
    special_attack: u16,
    special_defense: u16,
    speed: u16,
    accuracy: u16,
    evasion: u16,
}

impl Stats {
    /// Is used to calculate the stat when converting a Pokemon Model in a Pokemon Token.
    pub fn calculate_stats(model: PokemonModel,
                           dv: Dv,
                           nature: natures::Nature,
                           level: u16)
                           -> Stats {
        let hp = ((((2.0 * model.get_stats().get_stat(&enums::Stats::Hp) as f32 +
                     (dv.get_dv(enums::Stats::Hp) as f32 / 4.0)) as
                    f32 * level as f32) / 100.0) + level as f32 + 10.0) as u16;

        fn stat_formula(base: u16,
                        stat: enums::Stats,
                        dv: u8,
                        level: u16,
                        nature: natures::Nature)
                        -> u16 {
            let mut nature_modifier = 1.0;
            if nature.get_stats().0 == stat {
                nature_modifier = nature_modifier - 0.1;
            }
            if nature.get_stats().1 == stat {
                nature_modifier = nature_modifier + 0.1;
            }
            ((((2.0 * base as f32 + (dv as f32 / 4.0)) * level as f32) / 100.0 + 5.0) *
             nature_modifier) as u16
        }
        println!("{:?}", hp);

        Stats {
            hp: hp,
            attack: {
                stat_formula(model.get_stats().get_stat(&enums::Stats::Attack),
                             enums::Stats::Attack,
                             dv.get_dv(enums::Stats::Attack),
                             level,
                             nature.clone())
            },
            defense: {
                stat_formula(model.get_stats().get_stat(&enums::Stats::Defense),
                             enums::Stats::Defense,
                             dv.get_dv(enums::Stats::Defense),
                             level,
                             nature.clone())
            },
            speed: {
                stat_formula(model.get_stats().get_stat(&enums::Stats::Speed),
                             enums::Stats::Speed,
                             dv.get_dv(enums::Stats::Speed),
                             level,
                             nature.clone())
            },
            special_attack: {
                stat_formula(model.get_stats().get_stat(&enums::Stats::SpecialAttack),
                             enums::Stats::SpecialAttack,
                             dv.get_dv(enums::Stats::SpecialAttack),
                             level,
                             nature.clone())
            },
            special_defense: {
                stat_formula(model.get_stats().get_stat(&enums::Stats::SpecialDefense),
                             enums::Stats::SpecialDefense,
                             dv.get_dv(enums::Stats::SpecialDefense),
                             level,
                             nature)
            },
            accuracy: 100,
            evasion: 100,
        }
    }
    // Getter methods
    //
    /// Gets the stat value of the given stat
    pub fn get_stat(&self, stat: &enums::Stats) -> u16 {
        match stat {
            &enums::Stats::Hp => self.hp,
            &enums::Stats::Attack => self.attack,
            &enums::Stats::Defense => self.defense,
            &enums::Stats::SpecialAttack => self.special_attack,
            &enums::Stats::SpecialDefense => self.special_defense,
            &enums::Stats::Speed => self.speed,
            &enums::Stats::Evasion => self.evasion,
            &enums::Stats::Accuracy => self.accuracy,
            _ => 0,
        }
    }
    // Setter methods
    //
    /// Sets the stat value of the given stat
    pub fn set_stats(&mut self, stat: enums::Stats, value: u16) {
        match stat {
            enums::Stats::Hp => self.hp = value,
            enums::Stats::Attack => self.attack = value,
            enums::Stats::Defense => self.defense = value,
            enums::Stats::SpecialAttack => self.special_attack = value,
            enums::Stats::SpecialDefense => self.special_defense = value,
            enums::Stats::Speed => self.speed = value,
            enums::Stats::Evasion => self.evasion = value,
            enums::Stats::Accuracy => self.accuracy = value,
            _ => {}
        }
    }

    // Provides a default Stat struct with all Values set to 0
    pub fn default() -> Stats {
        Stats {
            hp: 0,
            attack: 0,
            defense: 0,
            special_attack: 0,
            special_defense: 0,
            speed: 0,
            accuracy: 0,
            evasion: 0,
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use self::rand::Rng;

#[derive(Debug, PartialEq)]
pub enum AliasDistributionError {
    InvalidWeights,
    NullDistribution,
}

impl ::std::fmt::Display for AliasDistributionError {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            AliasDistributionError::InvalidWeights => write!(f, "InvalidWeights"),
            AliasDistributionError::NullDistribution => write!(f, "NullDistribution"),
        }
    }
}

impl ::std::error::Error for AliasDistributionError {
    fn description(&self) -> &str {
        match *self {
            AliasDistributionError::InvalidWeights => "Negative weights are not allowed",
            AliasDistributionError::NullDistribution => "Sum of weights must not be zero",
        }
    }

    fn cause(&self) -> Option<&::std::error::Error> {
        None
    }
}

#[derive(Debug)]
pub struct AliasDistribution {
    probability_table: Vec<f64>,
    alias_table: Vec<usize>,
    pub entropy: f64,
}

impl AliasDistribution {
    pub fn new(weights: &Vec<f64>) -> Result<AliasDistribution, AliasDistributionError> {
        if weights.iter().any(|&w| w < 0.0) {
            return Err(AliasDistributionError::InvalidWeights);
        };
        let size = weights.len();
        let total = weights.iter().fold(0.0, |sum, x| sum + x);
        if total == 0.0 {
            return Err(AliasDistributionError::NullDistribution);
        };
        let mut entropy = 0.0;

        let mut probability_table = Vec::with_capacity(size);
        for weight in weights {
            let prob = weight / total;
            entropy -= prob * prob.log(2.0);
            probability_table.push(prob * (size as f64));
        }

        let mut alias_table: Vec<usize> = (0..size).collect();
        let mut overfull: Vec<usize> = Vec::new();
        let mut underfull: Vec<usize> = Vec::new();
        for (i, &prob) in probability_table.iter().enumerate() {
            if prob < 1.0 {
                underfull.push(i);
            } else {
                overfull.push(i);
            }
        }
        while !(overfull.is_empty() | underfull.is_empty()) {
            let i = underfull.pop().unwrap();
            let j = overfull.pop().unwrap();
            alias_table[i] = j;
            probability_table[j] += probability_table[i] - 1.0;
            if probability_table[j] < 1.0 {
                underfull.push(j)
            } else {
                overfull.push(j)
            };
        }

        Ok(AliasDistribution {
            probability_table: probability_table,
            alias_table: alias_table,
            entropy: entropy,
        })
    }

    pub fn choice(&self) -> usize {
        // TODO: Catch the potential error and let the caller decide what to do.
        let mut rng = rand::OsRng::new().unwrap();
        let i = rng.gen_range(0, self.probability_table.len());
        let y = rng.gen();
        let choice = if self.probability_table[i] >= y {
            i
        } else {
            self.alias_table[i]
        };

        choice
    }
}

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

    macro_rules! assert_approx_eq {
        ($a:expr, $b:expr) => {{
            let (a, b) = (&$a, &$b);
            assert!(
                (*a - *b).abs() < 1.0e-6,
                "{} is not approximately equal to {}",
                *a,
                *b
            );
        }};
    }

    #[test]
    fn test_new() {
        let mut test_cases = Vec::new();
        test_cases.push(vec![1.0, 2.0, 3.0, 4.0]);
        test_cases.push(vec![0.2, 0.2, 0.2, 0.2, 0.2]);
        test_cases.push(vec![3.0, 0.0, 5.0]);
        test_cases.push(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);

        for weights in test_cases {
            let total = weights.iter().fold(0.0, |x, sum| sum + x);
            let count = weights.len() as f64;
            let dist = AliasDistribution::new(&weights).unwrap();
            let mut ps = vec![0.0; weights.len()];
            for (i, (&j, p)) in dist
                .alias_table
                .iter()
                .zip(dist.probability_table)
                .enumerate()
            {
                ps[i] += p / count;
                ps[j] += (1.0 - p) / count;
            }
            for (p, w) in ps.iter().zip(weights) {
                assert_approx_eq!(p, w / total);
            }
        }
    }

    #[test]
    fn test_negative_weight() {
        let err = AliasDistribution::new(&vec![3.2, -0.3, 4.5]).unwrap_err();
        assert_eq!(err, AliasDistributionError::InvalidWeights);
    }

    #[test]
    fn test_zero_distribution() {
        let err = AliasDistribution::new(&vec![0.0, 0.0, 0.0]).unwrap_err();
        assert_eq!(err, AliasDistributionError::NullDistribution);
    }

    #[test]
    fn test_empty_distribution() {
        let err = AliasDistribution::new(&Vec::new()).unwrap_err();
        assert_eq!(err, AliasDistributionError::NullDistribution);
    }

    #[test]
    fn test_entropy() {
        let dist = AliasDistribution::new(&vec![1.0, 1.0]).unwrap();
        assert_approx_eq!(dist.entropy, 1.0);
        let dist = AliasDistribution::new(&vec![0.5, 0.5, 1.0, 2.0]).unwrap();
        assert_approx_eq!(dist.entropy, 1.75);
    }

    #[test]
    fn test_choice() {
        let dist = AliasDistribution::new(&vec![1.0, 2.0, 3.0]).unwrap();
        let choice = dist.choice();
        assert!(choice < 3, "{} is too large");
    }
}
<commit_msg>Fix up AliasDistributionError implementation<commit_after>extern crate rand;

use self::rand::Rng;
use std::fmt;

#[derive(Debug, PartialEq)]
pub enum AliasDistributionError {
    NegativeWeight,
    NullDistribution,
}

impl ::std::error::Error for AliasDistributionError {}

impl fmt::Display for AliasDistributionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            AliasDistributionError::NegativeWeight => {
                write!(f, "Negative weights are not allowed.")
            }
            AliasDistributionError::NullDistribution => {
                write!(f, "Sum of weights must be non-zero.")
            }
        }
    }
}

#[derive(Debug)]
pub struct AliasDistribution {
    probability_table: Vec<f64>,
    alias_table: Vec<usize>,
    pub entropy: f64,
}

impl AliasDistribution {
    pub fn new(weights: &Vec<f64>) -> Result<AliasDistribution, AliasDistributionError> {
        if weights.iter().any(|&w| w < 0.0) {
            return Err(AliasDistributionError::NegativeWeight);
        };
        let size = weights.len();
        let total = weights.iter().fold(0.0, |sum, x| sum + x);
        if total == 0.0 {
            return Err(AliasDistributionError::NullDistribution);
        };
        let mut entropy = 0.0;

        let mut probability_table = Vec::with_capacity(size);
        for weight in weights {
            let prob = weight / total;
            entropy -= prob * prob.log(2.0);
            probability_table.push(prob * (size as f64));
        }

        let mut alias_table: Vec<usize> = (0..size).collect();
        let mut overfull: Vec<usize> = Vec::new();
        let mut underfull: Vec<usize> = Vec::new();
        for (i, &prob) in probability_table.iter().enumerate() {
            if prob < 1.0 {
                underfull.push(i);
            } else {
                overfull.push(i);
            }
        }
        while !(overfull.is_empty() | underfull.is_empty()) {
            let i = underfull.pop().unwrap();
            let j = overfull.pop().unwrap();
            alias_table[i] = j;
            probability_table[j] += probability_table[i] - 1.0;
            if probability_table[j] < 1.0 {
                underfull.push(j)
            } else {
                overfull.push(j)
            };
        }

        Ok(AliasDistribution {
            probability_table: probability_table,
            alias_table: alias_table,
            entropy: entropy,
        })
    }

    pub fn choice(&self) -> usize {
        // TODO: Catch the potential error and let the caller decide what to do.
        let mut rng = rand::OsRng::new().unwrap();
        let i = rng.gen_range(0, self.probability_table.len());
        let y = rng.gen();
        let choice = if self.probability_table[i] >= y {
            i
        } else {
            self.alias_table[i]
        };

        choice
    }
}

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

    macro_rules! assert_approx_eq {
        ($a:expr, $b:expr) => {{
            let (a, b) = (&$a, &$b);
            assert!(
                (*a - *b).abs() < 1.0e-6,
                "{} is not approximately equal to {}",
                *a,
                *b
            );
        }};
    }

    #[test]
    fn test_new() {
        let mut test_cases = Vec::new();
        test_cases.push(vec![1.0, 2.0, 3.0, 4.0]);
        test_cases.push(vec![0.2, 0.2, 0.2, 0.2, 0.2]);
        test_cases.push(vec![3.0, 0.0, 5.0]);
        test_cases.push(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]);

        for weights in test_cases {
            let total = weights.iter().fold(0.0, |x, sum| sum + x);
            let count = weights.len() as f64;
            let dist = AliasDistribution::new(&weights).unwrap();
            let mut ps = vec![0.0; weights.len()];
            for (i, (&j, p)) in dist
                .alias_table
                .iter()
                .zip(dist.probability_table)
                .enumerate()
            {
                ps[i] += p / count;
                ps[j] += (1.0 - p) / count;
            }
            for (p, w) in ps.iter().zip(weights) {
                assert_approx_eq!(p, w / total);
            }
        }
    }

    #[test]
    fn test_negative_weight() {
        let err = AliasDistribution::new(&vec![3.2, -0.3, 4.5]).unwrap_err();
        assert_eq!(err, AliasDistributionError::NegativeWeight);
    }

    #[test]
    fn test_zero_distribution() {
        let err = AliasDistribution::new(&vec![0.0, 0.0, 0.0]).unwrap_err();
        assert_eq!(err, AliasDistributionError::NullDistribution);
    }

    #[test]
    fn test_empty_distribution() {
        let err = AliasDistribution::new(&Vec::new()).unwrap_err();
        assert_eq!(err, AliasDistributionError::NullDistribution);
    }

    #[test]
    fn test_entropy() {
        let dist = AliasDistribution::new(&vec![1.0, 1.0]).unwrap();
        assert_approx_eq!(dist.entropy, 1.0);
        let dist = AliasDistribution::new(&vec![0.5, 0.5, 1.0, 2.0]).unwrap();
        assert_approx_eq!(dist.entropy, 1.75);
    }

    #[test]
    fn test_choice() {
        let dist = AliasDistribution::new(&vec![1.0, 2.0, 3.0]).unwrap();
        let choice = dist.choice();
        assert!(choice < 3, "{} is too large");
    }
}
<|endoftext|>


<commit_before>extern crate rosc;

#[cfg(feature = "std")]
use rosc::address::Matcher;

#[cfg(feature = "std")]
#[test]
fn test_matcher_new() {
    let mut matcher;

    // Regular address using only alphanumeric parts
    matcher = Matcher::new("/oscillator/1/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/1/frequency").expect("Should match");
    matcher.match_address("/oscillator/1/phase").expect_err("Should not match");
    matcher.match_address("/oscillator/1/frequencyfoo").expect_err("Should not match");
    matcher.match_address("/prefix/oscillator/1/frequency").expect_err("Should not match");

    // Choice
    matcher = Matcher::new("/foo{bar,baz}").expect("Should be valid");
    matcher.match_address("/foobar").expect("Should match");
    matcher.match_address("/foobaz").expect("Should match");

    matcher = Matcher::new("/foo{bar,baz,tron}").expect("Should be valid");
    matcher.match_address("/footron").expect("Should match");

    // Character class
    // Character classes are sets or ranges of characters to match.
    // e.g. [a-z] will match any lower case alphabetic character. [abcd] will match the characters abcd.
    // They can be negated with '!', e.g. [!0-9] will match all characters except 0-9
    // Basic example
    matcher = Matcher::new("/oscillator/[0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");  // Beginning of range included
    matcher.match_address("/oscillator/6").expect("Should match");  // Middle of range
    matcher.match_address("/oscillator/9").expect("Should match");  // Last member of range included

    // Inverted order should work too
    matcher = Matcher::new("/oscillator/[9-0]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");
    matcher.match_address("/oscillator/6").expect("Should match");
    matcher.match_address("/oscillator/9").expect("Should match");

    // Multiple ranges
    matcher = Matcher::new("/oscillator/[a-zA-Z0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");
    matcher.match_address("/oscillator/a").expect("Should match");
    matcher.match_address("/oscillator/A").expect("Should match");

    // Negated range
    matcher = Matcher::new("/oscillator/[!0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/1").expect_err("Should not match");
    matcher.match_address("/oscillator/a").expect("Should match");

    // Extra exclamation points must be entirely ignored
    matcher = Matcher::new("/oscillator/[!0-9!a-z!]").expect("Should be valid");
    matcher.match_address("/oscillator/A").expect("Should match");

    // Trailing dash has no special meaning
    matcher = Matcher::new("/oscillator/[abcd-]").expect("Should be valid");
    matcher.match_address("/oscillator/a").expect("Should match");
    matcher.match_address("/oscillator/-").expect("Should match");

    // Single wildcard
    // A single wildcard '?' matches excatly one alphanumeric character
    matcher = Matcher::new("/oscillator/?/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/1/frequency").expect("Should match");
    matcher.match_address("/oscillator/F/frequency").expect("Should match");
    matcher.match_address("/oscillator//frequency").expect_err("Should not match");
    matcher.match_address("/oscillator/10/frequency").expect_err("Should not match");

    // Test if two consecutive wildcards match
    matcher = Matcher::new("/oscillator/??/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/10/frequency").expect("Should match");
    matcher.match_address("/oscillator/1/frequency").expect_err("Should not match");

    // Test if it works if it is surrounded by non-wildcards
    matcher = Matcher::new("/oscillator/prefixed?postfixed/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/prefixed1postfixed/frequency").expect("Should match");
    matcher.match_address("/oscillator/prefixedpostfixed/frequency").expect_err("Should not match");

    // Wildcard
    // Wildcards '*' match zero or more alphanumeric characters. The implementation is greedy,
    // meaning it will match the longest possible sequence
    matcher = Matcher::new("/oscillator/*/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/anything123/frequency").expect("Should match");
    // Test that wildcard doesn't cross part boundary
    matcher.match_address("/oscillator/extra/part/frequency").expect_err("Should not match");
    matcher.match_address("/oscillator//frequency").expect_err("Should not match");

    // Test greediness
    matcher = Matcher::new("/oscillator/*bar/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/foobarbar/frequency").expect("Should match");

    // Minimum length of 2
    matcher = Matcher::new("/oscillator/*??/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/f/frequency").expect_err("Should not match");

    // Minimum length of 2 and another component follows
    matcher = Matcher::new("/oscillator/*??baz/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobarbaz/frequency").expect("Should match");
    matcher.match_address("/oscillator/fbaz/frequency").expect_err("Should not match");

    // Mix with character class
    matcher = Matcher::new("/oscillator/*[a-d]/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/a/frequency").expect("Should match");
    matcher.match_address("/oscillator/fooa/frequency").expect("Should match");
    matcher.match_address("/oscillator/foox/frequency").expect_err("Should not match");

    // Mix with choice
    matcher = Matcher::new("/oscillator/*{bar,baz}/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/baz/frequency").expect("Should match");
    matcher.match_address("/oscillator/something/frequency").expect_err("Should not match");
}

#[cfg(feature = "std")]
#[test]
fn test_bad_address_pattern() {
    let expected_err = "bad OSC address pattern: bad address pattern";
    assert_eq!(Matcher::new("").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("//empty/parts/").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("////").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/{unclosed,alternative").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/unclosed/[range-").unwrap_err().to_string(), expected_err);
}

#[cfg(feature = "std")]
#[test]
fn test_bad_address() {
    let matcher = Matcher::new("/does-not-matter").expect("Matcher::new");
    let expected_err = "bad OSC address: bad address";
    assert_eq!(matcher.match_address("").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/wildcards?").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/wildcards*").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/ranges[a-z]").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/ranges[!a-z]").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/{contains,alternative}").unwrap_err().to_string(), expected_err);
}
<commit_msg>Fix name of test<commit_after>extern crate rosc;

#[cfg(feature = "std")]
use rosc::address::Matcher;

#[cfg(feature = "std")]
#[test]
fn test_matcher() {
    let mut matcher;

    // Regular address using only alphanumeric parts
    matcher = Matcher::new("/oscillator/1/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/1/frequency").expect("Should match");
    matcher.match_address("/oscillator/1/phase").expect_err("Should not match");
    matcher.match_address("/oscillator/1/frequencyfoo").expect_err("Should not match");
    matcher.match_address("/prefix/oscillator/1/frequency").expect_err("Should not match");

    // Choice
    matcher = Matcher::new("/foo{bar,baz}").expect("Should be valid");
    matcher.match_address("/foobar").expect("Should match");
    matcher.match_address("/foobaz").expect("Should match");

    matcher = Matcher::new("/foo{bar,baz,tron}").expect("Should be valid");
    matcher.match_address("/footron").expect("Should match");

    // Character class
    // Character classes are sets or ranges of characters to match.
    // e.g. [a-z] will match any lower case alphabetic character. [abcd] will match the characters abcd.
    // They can be negated with '!', e.g. [!0-9] will match all characters except 0-9
    // Basic example
    matcher = Matcher::new("/oscillator/[0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");  // Beginning of range included
    matcher.match_address("/oscillator/6").expect("Should match");  // Middle of range
    matcher.match_address("/oscillator/9").expect("Should match");  // Last member of range included

    // Inverted order should work too
    matcher = Matcher::new("/oscillator/[9-0]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");
    matcher.match_address("/oscillator/6").expect("Should match");
    matcher.match_address("/oscillator/9").expect("Should match");

    // Multiple ranges
    matcher = Matcher::new("/oscillator/[a-zA-Z0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/0").expect("Should match");
    matcher.match_address("/oscillator/a").expect("Should match");
    matcher.match_address("/oscillator/A").expect("Should match");

    // Negated range
    matcher = Matcher::new("/oscillator/[!0-9]").expect("Should be valid");
    matcher.match_address("/oscillator/1").expect_err("Should not match");
    matcher.match_address("/oscillator/a").expect("Should match");

    // Extra exclamation points must be entirely ignored
    matcher = Matcher::new("/oscillator/[!0-9!a-z!]").expect("Should be valid");
    matcher.match_address("/oscillator/A").expect("Should match");

    // Trailing dash has no special meaning
    matcher = Matcher::new("/oscillator/[abcd-]").expect("Should be valid");
    matcher.match_address("/oscillator/a").expect("Should match");
    matcher.match_address("/oscillator/-").expect("Should match");

    // Single wildcard
    // A single wildcard '?' matches excatly one alphanumeric character
    matcher = Matcher::new("/oscillator/?/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/1/frequency").expect("Should match");
    matcher.match_address("/oscillator/F/frequency").expect("Should match");
    matcher.match_address("/oscillator//frequency").expect_err("Should not match");
    matcher.match_address("/oscillator/10/frequency").expect_err("Should not match");

    // Test if two consecutive wildcards match
    matcher = Matcher::new("/oscillator/??/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/10/frequency").expect("Should match");
    matcher.match_address("/oscillator/1/frequency").expect_err("Should not match");

    // Test if it works if it is surrounded by non-wildcards
    matcher = Matcher::new("/oscillator/prefixed?postfixed/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/prefixed1postfixed/frequency").expect("Should match");
    matcher.match_address("/oscillator/prefixedpostfixed/frequency").expect_err("Should not match");

    // Wildcard
    // Wildcards '*' match zero or more alphanumeric characters. The implementation is greedy,
    // meaning it will match the longest possible sequence
    matcher = Matcher::new("/oscillator/*/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/anything123/frequency").expect("Should match");
    // Test that wildcard doesn't cross part boundary
    matcher.match_address("/oscillator/extra/part/frequency").expect_err("Should not match");
    matcher.match_address("/oscillator//frequency").expect_err("Should not match");

    // Test greediness
    matcher = Matcher::new("/oscillator/*bar/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/foobarbar/frequency").expect("Should match");

    // Minimum length of 2
    matcher = Matcher::new("/oscillator/*??/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/f/frequency").expect_err("Should not match");

    // Minimum length of 2 and another component follows
    matcher = Matcher::new("/oscillator/*??baz/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobarbaz/frequency").expect("Should match");
    matcher.match_address("/oscillator/fbaz/frequency").expect_err("Should not match");

    // Mix with character class
    matcher = Matcher::new("/oscillator/*[a-d]/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/a/frequency").expect("Should match");
    matcher.match_address("/oscillator/fooa/frequency").expect("Should match");
    matcher.match_address("/oscillator/foox/frequency").expect_err("Should not match");

    // Mix with choice
    matcher = Matcher::new("/oscillator/*{bar,baz}/frequency").expect("Should be valid");
    matcher.match_address("/oscillator/foobar/frequency").expect("Should match");
    matcher.match_address("/oscillator/baz/frequency").expect("Should match");
    matcher.match_address("/oscillator/something/frequency").expect_err("Should not match");

    // Check for allowed literal characters
    matcher = Matcher::new("/[!-~]").expect("Should be valid");
    matcher.match_address("/a").expect("Should match");
}

#[cfg(feature = "std")]
#[test]
fn test_bad_address_pattern() {
    let expected_err = "bad OSC address pattern: bad address pattern";
    assert_eq!(Matcher::new("").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("//empty/parts/").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("////").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/{unclosed,alternative").unwrap_err().to_string(), expected_err);
    assert_eq!(Matcher::new("/unclosed/[range-").unwrap_err().to_string(), expected_err);
}

#[cfg(feature = "std")]
#[test]
fn test_bad_address() {
    let matcher = Matcher::new("/does-not-matter").expect("Matcher::new");
    let expected_err = "bad OSC address: bad address";
    assert_eq!(matcher.match_address("").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/wildcards?").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/wildcards*").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/ranges[a-z]").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/contains/ranges[!a-z]").unwrap_err().to_string(), expected_err);
    assert_eq!(matcher.match_address("/{contains,alternative}").unwrap_err().to_string(), expected_err);
}
<|endoftext|>


<commit_before>#[macro_use(wayland_env)]
extern crate wayland_client as wayc;
extern crate wayland_server as ways;

mod helpers;

use helpers::{TestClient, TestServer, roundtrip};

mod server_utils {
    use ways::{Client, EventLoop, EventLoopHandle, GlobalHandler};
    use ways::protocol::wl_compositor::WlCompositor;

    struct CompositorHandler;

    impl GlobalHandler<WlCompositor> for CompositorHandler {
        fn bind(&mut self, _: &mut EventLoopHandle, _: &Client, _: WlCompositor) {}
    }

    // max supported version: 4
    pub fn insert_compositor(event_loop: &mut EventLoop, v: i32) {
        let hid = event_loop.add_handler(CompositorHandler);
        let _ = event_loop.register_global::<WlCompositor, CompositorHandler>(hid, v);
    }
}

wayland_env!(ClientEnv);

mod client_utils {
    use super::ClientEnv;
    use wayc::{EnvHandler, EventQueue};
    use wayc::protocol::wl_registry::WlRegistry;

    pub fn insert_handler(event_queue: &mut EventQueue, registry: &WlRegistry) -> usize {
        let hid = event_queue.add_handler(EnvHandler::<ClientEnv>::new());
        event_queue.register::<_, EnvHandler<ClientEnv>>(registry, hid);
        hid
    }
}

#[test]
fn simple_global() {
    // server setup
    //
    let mut server = TestServer::new();
    self::server_utils::insert_compositor(&mut server.event_loop, 1);

    // client setup
    //
    let mut client = TestClient::new(&server.socket_name);
    let client_registry = client.display.get_registry();
    let client_handler_hid = self::client_utils::insert_handler(&mut client.event_queue, &client_registry);

    // message passing
    //
    roundtrip(&mut client, &mut server);

    // result assertions
    //
    let state = client.event_queue.state();
    let env = state.get_handler::<wayc::EnvHandler<ClientEnv>>(client_handler_hid);
    let globals = env.globals();
    assert!(globals.len() == 1);
    assert_eq!(globals[0], (1, "wl_compositor".into(), 1));
}

#[test]
fn multi_versions() {
    // server setup
    //
    let mut server = TestServer::new();
    self::server_utils::insert_compositor(&mut server.event_loop, 4);
    self::server_utils::insert_compositor(&mut server.event_loop, 2);
    self::server_utils::insert_compositor(&mut server.event_loop, 3);
    self::server_utils::insert_compositor(&mut server.event_loop, 1);

    // client setup
    //
    let mut client = TestClient::new(&server.socket_name);
    let client_registry = client.display.get_registry();
    let client_handler_hid = self::client_utils::insert_handler(&mut client.event_queue, &client_registry);

    // message passing
    //
    client.display.flush().unwrap();
    server.answer();
    client.event_queue.dispatch().unwrap();

    // result assertions
    //
    let state = client.event_queue.state();
    let env = state.get_handler::<wayc::EnvHandler<ClientEnv>>(client_handler_hid);
    let globals = env.globals();
    assert!(globals.len() == 4);
    let mut seen = [false; 4];
    for &(_, ref interface, version) in globals {
        assert!(interface == "wl_compositor");
        seen[version as usize - 1] = true;
    }
    assert_eq!(seen, [true, true, true, true]);
}
<commit_msg>tests: simplify basic_global<commit_after>#[macro_use(wayland_env)]
extern crate wayland_client as wayc;
extern crate wayland_server as ways;

mod helpers;

use helpers::{TestClient, TestServer, roundtrip};

mod server_utils {
    use ways::{Client, EventLoop, EventLoopHandle, GlobalHandler};
    use ways::protocol::wl_compositor::WlCompositor;

    struct CompositorHandler;

    impl GlobalHandler<WlCompositor> for CompositorHandler {
        fn bind(&mut self, _: &mut EventLoopHandle, _: &Client, _: WlCompositor) {}
    }

    // max supported version: 4
    pub fn insert_compositor(event_loop: &mut EventLoop, v: i32) {
        let hid = event_loop.add_handler(CompositorHandler);
        let _ = event_loop.register_global::<WlCompositor, CompositorHandler>(hid, v);
    }
}

wayland_env!(ClientEnv);

mod client_utils {
    use super::ClientEnv;
    use wayc::{EnvHandler, EventQueue};
    use wayc::protocol::wl_registry::WlRegistry;

    pub fn insert_handler(event_queue: &mut EventQueue, registry: &WlRegistry) -> usize {
        let hid = event_queue.add_handler(EnvHandler::<ClientEnv>::new());
        event_queue.register::<_, EnvHandler<ClientEnv>>(registry, hid);
        hid
    }
}

#[test]
fn simple_global() {
    // server setup
    //
    let mut server = TestServer::new();
    self::server_utils::insert_compositor(&mut server.event_loop, 1);

    // client setup
    //
    let mut client = TestClient::new(&server.socket_name);
    let client_registry = client.display.get_registry();
    let client_handler_hid = self::client_utils::insert_handler(&mut client.event_queue, &client_registry);

    // message passing
    //
    roundtrip(&mut client, &mut server);

    // result assertions
    //
    let state = client.event_queue.state();
    let env = state.get_handler::<wayc::EnvHandler<ClientEnv>>(client_handler_hid);
    let globals = env.globals();
    assert!(globals.len() == 1);
    assert_eq!(globals[0], (1, "wl_compositor".into(), 1));
}

#[test]
fn multi_versions() {
    // server setup
    //
    let mut server = TestServer::new();
    self::server_utils::insert_compositor(&mut server.event_loop, 4);
    self::server_utils::insert_compositor(&mut server.event_loop, 2);
    self::server_utils::insert_compositor(&mut server.event_loop, 3);
    self::server_utils::insert_compositor(&mut server.event_loop, 1);

    // client setup
    //
    let mut client = TestClient::new(&server.socket_name);
    let client_registry = client.display.get_registry();
    let client_handler_hid = self::client_utils::insert_handler(&mut client.event_queue, &client_registry);

    // message passing
    //
    roundtrip(&mut client, &mut server);

    // result assertions
    //
    let state = client.event_queue.state();
    let env = state.get_handler::<wayc::EnvHandler<ClientEnv>>(client_handler_hid);
    let globals = env.globals();
    assert!(globals.len() == 4);
    let mut seen = [false; 4];
    for &(_, ref interface, version) in globals {
        assert!(interface == "wl_compositor");
        seen[version as usize - 1] = true;
    }
    assert_eq!(seen, [true, true, true, true]);
}
<|endoftext|>


<commit_before>extern crate syntect;
extern crate liquid;
extern crate pulldown_cmark as cmark;

use error;
use itertools::Itertools;

use liquid::Renderable;
use liquid::Context;
use liquid::Token::{self, Identifier};
use liquid::lexer::Element::{self, Expression, Tag, Raw};
use liquid::Error;

use syntect::parsing::{SyntaxDefinition, SyntaxSet};
use syntect::highlighting::{ThemeSet, Theme};
use syntect::html::{IncludeBackground, highlighted_snippet_for_string, styles_to_coloured_html,
                    start_coloured_html_snippet};
use syntect::easy::HighlightLines;

use std::ascii::AsciiExt;
use std::borrow::Cow::Owned;

use self::cmark::Parser;
use self::cmark::Tag as cmarkTag;
use self::cmark::Event::{self, Start, End, Text, Html};

struct Setup {
    syntax_set: SyntaxSet,
    theme_set: ThemeSet,
}

unsafe impl Send for Setup {}
unsafe impl Sync for Setup {}

lazy_static!{
    static ref SETUP: Setup = Setup {
        syntax_set: SyntaxSet::load_defaults_newlines(),
        theme_set: ThemeSet::load_defaults()
    };
}

struct CodeBlock {
    lang: Option<String>,
    code: String,
    theme: Theme,
}

impl Renderable for CodeBlock {
    fn render(&self, _: &mut Context) -> Result<Option<String>, Error> {
        let syntax = match self.lang {
                Some(ref lang) => SETUP.syntax_set.find_syntax_by_token(lang),
                _ => None,
            }
            .unwrap_or_else(|| SETUP.syntax_set.find_syntax_plain_text());

        Ok(Some(highlighted_snippet_for_string(&self.code, syntax, &self.theme)))
    }
}

pub struct DecoratedParser<'a> {
    h: Option<HighlightLines<'a>>,
    parser: Parser<'a>,
    theme: &'a Theme,
}

impl<'a> DecoratedParser<'a> {
    pub fn new(parser: Parser<'a>, theme: &'a Theme) -> Self {
        DecoratedParser {
            h: None,
            parser: parser,
            theme: &theme,
        }
    }
}

impl<'a> Iterator for DecoratedParser<'a> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Event<'a>> {
        match self.parser.next() {
            Some(item) => {
                if let Text(text) = item {
                    if let Some(ref mut h) = self.h {
                        let highlighted = &h.highlight(&text);
                        let html = styles_to_coloured_html(highlighted, IncludeBackground::Yes);
                        Some(Html(Owned(html)))
                    } else {
                        Some(Text(text))
                    }
                } else {
                    if let Start(cmarkTag::CodeBlock(ref info)) = item {
                        // set local highlighter, if found
                        let cur_syntax =
                            info.clone()
                                .split(' ')
                                .next()
                                .and_then(|lang| SETUP.syntax_set.find_syntax_by_token(lang))
                                .unwrap_or_else(|| SETUP.syntax_set.find_syntax_plain_text());
                        self.h = Some(HighlightLines::new(&cur_syntax, self.theme));
                        let snippet = start_coloured_html_snippet(self.theme);
                        return Some(Html(Owned(snippet)));
                    }
                    if let End(cmarkTag::CodeBlock(_)) = item {
                        // reset highlighter
                        self.h = None;
                        // close the code block
                        return Some(Html(Owned("
".to_owned())));
                    }

                    Some(item)
                }
            }
            None => None,
        }
    }
}

pub fn initialize_codeblock(arguments: &[Token],
                            tokens: &[Element],
                            theme_name: &str)
                            -> Result<Box<Renderable>, Error> {

    let content = tokens
        .iter()
        .fold("".to_owned(), |a, b| {
            match *b {
                    Expression(_, ref text) |
                    Tag(_, ref text) |
                    Raw(ref text) => text,
                }
                .to_owned() + &a
        });

    let lang = match arguments.iter().next() {
        Some(&Identifier(ref x)) => Some(x.clone()),
        _ => None,
    };

    Ok(Box::new(CodeBlock {
                    code: content,
                    lang: lang,
                    theme: SETUP.theme_set.themes[theme_name].clone(),
                }))
}

pub fn decorate_markdown<'a>(parser: Parser<'a>, theme_name: &str) -> DecoratedParser<'a> {
    DecoratedParser::new(parser, &SETUP.theme_set.themes[theme_name])
}

pub fn has_syntax_theme(name: &str) -> error::Result<bool> {
    #[cfg(not(windows))]
    return Ok(SETUP.theme_set.themes.contains_key(name));

    #[cfg(windows)]
    {
        use error::ErrorKind;
        return Err(ErrorKind::UnsupportedPlatform("syntax highlighting", "windows").into());
    }
}

pub fn list_syntax_themes<'a>() -> Vec<&'a String> {
    #[cfg(not(windows))]
    return SETUP.theme_set.themes.keys().collect::<Vec<_>>();

    #[cfg(windows)]
    return vec![];
}

pub fn list_syntaxes<'a>() -> Vec<String> {
    #[cfg(not(windows))]
    {
        fn definition_to_string(sd: &SyntaxDefinition) -> String {
            let extensions = sd.file_extensions.iter().join(&", ".to_owned());
            format!("{} [{}]", sd.name, extensions)
        }

        let mut syntaxes = SETUP
            .syntax_set
            .syntaxes()
            .iter()
            .map(definition_to_string)
            .collect::<Vec<_>>();

        // sort alphabetically with insensitive ascii case
        syntaxes.sort_by_key(|a| (a as &str).to_ascii_lowercase());

        return syntaxes;
    }

    #[cfg(windows)]
    return vec![];
}

#[cfg(test)]
mod test {

    use std::default::Default;
    use syntax_highlight::initialize_codeblock;
    use liquid::{self, Renderable, LiquidOptions, Context};

    const CODE_BLOCK: &'static str = "mod test {
        fn hello(arg: int) -> bool {
            \
                                      true
        }
    }
    ";

    const RENDERED: &'static str = "
\nmod test {\n        fn hello(arg: int) -> bool {\n            true\n        \
         }\n    \
         }\n    \
         \n
\n";
    #[test]
    fn test_codeblock_renders_rust() {
        let mut options: LiquidOptions = Default::default();
        options
            .blocks
            .insert("codeblock".to_string(),
                    Box::new(|_, args, tokens, _| {
                                 initialize_codeblock(args, tokens, "base16-ocean.dark")
                             }));
        let template = liquid::parse(&format!("{{% codeblock rust %}}{}{{% endcodeblock %}}",
                                              CODE_BLOCK),
                                     options)
                .unwrap();
        let mut data = Context::new();
        let output = template.render(&mut data);
        assert_eq!(output.unwrap(), Some(RENDERED.to_string()));
    }

}
<commit_msg>chore: Remove dead code from split<commit_after>extern crate syntect;
extern crate liquid;
extern crate pulldown_cmark as cmark;

use error;
use itertools::Itertools;

use liquid::Renderable;
use liquid::Context;
use liquid::Token::{self, Identifier};
use liquid::lexer::Element::{self, Expression, Tag, Raw};
use liquid::Error;

use syntect::parsing::{SyntaxDefinition, SyntaxSet};
use syntect::highlighting::{ThemeSet, Theme};
use syntect::html::{IncludeBackground, highlighted_snippet_for_string, styles_to_coloured_html,
                    start_coloured_html_snippet};
use syntect::easy::HighlightLines;

use std::ascii::AsciiExt;
use std::borrow::Cow::Owned;

use self::cmark::Parser;
use self::cmark::Tag as cmarkTag;
use self::cmark::Event::{self, Start, End, Text, Html};

struct Setup {
    syntax_set: SyntaxSet,
    theme_set: ThemeSet,
}

unsafe impl Send for Setup {}
unsafe impl Sync for Setup {}

lazy_static!{
    static ref SETUP: Setup = Setup {
        syntax_set: SyntaxSet::load_defaults_newlines(),
        theme_set: ThemeSet::load_defaults()
    };
}

struct CodeBlock {
    lang: Option<String>,
    code: String,
    theme: Theme,
}

impl Renderable for CodeBlock {
    fn render(&self, _: &mut Context) -> Result<Option<String>, Error> {
        let syntax = match self.lang {
                Some(ref lang) => SETUP.syntax_set.find_syntax_by_token(lang),
                _ => None,
            }
            .unwrap_or_else(|| SETUP.syntax_set.find_syntax_plain_text());

        Ok(Some(highlighted_snippet_for_string(&self.code, syntax, &self.theme)))
    }
}

pub struct DecoratedParser<'a> {
    h: Option<HighlightLines<'a>>,
    parser: Parser<'a>,
    theme: &'a Theme,
}

impl<'a> DecoratedParser<'a> {
    pub fn new(parser: Parser<'a>, theme: &'a Theme) -> Self {
        DecoratedParser {
            h: None,
            parser: parser,
            theme: &theme,
        }
    }
}

impl<'a> Iterator for DecoratedParser<'a> {
    type Item = Event<'a>;

    fn next(&mut self) -> Option<Event<'a>> {
        match self.parser.next() {
            Some(item) => {
                if let Text(text) = item {
                    if let Some(ref mut h) = self.h {
                        let highlighted = &h.highlight(&text);
                        let html = styles_to_coloured_html(highlighted, IncludeBackground::Yes);
                        Some(Html(Owned(html)))
                    } else {
                        Some(Text(text))
                    }
                } else {
                    if let Start(cmarkTag::CodeBlock(ref info)) = item {
                        // set local highlighter, if found
                        let cur_syntax =
                            info.clone()
                                .split(' ')
                                .next()
                                .and_then(|lang| SETUP.syntax_set.find_syntax_by_token(lang))
                                .unwrap_or_else(|| SETUP.syntax_set.find_syntax_plain_text());
                        self.h = Some(HighlightLines::new(&cur_syntax, self.theme));
                        let snippet = start_coloured_html_snippet(self.theme);
                        return Some(Html(Owned(snippet)));
                    }
                    if let End(cmarkTag::CodeBlock(_)) = item {
                        // reset highlighter
                        self.h = None;
                        // close the code block
                        return Some(Html(Owned("
".to_owned())));
                    }

                    Some(item)
                }
            }
            None => None,
        }
    }
}

pub fn initialize_codeblock(arguments: &[Token],
                            tokens: &[Element],
                            theme_name: &str)
                            -> Result<Box<Renderable>, Error> {

    let content = tokens
        .iter()
        .fold("".to_owned(), |a, b| {
            match *b {
                    Expression(_, ref text) |
                    Tag(_, ref text) |
                    Raw(ref text) => text,
                }
                .to_owned() + &a
        });

    let lang = match arguments.iter().next() {
        Some(&Identifier(ref x)) => Some(x.clone()),
        _ => None,
    };

    Ok(Box::new(CodeBlock {
                    code: content,
                    lang: lang,
                    theme: SETUP.theme_set.themes[theme_name].clone(),
                }))
}

pub fn decorate_markdown<'a>(parser: Parser<'a>, theme_name: &str) -> DecoratedParser<'a> {
    DecoratedParser::new(parser, &SETUP.theme_set.themes[theme_name])
}

pub fn has_syntax_theme(name: &str) -> error::Result<bool> {
    return Ok(SETUP.theme_set.themes.contains_key(name));
}

pub fn list_syntax_themes<'a>() -> Vec<&'a String> {
    return SETUP.theme_set.themes.keys().collect::<Vec<_>>();
}

pub fn list_syntaxes<'a>() -> Vec<String> {
    #[cfg(not(windows))]
    {
        fn definition_to_string(sd: &SyntaxDefinition) -> String {
            let extensions = sd.file_extensions.iter().join(&", ".to_owned());
            format!("{} [{}]", sd.name, extensions)
        }

        let mut syntaxes = SETUP
            .syntax_set
            .syntaxes()
            .iter()
            .map(definition_to_string)
            .collect::<Vec<_>>();

        // sort alphabetically with insensitive ascii case
        syntaxes.sort_by_key(|a| (a as &str).to_ascii_lowercase());

        return syntaxes;
    }

    #[cfg(windows)]
    return vec![];
}

#[cfg(test)]
mod test {

    use std::default::Default;
    use syntax_highlight::initialize_codeblock;
    use liquid::{self, Renderable, LiquidOptions, Context};

    const CODE_BLOCK: &'static str = "mod test {
        fn hello(arg: int) -> bool {
            \
                                      true
        }
    }
    ";

    const RENDERED: &'static str = "
\nmod test {\n        fn hello(arg: int) -> bool {\n            true\n        \
         }\n    \
         }\n    \
         \n
\n";
    #[test]
    fn test_codeblock_renders_rust() {
        let mut options: LiquidOptions = Default::default();
        options
            .blocks
            .insert("codeblock".to_string(),
                    Box::new(|_, args, tokens, _| {
                                 initialize_codeblock(args, tokens, "base16-ocean.dark")
                             }));
        let template = liquid::parse(&format!("{{% codeblock rust %}}{}{{% endcodeblock %}}",
                                              CODE_BLOCK),
                                     options)
                .unwrap();
        let mut data = Context::new();
        let output = template.render(&mut data);
        assert_eq!(output.unwrap(), Some(RENDERED.to_string()));
    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use super::*;
use crate::test_encode_decode::{compare_plane, DecodeResult, TestDecoder};
use crate::util::{CastFromPrimitive, Pixel};
use std::collections::VecDeque;
use std::marker::PhantomData;
use std::{
  mem::{self, MaybeUninit},
  ptr, slice,
};

use dav1d_sys::*;

pub(crate) struct Dav1dDecoder<T: Pixel> {
  dec: *mut Dav1dContext,
  pixel: PhantomData<T>,
}

impl<T: Pixel> TestDecoder<T> for Dav1dDecoder<T> {
  fn setup_decoder(_w: usize, _h: usize) -> Self {
    unsafe {
      let mut settings = MaybeUninit::uninit();
      dav1d_default_settings(settings.as_mut_ptr());

      // Was initialized by dav1d_default_settings().
      let settings = settings.assume_init();

      let mut dec: Dav1dDecoder<T> =
        Dav1dDecoder { dec: ptr::null_mut(), pixel: PhantomData };
      let ret = dav1d_open(&mut dec.dec, &settings);

      if ret != 0 {
        panic!("Cannot instantiate the decoder {}", ret);
      }

      dec
    }
  }

  fn decode_packet(
    &mut self, packet: &[u8], rec_fifo: &mut VecDeque<Frame<T>>, w: usize,
    h: usize, bit_depth: usize,
  ) -> DecodeResult {
    let mut corrupted_count = 0;
    unsafe {
      let mut data: Dav1dData = mem::zeroed();
      let ptr = dav1d_data_create(&mut data, packet.len());
      ptr::copy_nonoverlapping(packet.as_ptr(), ptr, packet.len());
      let ret = dav1d_send_data(self.dec, &mut data);
      debug!("Decoded. -> {}", ret);
      if ret != 0 {
        corrupted_count += 1;
      }

      if ret == 0 {
        loop {
          let mut pic: Dav1dPicture = mem::zeroed();
          debug!("Retrieving frame");
          let ret = dav1d_get_picture(self.dec, &mut pic);
          debug!("Retrieved.");
          if ret == -(EAGAIN as i32) {
            return DecodeResult::Done;
          }
          if ret != 0 {
            panic!("Decode fail");
          }

          let rec = rec_fifo.pop_front().unwrap();
          compare_pic(&pic, &rec, bit_depth, w, h);
        }
      }
    }
    if corrupted_count > 0 {
      DecodeResult::Corrupted(corrupted_count)
    } else {
      DecodeResult::NotDone
    }
  }
}

impl<T: Pixel> Drop for Dav1dDecoder<T> {
  fn drop(&mut self) {
    unsafe { dav1d_close(&mut self.dec) };
  }
}

fn compare_pic<T: Pixel>(
  pic: &Dav1dPicture, frame: &Frame<T>, bit_depth: usize, width: usize,
  height: usize,
) {
  use crate::frame::Plane;

  let cmp_plane = |data, stride, frame_plane: &Plane<T>| {
    let w = width >> frame_plane.cfg.xdec;
    let h = height >> frame_plane.cfg.ydec;
    let rec_stride = frame_plane.cfg.stride;

    if bit_depth > 8 {
      let stride = stride / 2;
      let dec = unsafe {
        let data = data as *const u16;
        let size = stride * h;

        slice::from_raw_parts(data, size)
      };

      let rec: Vec<u16> =
        frame_plane.data_origin().iter().map(|&v| u16::cast_from(v)).collect();

      compare_plane::<u16>(&rec[..], rec_stride, dec, stride, w, h);
    } else {
      let dec = unsafe {
        let data = data as *const u8;
        let size = stride * h;

        slice::from_raw_parts(data, size)
      };

      let rec: Vec<u8> =
        frame_plane.data_origin().iter().map(|&v| u8::cast_from(v)).collect();

      compare_plane::<u8>(&rec[..], rec_stride, dec, stride, w, h);
    }
  };

  let lstride = pic.stride[0] as usize;
  let cstride = pic.stride[1] as usize;

  cmp_plane(pic.data[0], lstride, &frame.planes[0]);
  cmp_plane(pic.data[1], cstride, &frame.planes[1]);
  cmp_plane(pic.data[2], cstride, &frame.planes[2]);
}
<commit_msg>Add safe wrappers to dav1d test_encode_decode<commit_after>// Copyright (c) 2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use super::*;
use crate::test_encode_decode::{compare_plane, DecodeResult, TestDecoder};
use crate::util::{CastFromPrimitive, Pixel};
use std::collections::VecDeque;
use std::marker::PhantomData;
use std::os::raw::c_int;
use std::{
  mem::{self, MaybeUninit},
  ptr, slice,
};

use dav1d_sys::*;

pub(crate) struct Dav1dDecoder<T: Pixel> {
  dec: *mut Dav1dContext,
  pixel: PhantomData<T>,
}

impl<T: Pixel> TestDecoder<T> for Dav1dDecoder<T> {
  fn setup_decoder(_w: usize, _h: usize) -> Self {
    unsafe {
      let mut settings = MaybeUninit::uninit();
      dav1d_default_settings(settings.as_mut_ptr());

      // Was initialized by dav1d_default_settings().
      let settings = settings.assume_init();

      let mut dec: Dav1dDecoder<T> =
        Dav1dDecoder { dec: ptr::null_mut(), pixel: PhantomData };
      let ret = dav1d_open(&mut dec.dec, &settings);

      if ret != 0 {
        panic!("Cannot instantiate the decoder {}", ret);
      }

      dec
    }
  }

  fn decode_packet(
    &mut self, packet: &[u8], rec_fifo: &mut VecDeque<Frame<T>>, w: usize,
    h: usize, bit_depth: usize,
  ) -> DecodeResult {
    let mut corrupted_count = 0;
    let mut data = SafeDav1dData::new(packet);
    let ret = data.send(self.dec);
    debug!("Decoded. -> {}", ret);
    if ret != 0 {
      corrupted_count += 1;
    }

    if ret == 0 {
      loop {
        let mut pic = SafeDav1dPicture::default();
        debug!("Retrieving frame");
        let ret = pic.get(self.dec);
        debug!("Retrieved.");
        if ret == -(EAGAIN as i32) {
          return DecodeResult::Done;
        }
        if ret != 0 {
          panic!("Decode fail");
        }

        let rec = rec_fifo.pop_front().unwrap();
        compare_pic(&pic.0, &rec, bit_depth, w, h);
      }
    }
    if corrupted_count > 0 {
      DecodeResult::Corrupted(corrupted_count)
    } else {
      DecodeResult::NotDone
    }
  }
}

impl<T: Pixel> Drop for Dav1dDecoder<T> {
  fn drop(&mut self) {
    unsafe { dav1d_close(&mut self.dec) };
  }
}

struct SafeDav1dData(Dav1dData);

impl SafeDav1dData {
  fn new(packet: &[u8]) -> Self {
    unsafe {
      let mut data = Self { 0: mem::zeroed() };
      let ptr = dav1d_data_create(&mut data.0, packet.len());
      ptr::copy_nonoverlapping(packet.as_ptr(), ptr, packet.len());
      data
    }
  }

  fn send(&mut self, context: *mut Dav1dContext) -> c_int {
    unsafe { dav1d_send_data(context, &mut self.0) }
  }
}

impl Drop for SafeDav1dData {
  fn drop(&mut self) {
    unsafe { dav1d_data_unref(&mut self.0) };
  }
}

struct SafeDav1dPicture(Dav1dPicture);

impl Default for SafeDav1dPicture {
  fn default() -> Self {
    Self { 0: unsafe { mem::zeroed() } }
  }
}

impl SafeDav1dPicture {
  fn get(&mut self, context: *mut Dav1dContext) -> c_int {
    unsafe { dav1d_get_picture(context, &mut self.0) }
  }
}

impl Drop for SafeDav1dPicture {
  fn drop(&mut self) {
    unsafe { dav1d_picture_unref(&mut self.0) }
  }
}

fn compare_pic<T: Pixel>(
  pic: &Dav1dPicture, frame: &Frame<T>, bit_depth: usize, width: usize,
  height: usize,
) {
  use crate::frame::Plane;

  let cmp_plane = |data, stride, frame_plane: &Plane<T>| {
    let w = width >> frame_plane.cfg.xdec;
    let h = height >> frame_plane.cfg.ydec;
    let rec_stride = frame_plane.cfg.stride;

    if bit_depth > 8 {
      let stride = stride / 2;
      let dec = unsafe {
        let data = data as *const u16;
        let size = stride * h;

        slice::from_raw_parts(data, size)
      };

      let rec: Vec<u16> =
        frame_plane.data_origin().iter().map(|&v| u16::cast_from(v)).collect();

      compare_plane::<u16>(&rec[..], rec_stride, dec, stride, w, h);
    } else {
      let dec = unsafe {
        let data = data as *const u8;
        let size = stride * h;

        slice::from_raw_parts(data, size)
      };

      let rec: Vec<u8> =
        frame_plane.data_origin().iter().map(|&v| u8::cast_from(v)).collect();

      compare_plane::<u8>(&rec[..], rec_stride, dec, stride, w, h);
    }
  };

  let lstride = pic.stride[0] as usize;
  let cstride = pic.stride[1] as usize;

  cmp_plane(pic.data[0], lstride, &frame.planes[0]);
  cmp_plane(pic.data[1], cstride, &frame.planes[1]);
  cmp_plane(pic.data[2], cstride, &frame.planes[2]);
}
<|endoftext|>