<commit_before>//! [GET /_matrix/client/r0/sync](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync)

use std::collections::HashMap;

use ruma_api_macros::ruma_api;
use ruma_events::{
    collections::{all, only},
    stripped,
};
use ruma_identifiers::RoomId;
use serde_derive::{Deserialize, Serialize};

use crate::r0::filter::FilterDefinition;

ruma_api! {
    metadata {
        description: "Get all new events from all rooms since the last sync or a given point of time.",
        method: GET,
        name: "sync",
        path: "/_matrix/client/r0/sync",
        rate_limited: false,
        requires_authentication: true,
    }

    request {
        /// A filter represented either as its full JSON definition or the ID of a saved filter.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub filter: Option<Filter>,
        /// A point in time to continue a sync from.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub since: Option<String>,
        /// Controls whether to include the full state for all rooms the user is a member of.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub full_state: Option<bool>,
        /// Controls whether the client is automatically marked as online by polling this API.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub set_presence: Option<SetPresence>,
        /// The maximum time to poll in milliseconds before returning this request.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub timeout: Option<u64>,
    }

    response {
        /// The batch token to supply in the `since` param of the next `/sync` request.
        pub next_batch: String,
        /// Updates to rooms.
        pub rooms: Rooms,
        /// Updates to the presence status of other users.
        pub presence: Presence,
    }

}

/// Whether to set presence or not during sync.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum SetPresence {
    /// Do not set the presence of the user calling this API.
    #[serde(rename = "offline")]
    Offline,
}

/// A filter represented either as its full JSON definition or the ID of a saved filter.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Filter {
    /// A complete filter definition serialized to JSON.
    FilterDefinition(FilterDefinition),
    /// The ID of a filter saved on the server.
    FilterId(String),
}

/// Updates to rooms.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Rooms {
    /// The rooms that the user has left or been banned from.
    pub leave: HashMap<RoomId, LeftRoom>,
    /// The rooms that the user has joined.
    pub join: HashMap<RoomId, JoinedRoom>,
    /// The rooms that the user has been invited to.
    pub invite: HashMap<RoomId, InvitedRoom>,
}

/// Historical updates to left rooms.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LeftRoom {
    /// The timeline of messages and state changes in the room up to the point when the user
    /// left.
    pub timeline: Timeline,
    /// The state updates for the room up to the start of the timeline.
    pub state: State,
}

/// Updates to joined rooms.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct JoinedRoom {
    /// Counts of unread notifications for this room.
    pub unread_notifications: UnreadNotificationsCount,
    /// The timeline of messages and state changes in the room.
    pub timeline: Timeline,
    /// Updates to the state, between the time indicated by the `since` parameter, and the start
    /// of the `timeline` (or all state up to the start of the `timeline`, if `since` is not
    /// given, or `full_state` is true).
    pub state: State,
    /// The private data that this user has attached to this room.
    pub account_data: AccountData,
    /// The ephemeral events in the room that aren't recorded in the timeline or state of the
    /// room. e.g. typing.
    pub ephemeral: Ephemeral,
}

/// unread notifications count
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct UnreadNotificationsCount {
    /// The number of unread notifications for this room with the highlight flag set.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub highlight_count: Option<u64>,
    /// The total number of unread notifications for this room.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub notification_count: Option<u64>,
}

/// Events in the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Timeline {
    /// True if the number of events returned was limited by the `limit` on the filter.
    pub limited: bool,
    /// A token that can be supplied to to the `from` parameter of the
    /// `/rooms/{roomId}/messages` endpoint.
    pub prev_batch: String,
    /// A list of events.
    pub events: Vec<all::RoomEvent>,
}

/// State events in the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct State {
    /// A list of state events.
    pub events: Vec<only::StateEvent>,
}

/// The private data that this user has attached to this room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AccountData {
    /// A list of events.
    pub events: Vec<only::Event>,
}

/// Ephemeral events not recorded in the timeline or state of the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Ephemeral {
    /// A list of events.
    pub events: Vec<only::Event>,
}

/// Updates to the rooms that the user has been invited to.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InvitedRoom {
    /// The state of a room that the user has been invited to.
    pub invite_state: InviteState,
}

/// The state of a room that the user has been invited to.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InviteState {
    /// A list of state events.
    pub events: Vec<stripped::StrippedState>,
}

/// Updates to the presence status of other users.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Presence {
    /// A list of events.
    pub events: Vec<only::Event>,
}
<commit_msg>r0::sync::sync_events: Fix (de)serialization of filter argument<commit_after>//! [GET /_matrix/client/r0/sync](https://matrix.org/docs/spec/client_server/r0.2.0.html#get-matrix-client-r0-sync)

use std::collections::HashMap;

use ruma_api_macros::ruma_api;
use ruma_events::{
    collections::{all, only},
    stripped,
};
use ruma_identifiers::RoomId;
use serde_derive::{Deserialize, Serialize};

use crate::r0::filter::FilterDefinition;

ruma_api! {
    metadata {
        description: "Get all new events from all rooms since the last sync or a given point of time.",
        method: GET,
        name: "sync",
        path: "/_matrix/client/r0/sync",
        rate_limited: false,
        requires_authentication: true,
    }

    request {
        /// A filter represented either as its full JSON definition or the ID of a saved filter.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub filter: Option<Filter>,
        /// A point in time to continue a sync from.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub since: Option<String>,
        /// Controls whether to include the full state for all rooms the user is a member of.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub full_state: Option<bool>,
        /// Controls whether the client is automatically marked as online by polling this API.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub set_presence: Option<SetPresence>,
        /// The maximum time to poll in milliseconds before returning this request.
        #[serde(skip_serializing_if = "Option::is_none")]
        #[ruma_api(query)]
        pub timeout: Option<u64>,
    }

    response {
        /// The batch token to supply in the `since` param of the next `/sync` request.
        pub next_batch: String,
        /// Updates to rooms.
        pub rooms: Rooms,
        /// Updates to the presence status of other users.
        pub presence: Presence,
    }

}

/// Whether to set presence or not during sync.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum SetPresence {
    /// Do not set the presence of the user calling this API.
    #[serde(rename = "offline")]
    Offline,
}

/// A filter represented either as its full JSON definition or the ID of a saved filter.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum Filter {
    // The filter definition needs to be (de)serialized twice because it is a URL-encoded JSON
    // string. Since #[ruma_api(query)] only does the latter and this is a very uncommon
    // setup, we implement it through custom serde logic for this specific enum variant rather than
    // adding another ruma_api attribute.
    //
    // On the deserialization side, because this is an enum with #[serde(untagged)], serde will
    // try the variants in order (https://serde.rs/enum-representations.html). That means because
    // FilterDefinition is the first variant, JSON decoding is attempted first which is almost
    // functionally equivalent to looking at whether the first symbol is a '{' as the spec says.
    // (there are probably some corner cases like leading whitespace)
    #[serde(with = "filter_def_serde")]
    /// A complete filter definition serialized to JSON.
    FilterDefinition(FilterDefinition),
    /// The ID of a filter saved on the server.
    FilterId(String),
}

mod filter_def_serde {
    use serde::{de::Error as _, ser::Error as _, Deserialize, Deserializer, Serializer};

    use crate::r0::filter::FilterDefinition;

    pub fn serialize<S>(filter_def: &FilterDefinition, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let string = serde_json::to_string(filter_def).map_err(S::Error::custom)?;
        serializer.serialize_str(&string)
    }

    pub fn deserialize<'de, D>(deserializer: D) -> Result<FilterDefinition, D::Error>
    where
        D: Deserializer<'de>,
    {
        let filter_str = <&str>::deserialize(deserializer)?;
        serde_json::from_str(filter_str).map_err(D::Error::custom)
    }
}

/// Updates to rooms.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Rooms {
    /// The rooms that the user has left or been banned from.
    pub leave: HashMap<RoomId, LeftRoom>,
    /// The rooms that the user has joined.
    pub join: HashMap<RoomId, JoinedRoom>,
    /// The rooms that the user has been invited to.
    pub invite: HashMap<RoomId, InvitedRoom>,
}

/// Historical updates to left rooms.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct LeftRoom {
    /// The timeline of messages and state changes in the room up to the point when the user
    /// left.
    pub timeline: Timeline,
    /// The state updates for the room up to the start of the timeline.
    pub state: State,
}

/// Updates to joined rooms.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct JoinedRoom {
    /// Counts of unread notifications for this room.
    pub unread_notifications: UnreadNotificationsCount,
    /// The timeline of messages and state changes in the room.
    pub timeline: Timeline,
    /// Updates to the state, between the time indicated by the `since` parameter, and the start
    /// of the `timeline` (or all state up to the start of the `timeline`, if `since` is not
    /// given, or `full_state` is true).
    pub state: State,
    /// The private data that this user has attached to this room.
    pub account_data: AccountData,
    /// The ephemeral events in the room that aren't recorded in the timeline or state of the
    /// room. e.g. typing.
    pub ephemeral: Ephemeral,
}

/// unread notifications count
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct UnreadNotificationsCount {
    /// The number of unread notifications for this room with the highlight flag set.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub highlight_count: Option<u64>,
    /// The total number of unread notifications for this room.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub notification_count: Option<u64>,
}

/// Events in the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Timeline {
    /// True if the number of events returned was limited by the `limit` on the filter.
    pub limited: bool,
    /// A token that can be supplied to to the `from` parameter of the
    /// `/rooms/{roomId}/messages` endpoint.
    pub prev_batch: String,
    /// A list of events.
    pub events: Vec<all::RoomEvent>,
}

/// State events in the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct State {
    /// A list of state events.
    pub events: Vec<only::StateEvent>,
}

/// The private data that this user has attached to this room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct AccountData {
    /// A list of events.
    pub events: Vec<only::Event>,
}

/// Ephemeral events not recorded in the timeline or state of the room.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Ephemeral {
    /// A list of events.
    pub events: Vec<only::Event>,
}

/// Updates to the rooms that the user has been invited to.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InvitedRoom {
    /// The state of a room that the user has been invited to.
    pub invite_state: InviteState,
}

/// The state of a room that the user has been invited to.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct InviteState {
    /// A list of state events.
    pub events: Vec<stripped::StrippedState>,
}

/// Updates to the presence status of other users.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Presence {
    /// A list of events.
    pub events: Vec<only::Event>,
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Linus Färnstrand <faern@faern.net>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Support for sending and receiving data link layer packets on a fake network managed
//! by in memory FIFO queues. Useful for writing tests.

use std::io;
use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;
use std::time;

use datalink::{self, EthernetDataLinkChannelIterator, EthernetDataLinkReceiver,
               EthernetDataLinkSender, NetworkInterface};
use packet::ethernet::{EthernetPacket, MutableEthernetPacket};
use packet::Packet;
use util::MacAddr;

/// Configuration for the dummy datalink backend. Contains `std::sync::mpsc`
/// channels that are used to communicate with the fake network.
#[derive(Debug)]
pub struct Config {
    /// The fake network will pull packets (or errors) form this `Receiver`
    pub in_packets_rx: Receiver<io::Result<Box<[u8]>>>,

    in_packets_tx: Option<Sender<io::Result<Box<[u8]>>>>,

    /// All packets sent to this fake network will end up on this `Sender`
    pub out_packets_tx: Sender<Box<[u8]>>,

    out_packets_rx: Option<Receiver<Box<[u8]>>>,
}

impl Config {
    /// Get the `Sender` handle that can inject packets in the fake network
    pub fn inject_handle(&mut self) -> Option<Sender<io::Result<Box<[u8]>>>> {
        self.in_packets_tx.take()
    }

    /// Get the `Receiver` handle where packets sent to the fake network can be read
    pub fn read_handle(&mut self) -> Option<Receiver<Box<[u8]>>> {
        self.out_packets_rx.take()
    }
}

impl<'a> From<&'a datalink::Config> for Config {
    /// This conversion will not allow injecting and reading packets from the dummy network.
    /// To do that please create your own `dummy::Config`
    fn from(_config: &datalink::Config) -> Config {
        Config::default()
    }
}

impl Default for Config {
    /// This conversion will not allow injecting and reading packets from the dummy network.
    /// To do that please create your own `dummy::Config`
    fn default() -> Config {
        let (in_tx, in_rx) = mpsc::channel();
        let (out_tx, out_rx) = mpsc::channel();
        Config {
            in_packets_rx: in_rx,
            in_packets_tx: Some(in_tx),
            out_packets_tx: out_tx,
            out_packets_rx: Some(out_rx),
        }
    }
}

/// Create a data link channel backed by FIFO queues. Useful for debugging and testing.
pub fn channel(_: &NetworkInterface, config: Config) -> io::Result<datalink::Channel> {
    let sender = Box::new(MockEthernetDataLinkSender { out_packets: config.out_packets_tx });
    let receiver =
        Box::new(MockEthernetDataLinkReceiver { in_packets: Some(config.in_packets_rx) });

    Ok(datalink::Channel::Ethernet(sender, receiver))
}

struct MockEthernetDataLinkSender {
    out_packets: Sender<Box<[u8]>>,
}

impl EthernetDataLinkSender for MockEthernetDataLinkSender {
    fn build_and_send(&mut self,
                      num_packets: usize,
                      packet_size: usize,
                      func: &mut FnMut(MutableEthernetPacket))
        -> Option<io::Result<()>> {
        for _ in 0..num_packets {
            let mut buffer = vec![0; packet_size];
            {
                let pkg = match MutableEthernetPacket::new(&mut buffer[..]) {
                    Some(pkg) => pkg,
                    None => return None,
                };
                func(pkg);
            }
            // Send the data to the queue. Don't care if it's closed
            self.out_packets.send(buffer.into_boxed_slice()).unwrap_or(());
        }
        Some(Ok(()))
    }

    fn send_to(&mut self,
               packet: &EthernetPacket,
               _dst: Option<NetworkInterface>)
        -> Option<io::Result<()>> {
        let buffer = packet.packet().to_vec();
        self.out_packets.send(buffer.into_boxed_slice()).unwrap_or(());
        Some(Ok(()))
    }
}

struct MockEthernetDataLinkReceiver {
    in_packets: Option<Receiver<io::Result<Box<[u8]>>>>,
}

impl EthernetDataLinkReceiver for MockEthernetDataLinkReceiver {
    fn iter<'a>(&'a mut self) -> Box<EthernetDataLinkChannelIterator + 'a> {
        Box::new(MockEthernetDataLinkChannelIterator {
            in_packets: self.in_packets.take().expect("Only one receiver allowed"),
            used_packets: vec![],
        })
    }
}

struct MockEthernetDataLinkChannelIterator {
    in_packets: Receiver<io::Result<Box<[u8]>>>,
    used_packets: Vec<Box<[u8]>>,
}

impl<'a> EthernetDataLinkChannelIterator<'a> for MockEthernetDataLinkChannelIterator {
    fn next(&mut self) -> io::Result<EthernetPacket> {
        match self.in_packets.recv() {
            Ok(result) => {
                // A network event happened. Might be a packet or a simulated error
                match result {
                    Ok(buffer) => {
                        self.used_packets.push(buffer);
                        let buffer_ref = &*self.used_packets[self.used_packets.len() - 1];
                        let packet = EthernetPacket::new(buffer_ref).unwrap();
                        Ok(packet)
                    }
                    Err(e) => Err(e),
                }
            }
            Err(_) => {
                // The channel supplying fake packets is broken. The user lost/destroyed their
                // inject_handle. This means there will never be any more packets sent to this
                // dummy network. To simulate an idle network we block and sleep forever here.
                loop {
                    thread::sleep(time::Duration::new(::std::u64::MAX, 0));
                }
            }
        }
    }
}

/// Get three fake interfaces generated with `dummy_interface`.
pub fn interfaces() -> Vec<NetworkInterface> {
    (0..3).map(|i| dummy_interface(i)).collect()
}

/// Generates a fake `NetworkInterface`.
/// The name of the interface will be `ethX` where X is the integer `i`.
/// The index will be `i`.
/// The MAC will be `01:02:03:04:05:i`.
pub fn dummy_interface(i: u8) -> NetworkInterface {
    NetworkInterface {
        name: format!("eth{}", i),
        index: i as u32,
        mac: Some(MacAddr::new(1, 2, 3, 4, 5, i)),
        ips: None,
        flags: 0,
    }
}

#[cfg(test)]
mod tests {
    use std::sync::mpsc::{self, Receiver, Sender, TryRecvError};
    use std::io;
    use std::thread::{sleep, spawn};
    use std::time::Duration;

    use packet::{MutablePacket, Packet};
    use packet::ethernet::EthernetPacket;
    use datalink::{EthernetDataLinkReceiver, EthernetDataLinkSender};
    use datalink::Channel::Ethernet;

    #[test]
    fn send_too_small_packet_size() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that it fails to send with too small packet sizes
        assert!(tx.build_and_send(1, 0, &mut |_| {}).is_none());
    }

    #[test]
    fn send_nothing() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending zero packets yields zero packets
        tx.build_and_send(0,
                            20,
                            &mut |_| {
                                panic!("Should not be called");
                            })
            .unwrap()
            .unwrap();
        assert!(read_handle.try_recv().is_err());
    }

    #[test]
    fn send_one_packet() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending one packet yields one packet
        tx.build_and_send(1,
                            20,
                            &mut |mut pkg| {
                                assert_eq!(pkg.packet().len(), 20);
                                pkg.packet_mut()[0] = 9;
                                pkg.packet_mut()[19] = 201;
                            })
            .unwrap()
            .unwrap();
        let pkg = read_handle.try_recv().expect("Expected one packet to be sent");
        assert!(read_handle.try_recv().is_err());
        assert_eq!(pkg.len(), 20);
        assert_eq!(pkg[0], 9);
        assert_eq!(pkg[19], 201);
    }

    #[test]
    fn send_multiple_packets() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending multiple packets does the correct thing
        let mut closure_counter = 0;
        tx.build_and_send(3,
                            20,
                            &mut |mut pkg| {
                                pkg.packet_mut()[0] = closure_counter;
                                closure_counter += 1;
                            })
            .unwrap()
            .unwrap();
        for i in 0..3 {
            let pkg = read_handle.try_recv().expect("Expected a packet");
            assert_eq!(pkg[0], i);
        }
        assert!(read_handle.try_recv().is_err());
    }

    #[test]
    fn send_to() {
        let (_, read_handle, mut tx, _) = create_net();
        let mut buffer = vec![0; 20];
        buffer[1] = 34;
        buffer[18] = 76;
        let pkg = EthernetPacket::new(&buffer[..]).unwrap();

        tx.send_to(&pkg, None).unwrap().unwrap();
        let pkg = read_handle.try_recv().expect("Expected one packet to be sent");
        assert!(read_handle.try_recv().is_err());
        assert_eq!(pkg.len(), 20);
        assert_eq!(pkg[1], 34);
        assert_eq!(pkg[18], 76);
    }

    #[test]
    fn read_nothing() {
        let (inject_handle, _, _, mut rx) = create_net();
        let (control_tx, control_rx) = mpsc::channel();
        spawn(move || {
            let mut rx_iter = rx.iter();
            rx_iter.next().expect("Should not happen 1");
            control_tx.send(()).expect("Should not happen 2");
        });
        sleep(Duration::new(0, 1_000_000));
        match control_rx.try_recv() {
            Ok(_) => panic!("Nothing should have arrived"),
            Err(TryRecvError::Disconnected) => panic!("Thread should not have quit"),
            Err(TryRecvError::Empty) => (),
        }
    }

    #[test]
    fn read_one_pkg() {
        let (inject_handle, _, _, mut rx) = create_net();

        let buffer = vec![0; 20];
        inject_handle.send(Ok(buffer.into_boxed_slice())).unwrap();

        let mut rx_iter = rx.iter();
        let pkg = rx_iter.next().expect("Expected a packet");
        assert_eq!(pkg.packet().len(), 20);
    }

    #[test]
    fn read_multiple_pkgs() {
        let (inject_handle, _, _, mut rx) = create_net();

        for i in 0..3 {
            let buffer = vec![i; 20];
            inject_handle.send(Ok(buffer.into_boxed_slice())).unwrap();
        }

        let mut rx_iter = rx.iter();
        {
            let pkg1 = rx_iter.next().expect("Expected a packet");
            assert_eq!(pkg1.packet()[0], 0);
        }
        {
            let pkg2 = rx_iter.next().expect("Expected a packet");
            assert_eq!(pkg2.packet()[0], 1);
        }
        {
            let pkg3 = rx_iter.next().expect("Expected a packet");
            assert_eq!(pkg3.packet()[0], 2);
        }
    }

    fn create_net()
        -> (Sender<io::Result<Box<[u8]>>>,
            Receiver<Box<[u8]>>,
            Box<EthernetDataLinkSender>,
            Box<EthernetDataLinkReceiver>) {
        let interface = super::dummy_interface(56);
        let mut config = super::Config::default();
        let inject_handle = config.inject_handle().unwrap();
        let read_handle = config.read_handle().unwrap();

        let channel = super::channel(&interface, config);
        let (tx, rx) = match channel {
            Ok(Ethernet(tx, rx)) => (tx, rx),
            _ => panic!("Not a valid channel returned"),
        };
        (inject_handle, read_handle, tx, rx)
    }
}
<commit_msg>Sleep for a short time. u64::MAX caused panic<commit_after>// Copyright (c) 2016 Linus Färnstrand <faern@faern.net>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Support for sending and receiving data link layer packets on a fake network managed
//! by in memory FIFO queues. Useful for writing tests.

use std::io;
use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;
use std::time;

use datalink::{self, EthernetDataLinkChannelIterator, EthernetDataLinkReceiver,
               EthernetDataLinkSender, NetworkInterface};
use packet::ethernet::{EthernetPacket, MutableEthernetPacket};
use packet::Packet;
use util::MacAddr;

/// Configuration for the dummy datalink backend. Contains `std::sync::mpsc`
/// channels that are used to communicate with the fake network.
#[derive(Debug)]
pub struct Config {
    /// The fake network will pull packets (or errors) form this `Receiver`
    pub in_packets_rx: Receiver<io::Result<Box<[u8]>>>,

    in_packets_tx: Option<Sender<io::Result<Box<[u8]>>>>,

    /// All packets sent to this fake network will end up on this `Sender`
    pub out_packets_tx: Sender<Box<[u8]>>,

    out_packets_rx: Option<Receiver<Box<[u8]>>>,
}

impl Config {
    /// Get the `Sender` handle that can inject packets in the fake network
    pub fn inject_handle(&mut self) -> Option<Sender<io::Result<Box<[u8]>>>> {
        self.in_packets_tx.take()
    }

    /// Get the `Receiver` handle where packets sent to the fake network can be read
    pub fn read_handle(&mut self) -> Option<Receiver<Box<[u8]>>> {
        self.out_packets_rx.take()
    }
}

impl<'a> From<&'a datalink::Config> for Config {
    /// This conversion will not allow injecting and reading packets from the dummy network.
    /// To do that please create your own `dummy::Config`
    fn from(_config: &datalink::Config) -> Config {
        Config::default()
    }
}

impl Default for Config {
    /// This conversion will not allow injecting and reading packets from the dummy network.
    /// To do that please create your own `dummy::Config`
    fn default() -> Config {
        let (in_tx, in_rx) = mpsc::channel();
        let (out_tx, out_rx) = mpsc::channel();
        Config {
            in_packets_rx: in_rx,
            in_packets_tx: Some(in_tx),
            out_packets_tx: out_tx,
            out_packets_rx: Some(out_rx),
        }
    }
}

/// Create a data link channel backed by FIFO queues. Useful for debugging and testing.
pub fn channel(_: &NetworkInterface, config: Config) -> io::Result<datalink::Channel> {
    let sender = Box::new(MockEthernetDataLinkSender { out_packets: config.out_packets_tx });
    let receiver =
        Box::new(MockEthernetDataLinkReceiver { in_packets: Some(config.in_packets_rx) });

    Ok(datalink::Channel::Ethernet(sender, receiver))
}

struct MockEthernetDataLinkSender {
    out_packets: Sender<Box<[u8]>>,
}

impl EthernetDataLinkSender for MockEthernetDataLinkSender {
    fn build_and_send(&mut self,
                      num_packets: usize,
                      packet_size: usize,
                      func: &mut FnMut(MutableEthernetPacket))
        -> Option<io::Result<()>> {
        for _ in 0..num_packets {
            let mut buffer = vec![0; packet_size];
            {
                let pkg = match MutableEthernetPacket::new(&mut buffer[..]) {
                    Some(pkg) => pkg,
                    None => return None,
                };
                func(pkg);
            }
            // Send the data to the queue. Don't care if it's closed
            self.out_packets.send(buffer.into_boxed_slice()).unwrap_or(());
        }
        Some(Ok(()))
    }

    fn send_to(&mut self,
               packet: &EthernetPacket,
               _dst: Option<NetworkInterface>)
        -> Option<io::Result<()>> {
        let buffer = packet.packet().to_vec();
        self.out_packets.send(buffer.into_boxed_slice()).unwrap_or(());
        Some(Ok(()))
    }
}

struct MockEthernetDataLinkReceiver {
    in_packets: Option<Receiver<io::Result<Box<[u8]>>>>,
}

impl EthernetDataLinkReceiver for MockEthernetDataLinkReceiver {
    fn iter<'a>(&'a mut self) -> Box<EthernetDataLinkChannelIterator + 'a> {
        Box::new(MockEthernetDataLinkChannelIterator {
            in_packets: self.in_packets.take().expect("Only one receiver allowed"),
            used_packets: vec![],
        })
    }
}

struct MockEthernetDataLinkChannelIterator {
    in_packets: Receiver<io::Result<Box<[u8]>>>,
    used_packets: Vec<Box<[u8]>>,
}

impl<'a> EthernetDataLinkChannelIterator<'a> for MockEthernetDataLinkChannelIterator {
    fn next(&mut self) -> io::Result<EthernetPacket> {
        match self.in_packets.recv() {
            Ok(result) => {
                // A network event happened. Might be a packet or a simulated error
                match result {
                    Ok(buffer) => {
                        self.used_packets.push(buffer);
                        let buffer_ref = &*self.used_packets[self.used_packets.len() - 1];
                        let packet = EthernetPacket::new(buffer_ref).unwrap();
                        Ok(packet)
                    }
                    Err(e) => Err(e),
                }
            }
            Err(_) => {
                // The channel supplying fake packets is broken. The user lost/destroyed their
                // inject_handle. This means there will never be any more packets sent to this
                // dummy network. To simulate an idle network we block and sleep forever here.
                loop {
                    thread::sleep(time::Duration::new(10, 0));
                }
            }
        }
    }
}

/// Get three fake interfaces generated with `dummy_interface`.
pub fn interfaces() -> Vec<NetworkInterface> {
    (0..3).map(|i| dummy_interface(i)).collect()
}

/// Generates a fake `NetworkInterface`.
/// The name of the interface will be `ethX` where X is the integer `i`.
/// The index will be `i`.
/// The MAC will be `01:02:03:04:05:i`.
pub fn dummy_interface(i: u8) -> NetworkInterface {
    NetworkInterface {
        name: format!("eth{}", i),
        index: i as u32,
        mac: Some(MacAddr::new(1, 2, 3, 4, 5, i)),
        ips: None,
        flags: 0,
    }
}

#[cfg(test)]
mod tests {
    use std::sync::mpsc::{self, Receiver, Sender, TryRecvError};
    use std::io;
    use std::thread::{sleep, spawn};
    use std::time::Duration;

    use packet::{MutablePacket, Packet};
    use packet::ethernet::EthernetPacket;
    use datalink::{EthernetDataLinkReceiver, EthernetDataLinkSender};
    use datalink::Channel::Ethernet;

    #[test]
    fn send_too_small_packet_size() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that it fails to send with too small packet sizes
        assert!(tx.build_and_send(1, 0, &mut |_| {}).is_none());
    }

    #[test]
    fn send_nothing() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending zero packets yields zero packets
        tx.build_and_send(0,
                            20,
                            &mut |_| {
                                panic!("Should not be called");
                            })
            .unwrap()
            .unwrap();
        assert!(read_handle.try_recv().is_err());
    }

    #[test]
    fn send_one_packet() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending one packet yields one packet
        tx.build_and_send(1,
                            20,
                            &mut |mut pkg| {
                                assert_eq!(pkg.packet().len(), 20);
                                pkg.packet_mut()[0] = 9;
                                pkg.packet_mut()[19] = 201;
                            })
            .unwrap()
            .unwrap();
        let pkg = read_handle.try_recv().expect("Expected one packet to be sent");
        assert!(read_handle.try_recv().is_err());
        assert_eq!(pkg.len(), 20);
        assert_eq!(pkg[0], 9);
        assert_eq!(pkg[19], 201);
    }

    #[test]
    fn send_multiple_packets() {
        let (_, read_handle, mut tx, _) = create_net();
        // Check that sending multiple packets does the correct thing
        let mut closure_counter = 0;
        tx.build_and_send(3,
                            20,
                            &mut |mut pkg| {
                                pkg.packet_mut()[0] = closure_counter;
                                closure_counter += 1;
                            })
            .unwrap()
            .unwrap();
        for i in 0..3 {
            let pkg = read_handle.try_recv().expect("Expected a packet");
            assert_eq!(pkg[0], i);
        }
        assert!(read_handle.try_recv().is_err());
    }

    #[test]
    fn send_to() {
        let (_, read_handle, mut tx, _) = create_net();
        let mut buffer = vec![0; 20];
        buffer[1] = 34;
        buffer[18] = 76;
        let pkg = EthernetPacket::new(&buffer[..]).unwrap();

        tx.send_to(&pkg, None).unwrap().unwrap();
        let pkg = read_handle.try_recv().expect("Expected one packet to be sent");
        assert!(read_handle.try_recv().is_err());
        assert_eq!(pkg.len(), 20);
        assert_eq!(pkg[1], 34);
        assert_eq!(pkg[18], 76);
    }

    #[test]
    fn read_nothing() {
        let (inject_handle, _, _, mut rx) = create_net();
        let (control_tx, control_rx) = mpsc::channel();
        spawn(move || {
            let mut rx_iter = rx.iter();
            rx_iter.next().expect("Should not happen 1");
            control_tx.send(()).expect("Should not happen 2");
        });
        sleep(Duration::new(0, 1_000_000));
        match control_rx.try_recv() {
            Ok(_) => panic!("Nothing should have arrived"),
            Err(TryRecvError::Disconnected) => panic!("Thread should not have quit"),
            Err(TryRecvError::Empty) => (),
        }
    }

    #[test]
    fn read_one_pkg() {
        let (inject_handle, _, _, mut rx) = create_net();

        let buffer = vec![0; 20];
        inject_handle.send(Ok(buffer.into_boxed_slice())).unwrap();

        let mut rx_iter = rx.iter();
        let pkg = rx_iter.next().expect("Expected a packet");
        assert_eq!(pkg.packet().len(), 20);
    }

    #[test]
    fn read_multiple_pkgs() {
        let (inject_handle, _, _, mut rx) = create_net();

        for i in 0..3 {
            let buffer = vec![i; 20];
            inject_handle.send(Ok(buffer.into_boxed_slice())).unwrap();
        }

        let mut rx_iter = rx.iter();
        {
            let pkg1 = rx_iter.next().expect("Expected a packet");
            assert_eq!(pkg1.packet()[0], 0);
        }
        {
            let pkg2 = rx_iter.next().expect("Expected a packet");
            assert_eq!(pkg2.packet()[0], 1);
        }
        {
            let pkg3 = rx_iter.next().expect("Expected a packet");
            assert_eq!(pkg3.packet()[0], 2);
        }
    }

    fn create_net()
        -> (Sender<io::Result<Box<[u8]>>>,
            Receiver<Box<[u8]>>,
            Box<EthernetDataLinkSender>,
            Box<EthernetDataLinkReceiver>) {
        let interface = super::dummy_interface(56);
        let mut config = super::Config::default();
        let inject_handle = config.inject_handle().unwrap();
        let read_handle = config.read_handle().unwrap();

        let channel = super::channel(&interface, config);
        let (tx, rx) = match channel {
            Ok(Ethernet(tx, rx)) => (tx, rx),
            _ => panic!("Not a valid channel returned"),
        };
        (inject_handle, read_handle, tx, rx)
    }
}
<|endoftext|>


<commit_before>use decoders::tiff::*;
use std::fmt;
use std::clone;

pub struct CFA {
  pub name: String,
  pub width: usize,
  pub height: usize,

  pattern: [[usize;48];48],
}

impl CFA {
  #[doc(hidden)] pub fn new_from_tag(pat: &TiffEntry) -> CFA {
    let mut patname = String::new();
    for i in 0..pat.count() {
      patname.push(match pat.get_u32(i as usize) {
        0 => 'R',
        1 => 'G',
        2 => 'B',
        _ => 'U',
      });
    }
    CFA::new(&patname)
  }

  pub fn new(patname: &str) -> CFA {
    let (width, height) = match patname.len() {
      0 => (0,0),
      4 => (2,2),
      36 => (6,6),
      16 => (2,8),
      144 => (12,12),
      _ => panic!(format!("Unknown CFA size \"{}\"", patname).to_string()),
    };
    let mut pattern: [[usize;48];48] = [[0;48];48];

    if width > 0 {
      // copy the pattern into the top left
      for (i,c) in patname.bytes().enumerate() {
        pattern[i/width][i%width] = match c {
          b'R' => 0,
          b'G' => 1,
          b'B' => 2,
          b'E' => 3,
          b'M' => 1,
          b'Y' => 3,
          _   => panic!(format!("Unknown CFA color \"{}\"", c).to_string()),
        };
      }

      // extend the pattern into the full matrix
      for row in 0..48 {
        for col in 0..48 {
          pattern[row][col] = pattern[row%height][col%width];
        }
      }
    }

    CFA {
      name: patname.to_string(),
      pattern: pattern,
      width: width,
      height: height,
    }
  }

  pub fn color_at(&self, row: usize, col: usize) -> usize {
    self.pattern[(row+48) % 48][(col+48) % 48]
  }

  pub fn shift(&self, x: usize, y: usize) -> CFA {
    let mut pattern: [[usize;48];48] = [[0;48];48];
    for row in 0..48 {
      for col in 0..48 {
        pattern[row][col] = self.color_at(row+y,col+x);
      }
    }
    CFA {
      name: format!("shifted-{}-{}-{}", x, y, self.name).to_string(),
      pattern: pattern,
      width: self.width,
      height: self.height,
    }
  }
}

impl fmt::Debug for CFA {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "CFA {{ {} }}", self.name)
  }
}

impl clone::Clone for CFA {
  fn clone(&self) -> CFA {
    let mut cpattern: [[usize;48];48] = [[0;48];48];
    for row in 0..48 {
      for col in 0..48 {
        cpattern[row][col] = self.pattern[row][col];
      }
    }
    CFA {
      name: self.name.clone(),
      pattern: cpattern,
      width: self.width,
      height: self.height,
    }
  }
}
<commit_msg>cfa: add some basic documentation<commit_after>use decoders::tiff::*;
use std::fmt;
use std::clone;

/// Representation of the color filter array pattern in raw cameras
///
/// # Example
/// ```
/// use rawloader::CFA;
/// let cfa = CFA::new("RGGB");
/// assert_eq!(cfa.color_at(0,0), 0);
/// assert_eq!(cfa.color_at(0,1), 1);
/// assert_eq!(cfa.color_at(1,0), 1);
/// assert_eq!(cfa.color_at(1,1), 2);
/// ```
///
/// You will almost always get your CFA struct from a RawImage decode, already fully
/// initialized and ready to be used in processing. The color_at() implementation is
/// designed to be fast so it can be called inside the inner loop of demosaic or other
/// color-aware algorithms that work on pre-demosaic data
pub struct CFA {
  pub name: String,
  pub width: usize,
  pub height: usize,

  pattern: [[usize;48];48],
}

impl CFA {
  #[doc(hidden)] pub fn new_from_tag(pat: &TiffEntry) -> CFA {
    let mut patname = String::new();
    for i in 0..pat.count() {
      patname.push(match pat.get_u32(i as usize) {
        0 => 'R',
        1 => 'G',
        2 => 'B',
        _ => 'U',
      });
    }
    CFA::new(&patname)
  }

  /// Create a new CFA from a string describing it. For simplicity the pattern is specified
  /// as each pixel being one of R/G/B/E representing the 0/1/2/3 colors in a 4 color image.
  /// The pattern is specified as the colors in each row concatenated so RGGB means that
  /// the first row is RG and the second row GB. Row size is determined by pattern size
  /// (e.g., the xtrans pattern is 6x6 and thus 36 characters long). In theory this could
  /// lead to confusion between different pattern sizes but in practice there are only
  /// a few oddball cameras no one cares about that do anything but 2x2 and 6x6 (and those
  /// work fine with this as well).
  pub fn new(patname: &str) -> CFA {
    let (width, height) = match patname.len() {
      0 => (0,0),
      4 => (2,2),
      36 => (6,6),
      16 => (2,8),
      144 => (12,12),
      _ => panic!(format!("Unknown CFA size \"{}\"", patname).to_string()),
    };
    let mut pattern: [[usize;48];48] = [[0;48];48];

    if width > 0 {
      // copy the pattern into the top left
      for (i,c) in patname.bytes().enumerate() {
        pattern[i/width][i%width] = match c {
          b'R' => 0,
          b'G' => 1,
          b'B' => 2,
          b'E' => 3,
          b'M' => 1,
          b'Y' => 3,
          _   => panic!(format!("Unknown CFA color \"{}\"", c).to_string()),
        };
      }

      // extend the pattern into the full matrix
      for row in 0..48 {
        for col in 0..48 {
          pattern[row][col] = pattern[row%height][col%width];
        }
      }
    }

    CFA {
      name: patname.to_string(),
      pattern: pattern,
      width: width,
      height: height,
    }
  }

  /// Get the color index at the given position. Designed to be fast so it can be called
  /// from inner loops without performance issues.
  pub fn color_at(&self, row: usize, col: usize) -> usize {
    self.pattern[(row+48) % 48][(col+48) % 48]
  }

  /// Shift the pattern left and/or down. This is useful when cropping the image to get
  /// the equivalent pattern of the crop when it's not a multiple of the pattern size.
  ///
  /// # Example
  /// ```
  /// use rawloader::CFA;
  /// let cfa = CFA::new("RGGB");
  /// assert_eq!(cfa.color_at(0,0), 0);
  /// assert_eq!(cfa.color_at(0,1), 1);
  /// assert_eq!(cfa.color_at(1,0), 1);
  /// assert_eq!(cfa.color_at(1,1), 2);
  ///
  /// let shifted = cfa.shift(1,1);
  /// assert_eq!(shifted.color_at(0,0), 2);
  /// assert_eq!(shifted.color_at(0,1), 1);
  /// assert_eq!(shifted.color_at(1,0), 1);
  /// assert_eq!(shifted.color_at(1,1), 0);
  /// ```
  pub fn shift(&self, x: usize, y: usize) -> CFA {
    let mut pattern: [[usize;48];48] = [[0;48];48];
    for row in 0..48 {
      for col in 0..48 {
        pattern[row][col] = self.color_at(row+y,col+x);
      }
    }
    CFA {
      name: format!("shifted-{}-{}-{}", x, y, self.name).to_string(),
      pattern: pattern,
      width: self.width,
      height: self.height,
    }
  }
}

impl fmt::Debug for CFA {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "CFA {{ {} }}", self.name)
  }
}

impl clone::Clone for CFA {
  fn clone(&self) -> CFA {
    let mut cpattern: [[usize;48];48] = [[0;48];48];
    for row in 0..48 {
      for col in 0..48 {
        cpattern[row][col] = self.pattern[row][col];
      }
    }
    CFA {
      name: self.name.clone(),
      pattern: cpattern,
      width: self.width,
      height: self.height,
    }
  }
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # DFA compiler
//!
//! The DFA compiler converts NDFAs into DFAs, using a DFA builder.
//!

use std::marker::PhantomData;
use std::collections::HashSet;
use std::collections::HashMap;
use std::iter::*;
use std::cmp::Ordering;

use super::dfa_builder::*;
use super::state_machine::*;

///
/// Builds a deterministic finite automaton from a NDFA
///
pub struct DfaCompiler<InputSymbol: PartialOrd+Clone, OutputSymbol, DfaType, Ndfa: StateMachine<InputSymbol, OutputSymbol>, Builder: DfaBuilder<InputSymbol, OutputSymbol, DfaType>> {
    /// State machine that is to be compiled
    ndfa: Ndfa,

    /// Builder where the state machine should be generated
    builder: Builder,

    // Phantom data to poke Rust's type system (it's too dumb to see that InputSymbol is used in both Ndfa and Builder there via the type constraint)
    #[allow(dead_code)]
    phantom: (PhantomData<InputSymbol>, PhantomData<OutputSymbol>, PhantomData<DfaType>)
}

/// Represents a state in the DFA (one or more states from the source)
#[derive(Eq, PartialEq, Hash, Clone)]
struct DfaState {
    source_states: Vec<StateId>
}

impl DfaState {
    /// Creates a DFA state from a set of source states
    fn create(source_states: Vec<StateId>) -> DfaState {
        let mut set = HashSet::new();
        for state in source_states {
            set.insert(state);
        }

        DfaState { source_states: Vec::from_iter(set.into_iter()) }
    }

    /// Removes any duplicate states from source_states
    fn dedupe(&mut self) {
        self.source_states.sort();
        self.source_states.dedup();
    }
}

/// Represents the transitions for a source state
struct DfaTransitions<InputSymbol> {
    state_id: StateId,
    transitions: Vec<(InputSymbol, DfaState)>
}

impl<InputSymbol: PartialOrd+Clone> DfaTransitions<InputSymbol> {
    /// Goes through the transitions in the object and merges the states of any with the same symbol
    fn merge_states(&mut self) {
        if self.transitions.len() > 0 {
            // Order the transitions so that if two transitions have the same input symbol, they are neighbours
            self.transitions.sort_by(|a, b| {
                let &(ref symbol_a, _) = a;
                let &(ref symbol_b, _) = b;

                if let Some(result) = symbol_a.partial_cmp(symbol_b) {
                    result
                } else {
                    // Unordered input symbols won't work well
                    Ordering::Equal
                }
            });

            // For any transition that has a duplicate state, combine it with the previous state
            let mut new_transitions = vec![];
            new_transitions.push(self.transitions[0].clone());

            for transit_idx in 1..self.transitions.len() {
                let len          = new_transitions.len();
                let this_transit = &mut self.transitions[transit_idx];

                if new_transitions[len-1].0 == this_transit.0 {
                    // Same symbol: expand this state
                    new_transitions[len-1].1.source_states.append(&mut this_transit.1.source_states);
                } else {
                    // Different symbol: add new state
                    new_transitions.push(this_transit.clone());
                }
            }

            // Ensure all of the states are sorted and de-duplicated
            for transit in &mut new_transitions {
                transit.1.dedupe();
            }

            // Update the transitions
            self.transitions = new_transitions;
        }
    }
}

impl<InputSymbol: PartialOrd+Clone, OutputSymbol, DfaType, Ndfa: StateMachine<InputSymbol, OutputSymbol>, Builder: DfaBuilder<InputSymbol, OutputSymbol, DfaType>>
    DfaCompiler<InputSymbol, OutputSymbol, DfaType, Ndfa, Builder> {
    ///
    /// Builds a DFA using an NDFA and a builder
    ///
    pub fn build(ndfa: Ndfa, builder: Builder) -> DfaType {
        let compiler = DfaCompiler::new(ndfa, builder);
        compiler.compile()
    }

    ///
    /// Creates a new DFA compiler using a particular builder and NDFA
    ///
    pub fn new(ndfa: Ndfa, builder: Builder) -> Self {
        DfaCompiler { ndfa: ndfa, builder: builder, phantom: (PhantomData, PhantomData, PhantomData) }
    }

    ///
    /// Compiles the NDFA into a DFA
    ///
    pub fn compile(self) -> DfaType {
        // We assume that input symbols are non-overlapping, which is not automatically the case for symbol ranges

        // Work out the state mapping for each input symbol
        let mut states       = vec![];
        let mut known_states = HashMap::new();
        let mut to_process   = vec![];

        // All state machines have state 0 as their starting state
        let state_zero = DfaState::create(vec![0]);

        states.push(DfaTransitions { state_id: 0, transitions: vec![] });
        known_states.insert(state_zero.clone(), 0);
        to_process.push(state_zero);

        while let Some(state) = to_process.pop() {
            // Create a new transitions object for this state
            let mut transitions = vec![];

            for source_state in &state.source_states {
                let source_transitions = self.ndfa.get_transitions_for_state(*source_state);

                for (symbol, state) in source_transitions {
                    transitions.push((symbol, DfaState::create(vec![state])));
                }
            }

            // Merge it so that we only have one transition per symbol
            let mut dfa_transitions = DfaTransitions { state_id: states.len() as StateId, transitions: transitions};
            dfa_transitions.merge_states();

            // Process any generated states that are not already in the DFA
            for &(_, ref maybe_new_state) in &dfa_transitions.transitions {
                if !known_states.contains_key(maybe_new_state) {
                    to_process.push(maybe_new_state.clone());
                }
            }

            // Store the new state
            known_states.insert(state.clone(), dfa_transitions.state_id);
            states.push(dfa_transitions);
        }

        // Build the DFA
        let mut builder = self.builder;

        for dfa_state in states {
            builder.start_state();

            for (symbol, target_state) in dfa_state.transitions {
                builder.transition(symbol, known_states[&target_state]);
            }
        }

        // TODO: output symbols

        // Generate the final DFA
        builder.build()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use super::super::regular_pattern::*;
    use super::super::state_machine::*;
    use super::super::symbol_range_dfa::*;

    #[test]
    fn can_create_compiler() {
        let ndfa     = "abc".into_pattern().to_ndfa("success");
        let builder  = SymbolRangeDfaBuilder::new();

        DfaCompiler::new(ndfa, builder);
    }

    #[test]
    fn can_build_dfa() {
        let ndfa     = "abc".into_pattern().to_ndfa("success");
        let builder  = SymbolRangeDfaBuilder::new();

        DfaCompiler::build(ndfa, builder);
    }
}
<commit_msg>Set the output symbol for the states that we generate<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # DFA compiler
//!
//! The DFA compiler converts NDFAs into DFAs, using a DFA builder.
//!

use std::marker::PhantomData;
use std::collections::HashSet;
use std::collections::HashMap;
use std::iter::*;
use std::cmp::Ordering;

use super::dfa_builder::*;
use super::state_machine::*;

///
/// Builds a deterministic finite automaton from a NDFA
///
pub struct DfaCompiler<InputSymbol: PartialOrd+Clone, OutputSymbol, DfaType, Ndfa: StateMachine<InputSymbol, OutputSymbol>, Builder: DfaBuilder<InputSymbol, OutputSymbol, DfaType>> {
    /// State machine that is to be compiled
    ndfa: Ndfa,

    /// Builder where the state machine should be generated
    builder: Builder,

    // Phantom data to poke Rust's type system (it's too dumb to see that InputSymbol is used in both Ndfa and Builder there via the type constraint)
    #[allow(dead_code)]
    phantom: (PhantomData<InputSymbol>, PhantomData<OutputSymbol>, PhantomData<DfaType>)
}

/// Represents a state in the DFA (one or more states from the source)
#[derive(Eq, PartialEq, Hash, Clone)]
struct DfaState {
    /// List of the states from the NDFA that make up this DFA state (will be ordered if `dedupe` is called)
    source_states: Vec<StateId>
}

impl DfaState {
    /// Creates a DFA state from a set of source states
    fn create(source_states: Vec<StateId>) -> DfaState {
        let mut set = HashSet::new();
        for state in source_states {
            set.insert(state);
        }

        DfaState { source_states: Vec::from_iter(set.into_iter()) }
    }

    /// Removes any duplicate states from source_states
    fn dedupe(&mut self) {
        self.source_states.sort();
        self.source_states.dedup();
    }
}

/// Represents the transitions for a source state
struct DfaTransitions<InputSymbol, OutputSymbol: Ord> {
    /// ID of this state in the resulting DFA
    state_id: StateId,

    /// Transitions for this state (will be unique if `merge_states` is called)
    transitions: Vec<(InputSymbol, DfaState)>,

    /// The output symbols for this state (empty if this is not an accepting state)
    output: Vec<OutputSymbol>
}

impl<InputSymbol: PartialOrd+Clone, OutputSymbol: Ord> DfaTransitions<InputSymbol, OutputSymbol> {
    /// Goes through the transitions in the object and merges the states of any with the same symbol
    fn merge_states(&mut self) {
        if self.transitions.len() > 0 {
            // Order the transitions so that if two transitions have the same input symbol, they are neighbours
            self.transitions.sort_by(|a, b| {
                let &(ref symbol_a, _) = a;
                let &(ref symbol_b, _) = b;

                if let Some(result) = symbol_a.partial_cmp(symbol_b) {
                    result
                } else {
                    // Unordered input symbols won't work well
                    Ordering::Equal
                }
            });

            // For any transition that has a duplicate state, combine it with the previous state
            let mut new_transitions = vec![];
            new_transitions.push(self.transitions[0].clone());

            for transit_idx in 1..self.transitions.len() {
                let len          = new_transitions.len();
                let this_transit = &mut self.transitions[transit_idx];

                if new_transitions[len-1].0 == this_transit.0 {
                    // Same symbol: expand this state
                    new_transitions[len-1].1.source_states.append(&mut this_transit.1.source_states);
                } else {
                    // Different symbol: add new state
                    new_transitions.push(this_transit.clone());
                }
            }

            // Ensure all of the states are sorted and de-duplicated
            for transit in &mut new_transitions {
                transit.1.dedupe();
            }

            // Update the transitions
            self.transitions = new_transitions;
        }
    }

    ///
    /// Finds the output symbol that corresponds to this state
    ///
    /// Rule is that if there is more than one output symbol then the symbol whose value is ordered lowest is the output for this state
    ///
    fn output_symbol(&mut self) -> Option<&OutputSymbol> {
        if self.output.len() > 0 {
            self.output.sort();
            Some(&self.output[0])
        } else {
            None
        }
    }
}

impl<InputSymbol: PartialOrd+Clone, OutputSymbol: Ord+Clone, DfaType, Ndfa: StateMachine<InputSymbol, OutputSymbol>, Builder: DfaBuilder<InputSymbol, OutputSymbol, DfaType>>
    DfaCompiler<InputSymbol, OutputSymbol, DfaType, Ndfa, Builder> {
    ///
    /// Builds a DFA using an NDFA and a builder
    ///
    pub fn build(ndfa: Ndfa, builder: Builder) -> DfaType {
        let compiler = DfaCompiler::new(ndfa, builder);
        compiler.compile()
    }

    ///
    /// Creates a new DFA compiler using a particular builder and NDFA
    ///
    pub fn new(ndfa: Ndfa, builder: Builder) -> Self {
        DfaCompiler { ndfa: ndfa, builder: builder, phantom: (PhantomData, PhantomData, PhantomData) }
    }

    ///
    /// Compiles the NDFA into a DFA
    ///
    pub fn compile(self) -> DfaType {
        // We assume that input symbols are non-overlapping, which is not automatically the case for symbol ranges

        // Work out the state mapping for each input symbol
        let mut states       = vec![];
        let mut known_states = HashMap::new();
        let mut to_process   = vec![];

        // All state machines have state 0 as their starting state
        let state_zero = DfaState::create(vec![0]);
        let state_zero_output = if let Some(output_symbol) = self.ndfa.output_symbol_for_state(0) { vec![output_symbol.clone()] } else { vec![] };

        states.push(DfaTransitions { state_id: 0, transitions: vec![], output: state_zero_output });
        known_states.insert(state_zero.clone(), 0);
        to_process.push(state_zero);

        while let Some(state) = to_process.pop() {
            // Create a new transitions object for this state
            let mut transitions = vec![];
            let mut output      = vec![];

            for source_state in &state.source_states {
                let source_transitions = self.ndfa.get_transitions_for_state(*source_state);

                for (symbol, state) in source_transitions {
                    transitions.push((symbol, DfaState::create(vec![state])));
                }

                if let Some(source_output) = self.ndfa.output_symbol_for_state(*source_state) {
                    output.push(source_output.clone());
                }
            }

            // Merge it so that we only have one transition per symbol
            let mut dfa_transitions = DfaTransitions { state_id: states.len() as StateId, transitions: transitions, output: output };
            dfa_transitions.merge_states();

            // Process any generated states that are not already in the DFA
            for &(_, ref maybe_new_state) in &dfa_transitions.transitions {
                if !known_states.contains_key(maybe_new_state) {
                    to_process.push(maybe_new_state.clone());
                }
            }

            // Store the new state
            known_states.insert(state.clone(), dfa_transitions.state_id);
            states.push(dfa_transitions);
        }

        // Build the DFA
        let mut builder = self.builder;

        for mut dfa_state in states {
            builder.start_state();

            if let Some(output_symbol) = dfa_state.output_symbol() {
                builder.accept(output_symbol.clone());
            }

            for (symbol, target_state) in dfa_state.transitions {
                builder.transition(symbol, known_states[&target_state]);
            }
        }

        // Generate the final DFA
        builder.build()
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use super::super::regular_pattern::*;
    use super::super::state_machine::*;
    use super::super::symbol_range_dfa::*;

    #[test]
    fn can_create_compiler() {
        let ndfa     = "abc".into_pattern().to_ndfa("success");
        let builder  = SymbolRangeDfaBuilder::new();

        DfaCompiler::new(ndfa, builder);
    }

    #[test]
    fn can_build_dfa() {
        let ndfa     = "abc".into_pattern().to_ndfa("success");
        let builder  = SymbolRangeDfaBuilder::new();

        DfaCompiler::build(ndfa, builder);
    }
}
<|endoftext|>


<commit_before>/// Provide syntax highlighting via [Syntect].
///
/// [Syntect]: https://docs.rs/syntect/1.0.0/syntect/

// Standard library
use std::default::Default;
use std::str;

// Third party
use quick_xml::{XmlReader, XmlWriter, Element, Event};
use syntect::html::highlighted_snippet_for_string;
use syntect::highlighting::{ThemeSet};
use syntect::parsing::SyntaxSet;

/// A `Language` is a `String` representing a code highlighting language.
type Language = String;

/// Define XML parsing states of interest for highlighting.
///
/// We use these in conjunction with `ParseEvent`s to drive a state machine
/// which tracks whether we are in a
#[derive(Clone, Debug, PartialEq)]
enum ParseState {
  /// Not in a code block at all.
  NotInBlock,
  /// Possibly the start of a highlight block, with the language as payload.
  MaybeStartBlock(Language),
  /// The start of the code block has been confirmed; highlight next text node.
  WillStartCodeBlock(Language),
  /// In a code block; use the content for highlighting.
  InCodeBlock(Language),
}

/// Define XML parsing events of interest for highlighting.
///
/// We don't care at all about any other items for this specific scenario; we
/// use these in conjunction with the `ParseState`
#[derive(Debug)]
enum ParseEvent {
  // Starting a `<pre>`; optionally specifying a language.
  StartPre(Option<Language>),
  // Starting a `<code>`.
  StartCode,
  // Ending a `<code>`.
  EndCode,
  Text,
  Whitespace,
  Other,
}

impl ParseState {
  fn next(&self, event: &ParseEvent) -> ParseState {
    use self::ParseState::*;
    use self::ParseEvent::*;

    match (self, event) {
      (&NotInBlock, &StartPre(Some(ref language))) =>
        MaybeStartBlock(language.clone()),
      (&MaybeStartBlock(ref language), &Whitespace) =>
        MaybeStartBlock(language.clone()),
      (&MaybeStartBlock(ref language), &StartCode) =>
        WillStartCodeBlock(language.clone()),
      (&WillStartCodeBlock(ref language), &Text) |
      (&WillStartCodeBlock(ref language), &Whitespace) =>
        InCodeBlock(language.clone()),
      (&InCodeBlock(_), &EndCode) => NotInBlock,
      (_, _) => NotInBlock,
    }
  }
}

impl Default for ParseState {
  fn default() -> ParseState { ParseState::NotInBlock }
}

impl<'a> From<&'a Event> for ParseEvent {
  fn from(event: &'a Event) -> ParseEvent {
    const PRE: &'static [u8] = b"pre";
    const CODE: &'static [u8] = b"code";
    const CLASS: &'static [u8] = b"class";
    const WHITE_SPACE: &'static [u8] = b"";

    match *event {
      Event::Start(ref element) => {
        match element.name() {
          PRE => {
            let maybe_class_attr = element
              .attributes()
              .map(|attr| attr.unwrap())
              .filter(|attr| attr.0 == CLASS)
              .next();

            match maybe_class_attr {
              Some(class_attr) => {
                match str::from_utf8(class_attr.1) {
                  Ok(lang) => ParseEvent::StartPre(Some(String::from(lang))),
                  Err(_) => ParseEvent::StartPre(None),
                }
              },
              None => ParseEvent::StartPre(None),
            }
          },
          CODE => ParseEvent::StartCode,
          _ => ParseEvent::Other,
        }
      },
      Event::End(ref element) => {
        match element.name() {
          CODE => ParseEvent::EndCode,
          _ => ParseEvent::Other,
        }
      },
      Event::Text(ref element) => {
        match element.name() {
          WHITE_SPACE => ParseEvent::Whitespace,
          _ => ParseEvent::Text,
        }

      },
      _ => ParseEvent::Other,
    }
  }
}

struct Accumulator {
  writer: XmlWriter<Vec<u8>>,
  state: ParseState,
}

pub fn syntax_highlight(html_string: String) -> String {
  let original_string = html_string.clone();
  let reader = XmlReader::from(html_string.as_str());

  let mut accumulator = Accumulator {
    writer: XmlWriter::new(Vec::<u8>::new()),
    state: ParseState::default(),
  };

  reader.fold(&mut accumulator, |acc, event| {
    let event = match event {
      Ok(event) => event,
      Err(_) => {
        return acc;
      }
    };

    let parse_event = ParseEvent::from(&event);
    acc.state = acc.state.next(&parse_event);

    let language = match acc.state.clone() {
      ParseState::InCodeBlock(language) => language,
      _ => {
        assert!(acc.writer.write(event.clone()).is_ok());
        return acc;
      }
    };

    let unescaped_content = match event.element().unescaped_content() {
      Ok(content) => content.into_owned(),
      Err(_) => {
        assert!(acc.writer.write(event.clone()).is_ok());
        return acc;
      }
    };

    let content_to_highlight = match str::from_utf8(&unescaped_content) {
      Ok(utf8_str) => utf8_str,
      Err(_) => {
        assert!(acc.writer.write(event.clone()).is_ok());
        return acc;
      },
    };

    let ss = SyntaxSet::load_defaults_nonewlines();
    let syntax = ss.find_syntax_by_token(&language);
    let valid_syntax = match syntax {
      Some(valid_syntax) => valid_syntax,
      None => {
        assert!(acc.writer.write(event.clone()).is_ok());
        return acc;
      }
    };

    let highlighted = highlighted_snippet_for_string(
      content_to_highlight,
      valid_syntax,
      &ThemeSet::load_defaults().themes["base16-eighties.dark"]
    );

    let text = Element::new(highlighted);
    assert!(acc.writer.write(Event::Text(text)).is_ok());

    acc
  });

  String::from_utf8(accumulator.writer.into_inner()).unwrap_or(original_string)
}

#[cfg(test)]
mod tests {

  #[test]
  fn test_parse_state() {
    use super::ParseState;
    use super::ParseEvent;

    let lang = String::from("rust");

    assert_eq!(
      ParseState::NotInBlock.next(&ParseEvent::StartPre(Some(lang.clone()))),
      ParseState::MaybeStartBlock(lang.clone())
    );

    assert_eq!(
      ParseState::NotInBlock.next(&ParseEvent::EndCode),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::NotInBlock.next(&ParseEvent::Other),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::NotInBlock.next(&ParseEvent::StartCode),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::MaybeStartBlock(lang.clone()).next(&ParseEvent::StartCode),
      ParseState::WillStartCodeBlock(lang.clone())
    );

    assert_eq!(
      ParseState::MaybeStartBlock(lang.clone()).next(&ParseEvent::Text),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::MaybeStartBlock(lang.clone()).next(&ParseEvent::EndCode),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::MaybeStartBlock(lang.clone())
        .next(&ParseEvent::StartPre(Some(lang.clone()))),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::MaybeStartBlock(lang.clone()).next(&ParseEvent::Other),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::WillStartCodeBlock(lang.clone()).next(&ParseEvent::Text),
      ParseState::InCodeBlock(lang.clone())
    );
  }
}
<commit_msg>Improve syntax highlighting state machine readability.<commit_after>/// Provide syntax highlighting via [Syntect].
///
/// [Syntect]: https://docs.rs/syntect/1.0.0/syntect/

// Standard library
use std::default::Default;
use std::str;

// Third party
use quick_xml::{XmlReader, XmlWriter, Element, Event};
use syntect::html::highlighted_snippet_for_string;
use syntect::highlighting::{ThemeSet};
use syntect::parsing::SyntaxSet;

/// A `Language` is a `String` representing a code highlighting language.
type Language = String;

/// Define XML parsing states of interest for highlighting.
///
/// We use these in conjunction with `ParseEvent`s to drive a state machine
/// which tracks whether we are in a
#[derive(Clone, Debug, PartialEq)]
enum ParseState {
  /// Not in a code block at all.
  NotInBlock,
  /// Possibly the start of a highlight block, with the language as payload.
  MaybeStartBlock(Language),
  /// The start of the code block has been confirmed; highlight next text node.
  WillStartCodeBlock(Language),
  /// In a code block; use the content for highlighting.
  InCodeBlock(Language),
}

/// Define XML parsing events of interest for highlighting.
///
/// We don't care at all about any other items for this specific scenario; we
/// use these in conjunction with the `ParseState`
#[derive(Debug)]
enum ParseEvent {
  // Starting a `<pre>`; optionally specifying a language.
  StartPre(Option<Language>),
  // Starting a `<code>`.
  StartCode,
  // Ending a `<code>`.
  EndCode,
  Text,
  Whitespace,
  Other,
}

impl ParseState {
  fn next(&self, event: &ParseEvent) -> ParseState {
    use self::ParseState::*;
    use self::ParseEvent::*;

    match (self, event) {
      (&NotInBlock, &StartPre(Some(ref language))) =>
        MaybeStartBlock(language.clone()),

      (&MaybeStartBlock(ref language), &Whitespace) =>
        MaybeStartBlock(language.clone()),

      (&MaybeStartBlock(ref language), &StartCode) =>
        WillStartCodeBlock(language.clone()),

      (&WillStartCodeBlock(ref language), &Text) |
      (&WillStartCodeBlock(ref language), &Whitespace) =>
        InCodeBlock(language.clone()),

      (&InCodeBlock(_), &EndCode) => NotInBlock,

      (_, _) => NotInBlock,
    }
  }
}

impl Default for ParseState {
  fn default() -> ParseState { ParseState::NotInBlock }
}

impl<'a> From<&'a Event> for ParseEvent {
  fn from(event: &'a Event) -> ParseEvent {
    const PRE: &'static [u8] = b"pre";
    const CODE: &'static [u8] = b"code";
    const CLASS: &'static [u8] = b"class";
    const WHITE_SPACE: &'static [u8] = b"";

    match *event {
      Event::Start(ref element) => {
        match element.name() {
          PRE => {
            let maybe_class_attr = element
              .attributes()
              .map(|attr| attr.unwrap())
              .filter(|attr| attr.0 == CLASS)
              .next();

            match maybe_class_attr {
              Some(class_attr) => {
                match str::from_utf8(class_attr.1) {
                  Ok(lang) => ParseEvent::StartPre(Some(String::from(lang))),
                  Err(_) => ParseEvent::StartPre(None),
                }
              },
              None => ParseEvent::StartPre(None),
            }
          },
          CODE => ParseEvent::StartCode,
          _ => ParseEvent::Other,
        }
      },
      Event::End(ref element) => {
        match element.name() {
          CODE => ParseEvent::EndCode,
          _ => ParseEvent::Other,
        }
      },
      Event::Text(ref element) => {
        match element.name() {
          WHITE_SPACE => ParseEvent::Whitespace,
          _ => ParseEvent::Text,
        }

      },
      _ => ParseEvent::Other,
    }
  }
}

struct Accumulator {
  writer: XmlWriter<Vec<u8>>,
  state: ParseState,
}

pub fn syntax_highlight(html_string: String) -> String {
  let original_string = html_string.clone();
  let reader = XmlReader::from(html_string.as_str());

  let mut accumulator = Accumulator {
    writer: XmlWriter::new(Vec::<u8>::new()),
    state: ParseState::default(),
  };

  reader.fold(&mut accumulator, |acc, event| {
    let event = match event {
      Ok(event) => event,
      Err(_) => {
        return acc;
      }
    };

    let parse_event = ParseEvent::from(&event);
    acc.state = acc.state.next(&parse_event);

    let language = match acc.state.clone() {
      ParseState::InCodeBlock(language) => language,
      _ => {
        assert!(acc.writer.write(event.clone()).is_ok());
        return acc;
      }
    };

    let unescaped_content = match event.element().unescaped_content() {
      Ok(content) => content.into_owned(),
      Err(_) => {
        assert!(acc.writer.write(event.clone()).is_ok());
        return acc;
      }
    };

    let content_to_highlight = match str::from_utf8(&unescaped_content) {
      Ok(utf8_str) => utf8_str,
      Err(_) => {
        assert!(acc.writer.write(event.clone()).is_ok());
        return acc;
      },
    };

    let ss = SyntaxSet::load_defaults_nonewlines();
    let syntax = ss.find_syntax_by_token(&language);
    let valid_syntax = match syntax {
      Some(valid_syntax) => valid_syntax,
      None => {
        assert!(acc.writer.write(event.clone()).is_ok());
        return acc;
      }
    };

    let highlighted = highlighted_snippet_for_string(
      content_to_highlight,
      valid_syntax,
      &ThemeSet::load_defaults().themes["base16-eighties.dark"]
    );

    let text = Element::new(highlighted);
    assert!(acc.writer.write(Event::Text(text)).is_ok());

    acc
  });

  String::from_utf8(accumulator.writer.into_inner()).unwrap_or(original_string)
}

#[cfg(test)]
mod tests {

  #[test]
  fn test_parse_state() {
    use super::ParseState;
    use super::ParseEvent;

    let lang = String::from("rust");

    assert_eq!(
      ParseState::NotInBlock.next(&ParseEvent::StartPre(Some(lang.clone()))),
      ParseState::MaybeStartBlock(lang.clone())
    );

    assert_eq!(
      ParseState::NotInBlock.next(&ParseEvent::EndCode),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::NotInBlock.next(&ParseEvent::Other),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::NotInBlock.next(&ParseEvent::StartCode),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::MaybeStartBlock(lang.clone()).next(&ParseEvent::StartCode),
      ParseState::WillStartCodeBlock(lang.clone())
    );

    assert_eq!(
      ParseState::MaybeStartBlock(lang.clone()).next(&ParseEvent::Text),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::MaybeStartBlock(lang.clone()).next(&ParseEvent::EndCode),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::MaybeStartBlock(lang.clone())
        .next(&ParseEvent::StartPre(Some(lang.clone()))),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::MaybeStartBlock(lang.clone()).next(&ParseEvent::Other),
      ParseState::NotInBlock
    );

    assert_eq!(
      ParseState::WillStartCodeBlock(lang.clone()).next(&ParseEvent::Text),
      ParseState::InCodeBlock(lang.clone())
    );
  }
}
<|endoftext|>


<commit_before>use std::vec::Vec;

use engine::{Actor, Map};
use engine::builders::MapFromString;
use util::units::{Direction, Point};

pub struct World {
    pub player: Actor,
    pub actors: Vec<Actor>,
    pub map: Map,
}

impl World {

    pub fn new() -> World {
        World {
            player: Actor::new("Player".to_string(), Point::new(1, 1), 100, '@'),
            actors: Vec::new(),
            map: Map::from_builder(MapFromString::new("#####\n#   #\n#   #\n#   #\n#####")),
        }
    }

    pub fn walk(&mut self, direction: Direction) {
        if !self.map.is_walkable(self.player.pos) { return; }

        self.player.walk(direction);
    }

}
<commit_msg>Fix walking considering the current cell instead of the destination<commit_after>use std::vec::Vec;

use engine::{Actor, Map};
use engine::builders::MapFromString;
use util::units::{Direction, Point};

pub struct World {
    pub player: Actor,
    pub actors: Vec<Actor>,
    pub map: Map,
}

impl World {

    pub fn new() -> World {
        World {
            player: Actor::new("Player".to_string(), Point::new(1, 1), 100, '@'),
            actors: Vec::new(),
            map: Map::from_builder(MapFromString::new("#####\n#   #\n#   #\n#   #\n#####")),
        }
    }

    pub fn walk(&mut self, direction: Direction) {
        if !self.map.is_walkable(self.player.pos.move_dir(direction)) { return; }

        self.player.walk(direction);
    }

}
<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Render stream extension. Stream is something you can send batches to.
//! It includes a renderer and an output, stored by constrained types.

use device::{Device, InstanceCount, Resources, VertexCount};
use device::draw::CommandBuffer;
use device::target::{ClearData, Mask, Mirror, Rect};
use render::{DrawError, Renderer, RenderFactory};
use render::batch::{Batch, Error};
use render::target::Output;

/// Generic output window.
pub trait Window<R: Resources>: Output<R> {
    /// Swap front and back buffers.
    fn swap_buffers(&mut self);
}

/// Render stream abstraction.
pub trait Stream<R: Resources> {
    /// Command buffer type to constraint the `Renderer`.
    type CommandBuffer: CommandBuffer<R>;
    /// Constrained `Output` type.
    type Output: Output<R>;

    /// Get the output only.
    fn get_output(&self) -> &Self::Output;

    /// Access both of the stream components.
    fn access(&mut self) -> (&mut Renderer<R, Self::CommandBuffer>, &Self::Output);

    /// Get width/height aspect, needed for projections.
    fn get_aspect_ratio(&self) -> f32 {
        let (w, h) = self.get_output().get_size();
        w as f32 / h as f32
    }

    /// Clear the canvas.
    fn clear(&mut self, data: ClearData) {
        let (ren, out) = self.access();
        let mask = out.get_mask();
        ren.clear(data, mask, out);
    }

    /// Blit on this stream from another `Output`.
    fn blit_on<I: Output<R>>(&mut self,
               source: &I, source_rect: Rect, dest_rect: Rect,
               mirror: Mirror, mask: Mask) {
        let (ren, out) = self.access();
        ren.blit(source, source_rect, out, dest_rect, mirror, mask);
    }

    /// Blit this stream to another `Output`.
    fn blit_to<O: Output<R>>(&mut self,
               destination: &O, dest_rect: Rect, source_rect: Rect,
               mirror: Mirror, mask: Mask) {
        let (ren, out) = self.access();
        ren.blit(out, source_rect, destination, dest_rect, mirror, mask);
    }

    /// Draw a simple `Batch`.
    fn draw<B: Batch<R> + ?Sized>(&mut self, batch: &B)
            -> Result<(), DrawError<Error>> {
        let (ren, out) = self.access();
        ren.draw(batch, None, out)
    }

    /// Draw an instanced `Batch`.
    fn draw_instanced<B: Batch<R> + ?Sized>(&mut self, batch: &B,
                      count: InstanceCount, base: VertexCount)
                      -> Result<(), DrawError<Error>> {
        let (ren, out) = self.access();
        ren.draw(batch, Some((count, base)), out)
    }

    /// Execute everything and clear the command buffer.
    fn flush<D>(&mut self, device: &mut D) where
        D: Device<Resources = R, CommandBuffer = Self::CommandBuffer>,
    {
        let (ren, _) = self.access();
        device.submit(ren.as_buffer());
        ren.reset();
    }
}

impl<'a, R: Resources, C: CommandBuffer<R>, O: Output<R>>
Stream<R> for (&'a mut Renderer<R, C>, &'a O) {
    type CommandBuffer = C;
    type Output = O;

    fn get_output(&self) -> &O {
        &self.1
    }

    fn access(&mut self) -> (&mut Renderer<R, C>, &O) {
        (&mut self.0, &self.1)
    }
}

/// A stream that owns its components.
pub struct OwnedStream<D: Device, O>{
    /// Renderer
    pub ren: Renderer<D::Resources, D::CommandBuffer>,
    /// Output
    pub out: O,
}

impl<
    D: Device,
    O: Output<D::Resources>,
> Stream<D::Resources> for OwnedStream<D, O> {
    type CommandBuffer = D::CommandBuffer;
    type Output = O;

    fn get_output(&self) -> &O {
        &self.out
    }

    fn access(&mut self) -> (&mut Renderer<D::Resources, D::CommandBuffer>, &O) {
        (&mut self.ren, &self.out)
    }
}

impl<D: Device, W: Window<D::Resources>> OwnedStream<D, W> {
    /// Show what we've been drawing all this time.
    pub fn present(&mut self, device: &mut D) {
        self.flush(device);
        self.out.swap_buffers();
        device.cleanup();
    }
}

/// A render factory extension that allows creating streams with new renderers.
pub trait StreamFactory<D: Device>: RenderFactory<D::Resources, D::CommandBuffer> {
    /// Create a new stream from a given output.
    fn create_stream<O: Output<D::Resources>>(&mut self, output: O) -> OwnedStream<D, O> {
        OwnedStream {
            ren: self.create_renderer(),
            out: output,
        }
    }
}

impl<D: Device, F: RenderFactory<D::Resources, D::CommandBuffer>>
StreamFactory<D> for F {}
<commit_msg>properly returning stream errors<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Render stream extension. Stream is something you can send batches to.
//! It includes a renderer and an output, stored by constrained types.

use device::{Device, InstanceCount, Resources, VertexCount};
use device::draw::CommandBuffer;
use device::target::{ClearData, Mask, Mirror, Rect};
use render::{BlitError, DrawError, Renderer, RenderFactory};
use render::batch::{Batch, Error};
use render::target::Output;

/// Generic output window.
pub trait Window<R: Resources>: Output<R> {
    /// Swap front and back buffers.
    fn swap_buffers(&mut self);
}

/// Render stream abstraction.
pub trait Stream<R: Resources> {
    /// Command buffer type to constraint the `Renderer`.
    type CommandBuffer: CommandBuffer<R>;
    /// Constrained `Output` type.
    type Output: Output<R>;

    /// Get the output only.
    fn get_output(&self) -> &Self::Output;

    /// Access both of the stream components.
    fn access(&mut self) -> (&mut Renderer<R, Self::CommandBuffer>, &Self::Output);

    /// Get width/height aspect, needed for projections.
    fn get_aspect_ratio(&self) -> f32 {
        let (w, h) = self.get_output().get_size();
        w as f32 / h as f32
    }

    /// Clear the canvas.
    fn clear(&mut self, data: ClearData) {
        let (ren, out) = self.access();
        let mask = out.get_mask();
        ren.clear(data, mask, out);
    }

    /// Blit on this stream from another `Output`.
    fn blit_on<I: Output<R>>(&mut self,
               source: &I, source_rect: Rect, dest_rect: Rect,
               mirror: Mirror, mask: Mask)
               -> Result<(), BlitError>
    {
        let (ren, out) = self.access();
        ren.blit(source, source_rect, out, dest_rect, mirror, mask)
    }

    /// Blit this stream to another `Output`.
    fn blit_to<O: Output<R>>(&mut self,
               destination: &O, dest_rect: Rect, source_rect: Rect,
               mirror: Mirror, mask: Mask)
               -> Result<(), BlitError>
    {
        let (ren, out) = self.access();
        ren.blit(out, source_rect, destination, dest_rect, mirror, mask)
    }

    /// Draw a simple `Batch`.
    fn draw<B: Batch<R> + ?Sized>(&mut self, batch: &B)
            -> Result<(), DrawError<Error>> {
        let (ren, out) = self.access();
        ren.draw(batch, None, out)
    }

    /// Draw an instanced `Batch`.
    fn draw_instanced<B: Batch<R> + ?Sized>(&mut self, batch: &B,
                      count: InstanceCount, base: VertexCount)
                      -> Result<(), DrawError<Error>> {
        let (ren, out) = self.access();
        ren.draw(batch, Some((count, base)), out)
    }

    /// Execute everything and clear the command buffer.
    fn flush<D>(&mut self, device: &mut D) where
        D: Device<Resources = R, CommandBuffer = Self::CommandBuffer>,
    {
        let (ren, _) = self.access();
        device.submit(ren.as_buffer());
        ren.reset();
    }
}

impl<'a, R: Resources, C: CommandBuffer<R>, O: Output<R>>
Stream<R> for (&'a mut Renderer<R, C>, &'a O) {
    type CommandBuffer = C;
    type Output = O;

    fn get_output(&self) -> &O {
        &self.1
    }

    fn access(&mut self) -> (&mut Renderer<R, C>, &O) {
        (&mut self.0, &self.1)
    }
}

/// A stream that owns its components.
pub struct OwnedStream<D: Device, O>{
    /// Renderer
    pub ren: Renderer<D::Resources, D::CommandBuffer>,
    /// Output
    pub out: O,
}

impl<
    D: Device,
    O: Output<D::Resources>,
> Stream<D::Resources> for OwnedStream<D, O> {
    type CommandBuffer = D::CommandBuffer;
    type Output = O;

    fn get_output(&self) -> &O {
        &self.out
    }

    fn access(&mut self) -> (&mut Renderer<D::Resources, D::CommandBuffer>, &O) {
        (&mut self.ren, &self.out)
    }
}

impl<D: Device, W: Window<D::Resources>> OwnedStream<D, W> {
    /// Show what we've been drawing all this time.
    pub fn present(&mut self, device: &mut D) {
        self.flush(device);
        self.out.swap_buffers();
        device.cleanup();
    }
}

/// A render factory extension that allows creating streams with new renderers.
pub trait StreamFactory<D: Device>: RenderFactory<D::Resources, D::CommandBuffer> {
    /// Create a new stream from a given output.
    fn create_stream<O: Output<D::Resources>>(&mut self, output: O) -> OwnedStream<D, O> {
        OwnedStream {
            ren: self.create_renderer(),
            out: output,
        }
    }
}

impl<D: Device, F: RenderFactory<D::Resources, D::CommandBuffer>>
StreamFactory<D> for F {}
<|endoftext|>


<commit_before>// Test various stacked-borrows-related things.
fn main() {
    deref_partially_dangling_raw();
    read_does_not_invalidate1();
    read_does_not_invalidate2();
    ref_raw_int_raw();
    mut_raw_then_mut_shr();
    mut_shr_then_mut_raw();
    mut_raw_mut();
    partially_invalidate_mut();
    drop_after_sharing();
    direct_mut_to_const_raw();
}

// Deref a raw ptr to access a field of a large struct, where the field
// is allocated but not the entire struct is.
// For now, we want to allow this.
fn deref_partially_dangling_raw() {
    let x = (1, 13);
    let xptr = &x as *const _ as *const (i32, i32, i32);
    let val = unsafe { (*xptr).1 };
    assert_eq!(val, 13);
}

// Make sure that reading from an `&mut` does, like reborrowing to `&`,
// NOT invalidate other reborrows.
fn read_does_not_invalidate1() {
    fn foo(x: &mut (i32, i32)) -> &i32 {
        let xraw = x as *mut (i32, i32);
        let ret = unsafe { &(*xraw).1 };
        let _val = x.1; // we just read, this does NOT invalidate the reborrows.
        ret
    }
    assert_eq!(*foo(&mut (1, 2)), 2);
}
// Same as above, but this time we first create a raw, then read from `&mut`
// and then freeze from the raw.
fn read_does_not_invalidate2() {
    fn foo(x: &mut (i32, i32)) -> &i32 {
        let xraw = x as *mut (i32, i32);
        let _val = x.1; // we just read, this does NOT invalidate the raw reborrow.
        let ret = unsafe { &(*xraw).1 };
        ret
    }
    assert_eq!(*foo(&mut (1, 2)), 2);
}

// Just to make sure that casting a ref to raw, to int and back to raw
// and only then using it works. This rules out ideas like "do escape-to-raw lazily";
// after casting to int and back, we lost the tag that could have let us do that.
fn ref_raw_int_raw() {
    let mut x = 3;
    let xref = &mut x;
    let xraw = xref as *mut i32 as usize as *mut i32;
    assert_eq!(unsafe { *xraw }, 3);
}

// Escape a mut to raw, then share the same mut and use the share, then the raw.
// That should work.
fn mut_raw_then_mut_shr() {
    let mut x = 2;
    let xref = &mut x;
    let xraw = &mut *xref as *mut _;
    let xshr = &*xref;
    assert_eq!(*xshr, 2);
    unsafe { *xraw = 4; }
    assert_eq!(x, 4);
}

// Create first a shared reference and then a raw pointer from a `&mut`
// should permit mutation through that raw pointer.
fn mut_shr_then_mut_raw() {
    let xref = &mut 2;
    let _xshr = &*xref;
    let xraw = xref as *mut _;
    unsafe { *xraw = 3; }
    assert_eq!(*xref, 3);
}

// Ensure that if we derive from a mut a raw, and then from that a mut,
// and then read through the original mut, that does not invalidate the raw.
// This shows that the read-exception for `&mut` applies even if the `Shr` item
// on the stack is not at the top.
fn mut_raw_mut() {
    let mut x = 2;
    {
        let xref1 = &mut x;
        let xraw = xref1 as *mut _;
        let _xref2 = unsafe { &mut *xraw };
        let _val = *xref1;
        unsafe { *xraw = 4; }
        // we can now use both xraw and xref1, for reading
        assert_eq!(*xref1, 4);
        assert_eq!(unsafe { *xraw }, 4);
        assert_eq!(*xref1, 4);
        assert_eq!(unsafe { *xraw }, 4);
        // we cannot use xref2; see `compile-fail/stacked-borows/illegal_read4.rs`
    }
    assert_eq!(x, 4);
}

fn partially_invalidate_mut() {
    let data = &mut (0u8, 0u8);
    let reborrow = &mut *data as *mut (u8, u8);
    let shard = unsafe { &mut (*reborrow).0 };
    data.1 += 1; // the deref overlaps with `shard`, but that is ok; the access does not overlap.
    *shard += 1; // so we can still use `shard`.
    assert_eq!(*data, (1, 1));
}

// Make sure that we can handle the situation where a loaction is frozen when being dropped.
fn drop_after_sharing() {
    let x = String::from("hello!");
    let _len = x.len();
}

// Make sure that coercing &mut T to *const T produces a writeable pointer.
fn direct_mut_to_const_raw() {
    // FIXME: This is currently disabled, waiting on a fix for <https://github.com/rust-lang/rust/issues/56604>
    /*let x = &mut 0;
    let y: *const i32 = x;
    unsafe { *(y as *mut i32) = 1; }
    assert_eq!(*x, 1);
    */
}
<commit_msg>test creating two raw pointers from the same mutable ref<commit_after>// Test various stacked-borrows-related things.
fn main() {
    deref_partially_dangling_raw();
    read_does_not_invalidate1();
    read_does_not_invalidate2();
    ref_raw_int_raw();
    mut_raw_then_mut_shr();
    mut_shr_then_mut_raw();
    mut_raw_mut();
    partially_invalidate_mut();
    drop_after_sharing();
    direct_mut_to_const_raw();
    two_raw();
}

// Deref a raw ptr to access a field of a large struct, where the field
// is allocated but not the entire struct is.
// For now, we want to allow this.
fn deref_partially_dangling_raw() {
    let x = (1, 13);
    let xptr = &x as *const _ as *const (i32, i32, i32);
    let val = unsafe { (*xptr).1 };
    assert_eq!(val, 13);
}

// Make sure that reading from an `&mut` does, like reborrowing to `&`,
// NOT invalidate other reborrows.
fn read_does_not_invalidate1() {
    fn foo(x: &mut (i32, i32)) -> &i32 {
        let xraw = x as *mut (i32, i32);
        let ret = unsafe { &(*xraw).1 };
        let _val = x.1; // we just read, this does NOT invalidate the reborrows.
        ret
    }
    assert_eq!(*foo(&mut (1, 2)), 2);
}
// Same as above, but this time we first create a raw, then read from `&mut`
// and then freeze from the raw.
fn read_does_not_invalidate2() {
    fn foo(x: &mut (i32, i32)) -> &i32 {
        let xraw = x as *mut (i32, i32);
        let _val = x.1; // we just read, this does NOT invalidate the raw reborrow.
        let ret = unsafe { &(*xraw).1 };
        ret
    }
    assert_eq!(*foo(&mut (1, 2)), 2);
}

// Just to make sure that casting a ref to raw, to int and back to raw
// and only then using it works. This rules out ideas like "do escape-to-raw lazily";
// after casting to int and back, we lost the tag that could have let us do that.
fn ref_raw_int_raw() {
    let mut x = 3;
    let xref = &mut x;
    let xraw = xref as *mut i32 as usize as *mut i32;
    assert_eq!(unsafe { *xraw }, 3);
}

// Escape a mut to raw, then share the same mut and use the share, then the raw.
// That should work.
fn mut_raw_then_mut_shr() {
    let mut x = 2;
    let xref = &mut x;
    let xraw = &mut *xref as *mut _;
    let xshr = &*xref;
    assert_eq!(*xshr, 2);
    unsafe { *xraw = 4; }
    assert_eq!(x, 4);
}

// Create first a shared reference and then a raw pointer from a `&mut`
// should permit mutation through that raw pointer.
fn mut_shr_then_mut_raw() {
    let xref = &mut 2;
    let _xshr = &*xref;
    let xraw = xref as *mut _;
    unsafe { *xraw = 3; }
    assert_eq!(*xref, 3);
}

// Ensure that if we derive from a mut a raw, and then from that a mut,
// and then read through the original mut, that does not invalidate the raw.
// This shows that the read-exception for `&mut` applies even if the `Shr` item
// on the stack is not at the top.
fn mut_raw_mut() {
    let mut x = 2;
    {
        let xref1 = &mut x;
        let xraw = xref1 as *mut _;
        let _xref2 = unsafe { &mut *xraw };
        let _val = *xref1;
        unsafe { *xraw = 4; }
        // we can now use both xraw and xref1, for reading
        assert_eq!(*xref1, 4);
        assert_eq!(unsafe { *xraw }, 4);
        assert_eq!(*xref1, 4);
        assert_eq!(unsafe { *xraw }, 4);
        // we cannot use xref2; see `compile-fail/stacked-borows/illegal_read4.rs`
    }
    assert_eq!(x, 4);
}

fn partially_invalidate_mut() {
    let data = &mut (0u8, 0u8);
    let reborrow = &mut *data as *mut (u8, u8);
    let shard = unsafe { &mut (*reborrow).0 };
    data.1 += 1; // the deref overlaps with `shard`, but that is ok; the access does not overlap.
    *shard += 1; // so we can still use `shard`.
    assert_eq!(*data, (1, 1));
}

// Make sure that we can handle the situation where a loaction is frozen when being dropped.
fn drop_after_sharing() {
    let x = String::from("hello!");
    let _len = x.len();
}

// Make sure that coercing &mut T to *const T produces a writeable pointer.
fn direct_mut_to_const_raw() {
    // FIXME: This is currently disabled, waiting on a fix for <https://github.com/rust-lang/rust/issues/56604>
    /*let x = &mut 0;
    let y: *const i32 = x;
    unsafe { *(y as *mut i32) = 1; }
    assert_eq!(*x, 1);
    */
}

// Make sure that we can create two raw pointers from a mutable reference and use them both.
fn two_raw() { unsafe {
    let x = &mut 0;
    // Given the implicit reborrows, the only reason this currently works is that we
    // do not track raw pointers: The creation of `y2` reborrows `x` and thus pops
    // `y1` off the stack.
    let y1 = x as *mut _;
    let y2 = x as *mut _;
    *y1 += 2;
    *y2 += 1;
} }
<|endoftext|>