<commit_before>use std::borrow::Cow;
use std::convert::Into;

use mio;
use mio::Token;
use mio_extras::timer::Timeout;
use url;

use io::ALL;
use message;
use protocol::CloseCode;
use result::{Error, Result};
use std::cmp::PartialEq;

#[derive(Debug, Clone)]
pub enum Signal {
    Message(message::Message),
    Close(CloseCode, Cow<'static, str>),
    Ping(Vec<u8>),
    Pong(Vec<u8>),
    Connect(url::Url),
    Shutdown,
    Timeout { delay: u64, token: Token },
    Cancel(Timeout),
}

#[derive(Debug, Clone)]
pub struct Command {
    token: Token,
    signal: Signal,
    connection_id: u32,
}

impl Command {
    pub fn token(&self) -> Token {
        self.token
    }

    pub fn into_signal(self) -> Signal {
        self.signal
    }

    pub fn connection_id(&self) -> u32 {
        self.connection_id
    }
}

/// A representation of the output of the WebSocket connection. Use this to send messages to the
/// other endpoint.
#[derive(Clone)]
pub struct Sender {
    token: Token,
    channel: mio::channel::SyncSender<Command>,
    connection_id: u32,
}

impl PartialEq for Sender {
    fn eq(&self, other: &Sender) -> bool {
        self.token == other.token && self.connection_id == other.connection_id
    }
}

impl Sender {
    #[doc(hidden)]
    #[inline]
    pub fn new(
        token: Token,
        channel: mio::channel::SyncSender<Command>,
        connection_id: u32,
    ) -> Sender {
        Sender {
            token,
            channel,
            connection_id,
        }
    }

    /// A Token identifying this sender within the WebSocket.
    #[inline]
    pub fn token(&self) -> Token {
        self.token
    }

    /// A connection_id identifying this sender within the WebSocket.
    #[inline]
    pub fn connection_id(&self) -> u32 {
        self.connection_id
    }

    /// Send a message over the connection.
    #[inline]
    pub fn send<M>(&self, msg: M) -> Result<()>
    where
        M: Into<message::Message>,
    {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Message(msg.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a message to the endpoints of all connections.
    ///
    /// Be careful with this method. It does not discriminate between client and server connections.
    /// If your WebSocket is only functioning as a server, then usage is simple, this method will
    /// send a copy of the message to each connected client. However, if you have a WebSocket that
    /// is listening for connections and is also connected to another WebSocket, this method will
    /// broadcast a copy of the message to all the clients connected and to that WebSocket server.
    #[inline]
    pub fn broadcast<M>(&self, msg: M) -> Result<()>
    where
        M: Into<message::Message>,
    {
        self.channel
            .send(Command {
                token: ALL,
                signal: Signal::Message(msg.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a close code to the other endpoint.
    #[inline]
    pub fn close(&self, code: CloseCode) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Close(code, "".into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a close code and provide a descriptive reason for closing.
    #[inline]
    pub fn close_with_reason<S>(&self, code: CloseCode, reason: S) -> Result<()>
    where
        S: Into<Cow<'static, str>>,
    {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Close(code, reason.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a ping to the other endpoint with the given test data.
    #[inline]
    pub fn ping(&self, data: Vec<u8>) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Ping(data),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a pong to the other endpoint responding with the given test data.
    #[inline]
    pub fn pong(&self, data: Vec<u8>) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Pong(data),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Queue a new connection on this WebSocket to the specified URL.
    #[inline]
    pub fn connect(&self, url: url::Url) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Connect(url),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Request that all connections terminate and that the WebSocket stop running.
    #[inline]
    pub fn shutdown(&self) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Shutdown,
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Schedule a `token` to be sent to the WebSocket Handler's `on_timeout` method
    /// after `ms` milliseconds
    #[inline]
    pub fn timeout(&self, ms: u64, token: Token) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Timeout { delay: ms, token },
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Queue the cancellation of a previously scheduled timeout.
    ///
    /// This method is not guaranteed to prevent the timeout from occurring, because it is
    /// possible to call this method after a timeout has already occurred. It is still necessary to
    /// handle spurious timeouts.
    #[inline]
    pub fn cancel(&self, timeout: Timeout) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Cancel(timeout),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }
}
<commit_msg>Add impl Debug for Sender<commit_after>use std::borrow::Cow;
use std::convert::Into;

use mio;
use mio::Token;
use mio_extras::timer::Timeout;
use url;

use io::ALL;
use message;
use protocol::CloseCode;
use result::{Error, Result};
use std::cmp::PartialEq;
use std::fmt;

#[derive(Debug, Clone)]
pub enum Signal {
    Message(message::Message),
    Close(CloseCode, Cow<'static, str>),
    Ping(Vec<u8>),
    Pong(Vec<u8>),
    Connect(url::Url),
    Shutdown,
    Timeout { delay: u64, token: Token },
    Cancel(Timeout),
}

#[derive(Debug, Clone)]
pub struct Command {
    token: Token,
    signal: Signal,
    connection_id: u32,
}

impl Command {
    pub fn token(&self) -> Token {
        self.token
    }

    pub fn into_signal(self) -> Signal {
        self.signal
    }

    pub fn connection_id(&self) -> u32 {
        self.connection_id
    }
}

/// A representation of the output of the WebSocket connection. Use this to send messages to the
/// other endpoint.
#[derive(Clone)]
pub struct Sender {
    token: Token,
    channel: mio::channel::SyncSender<Command>,
    connection_id: u32,
}

impl fmt::Debug for Sender {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Sender {{ token: {:?}, channel: _, connection_id: {:?} }}",
            self.token, self.connection_id)
    }
}

impl PartialEq for Sender {
    fn eq(&self, other: &Sender) -> bool {
        self.token == other.token && self.connection_id == other.connection_id
    }
}

impl Sender {
    #[doc(hidden)]
    #[inline]
    pub fn new(
        token: Token,
        channel: mio::channel::SyncSender<Command>,
        connection_id: u32,
    ) -> Sender {
        Sender {
            token,
            channel,
            connection_id,
        }
    }

    /// A Token identifying this sender within the WebSocket.
    #[inline]
    pub fn token(&self) -> Token {
        self.token
    }

    /// A connection_id identifying this sender within the WebSocket.
    #[inline]
    pub fn connection_id(&self) -> u32 {
        self.connection_id
    }

    /// Send a message over the connection.
    #[inline]
    pub fn send<M>(&self, msg: M) -> Result<()>
    where
        M: Into<message::Message>,
    {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Message(msg.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a message to the endpoints of all connections.
    ///
    /// Be careful with this method. It does not discriminate between client and server connections.
    /// If your WebSocket is only functioning as a server, then usage is simple, this method will
    /// send a copy of the message to each connected client. However, if you have a WebSocket that
    /// is listening for connections and is also connected to another WebSocket, this method will
    /// broadcast a copy of the message to all the clients connected and to that WebSocket server.
    #[inline]
    pub fn broadcast<M>(&self, msg: M) -> Result<()>
    where
        M: Into<message::Message>,
    {
        self.channel
            .send(Command {
                token: ALL,
                signal: Signal::Message(msg.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a close code to the other endpoint.
    #[inline]
    pub fn close(&self, code: CloseCode) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Close(code, "".into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a close code and provide a descriptive reason for closing.
    #[inline]
    pub fn close_with_reason<S>(&self, code: CloseCode, reason: S) -> Result<()>
    where
        S: Into<Cow<'static, str>>,
    {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Close(code, reason.into()),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a ping to the other endpoint with the given test data.
    #[inline]
    pub fn ping(&self, data: Vec<u8>) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Ping(data),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Send a pong to the other endpoint responding with the given test data.
    #[inline]
    pub fn pong(&self, data: Vec<u8>) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Pong(data),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Queue a new connection on this WebSocket to the specified URL.
    #[inline]
    pub fn connect(&self, url: url::Url) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Connect(url),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Request that all connections terminate and that the WebSocket stop running.
    #[inline]
    pub fn shutdown(&self) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Shutdown,
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Schedule a `token` to be sent to the WebSocket Handler's `on_timeout` method
    /// after `ms` milliseconds
    #[inline]
    pub fn timeout(&self, ms: u64, token: Token) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Timeout { delay: ms, token },
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }

    /// Queue the cancellation of a previously scheduled timeout.
    ///
    /// This method is not guaranteed to prevent the timeout from occurring, because it is
    /// possible to call this method after a timeout has already occurred. It is still necessary to
    /// handle spurious timeouts.
    #[inline]
    pub fn cancel(&self, timeout: Timeout) -> Result<()> {
        self.channel
            .send(Command {
                token: self.token,
                signal: Signal::Cancel(timeout),
                connection_id: self.connection_id,
            })
            .map_err(Error::from)
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
#![feature(globs)]

extern crate semver;
extern crate conduit;

use std::io::net::ip::IpAddr;

use conduit::{Method, Scheme, Host, Extensions, Headers, Request};

pub trait RequestDelegator {
    fn request<'a>(&'a self) -> &'a Request;
    fn mut_request<'a>(&'a mut self) -> &'a mut Request;

    fn http_version(&self) -> semver::Version {
        self.request().http_version()
    }

    fn conduit_version(&self) -> semver::Version {
        self.request().conduit_version()
    }

    fn method(&self) -> Method {
        self.request().method()
    }

    fn scheme(&self) -> Scheme {
        self.request().scheme()
    }

    fn host<'a>(&'a self) -> Host<'a> {
        self.request().host()
    }

    fn virtual_root<'a>(&'a self) -> Option<&'a str> {
        self.request().virtual_root()
    }

    fn path<'a>(&'a self) -> &'a str {
        self.request().path()
    }

    fn query_string<'a>(&'a self) -> Option<&'a str> {
        self.request().query_string()
    }

    fn remote_ip(&self) -> IpAddr {
        self.request().remote_ip()
    }

    fn content_length(&self) -> Option<uint> {
        self.request().content_length()
    }

    fn headers<'a>(&'a self) -> &'a Headers {
        self.request().headers()
    }

    fn body<'a>(&'a mut self) -> &'a mut Reader {
        self.mut_request().body()
    }

    fn extensions<'a>(&'a self) -> &'a Extensions {
        self.request().extensions()
    }

    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
        self.mut_request().mut_extensions()
    }
}

impl<'a> Request for &'a mut RequestDelegator {
    fn http_version(&self) -> semver::Version {
        self.http_version()
    }

    fn conduit_version(&self) -> semver::Version {
        self.conduit_version()
    }

    fn method(&self) -> Method {
        self.method()
    }

    fn scheme(&self) -> Scheme {
        self.scheme()
    }

    fn host<'a>(&'a self) -> Host<'a> {
        self.host()
    }

    fn virtual_root<'a>(&'a self) -> Option<&'a str> {
        self.virtual_root()
    }

    fn path<'a>(&'a self) -> &'a str {
        self.path()
    }

    fn query_string<'a>(&'a self) -> Option<&'a str> {
        self.query_string()
    }

    fn remote_ip(&self) -> IpAddr {
        self.remote_ip()
    }

    fn content_length(&self) -> Option<uint> {
        self.content_length()
    }

    fn headers<'a>(&'a self) -> &'a Headers {
        self.headers()
    }

    fn body<'a>(&'a mut self) -> &'a mut Reader {
        self.body()
    }

    fn extensions<'a>(&'a self) -> &'a Extensions {
        self.extensions()
    }

    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
        self.mut_extensions()
    }
}

#[cfg(test)]
mod tests {
    extern crate test = "conduit-test";
    use super::*;

    use conduit;
    use conduit::{Request, Method};

    struct OverrideRequest<'a> {
        request: &'a mut Request
    }

    impl<'a> RequestDelegator for OverrideRequest<'a> {
        fn request<'a>(&'a self) -> &'a Request {
            let req: &Request = self.request; req
        }

        fn mut_request<'a>(&'a mut self) -> &'a mut Request {
            let req: &mut Request = self.request; req
        }

        fn method(&self) -> Method {
            conduit::Get
        }
    }

    #[test]
    fn test_delegate() {
        let request = &mut test::MockRequest::new(conduit::Head, "/hello") as &mut Request;
        let override = OverrideRequest { request: request };

        assert_eq!(override.method(), conduit::Get);
        assert_eq!(override.path(), "/hello");
    }
}
<commit_msg>Add HeaderMap<commit_after>#![feature(macro_rules)]
#![feature(globs)]

extern crate semver;
extern crate conduit;

use std::iter;
use std::io::net::ip::IpAddr;
use std::collections::hashmap::{HashMap, Entries};

use conduit::{Method, Scheme, Host, Extensions, Headers, Request};

pub trait RequestDelegator {
    fn request<'a>(&'a self) -> &'a Request;
    fn mut_request<'a>(&'a mut self) -> &'a mut Request;

    fn http_version(&self) -> semver::Version {
        self.request().http_version()
    }

    fn conduit_version(&self) -> semver::Version {
        self.request().conduit_version()
    }

    fn method(&self) -> Method {
        self.request().method()
    }

    fn scheme(&self) -> Scheme {
        self.request().scheme()
    }

    fn host<'a>(&'a self) -> Host<'a> {
        self.request().host()
    }

    fn virtual_root<'a>(&'a self) -> Option<&'a str> {
        self.request().virtual_root()
    }

    fn path<'a>(&'a self) -> &'a str {
        self.request().path()
    }

    fn query_string<'a>(&'a self) -> Option<&'a str> {
        self.request().query_string()
    }

    fn remote_ip(&self) -> IpAddr {
        self.request().remote_ip()
    }

    fn content_length(&self) -> Option<uint> {
        self.request().content_length()
    }

    fn headers<'a>(&'a self) -> &'a Headers {
        self.request().headers()
    }

    fn body<'a>(&'a mut self) -> &'a mut Reader {
        self.mut_request().body()
    }

    fn extensions<'a>(&'a self) -> &'a Extensions {
        self.request().extensions()
    }

    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
        self.mut_request().mut_extensions()
    }
}

impl<'a> Request for &'a mut RequestDelegator {
    fn http_version(&self) -> semver::Version {
        self.http_version()
    }

    fn conduit_version(&self) -> semver::Version {
        self.conduit_version()
    }

    fn method(&self) -> Method {
        self.method()
    }

    fn scheme(&self) -> Scheme {
        self.scheme()
    }

    fn host<'a>(&'a self) -> Host<'a> {
        self.host()
    }

    fn virtual_root<'a>(&'a self) -> Option<&'a str> {
        self.virtual_root()
    }

    fn path<'a>(&'a self) -> &'a str {
        self.path()
    }

    fn query_string<'a>(&'a self) -> Option<&'a str> {
        self.query_string()
    }

    fn remote_ip(&self) -> IpAddr {
        self.remote_ip()
    }

    fn content_length(&self) -> Option<uint> {
        self.content_length()
    }

    fn headers<'a>(&'a self) -> &'a Headers {
        self.headers()
    }

    fn body<'a>(&'a mut self) -> &'a mut Reader {
        self.body()
    }

    fn extensions<'a>(&'a self) -> &'a Extensions {
        self.extensions()
    }

    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions {
        self.mut_extensions()
    }
}

type RawHeaders = HashMap<String, Vec<String>>;
type InHeader<'a> = (&'a String, &'a Vec<String>);
type OutHeader<'a> = (String, &'a Vec<String>);

#[deriving(PartialEq, Clone, Show)]
pub struct HeaderMap(HashMap<String, Vec<String>>);

impl HeaderMap {
    fn normalize(headers: HashMap<String, Vec<String>>) -> HeaderMap {
        let headers = headers.move_iter().map(|(k,v)| (to_lower(&k), v)).collect();
        HeaderMap(headers)
    }

    fn iter<'a>(&'a self) -> iter::Map<'a, InHeader<'a>, OutHeader<'a>, Entries<'a, String, Vec<String>>> {
        self.as_ref().iter().map(|(k,v)| (to_lower(k), v))
    }

    fn as_ref<'a>(&'a self) -> &'a HashMap<String, Vec<String>> {
        match *self {
            HeaderMap(ref map) => map
        }
    }

    fn as_mut<'a>(&'a mut self) -> &'a mut HashMap<String, Vec<String>> {
        match *self {
            HeaderMap(ref mut map) => map
        }
    }
}

impl Collection for HeaderMap {
    fn len(&self) -> uint {
        self.as_ref().len()
    }
}

impl Mutable for HeaderMap {
    fn clear(&mut self) {
        self.as_mut().clear()
    }
}

impl<S: Str> Map<S, Vec<String>> for HeaderMap {
    fn find<'a>(&'a self, key: &S) -> Option<&'a Vec<String>> {
        self.as_ref().find(&to_lower(key))
    }
}

impl<S: Str> MutableMap<S, Vec<String>> for HeaderMap {
    fn swap(&mut self, k: S, v: Vec<String>) -> Option<Vec<String>> {
        self.as_mut().swap(to_lower(&k), v)
    }

    fn pop(&mut self, k: &S) -> Option<Vec<String>> {
        self.as_mut().pop(&to_lower(k))
    }

    fn find_mut<'a>(&'a mut self, k: &S) -> Option<&'a mut Vec<String>> {
        self.as_mut().find_mut(&to_lower(k))
    }
}

fn to_lower<S: Str>(string: &S) -> String {
    string.as_slice().chars().map(|c| c.to_lowercase()).collect()
}

#[cfg(test)]
mod tests {
    extern crate test = "conduit-test";
    use super::*;

    use std::collections::HashMap;
    use conduit;
    use conduit::{Request, Method};

    struct OverrideRequest<'a> {
        request: &'a mut Request
    }

    impl<'a> RequestDelegator for OverrideRequest<'a> {
        fn request<'a>(&'a self) -> &'a Request {
            let req: &Request = self.request; req
        }

        fn mut_request<'a>(&'a mut self) -> &'a mut Request {
            let req: &mut Request = self.request; req
        }

        fn method(&self) -> Method {
            conduit::Get
        }
    }

    #[test]
    fn test_delegate() {
        let request = &mut test::MockRequest::new(conduit::Head, "/hello") as &mut Request;
        let override = OverrideRequest { request: request };

        assert_eq!(override.method(), conduit::Get);
        assert_eq!(override.path(), "/hello");
    }

    #[test]
    fn test_header_map() {
        let mut map = HeaderMap(HashMap::new());
        map.insert("Content-Type".to_str(), vec!("text/html".to_str()));
        map.insert("location".to_str(), vec!("http://example.com".to_str()));

        assert_eq!(map.find(&"content-type".to_str()), Some(&vec!("text/html".to_str())))
        assert_eq!(map.find(&"Location".to_str()), Some(&vec!("http://example.com".to_str())))
        assert_eq!(map.find(&"content-type"), Some(&vec!("text/html".to_str())))
        assert_eq!(map.find(&"Location"), Some(&vec!("http://example.com".to_str())))
    }

    #[test]
    fn test_header_map_with_static_inserts() {
        let mut map = HeaderMap(HashMap::new());
        map.insert("Content-Type", vec!("text/html".to_str()));
        map.insert("location", vec!("http://example.com".to_str()));

        assert_eq!(map.find(&"content-type".to_str()), Some(&vec!("text/html".to_str())))
        assert_eq!(map.find(&"Location".to_str()), Some(&vec!("http://example.com".to_str())))
        assert_eq!(map.find(&"content-type"), Some(&vec!("text/html".to_str())))
        assert_eq!(map.find(&"Location"), Some(&vec!("http://example.com".to_str())))
    }

    #[test]
    fn test_normalize() {
        let mut map = HashMap::new();
        map.insert("Content-Type".to_str(), vec!("text/html".to_str()));

        let headers = HeaderMap::normalize(map);
        assert_eq!(headers.find(&"Content-Type".to_str()), Some(&vec!("text/html".to_str())))
        assert_eq!(headers.find(&"Content-Type"), Some(&vec!("text/html".to_str())))
        assert_eq!(headers.find(&"content-type".to_str()), Some(&vec!("text/html".to_str())))
        assert_eq!(headers.find(&"content-type"), Some(&vec!("text/html".to_str())))
    }

    #[test]
    fn test_iterate() {
        let mut headers = HeaderMap(HashMap::new());
        headers.insert("Content-Type", vec!("text/html".to_str()));
        headers.insert("location", vec!("http://example.com".to_str()));

        assert!(headers.iter().any(|t| t == ("content-type".to_str(), &vec!("text/html".to_str()))));
        assert!(headers.iter().any(|t| t == ("location".to_str(), &vec!("http://example.com".to_str()))));
        assert!(headers.iter().count() == 2);
    }
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar, rustc_private)]
#![feature(const_fn)]

extern crate syntax;
extern crate rustc_plugin;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;
extern crate owning_ref;

use rustc_plugin::registry::Registry;
use syntax::ext::base::{SyntaxExtension, ExtCtxt, MacResult, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::codemap::{Span, Spanned};
use syntax::ast;
use syntax::util::small_vector::SmallVector;
use syntax::parse::parser::Parser;
use syntax::parse::PResult;
use syntax::parse::token::{self, intern, str_to_ident};
use syntax::tokenstream::TokenTree;
use syntax::ptr::P;

use std::sync::{RwLock, RwLockReadGuard, Mutex, MutexGuard};
use std::collections::HashMap;

use owning_ref::{OwningRef, RwLockReadGuardRef};

pub mod arch;
mod directive;
mod serialize;

/// Welcome to the documentation of the dynasm plugin. This mostly exists to ease
/// development and to show a glimpse of what is under the hood of dynasm. Please
/// be aware that nothing in here should be counted on to be stable, the only
/// guarantees are in the syntax the `dynasm!` macro parses and in the code it
/// generates.

#[plugin_registrar]
pub fn registrar(reg: &mut Registry) {
    reg.register_syntax_extension(
        intern("dynasm"),
        SyntaxExtension::NormalTT(
            Box::new(dynasm),
            None,
            false
        )
    );
}

/// dynasm! macro expansion result type
struct DynAsm<'cx, 'a: 'cx> {
    ecx: &'cx ExtCtxt<'a>,
    stmts: Vec<ast::Stmt>
}

impl<'cx, 'a> MacResult for DynAsm<'cx, 'a> {
    fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
        Some(self.ecx.expr_block(self.ecx.block(self.ecx.call_site(), self.stmts)))
    }

    fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
        Some(SmallVector::many(self.stmts))
    }

    fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
        if self.stmts.is_empty() {
            Some(SmallVector::zero())
        } else {
            None
        }
    }
}

/// The guts of the dynasm! macro start here.
fn dynasm<'cx>(ecx: &'cx mut ExtCtxt, span: Span, token_tree: &[TokenTree])
-> Box<MacResult + 'cx> {
    // expand all macros in our token tree first. This enables the use of rust macros
    // within dynasm (whenever this actually gets implemented within rustc)
    let token_tree = ecx.expander().fold_tts(token_tree);

    let mut parser = ecx.new_parser_from_tts(&token_tree);

    // due to the structure of directives / assembly, we have to evaluate while parsing as
    // things like aliases, arch choices, affect the way in which parsing works.

    match compile(ecx, &mut parser) {
        Ok(stmts) => Box::new(DynAsm {
            ecx: ecx,
            stmts: stmts
        }),
        Err(mut e) => {
            e.emit();
            DummyResult::any(span)
        }
    }
}

/// This struct contains all non-parsing state that dynasm! requires while parsing and compiling
pub struct State<'a> {
    pub stmts: Vec<serialize::Stmt>,
    pub target: P<ast::Expr>,
    pub crate_data: MutexGuard<'a, DynasmData>
}

/// top-level parsing. Handles common prefix symbols and diverts to the selected architecture
/// when an assembly instruction is encountered. When parsing fails an Err() is returned, when
/// non-parsing errors happen a local error message is generated but the function returns Ok().
fn compile<'a>(ecx: &mut ExtCtxt, parser: &mut Parser<'a>) -> PResult<'a, Vec<ast::Stmt>> {
    let target = parser.parse_expr()?;

    let crate_data = crate_local_data(ecx);

    let mut state = State {
        stmts: Vec::new(),
        target: target,
        crate_data: crate_data.lock().unwrap()
    };

    while !parser.check(&token::Eof) {
        parser.expect(&token::Semi)?;

        // ;; stmt
        if parser.eat(&token::Semi) {
            if let Some(stmt) = parser.parse_stmt()? {
                state.stmts.push(serialize::Stmt::Stmt(stmt));
            }
            continue;
        }

        // ; . directive
        if parser.eat(&token::Dot) {
            state.evaluate_directive(ecx, parser)?;
            continue;
        }

        // ; -> label :
        if parser.eat(&token::RArrow) {
            let span = parser.span;
            let name = parser.parse_ident()?;
            parser.expect(&token::Colon)?;
            state.stmts.push(serialize::Stmt::GlobalLabel(Spanned {span: span, node: name} ));
            continue;
        }

        // ; => expr
        if parser.eat(&token::FatArrow) {
            let expr = parser.parse_expr()?;
            state.stmts.push(serialize::Stmt::DynamicLabel(expr));
            continue;
        }

        // ; label :
        if parser.token.is_ident() && parser.look_ahead(1, |t| t == &token::Colon) {
            let span = parser.span;
            let name = parser.parse_ident()?;
            parser.expect(&token::Colon)?;
            state.stmts.push(serialize::Stmt::LocalLabel(Spanned {span: span, node: name} ));
            continue;
        }

        // anything else is an assembly instruction which should be in current_arch
        state.compile_instruction(ecx, parser)?;
    }

    Ok(serialize::serialize(ecx, state.target, state.stmts))
}

// Crate local data implementation.

type DynasmStorage = HashMap<ast::Ident, Mutex<DynasmData>>;

pub struct DynasmData {
    pub current_arch: arch::Arch,
    pub aliases: HashMap<ast::Name, ast::Name>
}

impl DynasmData {
    fn new() -> DynasmData {
        DynasmData {
            current_arch: arch::CURRENT_ARCH,
            aliases: HashMap::new()
        }
    }
}

pub type CrateLocalData = OwningRef<
    RwLockReadGuard<'static, DynasmStorage>,
    Mutex<DynasmData>
>;

pub fn crate_local_data(ecx: &ExtCtxt) -> CrateLocalData {
    let id = str_to_ident(&ecx.ecfg.crate_name);

    {
        let data = RwLockReadGuardRef::new(DYNASM_STORAGE.read().unwrap());

        if data.get(&id).is_some() {
            return data.map(|x| x.get(&id).unwrap())
        }
    }

    {
        let mut lock = DYNASM_STORAGE.write().unwrap();
        lock.insert(id, Mutex::new(DynasmData::new()));
    }
    RwLockReadGuardRef::new(DYNASM_STORAGE.read().unwrap())
                       .map(|x| x.get(&id).unwrap())
}

// this is where the actual storage resides.

lazy_static! {
    static ref DYNASM_STORAGE: RwLock<DynasmStorage> = RwLock::new(HashMap::new());
}
<commit_msg>SmallVector::zero has been removed, it has been replaced by SmallVector::new<commit_after>#![feature(plugin_registrar, rustc_private)]
#![feature(const_fn)]

extern crate syntax;
extern crate rustc_plugin;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;
extern crate owning_ref;

use rustc_plugin::registry::Registry;
use syntax::ext::base::{SyntaxExtension, ExtCtxt, MacResult, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::codemap::{Span, Spanned};
use syntax::ast;
use syntax::util::small_vector::SmallVector;
use syntax::parse::parser::Parser;
use syntax::parse::PResult;
use syntax::parse::token::{self, intern, str_to_ident};
use syntax::tokenstream::TokenTree;
use syntax::ptr::P;

use std::sync::{RwLock, RwLockReadGuard, Mutex, MutexGuard};
use std::collections::HashMap;

use owning_ref::{OwningRef, RwLockReadGuardRef};

pub mod arch;
mod directive;
mod serialize;

/// Welcome to the documentation of the dynasm plugin. This mostly exists to ease
/// development and to show a glimpse of what is under the hood of dynasm. Please
/// be aware that nothing in here should be counted on to be stable, the only
/// guarantees are in the syntax the `dynasm!` macro parses and in the code it
/// generates.

#[plugin_registrar]
pub fn registrar(reg: &mut Registry) {
    reg.register_syntax_extension(
        intern("dynasm"),
        SyntaxExtension::NormalTT(
            Box::new(dynasm),
            None,
            false
        )
    );
}

/// dynasm! macro expansion result type
struct DynAsm<'cx, 'a: 'cx> {
    ecx: &'cx ExtCtxt<'a>,
    stmts: Vec<ast::Stmt>
}

impl<'cx, 'a> MacResult for DynAsm<'cx, 'a> {
    fn make_expr(self: Box<Self>) -> Option<P<ast::Expr>> {
        Some(self.ecx.expr_block(self.ecx.block(self.ecx.call_site(), self.stmts)))
    }

    fn make_stmts(self: Box<Self>) -> Option<SmallVector<ast::Stmt>> {
        Some(SmallVector::many(self.stmts))
    }

    fn make_items(self: Box<Self>) -> Option<SmallVector<P<ast::Item>>> {
        if self.stmts.is_empty() {
            Some(SmallVector::new())
        } else {
            None
        }
    }
}

/// The guts of the dynasm! macro start here.
fn dynasm<'cx>(ecx: &'cx mut ExtCtxt, span: Span, token_tree: &[TokenTree])
-> Box<MacResult + 'cx> {
    // expand all macros in our token tree first. This enables the use of rust macros
    // within dynasm (whenever this actually gets implemented within rustc)
    let token_tree = ecx.expander().fold_tts(token_tree);

    let mut parser = ecx.new_parser_from_tts(&token_tree);

    // due to the structure of directives / assembly, we have to evaluate while parsing as
    // things like aliases, arch choices, affect the way in which parsing works.

    match compile(ecx, &mut parser) {
        Ok(stmts) => Box::new(DynAsm {
            ecx: ecx,
            stmts: stmts
        }),
        Err(mut e) => {
            e.emit();
            DummyResult::any(span)
        }
    }
}

/// This struct contains all non-parsing state that dynasm! requires while parsing and compiling
pub struct State<'a> {
    pub stmts: Vec<serialize::Stmt>,
    pub target: P<ast::Expr>,
    pub crate_data: MutexGuard<'a, DynasmData>
}

/// top-level parsing. Handles common prefix symbols and diverts to the selected architecture
/// when an assembly instruction is encountered. When parsing fails an Err() is returned, when
/// non-parsing errors happen a local error message is generated but the function returns Ok().
fn compile<'a>(ecx: &mut ExtCtxt, parser: &mut Parser<'a>) -> PResult<'a, Vec<ast::Stmt>> {
    let target = parser.parse_expr()?;

    let crate_data = crate_local_data(ecx);

    let mut state = State {
        stmts: Vec::new(),
        target: target,
        crate_data: crate_data.lock().unwrap()
    };

    while !parser.check(&token::Eof) {
        parser.expect(&token::Semi)?;

        // ;; stmt
        if parser.eat(&token::Semi) {
            if let Some(stmt) = parser.parse_stmt()? {
                state.stmts.push(serialize::Stmt::Stmt(stmt));
            }
            continue;
        }

        // ; . directive
        if parser.eat(&token::Dot) {
            state.evaluate_directive(ecx, parser)?;
            continue;
        }

        // ; -> label :
        if parser.eat(&token::RArrow) {
            let span = parser.span;
            let name = parser.parse_ident()?;
            parser.expect(&token::Colon)?;
            state.stmts.push(serialize::Stmt::GlobalLabel(Spanned {span: span, node: name} ));
            continue;
        }

        // ; => expr
        if parser.eat(&token::FatArrow) {
            let expr = parser.parse_expr()?;
            state.stmts.push(serialize::Stmt::DynamicLabel(expr));
            continue;
        }

        // ; label :
        if parser.token.is_ident() && parser.look_ahead(1, |t| t == &token::Colon) {
            let span = parser.span;
            let name = parser.parse_ident()?;
            parser.expect(&token::Colon)?;
            state.stmts.push(serialize::Stmt::LocalLabel(Spanned {span: span, node: name} ));
            continue;
        }

        // anything else is an assembly instruction which should be in current_arch
        state.compile_instruction(ecx, parser)?;
    }

    Ok(serialize::serialize(ecx, state.target, state.stmts))
}

// Crate local data implementation.

type DynasmStorage = HashMap<ast::Ident, Mutex<DynasmData>>;

pub struct DynasmData {
    pub current_arch: arch::Arch,
    pub aliases: HashMap<ast::Name, ast::Name>
}

impl DynasmData {
    fn new() -> DynasmData {
        DynasmData {
            current_arch: arch::CURRENT_ARCH,
            aliases: HashMap::new()
        }
    }
}

pub type CrateLocalData = OwningRef<
    RwLockReadGuard<'static, DynasmStorage>,
    Mutex<DynasmData>
>;

pub fn crate_local_data(ecx: &ExtCtxt) -> CrateLocalData {
    let id = str_to_ident(&ecx.ecfg.crate_name);

    {
        let data = RwLockReadGuardRef::new(DYNASM_STORAGE.read().unwrap());

        if data.get(&id).is_some() {
            return data.map(|x| x.get(&id).unwrap())
        }
    }

    {
        let mut lock = DYNASM_STORAGE.write().unwrap();
        lock.insert(id, Mutex::new(DynasmData::new()));
    }
    RwLockReadGuardRef::new(DYNASM_STORAGE.read().unwrap())
                       .map(|x| x.get(&id).unwrap())
}

// this is where the actual storage resides.

lazy_static! {
    static ref DYNASM_STORAGE: RwLock<DynasmStorage> = RwLock::new(HashMap::new());
}
<|endoftext|>


<commit_before>extern crate abstract_ns;
extern crate futures;
extern crate getopts;
extern crate ns_dns_tokio;
extern crate rand;
extern crate tokio_core;
extern crate tokio_io;
extern crate net2;
//extern crate tcp;

use self::futures::{Future, Stream, IntoFuture};
use self::futures::sync::oneshot;
use self::futures::sync::oneshot::{Sender, Receiver};
use self::tokio_core::net::{TcpListener};
use self::tokio_core::reactor::{Core, Timeout};

use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream};
use std::sync::{Arc, Barrier};
use std::thread;
use self::futures::Canceled;

use std::io::Error;
use std::io::ErrorKind;
use std::time::Duration;

pub struct StoppableCore {
    core: Core,
    // TOCONSIDER use a lock instead of a barrier?
    barrier: Arc<Barrier>,
    signal: Receiver<i64>,
}

/// Spans a shutdown thread and let it run into a barrier.
/// When the barrier is released, this thread will signal 1 on the Sender channel provided.
fn install_trigger_thread(oneshot_sender_stream: Sender<i64>) -> Arc<Barrier> {
    // barrier awaits the releaser thread and the signalling one
    let barrier = Arc::new(Barrier::new(2));
    let copy_for_thread = barrier.clone();
    // the releaser thread
    let builder = thread::Builder::new()
        .name("barrier to signal thread".into());
    builder.spawn(move || {
        debug!("waiting for end");
        copy_for_thread.wait();
        debug!("signalling end");
        // release the oneshot future blockig core.run()
        oneshot_sender_stream.send(1).unwrap();
    }).unwrap();
    barrier
}

impl StoppableCore {

    pub fn new() -> Result<StoppableCore, Error> {
        // this is the main event loop, powered by tokio core
        let core = Core::new()?;

        let (tx, rx) = oneshot::channel::<i64>();
        let barrier = install_trigger_thread(tx);

        Ok(StoppableCore {
            core: core,
            barrier: barrier,
            signal: rx,
        })
    }

    pub fn stop(& self) {
        self.barrier.wait();
    }

    pub fn run(mut self) -> Result<i64, Canceled> {
        self.core.run(self.signal)
    }

    ///
    /// Run the main event pump with a defined timeout
    /// ``` timeout = Duration::from_secs(timeout) ```
    ///
    pub fn run_timeout(mut self, timeout : Duration) -> Result<i64, Canceled> {

        let fut = Timeout::new(timeout, &self.core.handle()).into_future();
        let timeout = fut.flatten();

        let barrier = self.barrier.clone();
        let timeout_expired = timeout.and_then(move |_|-> Result<(), Error> {
            warn!("timeout expired");
            barrier.wait();
            Ok(())
        });

        self.core.handle().spawn(timeout_expired.into_future().map_err(|_|()));

        self.core.run(self.signal)
    }
}
<commit_msg>improve documentation<commit_after>extern crate abstract_ns;
extern crate futures;
extern crate getopts;
extern crate ns_dns_tokio;
extern crate rand;
extern crate tokio_core;
extern crate tokio_io;
extern crate net2;
//extern crate tcp;

use self::futures::{Future, Stream, IntoFuture};
use self::futures::sync::oneshot;
use self::futures::sync::oneshot::{Sender, Receiver};
use self::tokio_core::net::{TcpListener};
use self::tokio_core::reactor::{Core, Timeout};

use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream};
use std::sync::{Arc, Barrier};
use std::thread;
use self::futures::Canceled;

use std::io::Error;
use std::io::ErrorKind;
use std::time::Duration;

pub struct StoppableCore {
    core: Core,
    // TOCONSIDER use a lock instead of a barrier?
    barrier: Arc<Barrier>,
    signal: Receiver<i64>,
}

/// Spans a shutdown thread and let it run into a barrier.
/// When the barrier is released, this thread will signal 1 on the Sender channel provided.
/// Shutdown is as complicated, since the oneshot::sender is not clonable / threadsafe ...
fn install_trigger_thread(oneshot_sender_stream: Sender<i64>) -> Arc<Barrier> {
    // barrier awaits the releaser thread and the signalling one
    let barrier = Arc::new(Barrier::new(2));
    let copy_for_thread = barrier.clone();
    // the releaser thread
    let builder = thread::Builder::new()
        .name("barrier to signal thread".into());
    builder.spawn(move || {
        debug!("waiting for end");
        copy_for_thread.wait();
        debug!("signalling end");
        // release the oneshot future blockig core.run()
        oneshot_sender_stream.send(1).unwrap();
    }).unwrap();
    barrier
}

impl StoppableCore {

    pub fn new() -> Result<StoppableCore, Error> {
        // this is the main event loop, powered by tokio core
        let core = Core::new()?;

        let (tx, rx) = oneshot::channel::<i64>();
        let barrier = install_trigger_thread(tx);

        Ok(StoppableCore {
            core: core,
            barrier: barrier,
            signal: rx,
        })
    }

    pub fn stop(& self) {
        self.barrier.wait();
    }

    pub fn run(mut self) -> Result<i64, Canceled> {
        self.core.run(self.signal)
    }

    ///
    /// Run the main event pump with a defined timeout
    /// ``` timeout = Duration::from_secs(timeout) ```
    ///
    pub fn run_timeout(mut self, timeout : Duration) -> Result<i64, Canceled> {

        let fut = Timeout::new(timeout, &self.core.handle()).into_future();
        let timeout = fut.flatten();

        let barrier = self.barrier.clone();
        let timeout_expired = timeout.and_then(move |_|-> Result<(), Error> {
            warn!("timeout expired");
            barrier.wait();
            Ok(())
        });

        self.core.handle().spawn(timeout_expired.into_future().map_err(|_|()));

        self.core.run(self.signal)
    }
}
<|endoftext|>


<commit_before>//! This module provides an oct-tree of cubes, which are the basic building
//! blocks of Bismuth. A cube provides the following basic components:
//!
//!   1. Node data, which varies between branches and leaves.
//!   2. Node links, which refer to other nodes in the oct-tree.
//!   3. A spatial partition. This is calculated during traversals.
//!
//! Cubes bind this information together and act as a "recursive tree", where
//! any cube can be used to traverse its sub-tree of cubes.
//!
//! Leaf cubes provide geometric data that represents the shape and layout of
//! the game world.

mod geometry;
mod space;
mod tree;

use self::tree::{Cube, OrphanCube};

pub use self::geometry::{Edge, Geometry, Offset};
pub use self::space::{AABB, Axis, Direction, LogWidth, Orientation, Partition, Spatial};
pub use self::tree::{BranchNode, BranchPayload, LeafNode, LeafPayload, Node, OrphanNode, Root};

pub type CubeRef<'a> = Cube<'a, &'a Node>;
pub type CubeMut<'a> = Cube<'a, &'a mut Node>;
pub type OrphanCubeRef<'a> = OrphanCube<'a, &'a LeafPayload, &'a BranchPayload>;
pub type OrphanCubeMut<'a> = OrphanCube<'a, &'a mut LeafPayload, &'a mut BranchPayload>;

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>More documentation for the `cube` module.<commit_after>//! This module provides an oct-tree of `Cube`s, which are the basic building
//! blocks of **Bismuth**. The tree is internally comprised of `Node`s.
//! `BranchNode`s contain links to sub-trees and `LeafNode`s contain geometric
//! data associated with their respective spatial partition. However, `Node`s do
//! not contain any spatial data (origin, partition, etc.); instead, this is
//! calculated during traversals by `Cube`, which acts as a recursive view over
//! the `Node`s in the tree and provides the primary interface for interacting
//! with trees.
//!
//! Leaf `Cube`s provide the geometric and spatial data that together represent
//! the shape and layout of the game world.
//!
//! `Cube`s reference `Node`s in the tree, and abstract over the mutability of
//! those references. This module exposes the `CubeRef` and `CubeMut` type
//! definitions for immutable and mutable `Cube`s, respectively.
//!
//! Because `Cube`s reference `Node`s and `Node`s may reference other `Node`s
//! in a tree, orphan types are provided that only expose payloads and no links.
//! This is useful when collecting `Cube`s, because otherwise the references
//! into the rest of the tree would lead to aliasing. `OrphanCubeRef` and
//! `OrphanCubeMut` are the orphan analogues of `CubeRef` and `CubeMut`,
//! respectively. Orphans of course do not support indexing or traversal.
//!
//! `Root` can be used to create a new tree, and owns the root `Node`. `Root`s
//! expose `Cube`s to manipulate the tree.
//!
//! # Examples
//!
//! Subdividing and iterating over the cubes in a tree:
//!
//! ```
//! let mut root = Root::new(LogWidth::max_value());
//! let _ = root.to_cube_mut().subdivide();
//! for cube in root.to_cube().iter() {
//!     println!("origin: {}; width: {}", cube.partition().origin(), cube.partition().width());
//! }
//! ```

mod geometry;
mod space;
mod tree;

use self::tree::{Cube, OrphanCube};

pub use self::geometry::{Edge, Geometry, Offset};
pub use self::space::{AABB, Axis, Direction, LogWidth, Orientation, Partition, Spatial};
pub use self::tree::{BranchNode, BranchPayload, LeafNode, LeafPayload, Node, OrphanNode, Root};

pub type CubeRef<'a> = Cube<'a, &'a Node>;
pub type CubeMut<'a> = Cube<'a, &'a mut Node>;
pub type OrphanCubeRef<'a> = OrphanCube<'a, &'a LeafPayload, &'a BranchPayload>;
pub type OrphanCubeMut<'a> = OrphanCube<'a, &'a mut LeafPayload, &'a mut BranchPayload>;

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>


<commit_before>use cpu::common_defs::OpcodeExecInfo;

#[derive(Default)]
pub struct DecodeRegister {
    addr_init: u16,
    addr_intermediate: u16,
    addr_final: u16,

    value_init: u8,
    value_intermediate: u8,
    value_final: u8,

    info: OpcodeExecInfo,
}

#[allow(non_snake_case)]
#[derive(Default)]
pub struct CpuState {
    pc: u16,
    sp: u8,
    a:  u8,
    x:  u8,
    y:  u8,

    // flags
    C: bool, // carry
    Z: bool, // zero
    I: bool, // interrupt
    D: bool, // decimal
    B: bool, // break
             // bit 5 is not used by the nes and is always 1
    V: bool, // overflow
    S: bool, // sign/negative

    // these are not strictly 6502 registers, but are useful for modeling the cpu
    instruction_register: u16,
    decode_register:DecodeRegister,
}

impl CpuState {
    fn unpack_flags(self: &CpuState) -> u8 {
        ( (self.C as u8) << 0)
      | ( (self.Z as u8) << 1)
      | ( (self.I as u8) << 2)
      | ( (self.D as u8) << 3)
      | ( (self.B as u8) << 4)
      | ( (1           ) << 5) // flag 5 is unused
      | ( (self.V as u8) << 6)
      | ( (self.S as u8) << 7)
    }
    fn pack_flags(self: &mut CpuState,flags:u8) {
        self.C        = ( (flags >> 0) & 1) == 1;
        self.Z        = ( (flags >> 1) & 1) == 1;
        self.I        = ( (flags >> 2) & 1) == 1;
        self.D        = ( (flags >> 3) & 1) == 1;
        self.B        = ( (flags >> 4) & 1) == 1;
        // flags 5 is unused
        self.V        = ( (flags >> 6) & 1) == 1;
        self.S        = ( (flags >> 7) & 1) == 1;
    }
}
<commit_msg>fixed cpu_state fields all being private<commit_after>use cpu::common_defs::OpcodeExecInfo;

#[derive(Default)]
pub struct DecodeRegister {
    addr_init: u16,
    addr_intermediate: u16,
    addr_final: u16,

    value_init: u8,
    value_intermediate: u8,
    value_final: u8,

    info: OpcodeExecInfo,
}

#[allow(non_snake_case)]
#[derive(Default)]
pub struct CpuState {
    pub pc: u16,
    pub sp: u8,
    pub a:  u8,
    pub x:  u8,
    pub y:  u8,

    // flags
    pub C: bool, // carry
    pub Z: bool, // zero
    pub I: bool, // interrupt
    pub D: bool, // decimal
    pub B: bool, // break
             // bit 5 is not used by the nes and is always 1
    pub V: bool, // overflow
    pub S: bool, // sign/negative

    // these are not strictly 6502 registers, but are useful for modeling the cpu
    pub instruction_register: u16,
    pub decode_register:DecodeRegister,
}

impl CpuState {
    pub fn unpack_flags(self: &CpuState) -> u8 {
        ( (self.C as u8) << 0)
      | ( (self.Z as u8) << 1)
      | ( (self.I as u8) << 2)
      | ( (self.D as u8) << 3)
      | ( (self.B as u8) << 4)
      | ( (1           ) << 5) // flag 5 is unused
      | ( (self.V as u8) << 6)
      | ( (self.S as u8) << 7)
    }
    pub fn pack_flags(self: &mut CpuState,flags:u8) {
        self.C        = ( (flags >> 0) & 1) == 1;
        self.Z        = ( (flags >> 1) & 1) == 1;
        self.I        = ( (flags >> 2) & 1) == 1;
        self.D        = ( (flags >> 3) & 1) == 1;
        self.B        = ( (flags >> 4) & 1) == 1;
        // flags 5 is unused
        self.V        = ( (flags >> 6) & 1) == 1;
        self.S        = ( (flags >> 7) & 1) == 1;
    }
}
<|endoftext|>


<commit_before>// 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.

use super::commandinterpreter::SBCommandInterpreter;
use super::error::SBError;
use super::listener::SBListener;
use super::platform::SBPlatform;
use super::stream::SBStream;
use super::structureddata::SBStructuredData;
use super::target::SBTarget;
use std::ffi::{CStr, CString};
use std::fmt;
use std::iter;
use std::ptr;
use sys;

/// Creates [`SBTarget`]s, provides access to them and manages
/// the overall debugging experience.
///
/// # Initialization and Teardown
///
/// LLDB must be initialized before the functionality is used. This
/// is done with `SBDebugger::initialize()`:
///
/// ```
/// use lldb::SBDebugger;
///
/// SBDebugger::initialize();
/// ```
///
/// Similarly, it must be terminated after you are done using it:
///
/// ```
/// use lldb::SBDebugger;
///
/// SBDebugger::initialize();
/// // Use LLDB functionality ...
/// SBDebugger::terminate();
/// ```
///
/// Once you've initialized LLDB, you're ready to create an instance
/// of `SBDebugger`:
///
/// ```
/// use lldb::SBDebugger;
///
/// SBDebugger::initialize();
///
/// let debugger = SBDebugger::create(false);
/// // ... configure the debugger if needed ...
/// // ... create a target and do stuff ...
///
/// SBDebugger::terminate();
/// ```
///
/// # Configuration
///
/// ## Async Mode
///
/// While it is best to use LLDB in asynchronous mode, it does offer a
/// synchronous mode, which can be easier to use for quick experiments
/// or scripts.
///
/// In synchronous mode, calls to the LLDB API do not return until the
/// underlying action has been completed. This means that the thread
/// from which you call LLDB will be blocked during that time, so this
/// is not an ideal way to use LLDB for building interactive tools
/// or a new user interface.
///
/// In asynchronous mode, calls to the LLDB API will return immediately
/// without waiting for the action to complete. This means that actions
/// like launching a target, continuing the execution of a process and
/// so on won't be completed immediately and you must process events
/// to see what the results of an action are.
///
/// Synchronous mode can be enabled by using [`set_async`] and passing it
/// a `false` value. You can see if you're in asynchronous mode or not
/// by calling [`async`].
///
/// # Target Management
///
/// The `SBDebugger` instance tracks the various targets that are
/// currently known to the debugger.
///
/// Typically, you create a target with [`create_target`],
/// [`create_target_simple`] or one of the related methods.
///
/// Sometimes, you'll want to create a target without an associated
/// executable. A common use case for this is to attach to a process
/// by name or process ID where you don't know the executable in advance.
/// The most convenient way to do this is:
///
/// ```
/// # use lldb::SBDebugger;
/// # SBDebugger::initialize();
/// let debugger = SBDebugger::create(false);
/// if let Some(target) = debugger.create_target_simple("") {
///     println!("Got a target: {:?}", target);
///     // Now, maybe we'd like to attach to something.
/// }
/// # SBDebugger::terminate();
/// ```
///
/// You can iterate over these targets which have been created by
/// using [`targets`]:
///
/// ```no_run
/// # use lldb::{SBDebugger, SBTarget};
/// # fn look_at_targets(debugger: SBDebugger) {
/// // Iterate over the targets...
/// for target in debugger.targets() {
///     println!("Hello {:?}!", target);
/// }
/// // Or collect them into a vector!
/// let targets = debugger.targets().collect::<Vec<SBTarget>>();
/// # }
/// ```
///
/// # Platform Management
///
/// ...
///
/// [`SBTarget`]: struct.SBTarget.html
/// [`set_async`]: #method.set_async
/// [`async`]: #method.async
/// [`create_target`]: #method.create_target
/// [`create_target_simple`]: #method.create_target_simple
/// [`targets`]: #method.targets
pub struct SBDebugger {
    /// The underlying raw `SBDebuggerRef`.
    pub raw: sys::SBDebuggerRef,
}

impl SBDebugger {
    /// Initialize LLDB.
    ///
    /// This should be called before LLDB functionality is used.
    pub fn initialize() {
        unsafe { sys::SBDebuggerInitialize() };
    }

    /// Tear down LLDB.
    ///
    /// This should be called once the application no longer needs
    /// to use LLDB functionality. Typically, this is called as the
    /// application exits.
    pub fn terminate() {
        unsafe { sys::SBDebuggerTerminate() };
    }

    /// Create a new instance of `SBDebugger`.
    ///
    /// If `source_init_files` is `true`, then `~/.lldbinit` will
    /// be processed.
    pub fn create(source_init_files: bool) -> SBDebugger {
        SBDebugger {
            raw: unsafe { sys::SBDebuggerCreate2(source_init_files) },
        }
    }

    /// Get whether or not the debugger is in async mode.
    ///
    /// When in async mode, the debugger returns immediately when
    /// stepping or continuing without waiting for the process
    /// to change state.
    pub fn async(&self) -> bool {
        unsafe { sys::SBDebuggerGetAsync(self.raw) }
    }

    /// Set the debugger to be in async mode or not.
    ///
    /// When in async mode, the debugger returns immediately when
    /// stepping or continuing without waiting for the process
    /// to change state.
    pub fn set_async(&self, async: bool) {
        unsafe { sys::SBDebuggerSetAsync(self.raw, async) }
    }

    #[allow(missing_docs)]
    pub fn command_interpreter(&self) -> SBCommandInterpreter {
        SBCommandInterpreter::wrap(unsafe { sys::SBDebuggerGetCommandInterpreter(self.raw) })
    }

    /// Enable logging (defaults to `stderr`).
    ///
    /// `enable_log("lldb", &["default"])` is useful for troubleshooting in most
    /// cases. Include `"all"` in `categories` for extra verbosity.
    ///
    /// See invocations to `lldb_private::Log::Register` for more channels and
    /// categories.
    pub fn enable_log(&self, channel: &str, categories: &[&str]) -> bool {
        let channel = CString::new(channel).unwrap();
        let categories: Vec<_> = categories
            .iter()
            .map(|&s| CString::new(s).unwrap())
            .collect();
        let mut categories_ptr: Vec<_> = categories
            .iter()
            .map(|s| s.as_ptr())
            .chain(iter::once(ptr::null()))
            .collect();
        let ret = unsafe {
            sys::SBDebuggerEnableLog(self.raw, channel.as_ptr(), categories_ptr.as_mut_ptr())
        };
        ret
    }

    /// Get the LLDB version string.
    pub fn version() -> String {
        unsafe {
            match CStr::from_ptr(sys::SBDebuggerGetVersionString()).to_str() {
                Ok(s) => s.to_owned(),
                _ => panic!("No version string?"),
            }
        }
    }

    /// Create a target.
    ///
    /// The executable name may be an empty string to create
    /// an empty target.
    pub fn create_target(
        &self,
        executable: &str,
        target_triple: Option<&str>,
        platform_name: Option<&str>,
        add_dependent_modules: bool,
    ) -> Result<SBTarget, SBError> {
        let executable = CString::new(executable).unwrap();
        let target_triple = target_triple.map(|s| CString::new(s).unwrap());
        let platform_name = platform_name.map(|s| CString::new(s).unwrap());
        let error = SBError::new();
        let target = unsafe {
            sys::SBDebuggerCreateTarget(
                self.raw,
                executable.as_ptr(),
                target_triple.map_or(ptr::null(), |s| s.as_ptr()),
                platform_name.map_or(ptr::null(), |s| s.as_ptr()),
                add_dependent_modules,
                error.raw,
            )
        };
        if error.is_success() {
            Ok(SBTarget::wrap(target))
        } else {
            Err(error)
        }
    }

    /// Create a target from just an executable name.
    ///
    /// The executable name may be an empty string to create
    /// an empty target.
    ///
    /// Using [`create_target`] is preferred in most cases as
    /// that provides access to an `SBError` to inform the caller
    /// about what might have gone wrong.
    ///
    /// [`create_target`]: struct.SBDebugger.html#method.create_target
    pub fn create_target_simple(&self, executable: &str) -> Option<SBTarget> {
        let executable = CString::new(executable).unwrap();
        SBTarget::maybe_wrap(unsafe { sys::SBDebuggerCreateTarget2(self.raw, executable.as_ptr()) })
    }

    /// Get an iterator over the [targets] known to this debugger instance.
    ///
    /// [targets]: struct.SBTarget.html
    pub fn targets(&self) -> SBDebuggerTargetIter {
        SBDebuggerTargetIter {
            debugger: self,
            idx: 0,
        }
    }

    /// Get the default [SBListener] associated with the debugger.
    ///
    /// [SBListener]: struct.SBListener.html
    pub fn listener(&self) -> SBListener {
        SBListener::wrap(unsafe { sys::SBDebuggerGetListener(self.raw) })
    }

    /// Get the currently selected [`SBTarget`].
    ///
    /// [SBTarget]: struct.SBTarget.html
    pub fn selected_target(&self) -> Option<SBTarget> {
        SBTarget::maybe_wrap(unsafe { sys::SBDebuggerGetSelectedTarget(self.raw) })
    }

    /// Set the selected [`SBTarget`].
    ///
    /// [SBTarget]: struct.SBTarget.html
    pub fn set_selected_target(&self, target: &SBTarget) {
        unsafe { sys::SBDebuggerSetSelectedTarget(self.raw, target.raw) };
    }

    /// Get the currently selected [`SBPlatform`].
    ///
    /// [`SBPlatform`]: struct.SBPlatform.html
    pub fn selected_platform(&self) -> SBPlatform {
        unsafe {
            SBPlatform {
                raw: sys::SBDebuggerGetSelectedPlatform(self.raw),
            }
        }
    }

    /// Set the selected [`SBPlatform`].
    ///
    /// [`SBPlatform`]: struct.SBPlatform.html
    pub fn set_selected_platform(&self, platform: &SBPlatform) {
        unsafe { sys::SBDebuggerSetSelectedPlatform(self.raw, platform.raw) };
    }

    /// Get an iterator over the [platforms] known to this debugger instance.
    ///
    /// [platforms]: struct.SBPlatform.html
    pub fn platforms(&self) -> SBDebuggerPlatformIter {
        SBDebuggerPlatformIter {
            debugger: self,
            idx: 0,
        }
    }

    /// Get an iterator over the available platforms known to this debugger instance.
    pub fn available_platforms(&self) -> SBDebuggerAvailablePlatformIter {
        SBDebuggerAvailablePlatformIter {
            debugger: self,
            idx: 0,
        }
    }
}

/// Iterate over the [targets] known to a [debugger].
///
/// [targets]: struct.SBTarget.html
/// [debugger]: struct.SBDebugger.html
pub struct SBDebuggerTargetIter<'d> {
    debugger: &'d SBDebugger,
    idx: usize,
}

impl<'d> Iterator for SBDebuggerTargetIter<'d> {
    type Item = SBTarget;

    fn next(&mut self) -> Option<SBTarget> {
        if self.idx < unsafe { sys::SBDebuggerGetNumTargets(self.debugger.raw) as usize } {
            let r = Some(SBTarget {
                raw: unsafe { sys::SBDebuggerGetTargetAtIndex(self.debugger.raw, self.idx as u32) },
            });
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBDebuggerGetNumTargets(self.debugger.raw) } as usize;
        (sz - self.idx, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBDebuggerTargetIter<'d> {}

impl Clone for SBDebugger {
    fn clone(&self) -> SBDebugger {
        SBDebugger {
            raw: unsafe { sys::CloneSBDebugger(self.raw) },
        }
    }
}

impl fmt::Debug for SBDebugger {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBDebuggerGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBDebugger {{ {} }}", stream.data())
    }
}

impl Drop for SBDebugger {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBDebugger(self.raw) };
    }
}

unsafe impl Send for SBDebugger {}
unsafe impl Sync for SBDebugger {}

/// Iterate over the [platforms].
///
/// [platforms]: struct.SBPlatform.html
pub struct SBDebuggerPlatformIter<'d> {
    debugger: &'d SBDebugger,
    idx: u32,
}

impl<'d> Iterator for SBDebuggerPlatformIter<'d> {
    type Item = SBPlatform;

    fn next(&mut self) -> Option<SBPlatform> {
        if self.idx < unsafe { sys::SBDebuggerGetNumPlatforms(self.debugger.raw) } {
            let r = Some(SBPlatform::wrap(unsafe {
                sys::SBDebuggerGetPlatformAtIndex(self.debugger.raw, self.idx)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBDebuggerGetNumPlatforms(self.debugger.raw) } as usize;
        (sz - self.idx as usize, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBDebuggerPlatformIter<'d> {}

/// Iterate over the available platforms.
pub struct SBDebuggerAvailablePlatformIter<'d> {
    debugger: &'d SBDebugger,
    idx: u32,
}

impl<'d> Iterator for SBDebuggerAvailablePlatformIter<'d> {
    type Item = SBStructuredData;

    fn next(&mut self) -> Option<SBStructuredData> {
        if self.idx < unsafe { sys::SBDebuggerGetNumAvailablePlatforms(self.debugger.raw) } {
            let r = Some(SBStructuredData::wrap(unsafe {
                sys::SBDebuggerGetAvailablePlatformInfoAtIndex(self.debugger.raw, self.idx)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBDebuggerGetNumAvailablePlatforms(self.debugger.raw) } as usize;
        (sz - self.idx as usize, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBDebuggerAvailablePlatformIter<'d> {}

#[cfg(feature = "graphql")]
impl ::juniper::Context for SBDebugger {}

#[cfg(feature = "graphql")]
graphql_object!(SBDebugger: SBDebugger | &self | {
    field targets() -> Vec<SBTarget> {
        self.targets().collect()
    }

    field selected_target() -> Option<SBTarget> {
        self.selected_target()
    }

    field selected_platform() -> SBPlatform {
        self.selected_platform()
    }

    field platforms() -> Vec<SBPlatform> {
        self.platforms().collect()
    }

    field available_platforms() -> Vec<SBStructuredData> {
        self.available_platforms().collect()
    }
});

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

    #[test]
    fn it_works() {
        assert!(!SBDebugger::version().is_empty());
    }
}
<commit_msg>clippy: Remove unnecessary let binding.<commit_after>// 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.

use super::commandinterpreter::SBCommandInterpreter;
use super::error::SBError;
use super::listener::SBListener;
use super::platform::SBPlatform;
use super::stream::SBStream;
use super::structureddata::SBStructuredData;
use super::target::SBTarget;
use std::ffi::{CStr, CString};
use std::fmt;
use std::iter;
use std::ptr;
use sys;

/// Creates [`SBTarget`]s, provides access to them and manages
/// the overall debugging experience.
///
/// # Initialization and Teardown
///
/// LLDB must be initialized before the functionality is used. This
/// is done with `SBDebugger::initialize()`:
///
/// ```
/// use lldb::SBDebugger;
///
/// SBDebugger::initialize();
/// ```
///
/// Similarly, it must be terminated after you are done using it:
///
/// ```
/// use lldb::SBDebugger;
///
/// SBDebugger::initialize();
/// // Use LLDB functionality ...
/// SBDebugger::terminate();
/// ```
///
/// Once you've initialized LLDB, you're ready to create an instance
/// of `SBDebugger`:
///
/// ```
/// use lldb::SBDebugger;
///
/// SBDebugger::initialize();
///
/// let debugger = SBDebugger::create(false);
/// // ... configure the debugger if needed ...
/// // ... create a target and do stuff ...
///
/// SBDebugger::terminate();
/// ```
///
/// # Configuration
///
/// ## Async Mode
///
/// While it is best to use LLDB in asynchronous mode, it does offer a
/// synchronous mode, which can be easier to use for quick experiments
/// or scripts.
///
/// In synchronous mode, calls to the LLDB API do not return until the
/// underlying action has been completed. This means that the thread
/// from which you call LLDB will be blocked during that time, so this
/// is not an ideal way to use LLDB for building interactive tools
/// or a new user interface.
///
/// In asynchronous mode, calls to the LLDB API will return immediately
/// without waiting for the action to complete. This means that actions
/// like launching a target, continuing the execution of a process and
/// so on won't be completed immediately and you must process events
/// to see what the results of an action are.
///
/// Synchronous mode can be enabled by using [`set_async`] and passing it
/// a `false` value. You can see if you're in asynchronous mode or not
/// by calling [`async`].
///
/// # Target Management
///
/// The `SBDebugger` instance tracks the various targets that are
/// currently known to the debugger.
///
/// Typically, you create a target with [`create_target`],
/// [`create_target_simple`] or one of the related methods.
///
/// Sometimes, you'll want to create a target without an associated
/// executable. A common use case for this is to attach to a process
/// by name or process ID where you don't know the executable in advance.
/// The most convenient way to do this is:
///
/// ```
/// # use lldb::SBDebugger;
/// # SBDebugger::initialize();
/// let debugger = SBDebugger::create(false);
/// if let Some(target) = debugger.create_target_simple("") {
///     println!("Got a target: {:?}", target);
///     // Now, maybe we'd like to attach to something.
/// }
/// # SBDebugger::terminate();
/// ```
///
/// You can iterate over these targets which have been created by
/// using [`targets`]:
///
/// ```no_run
/// # use lldb::{SBDebugger, SBTarget};
/// # fn look_at_targets(debugger: SBDebugger) {
/// // Iterate over the targets...
/// for target in debugger.targets() {
///     println!("Hello {:?}!", target);
/// }
/// // Or collect them into a vector!
/// let targets = debugger.targets().collect::<Vec<SBTarget>>();
/// # }
/// ```
///
/// # Platform Management
///
/// ...
///
/// [`SBTarget`]: struct.SBTarget.html
/// [`set_async`]: #method.set_async
/// [`async`]: #method.async
/// [`create_target`]: #method.create_target
/// [`create_target_simple`]: #method.create_target_simple
/// [`targets`]: #method.targets
pub struct SBDebugger {
    /// The underlying raw `SBDebuggerRef`.
    pub raw: sys::SBDebuggerRef,
}

impl SBDebugger {
    /// Initialize LLDB.
    ///
    /// This should be called before LLDB functionality is used.
    pub fn initialize() {
        unsafe { sys::SBDebuggerInitialize() };
    }

    /// Tear down LLDB.
    ///
    /// This should be called once the application no longer needs
    /// to use LLDB functionality. Typically, this is called as the
    /// application exits.
    pub fn terminate() {
        unsafe { sys::SBDebuggerTerminate() };
    }

    /// Create a new instance of `SBDebugger`.
    ///
    /// If `source_init_files` is `true`, then `~/.lldbinit` will
    /// be processed.
    pub fn create(source_init_files: bool) -> SBDebugger {
        SBDebugger {
            raw: unsafe { sys::SBDebuggerCreate2(source_init_files) },
        }
    }

    /// Get whether or not the debugger is in async mode.
    ///
    /// When in async mode, the debugger returns immediately when
    /// stepping or continuing without waiting for the process
    /// to change state.
    pub fn async(&self) -> bool {
        unsafe { sys::SBDebuggerGetAsync(self.raw) }
    }

    /// Set the debugger to be in async mode or not.
    ///
    /// When in async mode, the debugger returns immediately when
    /// stepping or continuing without waiting for the process
    /// to change state.
    pub fn set_async(&self, async: bool) {
        unsafe { sys::SBDebuggerSetAsync(self.raw, async) }
    }

    #[allow(missing_docs)]
    pub fn command_interpreter(&self) -> SBCommandInterpreter {
        SBCommandInterpreter::wrap(unsafe { sys::SBDebuggerGetCommandInterpreter(self.raw) })
    }

    /// Enable logging (defaults to `stderr`).
    ///
    /// `enable_log("lldb", &["default"])` is useful for troubleshooting in most
    /// cases. Include `"all"` in `categories` for extra verbosity.
    ///
    /// See invocations to `lldb_private::Log::Register` for more channels and
    /// categories.
    pub fn enable_log(&self, channel: &str, categories: &[&str]) -> bool {
        let channel = CString::new(channel).unwrap();
        let categories: Vec<_> = categories
            .iter()
            .map(|&s| CString::new(s).unwrap())
            .collect();
        let mut categories_ptr: Vec<_> = categories
            .iter()
            .map(|s| s.as_ptr())
            .chain(iter::once(ptr::null()))
            .collect();
        unsafe {
            sys::SBDebuggerEnableLog(self.raw, channel.as_ptr(), categories_ptr.as_mut_ptr())
        }
    }

    /// Get the LLDB version string.
    pub fn version() -> String {
        unsafe {
            match CStr::from_ptr(sys::SBDebuggerGetVersionString()).to_str() {
                Ok(s) => s.to_owned(),
                _ => panic!("No version string?"),
            }
        }
    }

    /// Create a target.
    ///
    /// The executable name may be an empty string to create
    /// an empty target.
    pub fn create_target(
        &self,
        executable: &str,
        target_triple: Option<&str>,
        platform_name: Option<&str>,
        add_dependent_modules: bool,
    ) -> Result<SBTarget, SBError> {
        let executable = CString::new(executable).unwrap();
        let target_triple = target_triple.map(|s| CString::new(s).unwrap());
        let platform_name = platform_name.map(|s| CString::new(s).unwrap());
        let error = SBError::new();
        let target = unsafe {
            sys::SBDebuggerCreateTarget(
                self.raw,
                executable.as_ptr(),
                target_triple.map_or(ptr::null(), |s| s.as_ptr()),
                platform_name.map_or(ptr::null(), |s| s.as_ptr()),
                add_dependent_modules,
                error.raw,
            )
        };
        if error.is_success() {
            Ok(SBTarget::wrap(target))
        } else {
            Err(error)
        }
    }

    /// Create a target from just an executable name.
    ///
    /// The executable name may be an empty string to create
    /// an empty target.
    ///
    /// Using [`create_target`] is preferred in most cases as
    /// that provides access to an `SBError` to inform the caller
    /// about what might have gone wrong.
    ///
    /// [`create_target`]: struct.SBDebugger.html#method.create_target
    pub fn create_target_simple(&self, executable: &str) -> Option<SBTarget> {
        let executable = CString::new(executable).unwrap();
        SBTarget::maybe_wrap(unsafe { sys::SBDebuggerCreateTarget2(self.raw, executable.as_ptr()) })
    }

    /// Get an iterator over the [targets] known to this debugger instance.
    ///
    /// [targets]: struct.SBTarget.html
    pub fn targets(&self) -> SBDebuggerTargetIter {
        SBDebuggerTargetIter {
            debugger: self,
            idx: 0,
        }
    }

    /// Get the default [SBListener] associated with the debugger.
    ///
    /// [SBListener]: struct.SBListener.html
    pub fn listener(&self) -> SBListener {
        SBListener::wrap(unsafe { sys::SBDebuggerGetListener(self.raw) })
    }

    /// Get the currently selected [`SBTarget`].
    ///
    /// [SBTarget]: struct.SBTarget.html
    pub fn selected_target(&self) -> Option<SBTarget> {
        SBTarget::maybe_wrap(unsafe { sys::SBDebuggerGetSelectedTarget(self.raw) })
    }

    /// Set the selected [`SBTarget`].
    ///
    /// [SBTarget]: struct.SBTarget.html
    pub fn set_selected_target(&self, target: &SBTarget) {
        unsafe { sys::SBDebuggerSetSelectedTarget(self.raw, target.raw) };
    }

    /// Get the currently selected [`SBPlatform`].
    ///
    /// [`SBPlatform`]: struct.SBPlatform.html
    pub fn selected_platform(&self) -> SBPlatform {
        unsafe {
            SBPlatform {
                raw: sys::SBDebuggerGetSelectedPlatform(self.raw),
            }
        }
    }

    /// Set the selected [`SBPlatform`].
    ///
    /// [`SBPlatform`]: struct.SBPlatform.html
    pub fn set_selected_platform(&self, platform: &SBPlatform) {
        unsafe { sys::SBDebuggerSetSelectedPlatform(self.raw, platform.raw) };
    }

    /// Get an iterator over the [platforms] known to this debugger instance.
    ///
    /// [platforms]: struct.SBPlatform.html
    pub fn platforms(&self) -> SBDebuggerPlatformIter {
        SBDebuggerPlatformIter {
            debugger: self,
            idx: 0,
        }
    }

    /// Get an iterator over the available platforms known to this debugger instance.
    pub fn available_platforms(&self) -> SBDebuggerAvailablePlatformIter {
        SBDebuggerAvailablePlatformIter {
            debugger: self,
            idx: 0,
        }
    }
}

/// Iterate over the [targets] known to a [debugger].
///
/// [targets]: struct.SBTarget.html
/// [debugger]: struct.SBDebugger.html
pub struct SBDebuggerTargetIter<'d> {
    debugger: &'d SBDebugger,
    idx: usize,
}

impl<'d> Iterator for SBDebuggerTargetIter<'d> {
    type Item = SBTarget;

    fn next(&mut self) -> Option<SBTarget> {
        if self.idx < unsafe { sys::SBDebuggerGetNumTargets(self.debugger.raw) as usize } {
            let r = Some(SBTarget {
                raw: unsafe { sys::SBDebuggerGetTargetAtIndex(self.debugger.raw, self.idx as u32) },
            });
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBDebuggerGetNumTargets(self.debugger.raw) } as usize;
        (sz - self.idx, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBDebuggerTargetIter<'d> {}

impl Clone for SBDebugger {
    fn clone(&self) -> SBDebugger {
        SBDebugger {
            raw: unsafe { sys::CloneSBDebugger(self.raw) },
        }
    }
}

impl fmt::Debug for SBDebugger {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let stream = SBStream::new();
        unsafe { sys::SBDebuggerGetDescription(self.raw, stream.raw) };
        write!(fmt, "SBDebugger {{ {} }}", stream.data())
    }
}

impl Drop for SBDebugger {
    fn drop(&mut self) {
        unsafe { sys::DisposeSBDebugger(self.raw) };
    }
}

unsafe impl Send for SBDebugger {}
unsafe impl Sync for SBDebugger {}

/// Iterate over the [platforms].
///
/// [platforms]: struct.SBPlatform.html
pub struct SBDebuggerPlatformIter<'d> {
    debugger: &'d SBDebugger,
    idx: u32,
}

impl<'d> Iterator for SBDebuggerPlatformIter<'d> {
    type Item = SBPlatform;

    fn next(&mut self) -> Option<SBPlatform> {
        if self.idx < unsafe { sys::SBDebuggerGetNumPlatforms(self.debugger.raw) } {
            let r = Some(SBPlatform::wrap(unsafe {
                sys::SBDebuggerGetPlatformAtIndex(self.debugger.raw, self.idx)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBDebuggerGetNumPlatforms(self.debugger.raw) } as usize;
        (sz - self.idx as usize, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBDebuggerPlatformIter<'d> {}

/// Iterate over the available platforms.
pub struct SBDebuggerAvailablePlatformIter<'d> {
    debugger: &'d SBDebugger,
    idx: u32,
}

impl<'d> Iterator for SBDebuggerAvailablePlatformIter<'d> {
    type Item = SBStructuredData;

    fn next(&mut self) -> Option<SBStructuredData> {
        if self.idx < unsafe { sys::SBDebuggerGetNumAvailablePlatforms(self.debugger.raw) } {
            let r = Some(SBStructuredData::wrap(unsafe {
                sys::SBDebuggerGetAvailablePlatformInfoAtIndex(self.debugger.raw, self.idx)
            }));
            self.idx += 1;
            r
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let sz = unsafe { sys::SBDebuggerGetNumAvailablePlatforms(self.debugger.raw) } as usize;
        (sz - self.idx as usize, Some(sz))
    }
}

impl<'d> ExactSizeIterator for SBDebuggerAvailablePlatformIter<'d> {}

#[cfg(feature = "graphql")]
impl ::juniper::Context for SBDebugger {}

#[cfg(feature = "graphql")]
graphql_object!(SBDebugger: SBDebugger | &self | {
    field targets() -> Vec<SBTarget> {
        self.targets().collect()
    }

    field selected_target() -> Option<SBTarget> {
        self.selected_target()
    }

    field selected_platform() -> SBPlatform {
        self.selected_platform()
    }

    field platforms() -> Vec<SBPlatform> {
        self.platforms().collect()
    }

    field available_platforms() -> Vec<SBStructuredData> {
        self.available_platforms().collect()
    }
});

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

    #[test]
    fn it_works() {
        assert!(!SBDebugger::version().is_empty());
    }
}
<|endoftext|>