<commit_before>use super::loader::Loader;
use super::util;
use crate::error::{Error, Result};
use std::io::{self, Write};
use std::path::Path;
use std::{fs, str};
use tree_sitter_tags::TagsContext;

pub fn generate_tags(loader: &Loader, scope: Option<&str>, paths: &[String]) -> Result<()> {
    let mut lang = None;
    if let Some(scope) = scope {
        lang = loader.language_configuration_for_scope(scope)?;
        if lang.is_none() {
            return Error::err(format!("Unknown scope '{}'", scope));
        }
    }

    let mut context = TagsContext::new();
    let cancellation_flag = util::cancel_on_stdin();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();

    for path in paths {
        let path = Path::new(&path);
        let (language, language_config) = match lang {
            Some(v) => v,
            None => match loader.language_configuration_for_file_name(path)? {
                Some(v) => v,
                None => {
                    eprintln!("No language found for path {:?}", path);
                    continue;
                }
            },
        };

        if let Some(tags_config) = language_config.tags_config(language)? {
            let path_str = format!("{:?}", path);
            writeln!(&mut stdout, "{}", &path_str[1..path_str.len() - 1])?;

            let source = fs::read(path)?;
            for tag in context.generate_tags(tags_config, &source, Some(&cancellation_flag))? {
                let tag = tag?;
                write!(
                    &mut stdout,
                    "  {:<8} {:<40}\t{:>9}-{:<9}",
                    tag.kind,
                    str::from_utf8(&source[tag.name_range]).unwrap_or(""),
                    tag.span.start,
                    tag.span.end,
                )?;
                if let Some(docs) = tag.docs {
                    if docs.len() > 120 {
                        write!(&mut stdout, "\t{:?}...", &docs[0..120])?;
                    } else {
                        write!(&mut stdout, "\t{:?}", &docs)?;
                    }
                }
                writeln!(&mut stdout, "")?;
            }
        } else {
            eprintln!("No tags config found for path {:?}", path);
        }
    }

    Ok(())
}
<commit_msg>Show if tag is a def/ref in the cli<commit_after>use super::loader::Loader;
use super::util;
use crate::error::{Error, Result};
use std::io::{self, Write};
use std::path::Path;
use std::{fs, str};
use tree_sitter_tags::TagsContext;

pub fn generate_tags(loader: &Loader, scope: Option<&str>, paths: &[String]) -> Result<()> {
    let mut lang = None;
    if let Some(scope) = scope {
        lang = loader.language_configuration_for_scope(scope)?;
        if lang.is_none() {
            return Error::err(format!("Unknown scope '{}'", scope));
        }
    }

    let mut context = TagsContext::new();
    let cancellation_flag = util::cancel_on_stdin();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();

    for path in paths {
        let path = Path::new(&path);
        let (language, language_config) = match lang {
            Some(v) => v,
            None => match loader.language_configuration_for_file_name(path)? {
                Some(v) => v,
                None => {
                    eprintln!("No language found for path {:?}", path);
                    continue;
                }
            },
        };

        if let Some(tags_config) = language_config.tags_config(language)? {
            let path_str = format!("{:?}", path);
            writeln!(&mut stdout, "{}", &path_str[1..path_str.len() - 1])?;

            let source = fs::read(path)?;
            for tag in context.generate_tags(tags_config, &source, Some(&cancellation_flag))? {
                let tag = tag?;
                write!(
                    &mut stdout,
                    "  {:<8} {:<40}\t [{}] {:>9}-{:<9}",
                    tag.kind,
                    str::from_utf8(&source[tag.name_range]).unwrap_or(""),
                    if tag.is_definition { "definition" } else { "reference" },
                    tag.span.start,
                    tag.span.end,
                )?;
                if let Some(docs) = tag.docs {
                    if docs.len() > 120 {
                        write!(&mut stdout, "\t{:?}...", &docs[0..120])?;
                    } else {
                        write!(&mut stdout, "\t{:?}", &docs)?;
                    }
                }
                writeln!(&mut stdout, "")?;
            }
        } else {
            eprintln!("No tags config found for path {:?}", path);
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::net::{TcpListener, TcpStream, SocketAddr, ToSocketAddrs, Shutdown, SocketAddrV4, Ipv4Addr};
use std::io::{self, Read, Write, BufReader, BufWriter};
use std::time::Duration;
use std::os::unix::io::AsRawFd;
use std::fmt;

use mqtt3::{MqttRead, MqttWrite};
use ssl::{SslContext, SslStream};
use mock::MockStream;
use openssl::ssl::IntoSsl;

use NetworkStream::{
    Tcp,
    Ssl,
    Mock
};

pub struct NetworkOptions {
    ssl: Option<SslContext>
}

impl NetworkOptions {
    pub fn new() -> NetworkOptions {
        NetworkOptions {
            ssl: None
        }
    }

    pub fn tls(&mut self, ssl: SslContext) -> &mut NetworkOptions {
        self.ssl = Some(ssl); self
    }

    pub fn bind<A: ToSocketAddrs>(&self, addr: A) -> io::Result<NetworkListener> {
        Ok(NetworkListener {
            tcp: try!(TcpListener::bind(addr)),
            ssl: match self.ssl {
                Some(ref ssl) => Some(ssl.clone()),
                None => None
            }
        })
    }

    pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<NetworkStream> {
        let stream = try!(TcpStream::connect(addr));
        match self.ssl {
            Some(ref ssl) => Ok(NetworkStream::Ssl(try!(ssl.connect(stream)))),
            None => Ok(NetworkStream::Tcp(stream))
        }
    }
}

pub struct NetworkListener {
    tcp: TcpListener,
    ssl: Option<SslContext>,
}

impl NetworkListener {
    pub fn accept(&mut self) -> io::Result<(NetworkStream, SocketAddr)> {
        let (stream, addr) = try!(self.tcp.accept());
        match self.ssl {
            Some(ref ssl) => {
                match ssl.accept(stream) {
                    Ok(ssl_stream) => Ok((NetworkStream::Ssl(ssl_stream), addr)),
                    Err(e) => Err(e)
                }
            },
            None => Ok((NetworkStream::Tcp(stream), addr))
        }
    }
}

pub enum NetworkStream {
    Tcp(TcpStream),
    Ssl(SslStream),
    Mock(MockStream)
}

impl NetworkStream {
    pub fn try_clone(&self) -> io::Result<NetworkStream> {
        match *self {
            Tcp(ref s) => Ok(Tcp(try!(s.try_clone()))),
            Ssl(ref s) => Ok(Ssl(try!(s.try_clone()))),
            Mock(ref s) => Ok(Mock(s.clone()))
        }
    }

    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        match *self {
            Tcp(ref s) => s.peer_addr(),
            Ssl(ref s) => s.get_ref().peer_addr(),
            Mock(ref s) => Ok(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 80)))
        }
    }

    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        match *self {
            Tcp(ref s) => s.shutdown(how),
            Ssl(ref s) => s.get_ref().shutdown(how),
            Mock(_) => Ok(())
        }
    }

    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
        match *self {
            Tcp(ref s) => s.set_read_timeout(dur),
            Ssl(ref s) => s.get_ref().set_read_timeout(dur),
            Mock(_) => Ok(())
        }
    }

    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
        match *self {
            Tcp(ref s) => s.set_write_timeout(dur),
            Ssl(ref s) => s.get_ref().set_write_timeout(dur),
            Mock(ref s) => Ok(())
        }
    }
}

impl Read for NetworkStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            Tcp(ref mut s) => s.read(buf),
            Ssl(ref mut s) => s.read(buf),
            Mock(ref mut s) => s.read(buf)
        }
    }
}

impl Write for NetworkStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match *self {
            Tcp(ref mut s) => s.write(buf),
            Ssl(ref mut s) => s.write(buf),
            Mock(ref mut s) => s.write(buf)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match *self {
            Tcp(ref mut s) => s.flush(),
            Ssl(ref mut s) => s.flush(),
            Mock(ref mut s) => s.flush()
        }
    }
}

pub type NetworkReader = BufReader<NetworkStream>;
pub type NetworkWriter = BufWriter<NetworkStream>;

impl MqttRead for NetworkStream {}
impl MqttWrite for NetworkStream {}

#[cfg(test)]
mod test {
    use super::{NetworkOptions, NetworkListener, NetworkStream};
    use std::net::{TcpListener, TcpStream, Shutdown};
    use std::io::{self, Read, Write};
    use std::thread;

    #[test]
    fn tcp_server_client_test() {
        let mut listener = NetworkOptions::new().bind("127.0.0.1:8432").unwrap();

        thread::spawn(|| {
            let mut client = NetworkOptions::new().connect("127.0.0.1:8432").unwrap();
            client.write(&[0, 1, 2, 3, 4, 5]).unwrap();
            client.flush().unwrap();
            client.shutdown(Shutdown::Both).unwrap();
        });

        let (mut stream, addr) = listener.accept().unwrap();
        let mut req = Vec::new();
        stream.read_to_end(&mut req).unwrap();
        assert_eq!(req, vec![0, 1, 2, 3, 4, 5]);
    }
}
<commit_msg>netopt: Admit NetworkOptions::attach<commit_after>use std::net::{TcpListener, TcpStream, SocketAddr, ToSocketAddrs, Shutdown, SocketAddrV4, Ipv4Addr};
use std::io::{self, Read, Write, BufReader, BufWriter};
use std::time::Duration;
use std::os::unix::io::AsRawFd;
use std::fmt;

use mqtt3::{MqttRead, MqttWrite};
use ssl::{SslContext, SslStream};
use mock::MockStream;
use openssl::ssl::IntoSsl;

use NetworkStream::{
    Tcp,
    Ssl,
    Mock
};

pub struct NetworkOptions {
    ssl: Option<SslContext>,
    mock: Option<NetworkStream>
}

impl NetworkOptions {
    pub fn new() -> NetworkOptions {
        NetworkOptions {
            ssl: None,
            mock: None
        }
    }

    pub fn attach(&mut self, stream: NetworkStream) -> &mut NetworkOptions {
        self.mock = Some(stream); self
    }

    pub fn tls(&mut self, ssl: SslContext) -> &mut NetworkOptions {
        self.ssl = Some(ssl); self
    }

    pub fn bind<A: ToSocketAddrs>(&self, addr: A) -> io::Result<NetworkListener> {
        Ok(NetworkListener {
            tcp: try!(TcpListener::bind(addr)),
            ssl: match self.ssl {
                Some(ref ssl) => Some(ssl.clone()),
                None => None
            }
        })
    }

    pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<NetworkStream> {
        if let Some(ref stream) = self.mock {
            return Ok(try!(stream.try_clone()));
        };

        let stream = try!(TcpStream::connect(addr));
        match self.ssl {
            Some(ref ssl) => Ok(NetworkStream::Ssl(try!(ssl.connect(stream)))),
            None => Ok(NetworkStream::Tcp(stream))
        }
    }
}

pub struct NetworkListener {
    tcp: TcpListener,
    ssl: Option<SslContext>,
}

impl NetworkListener {
    pub fn accept(&mut self) -> io::Result<(NetworkStream, SocketAddr)> {
        let (stream, addr) = try!(self.tcp.accept());
        match self.ssl {
            Some(ref ssl) => {
                match ssl.accept(stream) {
                    Ok(ssl_stream) => Ok((NetworkStream::Ssl(ssl_stream), addr)),
                    Err(e) => Err(e)
                }
            },
            None => Ok((NetworkStream::Tcp(stream), addr))
        }
    }
}

pub enum NetworkStream {
    Tcp(TcpStream),
    Ssl(SslStream),
    Mock(MockStream)
}

impl NetworkStream {
    pub fn try_clone(&self) -> io::Result<NetworkStream> {
        match *self {
            Tcp(ref s) => Ok(Tcp(try!(s.try_clone()))),
            Ssl(ref s) => Ok(Ssl(try!(s.try_clone()))),
            Mock(ref s) => Ok(Mock(s.clone()))
        }
    }

    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
        match *self {
            Tcp(ref s) => s.peer_addr(),
            Ssl(ref s) => s.get_ref().peer_addr(),
            Mock(ref s) => Ok(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 80)))
        }
    }

    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
        match *self {
            Tcp(ref s) => s.shutdown(how),
            Ssl(ref s) => s.get_ref().shutdown(how),
            Mock(_) => Ok(())
        }
    }

    pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
        match *self {
            Tcp(ref s) => s.set_read_timeout(dur),
            Ssl(ref s) => s.get_ref().set_read_timeout(dur),
            Mock(_) => Ok(())
        }
    }

    pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
        match *self {
            Tcp(ref s) => s.set_write_timeout(dur),
            Ssl(ref s) => s.get_ref().set_write_timeout(dur),
            Mock(ref s) => Ok(())
        }
    }
}

impl Read for NetworkStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match *self {
            Tcp(ref mut s) => s.read(buf),
            Ssl(ref mut s) => s.read(buf),
            Mock(ref mut s) => s.read(buf)
        }
    }
}

impl Write for NetworkStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        match *self {
            Tcp(ref mut s) => s.write(buf),
            Ssl(ref mut s) => s.write(buf),
            Mock(ref mut s) => s.write(buf)
        }
    }

    fn flush(&mut self) -> io::Result<()> {
        match *self {
            Tcp(ref mut s) => s.flush(),
            Ssl(ref mut s) => s.flush(),
            Mock(ref mut s) => s.flush()
        }
    }
}

pub type NetworkReader = BufReader<NetworkStream>;
pub type NetworkWriter = BufWriter<NetworkStream>;

impl MqttRead for NetworkStream {}
impl MqttWrite for NetworkStream {}

#[cfg(test)]
mod test {
    use std::net::{TcpListener, TcpStream, Shutdown};
    use std::io::{self, Read, Write};
    use std::thread;
    use super::{NetworkOptions, NetworkListener, NetworkStream};
    use mock::MockStream;

    #[test]
    fn tcp_server_client_test() {
        let mut listener = NetworkOptions::new().bind("127.0.0.1:8432").unwrap();

        thread::spawn(|| {
            let mut client = NetworkOptions::new().connect("127.0.0.1:8432").unwrap();
            client.write(&[0, 1, 2, 3, 4, 5]).unwrap();
            client.flush().unwrap();
            client.shutdown(Shutdown::Both).unwrap();
        });

        let (mut stream, addr) = listener.accept().unwrap();
        let mut req = Vec::new();
        stream.read_to_end(&mut req).unwrap();
        assert_eq!(req, vec![0, 1, 2, 3, 4, 5]);
    }

    #[test]
    fn tcp_attach_test() {
        let stream = NetworkStream::Mock(MockStream::with_vec(vec![0xFE, 0xFD]));
        let mut options = NetworkOptions::new();
        options.attach(stream);
        let mut client = options.connect("127.0.0.1:80").unwrap();
        let mut buf = Vec::new();
        client.read_to_end(&mut buf).unwrap();
        assert_eq!(buf, vec![0xFE, 0xFD]);
    }
}
<|endoftext|>


<commit_before><commit_msg>Implement functions in find.rs<commit_after>use rustc_serialize::json;

use std::error::Error;
use std::fs::File;
use std::io::{ BufReader, Read };
use std::path::Path;

use package::pkg::{ Package, PackageList };
use package::update;

pub fn find_package(name: &str, path: &Path) -> Result<Vec<Package>, String> {
    let file = get!(File::open(path), "An error occured while opening package list.");
    let mut list = BufReader::new(file);
    let mut buffer = String::new();

    get!(list.read_to_string(&mut buffer), "An error occured while reading package list.");
    let list: PackageList = get!(json::decode(&buffer), "An error occured while decoding JSON.");

    let found = list.packages
                .into_iter()
                .filter(|x| !x.name.contains(name))
                .collect::<Vec<Package>>();

    match found.len() {
        0 => Err("Package not found".to_string()),
        _ => Ok(found)
    }
}

pub fn select_package<F>(name: &str, path: &Path, select: F) -> Result<Package, String>
    where F: Fn(u32) -> u32 {
    let found_packages = try!(find_package(name, path));
    let user_choice = select(found_packages.len() as u32); // note: Passed closure should check that number of user choice <= vector len
    Ok(found_packages[user_choice as usize].clone())
}<|endoftext|>


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

use about_loader;
use mime_classifier::MIMEClassifier;
use mime_guess::guess_mime_type;
use net_traits::ProgressMsg::{Done, Payload};
use net_traits::{LoadConsumer, LoadData, Metadata};
use resource_thread::{CancellationListener, ProgressSender};
use resource_thread::{send_error, start_sending_sniffed_opt};
use std::borrow::ToOwned;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::sync::Arc;
use url::Url;
use util::thread::spawn_named;

static READ_SIZE: usize = 8192;

enum ReadStatus {
    Partial(Vec<u8>),
    EOF,
}

enum LoadResult {
    Cancelled,
    Finished,
}

fn read_block(reader: &mut File) -> Result<ReadStatus, String> {
    let mut buf = vec![0; READ_SIZE];
    match reader.read(&mut buf) {
        Ok(0) => Ok(ReadStatus::EOF),
        Ok(n) => {
            buf.truncate(n);
            Ok(ReadStatus::Partial(buf))
        }
        Err(e) => Err(e.description().to_owned()),
    }
}

fn read_all(reader: &mut File, progress_chan: &ProgressSender, cancel_listener: &CancellationListener)
            -> Result<LoadResult, String> {
    loop {
        if cancel_listener.is_cancelled() {
            let _ = progress_chan.send(Done(Err("load cancelled".to_owned())));
            return Ok(LoadResult::Cancelled);
        }

        match try!(read_block(reader)) {
            ReadStatus::Partial(buf) => progress_chan.send(Payload(buf)).unwrap(),
            ReadStatus::EOF => return Ok(LoadResult::Finished),
        }
    }
}

fn get_progress_chan(load_data: LoadData, file_path: PathBuf,
                     senders: LoadConsumer, classifier: Arc<MIMEClassifier>, buf: &[u8])
                     -> Result<ProgressSender, ()> {
    let mut metadata = Metadata::default(load_data.url);
    let mime_type = guess_mime_type(file_path.as_path());
    metadata.set_content_type(Some(&mime_type));
    return start_sending_sniffed_opt(senders, metadata, classifier, buf, load_data.context);
}

pub fn factory(load_data: LoadData,
               senders: LoadConsumer,
               classifier: Arc<MIMEClassifier>,
               cancel_listener: CancellationListener) {
    assert!(&*load_data.url.scheme == "file");
    spawn_named("file_loader".to_owned(), move || {
        let file_path: Result<PathBuf, ()> = load_data.url.to_file_path();
        match file_path {
            Ok(file_path) => {
                match File::open(&file_path) {
                    Ok(ref mut reader) => {
                        if cancel_listener.is_cancelled() {
                            if let Ok(progress_chan) = get_progress_chan(load_data, file_path,
                                                                         senders, classifier, &[]) {
                                let _ = progress_chan.send(Done(Err("load cancelled".to_owned())));
                            }
                            return;
                        }
                        match read_block(reader) {
                            Ok(ReadStatus::Partial(buf)) => {
                                let progress_chan = get_progress_chan(load_data, file_path,
                                                                      senders, classifier, &buf).ok().unwrap();
                                progress_chan.send(Payload(buf)).unwrap();
                                let read_result = read_all(reader, &progress_chan, &cancel_listener);
                                if let Ok(load_result) = read_result {
                                    match load_result {
                                        LoadResult::Cancelled => return,
                                        LoadResult::Finished => progress_chan.send(Done(Ok(()))).unwrap(),
                                    }
                                }
                            }
                            Ok(ReadStatus::EOF) => {
                                if let Ok(chan) = get_progress_chan(load_data, file_path,
                                                                    senders, classifier, &[]) {
                                    let _ = chan.send(Done(Ok(())));
                                }
                            }
                            Err(e) => {
                                send_error(load_data.url, e, senders);
                            }
                        };
                    }
                    Err(_) => {
                        // this should be one of the three errors listed in
                        // http://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open
                        // but, we'll go for a "file not found!"
                        let url = Url::parse("about:not-found").unwrap();
                        let load_data_404 = LoadData::new(load_data.context, url, None);
                        about_loader::factory(load_data_404, senders, classifier, cancel_listener)
                    }
                }
            }
            Err(_) => {
                send_error(load_data.url, "Could not parse path".to_owned(), senders);
            }
        }
    });
}
<commit_msg>Flatten implementation of `net::file_loader::factory`.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use about_loader;
use mime_classifier::MIMEClassifier;
use mime_guess::guess_mime_type;
use net_traits::ProgressMsg::{Done, Payload};
use net_traits::{LoadConsumer, LoadData, Metadata};
use resource_thread::{CancellationListener, ProgressSender};
use resource_thread::{send_error, start_sending_sniffed_opt};
use std::borrow::ToOwned;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::sync::Arc;
use url::Url;
use util::thread::spawn_named;

static READ_SIZE: usize = 8192;

enum ReadStatus {
    Partial(Vec<u8>),
    EOF,
}

enum LoadResult {
    Cancelled,
    Finished,
}

fn read_block(reader: &mut File) -> Result<ReadStatus, String> {
    let mut buf = vec![0; READ_SIZE];
    match reader.read(&mut buf) {
        Ok(0) => Ok(ReadStatus::EOF),
        Ok(n) => {
            buf.truncate(n);
            Ok(ReadStatus::Partial(buf))
        }
        Err(e) => Err(e.description().to_owned()),
    }
}

fn read_all(reader: &mut File, progress_chan: &ProgressSender, cancel_listener: &CancellationListener)
            -> Result<LoadResult, String> {
    loop {
        if cancel_listener.is_cancelled() {
            let _ = progress_chan.send(Done(Err("load cancelled".to_owned())));
            return Ok(LoadResult::Cancelled);
        }

        match try!(read_block(reader)) {
            ReadStatus::Partial(buf) => progress_chan.send(Payload(buf)).unwrap(),
            ReadStatus::EOF => return Ok(LoadResult::Finished),
        }
    }
}

fn get_progress_chan(load_data: LoadData, file_path: PathBuf,
                     senders: LoadConsumer, classifier: Arc<MIMEClassifier>, buf: &[u8])
                     -> Result<ProgressSender, ()> {
    let mut metadata = Metadata::default(load_data.url);
    let mime_type = guess_mime_type(file_path.as_path());
    metadata.set_content_type(Some(&mime_type));
    return start_sending_sniffed_opt(senders, metadata, classifier, buf, load_data.context);
}

pub fn factory(load_data: LoadData,
               senders: LoadConsumer,
               classifier: Arc<MIMEClassifier>,
               cancel_listener: CancellationListener) {
    assert!(&*load_data.url.scheme == "file");
    spawn_named("file_loader".to_owned(), move || {
        let file_path = match load_data.url.to_file_path() {
            Ok(file_path) => file_path,
            Err(_) => {
                send_error(load_data.url, "Could not parse path".to_owned(), senders);
                return;
            },
        };
        let mut file = File::open(&file_path);
        let reader = match file {
            Ok(ref mut reader) => reader,
            Err(_) => {
                // this should be one of the three errors listed in
                // http://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open
                // but, we'll go for a "file not found!"
                let url = Url::parse("about:not-found").unwrap();
                let load_data_404 = LoadData::new(load_data.context, url, None);
                about_loader::factory(load_data_404, senders, classifier, cancel_listener);
                return;
            }
        };
        if cancel_listener.is_cancelled() {
            if let Ok(progress_chan) = get_progress_chan(load_data, file_path,
                                                         senders, classifier, &[]) {
                let _ = progress_chan.send(Done(Err("load cancelled".to_owned())));
            }
            return;
        }
        match read_block(reader) {
            Ok(ReadStatus::Partial(buf)) => {
                let progress_chan = get_progress_chan(load_data, file_path,
                                                      senders, classifier, &buf).ok().unwrap();
                progress_chan.send(Payload(buf)).unwrap();
                let read_result = read_all(reader, &progress_chan, &cancel_listener);
                if let Ok(load_result) = read_result {
                    match load_result {
                        LoadResult::Cancelled => return,
                        LoadResult::Finished => progress_chan.send(Done(Ok(()))).unwrap(),
                    }
                }
            }
            Ok(ReadStatus::EOF) => {
                if let Ok(chan) = get_progress_chan(load_data, file_path,
                                                    senders, classifier, &[]) {
                    let _ = chan.send(Done(Ok(())));
                }
            }
            Err(e) => {
                send_error(load_data.url, e, senders);
            }
        }
    });
}
<|endoftext|>


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

use about_loader;
use mime_classifier::MIMEClassifier;
use mime_guess::guess_mime_type;
use net_traits::ProgressMsg::{Done, Payload};
use net_traits::{LoadConsumer, LoadData, Metadata};
use resource_thread::{CancellationListener, ProgressSender};
use resource_thread::{send_error, start_sending_sniffed_opt};
use std::borrow::ToOwned;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::sync::Arc;
use url::Url;
use util::thread::spawn_named;

static READ_SIZE: usize = 8192;

enum ReadStatus {
    Partial(Vec<u8>),
    EOF,
}

enum LoadResult {
    Cancelled,
    Finished,
}

fn read_block(reader: &mut File) -> Result<ReadStatus, String> {
    let mut buf = vec![0; READ_SIZE];
    match reader.read(&mut buf) {
        Ok(0) => Ok(ReadStatus::EOF),
        Ok(n) => {
            buf.truncate(n);
            Ok(ReadStatus::Partial(buf))
        }
        Err(e) => Err(e.description().to_owned()),
    }
}

fn read_all(reader: &mut File, progress_chan: &ProgressSender, cancel_listener: &CancellationListener)
            -> Result<LoadResult, String> {
    loop {
        if cancel_listener.is_cancelled() {
            let _ = progress_chan.send(Done(Err("load cancelled".to_owned())));
            return Ok(LoadResult::Cancelled);
        }

        match try!(read_block(reader)) {
            ReadStatus::Partial(buf) => progress_chan.send(Payload(buf)).unwrap(),
            ReadStatus::EOF => return Ok(LoadResult::Finished),
        }
    }
}

fn get_progress_chan(load_data: LoadData, file_path: PathBuf,
                     senders: LoadConsumer, classifier: Arc<MIMEClassifier>, buf: &[u8])
                     -> Result<ProgressSender, ()> {
    let mut metadata = Metadata::default(load_data.url);
    let mime_type = guess_mime_type(file_path.as_path());
    metadata.set_content_type(Some(&mime_type));
    return start_sending_sniffed_opt(senders, metadata, classifier, buf, load_data.context);
}

pub fn factory(load_data: LoadData,
               senders: LoadConsumer,
               classifier: Arc<MIMEClassifier>,
               cancel_listener: CancellationListener) {
    assert!(&*load_data.url.scheme == "file");
    spawn_named("file_loader".to_owned(), move || {
        let file_path = match load_data.url.to_file_path() {
            Ok(file_path) => file_path,
            Err(_) => {
                send_error(load_data.url, "Could not parse path".to_owned(), senders);
                return;
            },
        };
        let mut file = File::open(&file_path);
        let reader = match file {
            Ok(ref mut reader) => reader,
            Err(_) => {
                // this should be one of the three errors listed in
                // http://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open
                // but, we'll go for a "file not found!"
                let url = Url::parse("about:not-found").unwrap();
                let load_data_404 = LoadData::new(load_data.context, url, None);
                about_loader::factory(load_data_404, senders, classifier, cancel_listener);
                return;
            }
        };
        if cancel_listener.is_cancelled() {
            if let Ok(progress_chan) = get_progress_chan(load_data, file_path,
                                                         senders, classifier, &[]) {
                let _ = progress_chan.send(Done(Err("load cancelled".to_owned())));
            }
            return;
        }
        match read_block(reader) {
            Ok(ReadStatus::Partial(buf)) => {
                let progress_chan = get_progress_chan(load_data, file_path,
                                                      senders, classifier, &buf).ok().unwrap();
                progress_chan.send(Payload(buf)).unwrap();
                let read_result = read_all(reader, &progress_chan, &cancel_listener);
                if let Ok(load_result) = read_result {
                    match load_result {
                        LoadResult::Cancelled => return,
                        LoadResult::Finished => progress_chan.send(Done(Ok(()))).unwrap(),
                    }
                }
            }
            Ok(ReadStatus::EOF) => {
                if let Ok(chan) = get_progress_chan(load_data, file_path,
                                                    senders, classifier, &[]) {
                    let _ = chan.send(Done(Ok(())));
                }
            }
            Err(e) => {
                send_error(load_data.url, e, senders);
            }
        }
    });
}
<commit_msg>Refactor `loop` into a `while` loop.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use about_loader;
use mime_classifier::MIMEClassifier;
use mime_guess::guess_mime_type;
use net_traits::ProgressMsg::{Done, Payload};
use net_traits::{LoadConsumer, LoadData, Metadata};
use resource_thread::{CancellationListener, ProgressSender};
use resource_thread::{send_error, start_sending_sniffed_opt};
use std::borrow::ToOwned;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::sync::Arc;
use url::Url;
use util::thread::spawn_named;

static READ_SIZE: usize = 8192;

enum ReadStatus {
    Partial(Vec<u8>),
    EOF,
}

enum LoadResult {
    Cancelled,
    Finished,
}

fn read_block(reader: &mut File) -> Result<ReadStatus, String> {
    let mut buf = vec![0; READ_SIZE];
    match reader.read(&mut buf) {
        Ok(0) => Ok(ReadStatus::EOF),
        Ok(n) => {
            buf.truncate(n);
            Ok(ReadStatus::Partial(buf))
        }
        Err(e) => Err(e.description().to_owned()),
    }
}

fn read_all(reader: &mut File, progress_chan: &ProgressSender, cancel_listener: &CancellationListener)
            -> Result<LoadResult, String> {
    while !cancel_listener.is_cancelled() {
        match try!(read_block(reader)) {
            ReadStatus::Partial(buf) => progress_chan.send(Payload(buf)).unwrap(),
            ReadStatus::EOF => return Ok(LoadResult::Finished),
        }
    }
    let _ = progress_chan.send(Done(Err("load cancelled".to_owned())));
    Ok(LoadResult::Cancelled)
}

fn get_progress_chan(load_data: LoadData, file_path: PathBuf,
                     senders: LoadConsumer, classifier: Arc<MIMEClassifier>, buf: &[u8])
                     -> Result<ProgressSender, ()> {
    let mut metadata = Metadata::default(load_data.url);
    let mime_type = guess_mime_type(file_path.as_path());
    metadata.set_content_type(Some(&mime_type));
    return start_sending_sniffed_opt(senders, metadata, classifier, buf, load_data.context);
}

pub fn factory(load_data: LoadData,
               senders: LoadConsumer,
               classifier: Arc<MIMEClassifier>,
               cancel_listener: CancellationListener) {
    assert!(&*load_data.url.scheme == "file");
    spawn_named("file_loader".to_owned(), move || {
        let file_path = match load_data.url.to_file_path() {
            Ok(file_path) => file_path,
            Err(_) => {
                send_error(load_data.url, "Could not parse path".to_owned(), senders);
                return;
            },
        };
        let mut file = File::open(&file_path);
        let reader = match file {
            Ok(ref mut reader) => reader,
            Err(_) => {
                // this should be one of the three errors listed in
                // http://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open
                // but, we'll go for a "file not found!"
                let url = Url::parse("about:not-found").unwrap();
                let load_data_404 = LoadData::new(load_data.context, url, None);
                about_loader::factory(load_data_404, senders, classifier, cancel_listener);
                return;
            }
        };
        if cancel_listener.is_cancelled() {
            if let Ok(progress_chan) = get_progress_chan(load_data, file_path,
                                                         senders, classifier, &[]) {
                let _ = progress_chan.send(Done(Err("load cancelled".to_owned())));
            }
            return;
        }
        match read_block(reader) {
            Ok(ReadStatus::Partial(buf)) => {
                let progress_chan = get_progress_chan(load_data, file_path,
                                                      senders, classifier, &buf).ok().unwrap();
                progress_chan.send(Payload(buf)).unwrap();
                let read_result = read_all(reader, &progress_chan, &cancel_listener);
                if let Ok(load_result) = read_result {
                    match load_result {
                        LoadResult::Cancelled => return,
                        LoadResult::Finished => progress_chan.send(Done(Ok(()))).unwrap(),
                    }
                }
            }
            Ok(ReadStatus::EOF) => {
                if let Ok(chan) = get_progress_chan(load_data, file_path,
                                                    senders, classifier, &[]) {
                    let _ = chan.send(Done(Ok(())));
                }
            }
            Err(e) => {
                send_error(load_data.url, e, senders);
            }
        }
    });
}
<|endoftext|>


<commit_before>#![deny(warnings)]

#[macro_use]
extern crate log;
extern crate capstone;
extern crate lgl;
extern crate libllama;

mod commands;
mod uilog;

use std::env;
use std::path::Path;

use libllama::{dbgcore, gdbstub, hwcore, ldr, msgs, io::gpu};

mod c {
    #![allow(warnings)]
    include!(concat!(env!("OUT_DIR"), "/qml_interop.rs"));
}

struct Backend<'a> {
    loader: &'a dyn ldr::Loader,
    debugger: dbgcore::DbgCore,
    cmd_active_cpu: dbgcore::ActiveCpu,
    gdb: gdbstub::GdbStub,
    fbs: hwcore::Framebuffers,
    fb_state: Option<gpu::FramebufState>,
    msg_client: msgs::Client<hwcore::Message>,
}

impl<'a> Backend<'a> {
    unsafe fn from_c<'b>(backend: *mut c::Backend) -> &'b mut Backend<'b> {
        &mut *(backend as *mut Backend)
    }

    fn to_c(&mut self) -> *mut c::Backend {
        (self as *mut Backend) as *mut c::Backend
    }

    fn update_fb_state(&mut self) {
        while let Ok(msg) = self.msg_client.try_recv() {
            if let hwcore::Message::FramebufState(state) = msg {
                self.fb_state = Some(state);
            } else {
                unreachable!();
            }
        }
    }
}

mod cbs {
    use std::slice;
    use std::str;

    use commands;
    use uilog;
    use {Backend, c};

    use lgl;
    use libllama::hwcore::Message;
    use libllama::io::hid;
    use libllama::dbgcore::ActiveCpu::Arm9;
    use libllama::io::gpu::ColorFormat;

    pub unsafe extern fn set_running(backend: *mut c::Backend, state: bool) {
        let backend = Backend::from_c(backend);
        if state {
            backend.debugger.ctx(Arm9)
                .resume();
        } else {
            backend.debugger.ctx(Arm9)
                .pause();
        }
    }

    pub unsafe extern fn is_running(backend: *mut c::Backend) -> bool {
        let backend = Backend::from_c(backend);
        backend.debugger.ctx(Arm9)
            .hwcore_mut()
            .running()
    }

    fn fix_color_rgba8(buf: &mut [u8]) {
        for window in buf.chunks_exact_mut(4) {
            let tmp = window[0];
            window[0] = window[1];
            window[1] = window[2];
            window[2] = window[3];
            window[3] = tmp;
        }
    }

    pub unsafe extern fn top_screen(backend: *mut c::Backend,
                                    buf_size_out: *mut usize,
                                    color_fmt: *mut c::ColorFormat) -> *const u8 {
        let backend = Backend::from_c(backend);

        backend.update_fb_state();
        if backend.fb_state.is_none() {
            *buf_size_out = 0;
            *color_fmt = c::ColorFormat_COLOR_RGB8;
            return std::ptr::null();
        }
        let fb_state = backend.fb_state.as_ref().unwrap();

        backend.debugger.ctx(Arm9)
            .hwcore_mut()
            .copy_framebuffers(&mut backend.fbs, fb_state);

        *color_fmt = match fb_state.color_fmt[0] {
            ColorFormat::Rgb8 => c::ColorFormat_COLOR_RGB8,
            ColorFormat::Rgba8 => {
                fix_color_rgba8(backend.fbs.top_screen.as_mut_slice());
                c::ColorFormat_COLOR_RGBA8
            },
            ColorFormat::Rgb565 => c::ColorFormat_COLOR_RGB565,
            ColorFormat::Rgb5a1 => c::ColorFormat_COLOR_RGB5A1,
            ColorFormat::Rgba4 => c::ColorFormat_COLOR_RGBA4,
        };

        *buf_size_out = backend.fbs.top_screen.len();
        backend.fbs.top_screen.as_ptr()
    }

    pub unsafe extern fn bot_screen(backend: *mut c::Backend,
                                    buf_size_out: *mut usize,
                                    color_fmt: *mut c::ColorFormat) -> *const u8 {
        let backend = Backend::from_c(backend);

        backend.update_fb_state();
        if backend.fb_state.is_none() {
            *buf_size_out = 0;
            *color_fmt = c::ColorFormat_COLOR_RGB8;
            return std::ptr::null();
        }
        let fb_state = backend.fb_state.as_ref().unwrap();

        backend.debugger.ctx(Arm9)
            .hwcore_mut()
            .copy_framebuffers(&mut backend.fbs, fb_state);

        *color_fmt = match fb_state.color_fmt[1] {
            ColorFormat::Rgb8 => c::ColorFormat_COLOR_RGB8,
            ColorFormat::Rgba8 => {
                fix_color_rgba8(backend.fbs.bot_screen.as_mut_slice());
                c::ColorFormat_COLOR_RGBA8
            },
            ColorFormat::Rgb565 => c::ColorFormat_COLOR_RGB565,
            ColorFormat::Rgb5a1 => c::ColorFormat_COLOR_RGB5A1,
            ColorFormat::Rgba4 => c::ColorFormat_COLOR_RGBA4,
        };

        *buf_size_out = backend.fbs.bot_screen.len();
        backend.fbs.bot_screen.as_ptr()
    }

    pub unsafe extern fn mod_button(backend: *mut c::Backend, button: i32, pressed: bool) {
        let backend = Backend::from_c(backend);
        let button = match button as i32 {
            c::Button_BUTTON_A => hid::Button::A,
            c::Button_BUTTON_B => hid::Button::B,
            c::Button_BUTTON_X => hid::Button::X,
            c::Button_BUTTON_Y => hid::Button::Y,
            c::Button_BUTTON_L => hid::Button::L,
            c::Button_BUTTON_R => hid::Button::R,
            c::Button_BUTTON_UP => hid::Button::Up,
            c::Button_BUTTON_DOWN => hid::Button::Down,
            c::Button_BUTTON_LEFT => hid::Button::Left,
            c::Button_BUTTON_RIGHT => hid::Button::Right,
            c::Button_BUTTON_SELECT => hid::Button::Select,
            c::Button_BUTTON_START => hid::Button::Start,
            _ => unreachable!()
        };
        let state = if pressed { hid::ButtonState::Pressed(button) }
                    else { hid::ButtonState::Released(button) };
        backend.msg_client.send(Message::HidUpdate(state));
    }

    pub unsafe extern fn run_command(backend: *mut c::Backend, str_buf: *const i8, str_len: usize) {
        let backend = Backend::from_c(backend);
        let input = {
            let slice = slice::from_raw_parts(str_buf as *const u8, str_len);
            str::from_utf8(slice).unwrap()
        };

        for cmd in input.split(';') {
            lgl::log("> ");
            lgl::log(cmd);
            lgl::log("\n");
            commands::handle(&mut backend.cmd_active_cpu, &mut backend.debugger, cmd.split_whitespace());
        }
    }

    pub unsafe extern fn use_trace_logs(_: *mut c::Backend, val: bool) {
        uilog::allow_trace(val);
    }

    pub unsafe extern fn reload_game(backend: *mut c::Backend) {
        let backend = Backend::from_c(backend);
        backend.msg_client.send(Message::Quit);
        backend.gdb.wait(); // Need to wait because the GDB thread owns the port
        *backend = super::load_game(backend.loader);
    }

    pub unsafe extern fn log(buf: c::LogBufferView) {
        let s = {
            let slice = slice::from_raw_parts(buf.buf_ptr as *const u8, buf.buf_size);
            str::from_utf8(slice).unwrap()
        };
        lgl::log(s)
    }

    pub unsafe extern fn buffer(buf: c::LogBufferMutView) -> c::LogBufferView {
        let new_slice = lgl::buffer(slice::from_raw_parts_mut(buf.buf_ptr as *mut u8, buf.buf_size));
        c::LogBufferView { buf_ptr: new_slice.as_ptr() as *const i8, buf_size: new_slice.len() }
    }

    pub extern fn buffer_size() -> usize {
        lgl::BUFFER_SIZE
    }
}

fn load_game<'a>(loader: &'a dyn ldr::Loader) -> Backend<'a> {
    let fbs = hwcore::Framebuffers::default();

    let mut hwcore = hwcore::HwCore::new(loader);
    let client_gdb = hwcore.take_client_gdb().unwrap();
    let client_user = hwcore.take_client_user().unwrap();

    let debugger = dbgcore::DbgCore::bind(hwcore);

    info!("Using ARM9 as active debug CPU");

    let backend = Backend {
        loader: loader,
        debugger: debugger.clone(),
        cmd_active_cpu: dbgcore::ActiveCpu::Arm9,
        gdb: gdbstub::GdbStub::new(client_gdb, debugger),
        fbs: fbs,
        fb_state: None,
        msg_client: client_user,
    };

    backend
}

fn c_args() -> Vec<Box<[u8]>> {
    let into_c_str = |arg: String| {
        let mut vec = arg.into_bytes();
        vec.push(b'\0');
        vec.into_boxed_slice()
    };

    let args = env::args();
    args.map(into_c_str)
        .collect()
}

fn main() {
    let _logger = uilog::init().unwrap();

    let path = env::args().nth(1).unwrap();
    let loader = ldr::make_loader(Path::new(&path));

    let callbacks = c::FrontendCallbacks {
        set_running: Some(cbs::set_running),
        is_running: Some(cbs::is_running),
        reload_game: Some(cbs::reload_game),

        top_screen: Some(cbs::top_screen),
        bot_screen: Some(cbs::bot_screen),
        mod_button: Some(cbs::mod_button),

        run_command: Some(cbs::run_command),
        use_trace_logs: Some(cbs::use_trace_logs),
        log: Some(cbs::log),
        buffer: Some(cbs::buffer),
        buffer_size: Some(cbs::buffer_size),
    };

    let mut backend = load_game(loader.as_ref());
    let mut args = c_args();
    let mut c_args: Vec<*mut u8> = args.iter_mut()
        .map(|arg| &mut arg[0] as *mut u8)
        .collect();

    unsafe {
        c::llama_open_gui(
            c_args.len() as i32,
            c_args.as_mut_ptr() as *mut *mut i8,
            backend.to_c(),
            &callbacks)
    };
}
<commit_msg>Use correctly typed buttons from FFI<commit_after>#![deny(warnings)]

#[macro_use]
extern crate log;
extern crate capstone;
extern crate lgl;
extern crate libllama;

mod commands;
mod uilog;

use std::env;
use std::path::Path;

use libllama::{dbgcore, gdbstub, hwcore, ldr, msgs, io::gpu};

mod c {
    #![allow(warnings)]
    include!(concat!(env!("OUT_DIR"), "/qml_interop.rs"));
}

struct Backend<'a> {
    loader: &'a dyn ldr::Loader,
    debugger: dbgcore::DbgCore,
    cmd_active_cpu: dbgcore::ActiveCpu,
    gdb: gdbstub::GdbStub,
    fbs: hwcore::Framebuffers,
    fb_state: Option<gpu::FramebufState>,
    msg_client: msgs::Client<hwcore::Message>,
}

impl<'a> Backend<'a> {
    unsafe fn from_c<'b>(backend: *mut c::Backend) -> &'b mut Backend<'b> {
        &mut *(backend as *mut Backend)
    }

    fn to_c(&mut self) -> *mut c::Backend {
        (self as *mut Backend) as *mut c::Backend
    }

    fn update_fb_state(&mut self) {
        while let Ok(msg) = self.msg_client.try_recv() {
            if let hwcore::Message::FramebufState(state) = msg {
                self.fb_state = Some(state);
            } else {
                unreachable!();
            }
        }
    }
}

mod cbs {
    use std::slice;
    use std::str;

    use commands;
    use uilog;
    use {Backend, c};

    use lgl;
    use libllama::hwcore::Message;
    use libllama::io::hid;
    use libllama::dbgcore::ActiveCpu::Arm9;
    use libllama::io::gpu::ColorFormat;

    pub unsafe extern fn set_running(backend: *mut c::Backend, state: bool) {
        let backend = Backend::from_c(backend);
        if state {
            backend.debugger.ctx(Arm9)
                .resume();
        } else {
            backend.debugger.ctx(Arm9)
                .pause();
        }
    }

    pub unsafe extern fn is_running(backend: *mut c::Backend) -> bool {
        let backend = Backend::from_c(backend);
        backend.debugger.ctx(Arm9)
            .hwcore_mut()
            .running()
    }

    fn fix_color_rgba8(buf: &mut [u8]) {
        for window in buf.chunks_exact_mut(4) {
            let tmp = window[0];
            window[0] = window[1];
            window[1] = window[2];
            window[2] = window[3];
            window[3] = tmp;
        }
    }

    pub unsafe extern fn top_screen(backend: *mut c::Backend,
                                    buf_size_out: *mut usize,
                                    color_fmt: *mut c::ColorFormat) -> *const u8 {
        let backend = Backend::from_c(backend);

        backend.update_fb_state();
        if backend.fb_state.is_none() {
            *buf_size_out = 0;
            *color_fmt = c::ColorFormat_COLOR_RGB8;
            return std::ptr::null();
        }
        let fb_state = backend.fb_state.as_ref().unwrap();

        backend.debugger.ctx(Arm9)
            .hwcore_mut()
            .copy_framebuffers(&mut backend.fbs, fb_state);

        *color_fmt = match fb_state.color_fmt[0] {
            ColorFormat::Rgb8 => c::ColorFormat_COLOR_RGB8,
            ColorFormat::Rgba8 => {
                fix_color_rgba8(backend.fbs.top_screen.as_mut_slice());
                c::ColorFormat_COLOR_RGBA8
            },
            ColorFormat::Rgb565 => c::ColorFormat_COLOR_RGB565,
            ColorFormat::Rgb5a1 => c::ColorFormat_COLOR_RGB5A1,
            ColorFormat::Rgba4 => c::ColorFormat_COLOR_RGBA4,
        };

        *buf_size_out = backend.fbs.top_screen.len();
        backend.fbs.top_screen.as_ptr()
    }

    pub unsafe extern fn bot_screen(backend: *mut c::Backend,
                                    buf_size_out: *mut usize,
                                    color_fmt: *mut c::ColorFormat) -> *const u8 {
        let backend = Backend::from_c(backend);

        backend.update_fb_state();
        if backend.fb_state.is_none() {
            *buf_size_out = 0;
            *color_fmt = c::ColorFormat_COLOR_RGB8;
            return std::ptr::null();
        }
        let fb_state = backend.fb_state.as_ref().unwrap();

        backend.debugger.ctx(Arm9)
            .hwcore_mut()
            .copy_framebuffers(&mut backend.fbs, fb_state);

        *color_fmt = match fb_state.color_fmt[1] {
            ColorFormat::Rgb8 => c::ColorFormat_COLOR_RGB8,
            ColorFormat::Rgba8 => {
                fix_color_rgba8(backend.fbs.bot_screen.as_mut_slice());
                c::ColorFormat_COLOR_RGBA8
            },
            ColorFormat::Rgb565 => c::ColorFormat_COLOR_RGB565,
            ColorFormat::Rgb5a1 => c::ColorFormat_COLOR_RGB5A1,
            ColorFormat::Rgba4 => c::ColorFormat_COLOR_RGBA4,
        };

        *buf_size_out = backend.fbs.bot_screen.len();
        backend.fbs.bot_screen.as_ptr()
    }

    pub unsafe extern fn mod_button(backend: *mut c::Backend, button: i32, pressed: bool) {
        let backend = Backend::from_c(backend);
        let button = match button as u32 {
            c::Button_BUTTON_A => hid::Button::A,
            c::Button_BUTTON_B => hid::Button::B,
            c::Button_BUTTON_X => hid::Button::X,
            c::Button_BUTTON_Y => hid::Button::Y,
            c::Button_BUTTON_L => hid::Button::L,
            c::Button_BUTTON_R => hid::Button::R,
            c::Button_BUTTON_UP => hid::Button::Up,
            c::Button_BUTTON_DOWN => hid::Button::Down,
            c::Button_BUTTON_LEFT => hid::Button::Left,
            c::Button_BUTTON_RIGHT => hid::Button::Right,
            c::Button_BUTTON_SELECT => hid::Button::Select,
            c::Button_BUTTON_START => hid::Button::Start,
            _ => unreachable!()
        };
        let state = if pressed { hid::ButtonState::Pressed(button) }
                    else { hid::ButtonState::Released(button) };
        backend.msg_client.send(Message::HidUpdate(state));
    }

    pub unsafe extern fn run_command(backend: *mut c::Backend, str_buf: *const i8, str_len: usize) {
        let backend = Backend::from_c(backend);
        let input = {
            let slice = slice::from_raw_parts(str_buf as *const u8, str_len);
            str::from_utf8(slice).unwrap()
        };

        for cmd in input.split(';') {
            lgl::log("> ");
            lgl::log(cmd);
            lgl::log("\n");
            commands::handle(&mut backend.cmd_active_cpu, &mut backend.debugger, cmd.split_whitespace());
        }
    }

    pub unsafe extern fn use_trace_logs(_: *mut c::Backend, val: bool) {
        uilog::allow_trace(val);
    }

    pub unsafe extern fn reload_game(backend: *mut c::Backend) {
        let backend = Backend::from_c(backend);
        backend.msg_client.send(Message::Quit);
        backend.gdb.wait(); // Need to wait because the GDB thread owns the port
        *backend = super::load_game(backend.loader);
    }

    pub unsafe extern fn log(buf: c::LogBufferView) {
        let s = {
            let slice = slice::from_raw_parts(buf.buf_ptr as *const u8, buf.buf_size);
            str::from_utf8(slice).unwrap()
        };
        lgl::log(s)
    }

    pub unsafe extern fn buffer(buf: c::LogBufferMutView) -> c::LogBufferView {
        let new_slice = lgl::buffer(slice::from_raw_parts_mut(buf.buf_ptr as *mut u8, buf.buf_size));
        c::LogBufferView { buf_ptr: new_slice.as_ptr() as *const i8, buf_size: new_slice.len() }
    }

    pub extern fn buffer_size() -> usize {
        lgl::BUFFER_SIZE
    }
}

fn load_game<'a>(loader: &'a dyn ldr::Loader) -> Backend<'a> {
    let fbs = hwcore::Framebuffers::default();

    let mut hwcore = hwcore::HwCore::new(loader);
    let client_gdb = hwcore.take_client_gdb().unwrap();
    let client_user = hwcore.take_client_user().unwrap();

    let debugger = dbgcore::DbgCore::bind(hwcore);

    info!("Using ARM9 as active debug CPU");

    let backend = Backend {
        loader: loader,
        debugger: debugger.clone(),
        cmd_active_cpu: dbgcore::ActiveCpu::Arm9,
        gdb: gdbstub::GdbStub::new(client_gdb, debugger),
        fbs: fbs,
        fb_state: None,
        msg_client: client_user,
    };

    backend
}

fn c_args() -> Vec<Box<[u8]>> {
    let into_c_str = |arg: String| {
        let mut vec = arg.into_bytes();
        vec.push(b'\0');
        vec.into_boxed_slice()
    };

    let args = env::args();
    args.map(into_c_str)
        .collect()
}

fn main() {
    let _logger = uilog::init().unwrap();

    let path = env::args().nth(1).unwrap();
    let loader = ldr::make_loader(Path::new(&path));

    let callbacks = c::FrontendCallbacks {
        set_running: Some(cbs::set_running),
        is_running: Some(cbs::is_running),
        reload_game: Some(cbs::reload_game),

        top_screen: Some(cbs::top_screen),
        bot_screen: Some(cbs::bot_screen),
        mod_button: Some(cbs::mod_button),

        run_command: Some(cbs::run_command),
        use_trace_logs: Some(cbs::use_trace_logs),
        log: Some(cbs::log),
        buffer: Some(cbs::buffer),
        buffer_size: Some(cbs::buffer_size),
    };

    let mut backend = load_game(loader.as_ref());
    let mut args = c_args();
    let mut c_args: Vec<*mut u8> = args.iter_mut()
        .map(|arg| &mut arg[0] as *mut u8)
        .collect();

    unsafe {
        c::llama_open_gui(
            c_args.len() as i32,
            c_args.as_mut_ptr() as *mut *mut i8,
            backend.to_c(),
            &callbacks)
    };
}
<|endoftext|>


<commit_before>//! TODO Documentation

use std::{panic, ptr};
use std::ffi::CStr;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use libc::c_float;
use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wlroots_sys::{wl_output_transform, wlr_output, wlr_output_effective_resolution,
                  wlr_output_events, wlr_output_make_current, wlr_output_mode,
                  wlr_output_set_mode, wlr_output_set_transform, wlr_output_swap_buffers};

use super::output_layout::OutputLayoutHandle;
use super::output_mode::OutputMode;
use errors::{UpgradeHandleErr, UpgradeHandleResult};
use utils::c_to_rust_string;

use Surface;

struct OutputState {
    handle: Weak<AtomicBool>,
    layout_handle: Option<OutputLayoutHandle>
}

#[derive(Debug)]
pub struct Output {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `OutputHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `OutputHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

/// A wrapper around a wlr_output.
#[derive(Debug)]
pub struct OutputHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

impl Output {
    /// Just like `std::clone::Clone`, but unsafe.
    ///
    /// # Unsafety
    /// You can create a reference leak using this method very easily,
    /// and it could make it so that weak handles to an output are dangling.
    ///
    /// This exists due to an issue in output_manager.rs that might be fixed
    /// with NLL, so if this is no longer necessary it should be removed asap.
    pub(crate) unsafe fn clone(&self) -> Output {
        Output { liveliness: self.liveliness.clone(),
                 output: self.output }
    }

    /// Makes a new `Output` from a `wlr_output`.
    ///
    /// # Safety
    /// This creates a totally new Output (e.g with its own reference count)
    /// so only do this once per `wlr_output`!
    pub(crate) unsafe fn new(output: *mut wlr_output) -> Self {
        (*output).data = ptr::null_mut();
        let liveliness = Rc::new(AtomicBool::new(false));
        let handle = Rc::downgrade(&liveliness);
        let state = Box::new(OutputState { handle,
                                           layout_handle: None });
        (*output).data = Box::into_raw(state) as *mut _;
        Output { liveliness: Some(liveliness),
                 output }
    }

    pub(crate) unsafe fn set_output_layout(&mut self, layout_handle: Option<OutputLayoutHandle>) {
        self.remove_from_output_layout();
        let user_data = self.user_data();
        if user_data.is_null() {
            return
        }
        let mut data = Box::from_raw(user_data);
        data.layout_handle = layout_handle;
        (*self.output).data = Box::into_raw(data) as *mut _;
    }

    unsafe fn user_data(&mut self) -> *mut OutputState {
        (*self.output).data as *mut _
    }

    /// Used to clear the pointer to an OutputLayout when the OutputLayout
    /// removes this Output from its listing.
    pub(crate) unsafe fn clear_output_layout_data(&mut self) {
        let user_data = self.user_data();
        if user_data.is_null() {
            return
        }
        let mut data = Box::from_raw(user_data);
        data.layout_handle = None;
        (*self.output).data = Box::into_raw(data) as *mut _;
    }

    /// Remove this Output from an OutputLayout, if it is part of an
    /// OutputLayout.
    pub(crate) unsafe fn remove_from_output_layout(&mut self) {
        let output_data = self.user_data();
        if output_data.is_null() {
            return
        }
        // Remove output from previous output layout.
        if let Some(mut layout_handle) = (*output_data).layout_handle.take() {
            match layout_handle.run(|layout| layout.remove(self)) {
                Ok(_) | Err(UpgradeHandleErr::AlreadyDropped) => self.clear_output_layout_data(),
                Err(UpgradeHandleErr::AlreadyBorrowed) => {
                    panic!("Could not add OutputLayout to Output user data!")
                }
            }
        }
    }

    /// Gets the OutputLayout this Output is a part of, if it is part
    /// of an OutputLayout.
    ///
    /// # Safety
    /// Note that this isn't exposed to user space, as they could easily
    /// create two mutable pointers to the same structure. We keep it internally
    /// though because we use it during the cleanup process.
    pub(crate) unsafe fn layout(&mut self) -> Option<OutputLayoutHandle> {
        let data = self.user_data();
        if data.is_null() {
            None
        } else {
            (*data).layout_handle.clone()
        }
    }

    /// Sets the best modesetting for an output.
    ///
    /// NOTE You _cannot_ call this when the output will be removed.
    ///
    /// I'm still marking it as safe though because we protect against that
    /// action in the output destruction callback.
    pub fn choose_best_mode(&mut self) {
        unsafe {
            let modes = (*self.output).modes;
            let length = ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                       wl_list_length,
                                       &modes as *const _ as _);
            if length > 0 {
                // TODO Better logging
                wlr_log!(L_DEBUG, "output added {:?}", self);
                let first_mode_ptr: *mut wlr_output_mode;
                first_mode_ptr = container_of!(&mut (*modes.prev) as *mut _, wlr_output_mode, link);
                wlr_output_set_mode(self.as_ptr(), first_mode_ptr);
            }
        }
    }

    /// Gets the name of the output in UTF-8.
    pub fn name(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).name.as_ptr()).to_string_lossy()
                                                        .into_owned()
        }
    }

    /// Gets the make of the output in UTF-8.
    pub fn make(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).make.as_ptr()).expect("Could not parse make as UTF-8")
        }
    }

    /// Gets the model of the output in UTF-8.
    pub fn model(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).model.as_ptr()).expect("Could not parse model as UTF-8")
        }
    }

    /// Gets the serial of the output in UTF-8.
    pub fn serial(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).serial.as_ptr()).expect("Could not parse serial as \
                                                                     UTF-8")
        }
    }

    /// Determines if the output is enabled or not.
    pub fn enabled(&self) -> bool {
        unsafe { (*self.output).enabled }
    }

    /// Get the scale of the output
    pub fn scale(&self) -> c_float {
        unsafe { (*self.output).scale }
    }

    /// Determines if the output should have its buffers swapped or not.
    pub fn needs_swap(&self) -> bool {
        unsafe { (*self.output).needs_swap }
    }

    pub fn current_mode(&self) -> Option<OutputMode> {
        unsafe {
            if (*self.output).current_mode.is_null() {
                None
            } else {
                Some(OutputMode::new((*self.output).current_mode))
            }
        }
    }

    pub fn fullscreen_surface(&self) -> Option<Surface> {
        unsafe {
            if (*self.output).fullscreen_surface.is_null() {
                None
            } else {
                Some(Surface::from_ptr((*self.output).fullscreen_surface))
            }
        }
    }

    /// Gets the output position in layout space reported to clients.
    pub fn layout_space_pos(&self) -> (i32, i32) {
        unsafe { ((*self.output).lx, (*self.output).ly) }
    }

    pub fn make_current(&mut self) {
        unsafe { wlr_output_make_current(self.output) }
    }

    pub fn swap_buffers(&mut self) {
        unsafe { wlr_output_swap_buffers(self.output) }
    }

    /// Get the dimensions of the output as (width, height).
    pub fn dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).width, (*self.output).height) }
    }

    /// Get the physical dimensions of the output as (width, height).
    pub fn physical_dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).phys_width, (*self.output).phys_height) }
    }

    pub fn effective_resolution(&self) -> (i32, i32) {
        unsafe {
            let (mut x, mut y) = (0, 0);
            wlr_output_effective_resolution(self.output, &mut x, &mut y);
            (x, y)
        }
    }

    pub fn transform_matrix(&self) -> [c_float; 16] {
        unsafe { (*self.output).transform_matrix }
    }

    pub fn transform(&mut self, transform: wl_output_transform) {
        unsafe {
            wlr_output_set_transform(self.output, transform);
        }
    }

    /// Get the modes associated with this output.
    ///
    /// Note that some backends may have zero modes.
    pub fn modes(&self) -> Vec<OutputMode> {
        unsafe {
            let mut result = vec![];
            wl_list_for_each!((*self.output).modes, link, (mode: wlr_output_mode) => {
                result.push(OutputMode::new(mode))
            });
            result
        }
    }

    /// TODO Make safe
    pub unsafe fn events(&self) -> wlr_output_events {
        (*self.output).events
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }

    /// Creates a weak reference to an `Output`.
    ///
    /// # Panics
    /// If this `Output` is a previously upgraded `OutputHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> OutputHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade a previously upgraded OutputHandle");
        OutputHandle { handle: Rc::downgrade(arc),
                       output: self.output }
    }

    unsafe fn from_handle(handle: &OutputHandle) -> Self {
        Output { liveliness: None,
                 output: handle.as_ptr() }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Output")
            .store(val, Ordering::Release);
    }
}

impl Drop for Output {
    fn drop(&mut self) {
        // NOTE
        // We do _not_ need to call wlr_output_destroy for the output
        // That is handled by the backend automatically
        match self.liveliness {
            None => return,
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped output {:p}", self.output);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Output {:p}",
                                 weak_count,
                                 self.output);
                    }
                } else {
                    return
                }
            }
        }
        // TODO Move back up in the some after NLL is a thing.
        unsafe {
            self.remove_from_output_layout();
        }
    }
}

impl OutputHandle {
    /// Creates an OutputHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(output: *mut wlr_output) -> Self {
        let data = Box::from_raw((*output).data as *mut OutputState);
        let handle = data.handle.clone();
        (*output).data = Box::into_raw(data) as *mut _;
        OutputHandle { handle, output }
    }

    /// Upgrades the output handle to a reference to the backing `Output`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Output`
    /// which may live forever..
    /// But no output lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Output> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let output = Output::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(output)
            })
    }

    /// Run a function on the referenced Output, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Output does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Output) -> R
    {
        let mut output = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut output)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running output callback, mutable lock \
                                                    was false for: {:?}",
                                                   output);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }
}

impl PartialEq for OutputHandle {
    fn eq(&self, other: &OutputHandle) -> bool {
        self.output == other.output
    }
}

impl Eq for OutputHandle {}
<commit_msg>Removed output::events<commit_after>//! TODO Documentation

use std::{panic, ptr};
use std::ffi::CStr;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering};

use libc::c_float;
use wayland_sys::server::WAYLAND_SERVER_HANDLE;
use wlroots_sys::{wl_output_transform, wlr_output, wlr_output_effective_resolution,
                  wlr_output_events, wlr_output_make_current, wlr_output_mode,
                  wlr_output_set_mode, wlr_output_set_transform, wlr_output_swap_buffers};

use super::output_layout::OutputLayoutHandle;
use super::output_mode::OutputMode;
use errors::{UpgradeHandleErr, UpgradeHandleResult};
use utils::c_to_rust_string;

use Surface;

struct OutputState {
    handle: Weak<AtomicBool>,
    layout_handle: Option<OutputLayoutHandle>
}

#[derive(Debug)]
pub struct Output {
    /// The structure that ensures weak handles to this structure are still alive.
    ///
    /// They contain weak handles, and will safely not use dead memory when this
    /// is freed by wlroots.
    ///
    /// If this is `None`, then this is from an upgraded `OutputHandle`, and
    /// the operations are **unchecked**.
    /// This is means safe operations might fail, but only if you use the unsafe
    /// marked function `upgrade` on a `OutputHandle`.
    liveliness: Option<Rc<AtomicBool>>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

/// A wrapper around a wlr_output.
#[derive(Debug)]
pub struct OutputHandle {
    /// The Rc that ensures that this handle is still alive.
    ///
    /// When wlroots deallocates the pointer associated with this handle,
    /// this can no longer be used.
    handle: Weak<AtomicBool>,
    /// The output ptr that refers to this `Output`
    output: *mut wlr_output
}

impl Output {
    /// Just like `std::clone::Clone`, but unsafe.
    ///
    /// # Unsafety
    /// You can create a reference leak using this method very easily,
    /// and it could make it so that weak handles to an output are dangling.
    ///
    /// This exists due to an issue in output_manager.rs that might be fixed
    /// with NLL, so if this is no longer necessary it should be removed asap.
    pub(crate) unsafe fn clone(&self) -> Output {
        Output { liveliness: self.liveliness.clone(),
                 output: self.output }
    }

    /// Makes a new `Output` from a `wlr_output`.
    ///
    /// # Safety
    /// This creates a totally new Output (e.g with its own reference count)
    /// so only do this once per `wlr_output`!
    pub(crate) unsafe fn new(output: *mut wlr_output) -> Self {
        (*output).data = ptr::null_mut();
        let liveliness = Rc::new(AtomicBool::new(false));
        let handle = Rc::downgrade(&liveliness);
        let state = Box::new(OutputState { handle,
                                           layout_handle: None });
        (*output).data = Box::into_raw(state) as *mut _;
        Output { liveliness: Some(liveliness),
                 output }
    }

    pub(crate) unsafe fn set_output_layout(&mut self, layout_handle: Option<OutputLayoutHandle>) {
        self.remove_from_output_layout();
        let user_data = self.user_data();
        if user_data.is_null() {
            return
        }
        let mut data = Box::from_raw(user_data);
        data.layout_handle = layout_handle;
        (*self.output).data = Box::into_raw(data) as *mut _;
    }

    unsafe fn user_data(&mut self) -> *mut OutputState {
        (*self.output).data as *mut _
    }

    /// Used to clear the pointer to an OutputLayout when the OutputLayout
    /// removes this Output from its listing.
    pub(crate) unsafe fn clear_output_layout_data(&mut self) {
        let user_data = self.user_data();
        if user_data.is_null() {
            return
        }
        let mut data = Box::from_raw(user_data);
        data.layout_handle = None;
        (*self.output).data = Box::into_raw(data) as *mut _;
    }

    /// Remove this Output from an OutputLayout, if it is part of an
    /// OutputLayout.
    pub(crate) unsafe fn remove_from_output_layout(&mut self) {
        let output_data = self.user_data();
        if output_data.is_null() {
            return
        }
        // Remove output from previous output layout.
        if let Some(mut layout_handle) = (*output_data).layout_handle.take() {
            match layout_handle.run(|layout| layout.remove(self)) {
                Ok(_) | Err(UpgradeHandleErr::AlreadyDropped) => self.clear_output_layout_data(),
                Err(UpgradeHandleErr::AlreadyBorrowed) => {
                    panic!("Could not add OutputLayout to Output user data!")
                }
            }
        }
    }

    /// Gets the OutputLayout this Output is a part of, if it is part
    /// of an OutputLayout.
    ///
    /// # Safety
    /// Note that this isn't exposed to user space, as they could easily
    /// create two mutable pointers to the same structure. We keep it internally
    /// though because we use it during the cleanup process.
    pub(crate) unsafe fn layout(&mut self) -> Option<OutputLayoutHandle> {
        let data = self.user_data();
        if data.is_null() {
            None
        } else {
            (*data).layout_handle.clone()
        }
    }

    /// Sets the best modesetting for an output.
    ///
    /// NOTE You _cannot_ call this when the output will be removed.
    ///
    /// I'm still marking it as safe though because we protect against that
    /// action in the output destruction callback.
    pub fn choose_best_mode(&mut self) {
        unsafe {
            let modes = (*self.output).modes;
            let length = ffi_dispatch!(WAYLAND_SERVER_HANDLE,
                                       wl_list_length,
                                       &modes as *const _ as _);
            if length > 0 {
                // TODO Better logging
                wlr_log!(L_DEBUG, "output added {:?}", self);
                let first_mode_ptr: *mut wlr_output_mode;
                first_mode_ptr = container_of!(&mut (*modes.prev) as *mut _, wlr_output_mode, link);
                wlr_output_set_mode(self.as_ptr(), first_mode_ptr);
            }
        }
    }

    /// Gets the name of the output in UTF-8.
    pub fn name(&self) -> String {
        unsafe {
            CStr::from_ptr((*self.output).name.as_ptr()).to_string_lossy()
                                                        .into_owned()
        }
    }

    /// Gets the make of the output in UTF-8.
    pub fn make(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).make.as_ptr()).expect("Could not parse make as UTF-8")
        }
    }

    /// Gets the model of the output in UTF-8.
    pub fn model(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).model.as_ptr()).expect("Could not parse model as UTF-8")
        }
    }

    /// Gets the serial of the output in UTF-8.
    pub fn serial(&self) -> String {
        unsafe {
            c_to_rust_string((*self.output).serial.as_ptr()).expect("Could not parse serial as \
                                                                     UTF-8")
        }
    }

    /// Determines if the output is enabled or not.
    pub fn enabled(&self) -> bool {
        unsafe { (*self.output).enabled }
    }

    /// Get the scale of the output
    pub fn scale(&self) -> c_float {
        unsafe { (*self.output).scale }
    }

    /// Determines if the output should have its buffers swapped or not.
    pub fn needs_swap(&self) -> bool {
        unsafe { (*self.output).needs_swap }
    }

    pub fn current_mode(&self) -> Option<OutputMode> {
        unsafe {
            if (*self.output).current_mode.is_null() {
                None
            } else {
                Some(OutputMode::new((*self.output).current_mode))
            }
        }
    }

    pub fn fullscreen_surface(&self) -> Option<Surface> {
        unsafe {
            if (*self.output).fullscreen_surface.is_null() {
                None
            } else {
                Some(Surface::from_ptr((*self.output).fullscreen_surface))
            }
        }
    }

    /// Gets the output position in layout space reported to clients.
    pub fn layout_space_pos(&self) -> (i32, i32) {
        unsafe { ((*self.output).lx, (*self.output).ly) }
    }

    pub fn make_current(&mut self) {
        unsafe { wlr_output_make_current(self.output) }
    }

    pub fn swap_buffers(&mut self) {
        unsafe { wlr_output_swap_buffers(self.output) }
    }

    /// Get the dimensions of the output as (width, height).
    pub fn dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).width, (*self.output).height) }
    }

    /// Get the physical dimensions of the output as (width, height).
    pub fn physical_dimensions(&self) -> (i32, i32) {
        unsafe { ((*self.output).phys_width, (*self.output).phys_height) }
    }

    pub fn effective_resolution(&self) -> (i32, i32) {
        unsafe {
            let (mut x, mut y) = (0, 0);
            wlr_output_effective_resolution(self.output, &mut x, &mut y);
            (x, y)
        }
    }

    pub fn transform_matrix(&self) -> [c_float; 16] {
        unsafe { (*self.output).transform_matrix }
    }

    pub fn transform(&mut self, transform: wl_output_transform) {
        unsafe {
            wlr_output_set_transform(self.output, transform);
        }
    }

    /// Get the modes associated with this output.
    ///
    /// Note that some backends may have zero modes.
    pub fn modes(&self) -> Vec<OutputMode> {
        unsafe {
            let mut result = vec![];
            wl_list_for_each!((*self.output).modes, link, (mode: wlr_output_mode) => {
                result.push(OutputMode::new(mode))
            });
            result
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }

    /// Creates a weak reference to an `Output`.
    ///
    /// # Panics
    /// If this `Output` is a previously upgraded `OutputHandle`,
    /// then this function will panic.
    pub fn weak_reference(&self) -> OutputHandle {
        let arc = self.liveliness.as_ref()
                      .expect("Cannot downgrade a previously upgraded OutputHandle");
        OutputHandle { handle: Rc::downgrade(arc),
                       output: self.output }
    }

    unsafe fn from_handle(handle: &OutputHandle) -> Self {
        Output { liveliness: None,
                 output: handle.as_ptr() }
    }

    /// Manually set the lock used to determine if a double-borrow is
    /// occuring on this structure.
    ///
    /// # Panics
    /// Panics when trying to set the lock on an upgraded handle.
    pub(crate) unsafe fn set_lock(&self, val: bool) {
        self.liveliness.as_ref()
            .expect("Tried to set lock on borrowed Output")
            .store(val, Ordering::Release);
    }
}

impl Drop for Output {
    fn drop(&mut self) {
        // NOTE
        // We do _not_ need to call wlr_output_destroy for the output
        // That is handled by the backend automatically
        match self.liveliness {
            None => return,
            Some(ref liveliness) => {
                if Rc::strong_count(liveliness) == 1 {
                    wlr_log!(L_DEBUG, "Dropped output {:p}", self.output);
                    let weak_count = Rc::weak_count(liveliness);
                    if weak_count > 0 {
                        wlr_log!(L_DEBUG,
                                 "Still {} weak pointers to Output {:p}",
                                 weak_count,
                                 self.output);
                    }
                } else {
                    return
                }
            }
        }
        // TODO Move back up in the some after NLL is a thing.
        unsafe {
            self.remove_from_output_layout();
        }
    }
}

impl OutputHandle {
    /// Creates an OutputHandle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    pub(crate) unsafe fn from_ptr(output: *mut wlr_output) -> Self {
        let data = Box::from_raw((*output).data as *mut OutputState);
        let handle = data.handle.clone();
        (*output).data = Box::into_raw(data) as *mut _;
        OutputHandle { handle, output }
    }

    /// Upgrades the output handle to a reference to the backing `Output`.
    ///
    /// # Unsafety
    /// This function is unsafe, because it creates an unbound `Output`
    /// which may live forever..
    /// But no output lives forever and might be disconnected at any time.
    pub(crate) unsafe fn upgrade(&self) -> UpgradeHandleResult<Output> {
        self.handle.upgrade()
            .ok_or(UpgradeHandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let output = Output::from_handle(self);
                if check.load(Ordering::Acquire) {
                    return Err(UpgradeHandleErr::AlreadyBorrowed)
                }
                check.store(true, Ordering::Release);
                Ok(output)
            })
    }

    /// Run a function on the referenced Output, if it still exists
    ///
    /// Returns the result of the function, if successful
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the output
    /// to a short lived scope of an anonymous function,
    /// this function ensures the Output does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if you run this function within the another run to the same `Output`.
    ///
    /// So don't nest `run` calls and everything will be ok :).
    pub fn run<F, R>(&mut self, runner: F) -> UpgradeHandleResult<R>
        where F: FnOnce(&mut Output) -> R
    {
        let mut output = unsafe { self.upgrade()? };
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut output)));
        self.handle.upgrade().map(|check| {
                                      // Sanity check that it hasn't been tampered with.
                                      if !check.load(Ordering::Acquire) {
                                          wlr_log!(L_ERROR,
                                                   "After running output callback, mutable lock \
                                                    was false for: {:?}",
                                                   output);
                                          panic!("Lock in incorrect state!");
                                      }
                                      check.store(false, Ordering::Release);
                                  });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_output {
        self.output
    }
}

impl PartialEq for OutputHandle {
    fn eq(&self, other: &OutputHandle) -> bool {
        self.output == other.output
    }
}

impl Eq for OutputHandle {}
<|endoftext|>


<commit_before>extern crate docker;

use docker::Client;

#[test]
fn get_all(){
    let client = Client::from_env();

    assert!(client.images().all().unwrap().len()>1);
    assert!(client.containers().all().unwrap().len()>1);
    assert!(client.networks().all().unwrap().len()>1);
}<commit_msg>add swarm to integreation test<commit_after>extern crate docker;

use docker::Client;

#[test]
fn get_all(){
    let client = Client::from_env();

    assert!(client.images().all().unwrap().len()>1);
    assert!(client.containers().all().unwrap().len()>1);
    assert!(client.networks().all().unwrap().len()>1);
    assert!(client.swarm().get().is_ok());
}<|endoftext|>


<commit_before>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::async::Server;

use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};
use futures_cpupool::CpuPool;

use std::sync::{RwLock, Arc, Mutex};
use std::thread;
use std::rc::Rc;
use std::fmt::Debug;
use std::time::Duration;
use std::ops::Deref;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let remote = core.remote();
    let server = Server::bind("localhost:8081", &handle).unwrap();
    let pool = Rc::new(CpuPool::new_num_cpus());
    let connections = Arc::new(RwLock::new(Vec::new()));
    let state = Arc::new(RwLock::new(State::new()));
    let (read_channel_out, read_channel_in) = futures::sync::mpsc::unbounded();
    let handle_inner = handle.clone();
    let connections_inner = connections.clone();
    let connection_handler = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(move |(upgrade, addr)| {
            let connections = connections_inner.clone();
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle_inner);
                return Ok(());
            }
            let read_channel_out = read_channel_out.clone();
            upgrade
                .use_protocol("rust-websocket")
                .accept()
                .and_then(move |(framed, _)| {
                    let (sink, stream) = framed.split();
                    read_channel_out.send(stream).wait().unwrap();
                    connections.write().unwrap().push(Arc::new(RwLock::new(sink)));
                    Ok(())
                })
                .wait()
                .unwrap();
            Ok(())
        })
        .map_err(|_| ());

    let state_read = state.clone();
    let remote_write = remote.clone();
    let read_handler = pool.spawn_fn(|| {
        read_channel_in.for_each(move |stream| {
            let state_read = state_read.clone();
            remote_write.spawn(|_| {
                stream.for_each(move |msg| {
                                    handle_incoming(&mut state_read.write().unwrap(), &msg);
                                    Ok(())
                                })
                    .map_err(|_| ())
            });
            Ok(())
        })
    });

    let connections_inner = connections.clone();
    let (write_channel_out, write_channel_in) = futures::sync::mpsc::unbounded();

    type MessageCodec = websocket::async::MessageCodec<OwnedMessage>;
    type Framed = websocket::client::async::Framed<tokio_core::net::TcpStream, MessageCodec>;
    type SplitSink = futures::stream::SplitSink<Framed>;
    let write_handler = pool.spawn_fn(move || {
        write_channel_in.for_each(move |(sink, state): (Arc<RwLock<SplitSink>>,
                                                        Arc<RwLock<State>>)| {
                let msg = serde_json::to_string(state.read().unwrap().deref()).unwrap();
                println!("Sending message: {}", msg);
                sink.write()
                    .unwrap()
                    .start_send(OwnedMessage::Text(msg))
                    .unwrap();
                sink.write()
                    .unwrap()
                    .poll_complete()
                    .unwrap();
                Ok(())
            })
            .map_err(|_| ())
    });

    let game_loop = pool.spawn_fn(move || {
        future::loop_fn(write_channel_out, move |write_channel_out| {
            thread::sleep(Duration::from_millis(100));
            if !connections.read().unwrap().is_empty() {
                write_channel_out
                    .clone()
                    .send((connections.write().unwrap()[0].clone(), state.clone()))
                    .wait()
                    .unwrap();
            }
            match 1 {
                1 => Ok(Loop::Continue(write_channel_out)),
                2 => Ok(Loop::Break(())),
                _ => Err(()),
            }
        })
    });

    let handlers = game_loop
        .select2(connection_handler
        .select2(read_handler
        .select(write_handler)));
    core
        .run(handlers)
        .map_err(|_| println!("err"))
        .unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &OwnedMessage) {
    match msg {
        &OwnedMessage::Text(ref txt) => {
            println!("Received message: {}", txt);
            //state.msg = txt.clone();
        }
        _ => {}
    }
}

#[derive(Serialize, Deserialize)]
struct State {
    positions: Vec<Pos>,
}

impl State {
    fn new() -> Self {
        Self { positions: Vec::new() }
    }
}

#[derive(Serialize, Deserialize)]
struct Pos {
    x: i32,
    y: i32,
}

impl Pos {
    fn new(x: i32, y: i32) -> Self {
        Self { x, y }
    }

    fn add_x(&mut self, x: i32) -> &mut Self {
        self.x += x;
        self
    }

    fn add_y(&mut self, y: i32) -> &mut Self {
        self.y += y;
        self
    }

    fn add(&mut self, x: i32, y: i32) -> &mut Self {
        self.x += x;
        self.y += y;
        self
    }
}
<commit_msg>Core: Accomodate to clippy<commit_after>extern crate websocket;
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::async::Server;

use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};
use futures_cpupool::CpuPool;

use std::sync::{RwLock, Arc};
use std::thread;
use std::rc::Rc;
use std::fmt::Debug;
use std::time::Duration;
use std::ops::Deref;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let remote = core.remote();
    let server = Server::bind("localhost:8081", &handle).unwrap();
    let pool = Rc::new(CpuPool::new_num_cpus());
    let connections = Arc::new(RwLock::new(Vec::new()));
    let state = Arc::new(RwLock::new(State::new()));
    let (read_channel_out, read_channel_in) = futures::sync::mpsc::unbounded();
    let handle_inner = handle.clone();
    let connections_inner = connections.clone();
    let connection_handler = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(move |(upgrade, addr)| {
            let connections = connections_inner.clone();
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle_inner);
                return Ok(());
            }
            let read_channel_out = read_channel_out.clone();
            upgrade
                .use_protocol("rust-websocket")
                .accept()
                .and_then(move |(framed, _)| {
                    let (sink, stream) = framed.split();
                    read_channel_out.send(stream).wait().unwrap();
                    connections.write().unwrap().push(Arc::new(RwLock::new(sink)));
                    Ok(())
                })
                .wait()
                .unwrap();
            Ok(())
        })
        .map_err(|_| ());

    let state_read = state.clone();
    let remote_write = remote.clone();
    let read_handler = pool.spawn_fn(|| {
        read_channel_in.for_each(move |stream| {
            let state_read = state_read.clone();
            remote_write.spawn(|_| {
                stream.for_each(move |msg| {
                                    handle_incoming(&mut state_read.write().unwrap(), &msg);
                                    Ok(())
                                })
                    .map_err(|_| ())
            });
            Ok(())
        })
    });

    let (write_channel_out, write_channel_in) = futures::sync::mpsc::unbounded();

    type MessageCodec = websocket::async::MessageCodec<OwnedMessage>;
    type Framed = websocket::client::async::Framed<tokio_core::net::TcpStream, MessageCodec>;
    type SplitSink = futures::stream::SplitSink<Framed>;
    let write_handler = pool.spawn_fn(move || {
        write_channel_in.for_each(move |(sink, state): (Arc<RwLock<SplitSink>>,
                                                        Arc<RwLock<State>>)| {
                let msg = serde_json::to_string(state.read().unwrap().deref()).unwrap();
                println!("Sending message: {}", msg);
                sink.write()
                    .unwrap()
                    .start_send(OwnedMessage::Text(msg))
                    .unwrap();
                sink.write()
                    .unwrap()
                    .poll_complete()
                    .unwrap();
                Ok(())
            })
            .map_err(|_| ())
    });

    let game_loop = pool.spawn_fn(move || {
        future::loop_fn(write_channel_out, move |write_channel_out| {
            thread::sleep(Duration::from_millis(100));
            if !connections.read().unwrap().is_empty() {
                write_channel_out.clone()
                    .send((connections.write().unwrap()[0].clone(), state.clone()))
                    .wait()
                    .unwrap();
            }
            match 1 {
                1 => Ok(Loop::Continue(write_channel_out)),
                2 => Ok(Loop::Break(())),
                _ => Err(()),
            }
        })
    });

    let handlers =
        game_loop.select2(connection_handler.select2(read_handler.select(write_handler)));
    core.run(handlers).map_err(|_| println!("err")).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("Error in {}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(_: &mut State, msg: &OwnedMessage) {
    if let OwnedMessage::Text(ref txt) = *msg {
        println!("Received message: {}", txt);
        //state.msg = txt.clone();
    }
}

#[derive(Serialize, Deserialize)]
struct State {
    positions: Vec<Pos>,
}

impl State {
    fn new() -> Self {
        Self { positions: Vec::new() }
    }
}

#[derive(Serialize, Deserialize)]
struct Pos {
    x: i32,
    y: i32,
}

/*
impl Pos {
    fn new(x: i32, y: i32) -> Self {
        Self { x, y }
    }

    fn add_x(&mut self, x: i32) -> &mut Self {
        self.x += x;
        self
    }

    fn add_y(&mut self, y: i32) -> &mut Self {
        self.y += y;
        self
    }

    fn add(&mut self, x: i32, y: i32) -> &mut Self {
        self.x += x;
        self.y += y;
        self
    }
}
*/
<|endoftext|>