<commit_before>//! A "prelude" for users of the `tokio` crate.
//!
//! This prelude is similar to the standard library's prelude in that you'll
//! almost always want to import its entire contents, but unlike the standard
//! library's prelude you'll have to do so manually:
//!
//! ```
//! # #![allow(warnings)]
//! use tokio::prelude::*;
//! ```
//!
//! The prelude may grow over time as additional items see ubiquitous use.

pub use crate::future::FutureExt as _;
pub use futures_util::future::FutureExt as _;
pub use std::future::Future;

pub use crate::stream::{Stream, StreamExt as _};
pub use futures_sink::Sink;
pub use futures_util::sink::SinkExt as _;
pub use futures_util::stream::StreamExt as _;

#[cfg(feature = "io")]
pub use tokio_io::{
    AsyncBufRead, AsyncBufReadExt as _, AsyncRead, AsyncReadExt as _, AsyncWrite,
    AsyncWriteExt as _,
};
<commit_msg>chore: annotate prelude re-exports as `doc(no_inline)` (#1601)<commit_after>//! A "prelude" for users of the `tokio` crate.
//!
//! This prelude is similar to the standard library's prelude in that you'll
//! almost always want to import its entire contents, but unlike the standard
//! library's prelude you'll have to do so manually:
//!
//! ```
//! # #![allow(warnings)]
//! use tokio::prelude::*;
//! ```
//!
//! The prelude may grow over time as additional items see ubiquitous use.

#[doc(no_inline)]
pub use crate::future::FutureExt as _;
#[doc(no_inline)]
pub use futures_util::future::FutureExt as _;
pub use std::future::Future;

pub use crate::stream::Stream;
#[doc(no_inline)]
pub use crate::stream::StreamExt as _;
pub use futures_sink::Sink;
#[doc(no_inline)]
pub use futures_util::sink::SinkExt as _;
#[doc(no_inline)]
pub use futures_util::stream::StreamExt as _;

#[cfg(feature = "io")]
pub use tokio_io::{AsyncBufRead, AsyncRead, AsyncWrite};
#[cfg(feature = "io")]
#[doc(no_inline)]
pub use tokio_io::{AsyncBufReadExt as _, AsyncReadExt as _, AsyncWriteExt as _};
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate tsutils;

#[macro_use]
extern crate log;

fn main() {
    env_logger::init().unwrap();

    let mut args = std::env::args().skip(1);
    if let Some(input_path) = args.next() {
        if let Some(output_path) = args.next() {
            let input = std::fs::File::open(input_path).unwrap();
            let output = std::fs::File::create(output_path).unwrap();
            drop_av(input, output).unwrap();
            return;
        }
    }
    std::process::exit(1);
}

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    PsiParseError(tsutils::psi::ParseError),
    Custom(std::borrow::Cow<'static, str>),
}

impl From<std::io::Error> for Error {
    fn from(e: std::io::Error) -> Self {
        Error::Io(e)
    }
}

impl From<&'static str> for Error {
    fn from(e: &'static str) -> Self {
        Error::Custom(std::borrow::Cow::from(e))
    }
}

impl From<String> for Error {
    fn from(e: String) -> Self {
        Error::Custom(std::borrow::Cow::from(e))
    }
}

impl From<tsutils::psi::ParseError> for Error {
    fn from(e: tsutils::psi::ParseError) -> Self {
        Error::PsiParseError(e)
    }
}

fn drop_av<R, W>(reader: R, mut writer: W) -> Result<(), Error>
    where R: std::io::Read,
          W: std::io::Write
{
    let mut pat = None;
    let mut payloads: std::collections::HashMap<u16, Vec<u8>> = std::collections::HashMap::new();
    let mut av_pids = std::collections::HashSet::new();
    let mut nonav_pids = std::collections::HashSet::new();

    for buf in tsutils::packet::ts_packets(reader) {
        let buf = try!(buf);
        let packet = tsutils::TsPacket::new(&buf);
        if !packet.check_sync_byte() {
            return Err(Error::from("sync_byte failed"));
        }
        if packet.transport_error_indicator {
            return Err(Error::from("transport_error_indicator is set"));
        }

        if packet.payload_unit_start_indicator {
            if let Some(payload) = payloads.get(&packet.pid) {
                match packet.pid {
                    0x0000 => {
                        pat = Some(try!(tsutils::ProgramAssociationTable::parse(payload)));
                    }
                    _ => {
                        if let Some(ref pat) = pat {
                            if let Some(&program_number) = pat.program_map.get(&packet.pid) {
                                let pmt = try!(tsutils::ProgramMapTable::parse(payload));
                                if pmt.program_number != program_number {
                                    return Err(Error::from(format!("Inconsistent \
                                                                    program_number for PID={}: \
                                                                    PAT says {} but PMT says {}",
                                                                   packet.pid,
                                                                   program_number,
                                                                   pmt.program_number)));
                                }
                                for es in pmt.es_info {
                                    if !av_pids.contains(&es.elementary_pid) &&
                                       !nonav_pids.contains(&es.elementary_pid) {
                                        match es.stream_type {
                                            0x0f => {
                                                // Audio
                                                av_pids.insert(es.elementary_pid);
                                            }
                                            0x02 | 0x1b => {
                                                // Video
                                                av_pids.insert(es.elementary_pid);
                                            }
                                            _ => {
                                                debug!("non-AV stream_type={:x} pid={:x}",
                                                       es.stream_type,
                                                       es.elementary_pid);
                                                nonav_pids.insert(es.elementary_pid);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if let Some(data_bytes) = packet.data_bytes {
                payloads.insert(packet.pid, data_bytes.to_vec());
            } else {
                return Err(Error::from("payload_unit_start_indicator is set, but no \
                                                 data_bytes"));
            }
        } else {
            if let Some(data_bytes) = packet.data_bytes {
                match payloads.entry(packet.pid) {
                    std::collections::hash_map::Entry::Occupied(mut entry) => {
                        entry.get_mut().extend_from_slice(data_bytes);
                    }
                    std::collections::hash_map::Entry::Vacant(entry) => {
                        entry.insert(data_bytes.to_vec());
                    }
                }
            }
        }

        if !av_pids.contains(&packet.pid) {
            try!(writer.write(&buf));
        }
    }
    Ok(())
}
<commit_msg>Simplify<commit_after>extern crate env_logger;
extern crate tsutils;

#[macro_use]
extern crate log;

fn main() {
    env_logger::init().unwrap();

    let mut args = std::env::args().skip(1);
    if let Some(input_path) = args.next() {
        if let Some(output_path) = args.next() {
            let input = std::fs::File::open(input_path).unwrap();
            let output = std::fs::File::create(output_path).unwrap();
            drop_av(input, output).unwrap();
            return;
        }
    }
    std::process::exit(1);
}

#[derive(Debug)]
pub enum Error {
    Io(std::io::Error),
    PsiParseError(tsutils::psi::ParseError),
    Custom(std::borrow::Cow<'static, str>),
}

impl From<std::io::Error> for Error {
    fn from(e: std::io::Error) -> Self {
        Error::Io(e)
    }
}

impl From<&'static str> for Error {
    fn from(e: &'static str) -> Self {
        Error::Custom(std::borrow::Cow::from(e))
    }
}

impl From<String> for Error {
    fn from(e: String) -> Self {
        Error::Custom(std::borrow::Cow::from(e))
    }
}

impl From<tsutils::psi::ParseError> for Error {
    fn from(e: tsutils::psi::ParseError) -> Self {
        Error::PsiParseError(e)
    }
}

fn drop_av<R, W>(reader: R, mut writer: W) -> Result<(), Error>
    where R: std::io::Read,
          W: std::io::Write
{
    let mut pat = None;
    let mut payloads: std::collections::HashMap<u16, Vec<u8>> = std::collections::HashMap::new();
    let mut av_pids = std::collections::HashSet::new();
    let mut nonav_pids = std::collections::HashSet::new();

    for buf in tsutils::packet::ts_packets(reader) {
        let buf = try!(buf);
        let packet = tsutils::TsPacket::new(&buf);
        if !packet.check_sync_byte() {
            return Err(Error::from("sync_byte failed"));
        }
        if packet.transport_error_indicator {
            return Err(Error::from("transport_error_indicator is set"));
        }

        if packet.payload_unit_start_indicator {
            if let Some(payload) = payloads.remove(&packet.pid) {
                match packet.pid {
                    0x0000 => {
                        pat = Some(try!(tsutils::ProgramAssociationTable::parse(&payload)));
                    }
                    _ => {
                        if let Some(ref pat) = pat {
                            if let Some(&program_number) = pat.program_map.get(&packet.pid) {
                                let pmt = try!(tsutils::ProgramMapTable::parse(&payload));
                                if pmt.program_number != program_number {
                                    return Err(Error::from(format!("Inconsistent \
                                                                    program_number for PID={}: \
                                                                    PAT says {} but PMT says {}",
                                                                   packet.pid,
                                                                   program_number,
                                                                   pmt.program_number)));
                                }
                                for es in pmt.es_info {
                                    if !av_pids.contains(&es.elementary_pid) &&
                                       !nonav_pids.contains(&es.elementary_pid) {
                                        match es.stream_type {
                                            0x0f => {
                                                // Audio
                                                av_pids.insert(es.elementary_pid);
                                            }
                                            0x02 | 0x1b => {
                                                // Video
                                                av_pids.insert(es.elementary_pid);
                                            }
                                            _ => {
                                                debug!("non-AV stream_type={:x} pid={:x}",
                                                       es.stream_type,
                                                       es.elementary_pid);
                                                nonav_pids.insert(es.elementary_pid);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        if let Some(data_bytes) = packet.data_bytes {
            payloads.entry(packet.pid)
                .or_insert(Vec::new())
                .extend_from_slice(data_bytes);
        }

        if !av_pids.contains(&packet.pid) {
            try!(writer.write(&buf));
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use crate::common::*;
use std::process::Command;

pub fn build_and_link() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let build_dir = Path::new(&out_dir).join("libffi-build");
    let prefix = Path::new(&out_dir).join("libffi-root");
    let libdir = Path::new(&prefix).join("lib");
    let libdir64 = Path::new(&prefix).join("lib64");

    // Copy LIBFFI_DIR into build_dir to avoid an unnecessary build
    if let Err(e) = fs::remove_dir_all(&build_dir) {
        assert_eq!(
            e.kind(),
            std::io::ErrorKind::NotFound,
            "can't remove the build directory: {}",
            e
        );
    }
    run_command(
        "Copying libffi into the build directory",
        Command::new("cp").arg("-R").arg("libffi").arg(&build_dir),
    );

    // Generate configure, run configure, make, make install
    configure_libffi(prefix, &build_dir);

    run_command(
        "Building libffi",
        Command::new("make")
            .env_remove("DESTDIR")
            .arg("install")
            .current_dir(&build_dir),
    );

    // Cargo linking directives
    println!("cargo:rustc-link-lib=static=ffi");
    println!("cargo:rustc-link-search={}", libdir.display());
    println!("cargo:rustc-link-search={}", libdir64.display());
}

pub fn probe_and_link() {
    println!("cargo:rustc-link-lib=dylib=ffi");
}

pub fn configure_libffi(prefix: PathBuf, build_dir: &Path) {
    let mut command = Command::new("sh");

    command
        .arg("configure")
        .arg("--with-pic")
        .arg("--disable-docs");

    let target = std::env::var("TARGET").unwrap();
    let host = std::env::var("HOST").unwrap();
    if target != host {
        // Autoconf uses riscv64 while Rust uses riscv64gc for the architecture
        if target == "riscv64gc-unknown-linux-gnu" {
            command.arg("--host=riscv64-unknown-linux-gnu");
        } else {
            command.arg(format!("--host={}", target));
        }
    }

    let mut c_cfg = cc::Build::new();
    c_cfg
        .cargo_metadata(false)
        .target(&target)
        .warnings(false)
        .host(&host);
    let c_compiler = c_cfg.get_compiler();

    command.env("CC", c_compiler.path());

    let mut cflags = c_compiler.cflags_env();
    match env::var_os("CFLAGS") {
        None => (),
        Some(flags) => {
            cflags.push(" ");
            cflags.push(&flags);
        }
    }
    command.env("CFLAGS", cflags);

    for (k, v) in c_compiler.env().iter() {
        command.env(k, v);
    }

    command.current_dir(&build_dir);

    if cfg!(windows) {
        // When using MSYS2, OUT_DIR will be a Windows like path such as
        // C:\foo\bar. Unfortunately, the various scripts used for building
        // libffi do not like such a path, so we have to turn this into a Unix
        // like path such as /c/foo/bar.
        //
        // This code assumes the path only uses : for the drive letter, and only
        // uses \ as a component separator. It will likely break for file paths
        // that include a :.
        let mut msys_prefix = prefix
            .to_str()
            .unwrap()
            .replace(":\\", "/")
            .replace("\\", "/");

        msys_prefix.insert(0, '/');

        command.arg("--prefix").arg(msys_prefix);
    } else {
        command.arg("--prefix").arg(prefix);
    }

    run_command("Configuring libffi", &mut command);
}
<commit_msg>Don't build shared library as we only link the static version<commit_after>use crate::common::*;
use std::process::Command;

pub fn build_and_link() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let build_dir = Path::new(&out_dir).join("libffi-build");
    let prefix = Path::new(&out_dir).join("libffi-root");
    let libdir = Path::new(&prefix).join("lib");
    let libdir64 = Path::new(&prefix).join("lib64");

    // Copy LIBFFI_DIR into build_dir to avoid an unnecessary build
    if let Err(e) = fs::remove_dir_all(&build_dir) {
        assert_eq!(
            e.kind(),
            std::io::ErrorKind::NotFound,
            "can't remove the build directory: {}",
            e
        );
    }
    run_command(
        "Copying libffi into the build directory",
        Command::new("cp").arg("-R").arg("libffi").arg(&build_dir),
    );

    // Generate configure, run configure, make, make install
    configure_libffi(prefix, &build_dir);

    run_command(
        "Building libffi",
        Command::new("make")
            .env_remove("DESTDIR")
            .arg("install")
            .current_dir(&build_dir),
    );

    // Cargo linking directives
    println!("cargo:rustc-link-lib=static=ffi");
    println!("cargo:rustc-link-search={}", libdir.display());
    println!("cargo:rustc-link-search={}", libdir64.display());
}

pub fn probe_and_link() {
    println!("cargo:rustc-link-lib=dylib=ffi");
}

pub fn configure_libffi(prefix: PathBuf, build_dir: &Path) {
    let mut command = Command::new("sh");

    command
        .arg("configure")
        .arg("--with-pic")
        .arg("--disable-shared")
        .arg("--disable-docs");

    let target = std::env::var("TARGET").unwrap();
    let host = std::env::var("HOST").unwrap();
    if target != host {
        // Autoconf uses riscv64 while Rust uses riscv64gc for the architecture
        if target == "riscv64gc-unknown-linux-gnu" {
            command.arg("--host=riscv64-unknown-linux-gnu");
        } else {
            command.arg(format!("--host={}", target));
        }
    }

    let mut c_cfg = cc::Build::new();
    c_cfg
        .cargo_metadata(false)
        .target(&target)
        .warnings(false)
        .host(&host);
    let c_compiler = c_cfg.get_compiler();

    command.env("CC", c_compiler.path());

    let mut cflags = c_compiler.cflags_env();
    match env::var_os("CFLAGS") {
        None => (),
        Some(flags) => {
            cflags.push(" ");
            cflags.push(&flags);
        }
    }
    command.env("CFLAGS", cflags);

    for (k, v) in c_compiler.env().iter() {
        command.env(k, v);
    }

    command.current_dir(&build_dir);

    if cfg!(windows) {
        // When using MSYS2, OUT_DIR will be a Windows like path such as
        // C:\foo\bar. Unfortunately, the various scripts used for building
        // libffi do not like such a path, so we have to turn this into a Unix
        // like path such as /c/foo/bar.
        //
        // This code assumes the path only uses : for the drive letter, and only
        // uses \ as a component separator. It will likely break for file paths
        // that include a :.
        let mut msys_prefix = prefix
            .to_str()
            .unwrap()
            .replace(":\\", "/")
            .replace("\\", "/");

        msys_prefix.insert(0, '/');

        command.arg("--prefix").arg(msys_prefix);
    } else {
        command.arg("--prefix").arg(prefix);
    }

    run_command("Configuring libffi", &mut command);
}
<|endoftext|>


<commit_before>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
use std;
use std::io;
use std::net::SocketAddr;
use std::sync::Arc;
use std::time::Duration;

use futures::{Async, Future, Poll, Stream};

use tokio_core::reactor::Core;
use tokio_reactor::Handle;
use tokio_tcp;
use tokio_udp;

use trust_dns::error::*;
use trust_dns::serialize::binary::{BinDecodable, BinDecoder};
use trust_dns::tcp::TcpStream;
use trust_dns::udp::UdpStream;
use trust_dns::BufStreamHandle;

#[cfg(feature = "dns-over-openssl")]
use trust_dns_openssl::{tls_server, TlsStream};

#[cfg(feature = "dns-over-openssl")]
use trust_dns_openssl::tls_server::*;

use authority::MessageRequest;
use server::{Request, RequestHandler, ResponseHandle, TimeoutStream};

// TODO, would be nice to have a Slab for buffers here...

/// A Futures based implementation of a DNS server
pub struct ServerFuture<T: RequestHandler + 'static> {
    io_loop: Core,
    handler: Arc<T>,
}

impl<T: RequestHandler> ServerFuture<T> {
    /// Creates a new ServerFuture with the specified Handler.
    pub fn new(handler: T) -> io::Result<ServerFuture<T>> {
        Ok(ServerFuture {
            io_loop: Core::new()?,
            handler: Arc::new(handler),
        })
    }

    /// Register a UDP socket. Should be bound before calling this function.
    pub fn register_socket(&self, socket: tokio_udp::UdpSocket) {
        debug!("registered udp: {:?}", socket);

        // create the new UdpStream
        let (buf_stream, stream_handle) = UdpStream::with_bound(socket);
        //let request_stream = RequestStream::new(buf_stream, stream_handle);
        let handler = self.handler.clone();

        // this spawns a ForEach future which handles all the requests into a Handler.
        self.io_loop.handle().spawn(
            buf_stream
                .for_each(move |(buffer, src_addr)| {
                    Self::handle_request(buffer, src_addr, stream_handle.clone(), handler.clone())
                        .map_err(move |e| {
                            debug!("error parsing UDP request src: {:?} error: {}", src_addr, e)
                        })
                        .ok();

                    // continue processing...
                    Ok(())
                })
                .map_err(|e| panic!("error in UDP request_stream handler: {}", e)),
        );
    }

    /// Register a UDP socket. Should be bound before calling this function.
    pub fn register_socket_std(&self, socket: std::net::UdpSocket) {
        self.register_socket(tokio_udp::UdpSocket::from_std(socket, &Handle::current()).expect("bad handle?"))
    }

    /// Register a TcpListener to the Server. This should already be bound to either an IPv6 or an
    ///  IPv4 address.
    ///
    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
    ///  to not make this too low depending on use cases.
    ///
    /// # Arguments
    /// * `listener` - a bound TCP socket
    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
    ///               requests within this time period will be closed. In the future it should be
    ///               possible to create long-lived queries, but these should be from trusted sources
    ///               only, this would require some type of whitelisting.
    pub fn register_listener(
        &self,
        listener: tokio_tcp::TcpListener,
        timeout: Duration,
    ) -> io::Result<()> {
        let handle = self.io_loop.handle();
        let handler = self.handler.clone();
        debug!("registered tcp: {:?}", listener);

        // for each incoming request...
        self.io_loop.handle().spawn(
            listener
                .incoming()
                .for_each(move |tcp_stream| {
                    let src_addr = tcp_stream.peer_addr().unwrap();
                    debug!("accepted request from: {}", src_addr);
                    // take the created stream...
                    let (buf_stream, stream_handle) = TcpStream::from_stream(tcp_stream, src_addr);
                    let timeout_stream = TimeoutStream::new(buf_stream, timeout);
                    //let request_stream = RequestStream::new(timeout_stream, stream_handle);
                    let handler = handler.clone();

                    // and spawn to the io_loop
                    handle.spawn(
                        timeout_stream
                            .for_each(move |(buffer, src_addr)| {
                                Self::handle_request(
                                    buffer,
                                    src_addr,
                                    stream_handle.clone(),
                                    handler.clone(),
                                )
                            })
                            .map_err(move |e| {
                                debug!(
                                    "error in TCP request_stream src: {:?} error: {}",
                                    src_addr, e
                                )
                            }),
                    );

                    Ok(())
                })
                .map_err(|e| panic!("error in inbound tcp_stream: {}", e)),
        );

        Ok(())
    }

    /// Register a TcpListener to the Server. This should already be bound to either an IPv6 or an
    ///  IPv4 address.
    ///
    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
    ///  to not make this too low depending on use cases.
    ///
    /// # Arguments
    /// * `listener` - a bound TCP socket
    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
    ///               requests within this time period will be closed. In the future it should be
    ///               possible to create long-lived queries, but these should be from trusted sources
    ///               only, this would require some type of whitelisting.
    pub fn register_listener_std(
        &self,
        listener: std::net::TcpListener,
        timeout: Duration,
    ) -> io::Result<()> {
        self.register_listener(tokio_tcp::TcpListener::from_std(listener, &Handle::current())?, timeout)
    }

    /// Register a TlsListener to the Server. The TlsListener should already be bound to either an
    /// IPv6 or an IPv4 address.
    ///
    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
    ///  to not make this too low depending on use cases.
    ///
    /// # Arguments
    /// * `listener` - a bound TCP (needs to be on a different port from standard TCP connections) socket
    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
    ///               requests within this time period will be closed. In the future it should be
    ///               possible to create long-lived queries, but these should be from trusted sources
    ///               only, this would require some type of whitelisting.
    /// * `pkcs12` - certificate used to announce to clients
    #[cfg(feature = "dns-over-openssl")]
    pub fn register_tls_listener(
        &self,
        listener: tokio_tcp::TcpListener,
        timeout: Duration,
        pkcs12: ParsedPkcs12,
    ) -> io::Result<()> {
        let handle = self.io_loop.handle();
        let handler = self.handler.clone();
        debug!("registered tcp: {:?}", listener);

        let tls_acceptor = tls_server::new_acceptor(&pkcs12)?;

        // for each incoming request...
        self.io_loop.handle().spawn(
            listener
                .incoming()
                .for_each(move |tcp_stream| {
                    let src_addr = tcp_stream.peer_addr().unwrap();
                    debug!("accepted request from: {}", src_addr);
                    let handle = handle.clone();
                    let handler = handler.clone();

                    // take the created stream...
                    tls_acceptor
                        .accept_async(tcp_stream)
                        .map_err(|e| {
                            io::Error::new(
                                io::ErrorKind::ConnectionRefused,
                                format!("tls error: {}", e),
                            )
                        })
                        .and_then(move |tls_stream| {
                            let (buf_stream, stream_handle) =
                                TlsStream::from_stream(tls_stream, src_addr);
                            let timeout_stream = TimeoutStream::new(buf_stream, timeout);
                            //let request_stream = RequestStream::new(timeout_stream, stream_handle);
                            let handler = handler.clone();

                            // and spawn to the io_loop
                            handle.spawn(
                                timeout_stream
                                    .for_each(move |(buffer, addr)| {
                                        Self::handle_request(
                                            buffer,
                                            addr,
                                            stream_handle.clone(),
                                            handler.clone(),
                                        )
                                    })
                                    .map_err(move |e| {
                                        debug!(
                                            "error in TCP request_stream src: {:?} error: {}",
                                            src_addr, e
                                        )
                                    }),
                            );

                            Ok(())
                        })
                    //.map_err(move |e| debug!("error TLS handshake: {:?} error: {:?}", src_addr, e))
                })
                .map_err(|e| panic!("error in inbound tls_stream: {}", e)),
        );

        Ok(())
    }

    /// Register a TlsListener to the Server. The TlsListener should already be bound to either an
    /// IPv6 or an IPv4 address.
    ///
    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
    ///  to not make this too low depending on use cases.
    ///
    /// # Arguments
    /// * `listener` - a bound TCP (needs to be on a different port from standard TCP connections) socket
    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
    ///               requests within this time period will be closed. In the future it should be
    ///               possible to create long-lived queries, but these should be from trusted sources
    ///               only, this would require some type of whitelisting.
    /// * `pkcs12` - certificate used to announce to clients
    #[cfg(feature = "dns-over-openssl")]
    pub fn register_tls_listener_std(
        &self,
        listener: std::net::TcpListener,
        timeout: Duration,
        pkcs12: ParsedPkcs12,
    ) -> io::Result<()> {
        self.register_tls_listener(tokio_tcp::TcpListener::from_std(listener, &Handle::current())?, timeout, pkcs12)
    }

    /// TODO: how to do threads? should we do a bunch of listener threads and then query threads?
    /// Ideally the processing would be n-threads for recieving, which hand off to m-threads for
    ///  request handling. It would generally be the case that n <= m.
    pub fn listen(&mut self) -> io::Result<()> {
        info!("Server starting up");
        self.io_loop.run(Forever)?;

        Err(io::Error::new(
            io::ErrorKind::Interrupted,
            "Server stopping due to interruption",
        ))
    }

    /// Returns a reference to the tokio core loop driving this Server instance
    pub fn tokio_core(&mut self) -> &mut Core {
        &mut self.io_loop
    }

    fn handle_request(
        buffer: Vec<u8>,
        src_addr: SocketAddr,
        stream_handle: BufStreamHandle<ClientError>,
        handler: Arc<T>,
    ) -> io::Result<()> {
        let response_handle = ResponseHandle::new(src_addr, stream_handle);

        // TODO: rather than decoding the message here, this RequestStream should instead
        //       forward the request to another sender such that we could pull serialization off
        //       the IO thread.
        // decode any messages that are ready
        let mut decoder = BinDecoder::new(&buffer);
        let message = MessageRequest::read(&mut decoder)?;

        let request = Request {
            message: message,
            src: src_addr,
        };

        info!(
            "request: {} type: {:?} op_code: {:?} dnssec: {} {}",
            request.message.id(),
            request.message.message_type(),
            request.message.op_code(),
            request
                .message
                .edns()
                .map_or(false, |edns| edns.dnssec_ok()),
            request
                .message
                .queries()
                .first()
                .map(|q| q.original().to_string())
                .unwrap_or_else(|| "empty_queries".to_string()),
        );

        handler.handle_request(&request, response_handle)
    }
}

struct Forever;

impl Future for Forever {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // run forever...
        Ok(Async::NotReady)
    }
}
<commit_msg>server: add a mutex around handler in server_future<commit_after>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
use std;
use std::io;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use futures::{Async, Future, Poll, Stream};

use tokio_core::reactor::Core;
use tokio_reactor::Handle;
use tokio_tcp;
use tokio_udp;

use trust_dns::error::*;
use trust_dns::serialize::binary::{BinDecodable, BinDecoder};
use trust_dns::tcp::TcpStream;
use trust_dns::udp::UdpStream;
use trust_dns::BufStreamHandle;

#[cfg(feature = "dns-over-openssl")]
use trust_dns_openssl::{tls_server, TlsStream};

#[cfg(feature = "dns-over-openssl")]
use trust_dns_openssl::tls_server::*;

use authority::MessageRequest;
use server::{Request, RequestHandler, ResponseHandle, TimeoutStream};

// TODO, would be nice to have a Slab for buffers here...

/// A Futures based implementation of a DNS server
pub struct ServerFuture<T: RequestHandler + Send + 'static> {
    io_loop: Core,
    handler: Arc<Mutex<T>>,
}

impl<T: RequestHandler + Send> ServerFuture<T> {
    /// Creates a new ServerFuture with the specified Handler.
    pub fn new(handler: T) -> io::Result<ServerFuture<T>> {
        Ok(ServerFuture {
            io_loop: Core::new()?,
            handler: Arc::new(Mutex::new(handler)),
        })
    }

    /// Register a UDP socket. Should be bound before calling this function.
    pub fn register_socket(&self, socket: tokio_udp::UdpSocket) {
        debug!("registered udp: {:?}", socket);

        // create the new UdpStream
        let (buf_stream, stream_handle) = UdpStream::with_bound(socket);
        //let request_stream = RequestStream::new(buf_stream, stream_handle);
        let handler = self.handler.clone();

        // this spawns a ForEach future which handles all the requests into a Handler.
        self.io_loop.handle().spawn(
            buf_stream
                .for_each(move |(buffer, src_addr)| {
                    Self::handle_request(buffer, src_addr, stream_handle.clone(), handler.clone())
                        .map_err(move |e| {
                            debug!("error parsing UDP request src: {:?} error: {}", src_addr, e)
                        })
                        .ok();

                    // continue processing...
                    Ok(())
                })
                .map_err(|e| panic!("error in UDP request_stream handler: {}", e)),
        );
    }

    /// Register a UDP socket. Should be bound before calling this function.
    pub fn register_socket_std(&self, socket: std::net::UdpSocket) {
        self.register_socket(tokio_udp::UdpSocket::from_std(socket, &Handle::current()).expect("bad handle?"))
    }

    /// Register a TcpListener to the Server. This should already be bound to either an IPv6 or an
    ///  IPv4 address.
    ///
    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
    ///  to not make this too low depending on use cases.
    ///
    /// # Arguments
    /// * `listener` - a bound TCP socket
    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
    ///               requests within this time period will be closed. In the future it should be
    ///               possible to create long-lived queries, but these should be from trusted sources
    ///               only, this would require some type of whitelisting.
    pub fn register_listener(
        &self,
        listener: tokio_tcp::TcpListener,
        timeout: Duration,
    ) -> io::Result<()> {
        let handle = self.io_loop.handle();
        let handler = self.handler.clone();
        debug!("registered tcp: {:?}", listener);

        // for each incoming request...
        self.io_loop.handle().spawn(
            listener
                .incoming()
                .for_each(move |tcp_stream| {
                    let src_addr = tcp_stream.peer_addr().unwrap();
                    debug!("accepted request from: {}", src_addr);
                    // take the created stream...
                    let (buf_stream, stream_handle) = TcpStream::from_stream(tcp_stream, src_addr);
                    let timeout_stream = TimeoutStream::new(buf_stream, timeout);
                    //let request_stream = RequestStream::new(timeout_stream, stream_handle);
                    let handler = handler.clone();

                    // and spawn to the io_loop
                    handle.spawn(
                        timeout_stream
                            .for_each(move |(buffer, src_addr)| {
                                Self::handle_request(
                                    buffer,
                                    src_addr,
                                    stream_handle.clone(),
                                    handler.clone(),
                                )
                            })
                            .map_err(move |e| {
                                debug!(
                                    "error in TCP request_stream src: {:?} error: {}",
                                    src_addr, e
                                )
                            }),
                    );

                    Ok(())
                })
                .map_err(|e| panic!("error in inbound tcp_stream: {}", e)),
        );

        Ok(())
    }

    /// Register a TcpListener to the Server. This should already be bound to either an IPv6 or an
    ///  IPv4 address.
    ///
    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
    ///  to not make this too low depending on use cases.
    ///
    /// # Arguments
    /// * `listener` - a bound TCP socket
    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
    ///               requests within this time period will be closed. In the future it should be
    ///               possible to create long-lived queries, but these should be from trusted sources
    ///               only, this would require some type of whitelisting.
    pub fn register_listener_std(
        &self,
        listener: std::net::TcpListener,
        timeout: Duration,
    ) -> io::Result<()> {
        self.register_listener(tokio_tcp::TcpListener::from_std(listener, &Handle::current())?, timeout)
    }

    /// Register a TlsListener to the Server. The TlsListener should already be bound to either an
    /// IPv6 or an IPv4 address.
    ///
    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
    ///  to not make this too low depending on use cases.
    ///
    /// # Arguments
    /// * `listener` - a bound TCP (needs to be on a different port from standard TCP connections) socket
    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
    ///               requests within this time period will be closed. In the future it should be
    ///               possible to create long-lived queries, but these should be from trusted sources
    ///               only, this would require some type of whitelisting.
    /// * `pkcs12` - certificate used to announce to clients
    #[cfg(feature = "dns-over-openssl")]
    pub fn register_tls_listener(
        &self,
        listener: tokio_tcp::TcpListener,
        timeout: Duration,
        pkcs12: ParsedPkcs12,
    ) -> io::Result<()> {
        let handle = self.io_loop.handle();
        let handler = self.handler.clone();
        debug!("registered tcp: {:?}", listener);

        let tls_acceptor = tls_server::new_acceptor(&pkcs12)?;

        // for each incoming request...
        self.io_loop.handle().spawn(
            listener
                .incoming()
                .for_each(move |tcp_stream| {
                    let src_addr = tcp_stream.peer_addr().unwrap();
                    debug!("accepted request from: {}", src_addr);
                    let handle = handle.clone();
                    let handler = handler.clone();

                    // take the created stream...
                    tls_acceptor
                        .accept_async(tcp_stream)
                        .map_err(|e| {
                            io::Error::new(
                                io::ErrorKind::ConnectionRefused,
                                format!("tls error: {}", e),
                            )
                        })
                        .and_then(move |tls_stream| {
                            let (buf_stream, stream_handle) =
                                TlsStream::from_stream(tls_stream, src_addr);
                            let timeout_stream = TimeoutStream::new(buf_stream, timeout);
                            //let request_stream = RequestStream::new(timeout_stream, stream_handle);
                            let handler = handler.clone();

                            // and spawn to the io_loop
                            handle.spawn(
                                timeout_stream
                                    .for_each(move |(buffer, addr)| {
                                        Self::handle_request(
                                            buffer,
                                            addr,
                                            stream_handle.clone(),
                                            handler.clone(),
                                        )
                                    })
                                    .map_err(move |e| {
                                        debug!(
                                            "error in TCP request_stream src: {:?} error: {}",
                                            src_addr, e
                                        )
                                    }),
                            );

                            Ok(())
                        })
                    //.map_err(move |e| debug!("error TLS handshake: {:?} error: {:?}", src_addr, e))
                })
                .map_err(|e| panic!("error in inbound tls_stream: {}", e)),
        );

        Ok(())
    }

    /// Register a TlsListener to the Server. The TlsListener should already be bound to either an
    /// IPv6 or an IPv4 address.
    ///
    /// To make the server more resilient to DOS issues, there is a timeout. Care should be taken
    ///  to not make this too low depending on use cases.
    ///
    /// # Arguments
    /// * `listener` - a bound TCP (needs to be on a different port from standard TCP connections) socket
    /// * `timeout` - timeout duration of incoming requests, any connection that does not send
    ///               requests within this time period will be closed. In the future it should be
    ///               possible to create long-lived queries, but these should be from trusted sources
    ///               only, this would require some type of whitelisting.
    /// * `pkcs12` - certificate used to announce to clients
    #[cfg(feature = "dns-over-openssl")]
    pub fn register_tls_listener_std(
        &self,
        listener: std::net::TcpListener,
        timeout: Duration,
        pkcs12: ParsedPkcs12,
    ) -> io::Result<()> {
        self.register_tls_listener(tokio_tcp::TcpListener::from_std(listener, &Handle::current())?, timeout, pkcs12)
    }

    /// TODO: how to do threads? should we do a bunch of listener threads and then query threads?
    /// Ideally the processing would be n-threads for recieving, which hand off to m-threads for
    ///  request handling. It would generally be the case that n <= m.
    pub fn listen(&mut self) -> io::Result<()> {
        info!("Server starting up");
        self.io_loop.run(Forever)?;

        Err(io::Error::new(
            io::ErrorKind::Interrupted,
            "Server stopping due to interruption",
        ))
    }

    /// Returns a reference to the tokio core loop driving this Server instance
    pub fn tokio_core(&mut self) -> &mut Core {
        &mut self.io_loop
    }

    fn handle_request(
        buffer: Vec<u8>,
        src_addr: SocketAddr,
        stream_handle: BufStreamHandle<ClientError>,
        handler: Arc<Mutex<T>>,
    ) -> io::Result<()> {
        let response_handle = ResponseHandle::new(src_addr, stream_handle);

        // TODO: rather than decoding the message here, this RequestStream should instead
        //       forward the request to another sender such that we could pull serialization off
        //       the IO thread.
        // decode any messages that are ready
        let mut decoder = BinDecoder::new(&buffer);
        let message = MessageRequest::read(&mut decoder)?;

        let request = Request {
            message: message,
            src: src_addr,
        };

        info!(
            "request: {} type: {:?} op_code: {:?} dnssec: {} {}",
            request.message.id(),
            request.message.message_type(),
            request.message.op_code(),
            request
                .message
                .edns()
                .map_or(false, |edns| edns.dnssec_ok()),
            request
                .message
                .queries()
                .first()
                .map(|q| q.original().to_string())
                .unwrap_or_else(|| "empty_queries".to_string()),
        );

        handler.lock().unwrap().handle_request(&request, response_handle)
    }
}

struct Forever;

impl Future for Forever {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        // run forever...
        Ok(Async::NotReady)
    }
}
<|endoftext|>


<commit_before>extern crate regex;

use regex::Regex;

struct Gradient {
    start: Vec<u32>,
    steps: Vec<u32>,
    n: u32,
    total: u32,
}

impl Gradient {
    fn to_parts(hex: &String) -> Vec<u32> {
        vec![0, 0, 0]
    }

    fn to_steps(start: &[u32], stop: &[u32]) -> Vec<u32> {
        vec![17, 17, 17]
    }

    pub fn new(start: String, stop: String, n: u32) -> Gradient {
        let from = Gradient::to_parts(&start);
        let to = Gradient::to_parts(&stop);
        let steps = Gradient::to_steps(&from[..], &to[..]);

        Gradient{
            start: from,
            steps: steps,
            n: 0,
            total: n,
        }
    }
}

impl Iterator for Gradient {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        match self.n {
            n if n == self.total => None,
            n => {
                let rgb: String = self.start
                    .iter()
                    .zip(self.steps.iter())
                    .map(|(&a, &b)| a + (b * n))
                    .map(|i| format!("{:02x}", i))
                    .collect();

                self.n += 1;

                Some(rgb)
            }
        }
    }
}

fn main() {
    let g = Gradient::new("000000".to_string(), "ffffff".to_string(), 10000);

    g.collect::<Vec<String>>();
}

#[test]
fn it_works() {
    let g = Gradient::new("000000".to_string(), "ffffff".to_string(), 16);

    assert_eq!(g.take(2).collect::<Vec<String>>(), vec!["000000".to_string(), "111111".to_string()]);
}
<commit_msg>Added to_parts function kind of ignoring error handling for now<commit_after>extern crate regex;

use regex::Regex;

struct Gradient {
    start: Vec<u32>,
    steps: Vec<u32>,
    n: u32,
    total: u32,
}

impl Gradient {
    fn to_parts(hex: &str) -> Vec<u32> {
        let re = Regex::new(r"[0-9a-fA-F]{2}").unwrap();

        re.split(&hex)
          .map(|c| u32::from_str_radix(c, 16).unwrap_or(0))
          .collect()
    }

    fn to_steps(start: &[u32], stop: &[u32]) -> Vec<u32> {
        vec![17, 17, 17]
    }

    pub fn new(start: String, stop: String, n: u32) -> Gradient {
        let from = Gradient::to_parts(&start[..]);
        let to = Gradient::to_parts(&stop[..]);
        let steps = Gradient::to_steps(&from[..], &to[..]);

        Gradient{
            start: from,
            steps: steps,
            n: 0,
            total: n,
        }
    }
}

impl Iterator for Gradient {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        match self.n {
            n if n == self.total => None,
            n => {
                let rgb: String = self.start
                    .iter()
                    .zip(self.steps.iter())
                    .map(|(&a, &b)| a + (b * n))
                    .map(|i| format!("{:02x}", i))
                    .collect();

                self.n += 1;

                Some(rgb)
            }
        }
    }
}

fn main() {
    let g = Gradient::new("000000".to_string(), "ffffff".to_string(), 10000);

    g.collect::<Vec<String>>();
}

#[test]
fn it_works() {
    let g = Gradient::new("000000".to_string(), "ffffff".to_string(), 16);
    let result = vec!["000000", "111111", "222222", "333333", "444444",
                      "555555", "666666", "777777", "888888", "999999",
                      "aaaaaa", "bbbbbb", "cccccc", "dddddd", "eeeeee",
                      "ffffff"];

    assert_eq!(g.collect::<Vec<String>>(), result.iter().map(|r| r.to_string()).collect::<Vec<String>>());
}
<|endoftext|>


<commit_before>#[cfg_attr(rustfmt, rustfmt_skip)]
static RUST_KEYWORDS: &'static [&'static str] = &[
    "as",
    "async",
    "await",
    "break",
    "crate",
    "else",
    "enum",
    "extern",
    "false",
    "fn",
    "for",
    "if",
    "impl",
    "in",
    "let",
    "loop",
    "match",
    "mod",
    "move",
    "mut",
    "pub",
    "ref",
    "return",
    "static",
    "self",
    "Self",
    "struct",
    "super",
    "true",
    "trait",
    "type",
    "unsafe",
    "use",
    "while",
    "continue",
    "box",
    "const",
    "where",
    "virtual",
    "proc",
    "alignof",
    "become",
    "offsetof",
    "priv",
    "pure",
    "sizeof",
    "typeof",
    "unsized",
    "yield",
    "do",
    "abstract",
    "final",
    "override",
    "macro",
];

pub fn is_rust_keyword(ident: &str) -> bool {
    RUST_KEYWORDS.contains(&ident)
}

fn hex_digit(value: u32) -> char {
    if value < 10 {
        (b'0' + value as u8) as char
    } else if value < 0x10 {
        (b'a' + value as u8 - 10) as char
    } else {
        unreachable!()
    }
}

pub fn quote_escape_str(s: &str) -> String {
    let mut buf = String::new();
    buf.push('"');
    buf.extend(s.chars().flat_map(|c| c.escape_default()));
    buf.push('"');
    buf
}

pub fn quote_escape_bytes(bytes: &[u8]) -> String {
    let mut buf = String::new();
    buf.push('b');
    buf.push('"');
    for &b in bytes {
        match b {
            b'\n' => buf.push_str(r"\n"),
            b'\r' => buf.push_str(r"\r"),
            b'\t' => buf.push_str(r"\t"),
            b'"' => buf.push_str("\\\""),
            b'\\' => buf.push_str(r"\\"),
            b'\x20'..=b'\x7e' => buf.push(b as char),
            _ => {
                buf.push_str(r"\x");
                buf.push(hex_digit((b as u32) >> 4));
                buf.push(hex_digit((b as u32) & 0x0f));
            }
        }
    }
    buf.push('"');
    buf
}

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn test_quote_escape_bytes() {
        assert_eq!("b\"\"", quote_escape_bytes(b""));
        assert_eq!("b\"xyZW\"", quote_escape_bytes(b"xyZW"));
        assert_eq!("b\"aa\\\"bb\"", quote_escape_bytes(b"aa\"bb"));
        assert_eq!("b\"aa\\r\\n\\tbb\"", quote_escape_bytes(b"aa\r\n\tbb"));
        assert_eq!(
            "b\"\\x00\\x01\\x12\\xfe\\xff\"",
            quote_escape_bytes(b"\x00\x01\x12\xfe\xff")
        );
    }
}
<commit_msg>Add dyn to the list of keywords<commit_after>#[cfg_attr(rustfmt, rustfmt_skip)]
static RUST_KEYWORDS: &'static [&'static str] = &[
    "as",
    "async",
    "await",
    "break",
    "crate",
    "dyn",
    "else",
    "enum",
    "extern",
    "false",
    "fn",
    "for",
    "if",
    "impl",
    "in",
    "let",
    "loop",
    "match",
    "mod",
    "move",
    "mut",
    "pub",
    "ref",
    "return",
    "static",
    "self",
    "Self",
    "struct",
    "super",
    "true",
    "trait",
    "type",
    "unsafe",
    "use",
    "while",
    "continue",
    "box",
    "const",
    "where",
    "virtual",
    "proc",
    "alignof",
    "become",
    "offsetof",
    "priv",
    "pure",
    "sizeof",
    "typeof",
    "unsized",
    "yield",
    "do",
    "abstract",
    "final",
    "override",
    "macro",
];

pub fn is_rust_keyword(ident: &str) -> bool {
    RUST_KEYWORDS.contains(&ident)
}

fn hex_digit(value: u32) -> char {
    if value < 10 {
        (b'0' + value as u8) as char
    } else if value < 0x10 {
        (b'a' + value as u8 - 10) as char
    } else {
        unreachable!()
    }
}

pub fn quote_escape_str(s: &str) -> String {
    let mut buf = String::new();
    buf.push('"');
    buf.extend(s.chars().flat_map(|c| c.escape_default()));
    buf.push('"');
    buf
}

pub fn quote_escape_bytes(bytes: &[u8]) -> String {
    let mut buf = String::new();
    buf.push('b');
    buf.push('"');
    for &b in bytes {
        match b {
            b'\n' => buf.push_str(r"\n"),
            b'\r' => buf.push_str(r"\r"),
            b'\t' => buf.push_str(r"\t"),
            b'"' => buf.push_str("\\\""),
            b'\\' => buf.push_str(r"\\"),
            b'\x20'..=b'\x7e' => buf.push(b as char),
            _ => {
                buf.push_str(r"\x");
                buf.push(hex_digit((b as u32) >> 4));
                buf.push(hex_digit((b as u32) & 0x0f));
            }
        }
    }
    buf.push('"');
    buf
}

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn test_quote_escape_bytes() {
        assert_eq!("b\"\"", quote_escape_bytes(b""));
        assert_eq!("b\"xyZW\"", quote_escape_bytes(b"xyZW"));
        assert_eq!("b\"aa\\\"bb\"", quote_escape_bytes(b"aa\"bb"));
        assert_eq!("b\"aa\\r\\n\\tbb\"", quote_escape_bytes(b"aa\r\n\tbb"));
        assert_eq!(
            "b\"\\x00\\x01\\x12\\xfe\\xff\"",
            quote_escape_bytes(b"\x00\x01\x12\xfe\xff")
        );
    }
}
<|endoftext|>


<commit_before><commit_msg>[Rust] Extract type name.<commit_after><|endoftext|>


<commit_before><commit_msg>changed last libc++ to stdc++<commit_after><|endoftext|>


<commit_before><commit_msg>Implemented Error trait.<commit_after><|endoftext|>


<commit_before>use crate::{Error, Reference, Statuses};
use git2;
use std::path::{Path, PathBuf};

pub struct GitRepo {
    path: PathBuf,
    repo: git2::Repository,
}

unsafe impl Send for GitRepo {}

impl GitRepo {
    pub fn open<P>(path: P) -> Result<Self, Error>
    where
        P: Into<PathBuf>,
        P: AsRef<Path>,
    {
        let owned_path = path.into();
        let git_repo = git2::Repository::open(&owned_path)?;

        let repo = Self {
            path: owned_path,
            repo: git_repo,
        };

        Ok(repo)
    }

    pub fn path(&self) -> &Path {
        &self.path
    }

    pub fn statuses(&self) -> Result<Statuses<'_>, Error> {
        let mut opts = git2::StatusOptions::new();

        opts.include_ignored(false)
            .include_untracked(true)
            .recurse_untracked_dirs(true)
            .include_unreadable_as_untracked(true)
            .disable_pathspec_match(true)
            .exclude_submodules(true);

        self.repo
            .statuses(Some(&mut opts))
            .map(|x| x.into())
            .map_err(|x| x.into())
    }

    pub fn reset(&self) -> Result<Reference, Error> {
        let head = self.repo.head()?;
        let obj = head.peel(git2::ObjectType::Any)?;

        self.repo.reset(&obj, git2::ResetType::Hard, None)?;

        Reference::from_ref(&head)
    }

    pub fn checkout(&self, branch_name: &str) -> Result<bool, Error> {
        let branch_type = self.get_branch_type(branch_name)?;
        let branch = self.repo.find_branch(branch_name, branch_type)?;
        let obj = branch.get().peel(git2::ObjectType::Commit)?;

        match branch_type {
            git2::BranchType::Local => self.checkout_local(branch_name, &obj),
            git2::BranchType::Remote => self.checkout_remote(&obj),
        }
    }

    pub fn delete_local_branch(&self, branch_name: &str) -> Result<(), Error> {
        self.repo
            .find_branch(branch_name, git2::BranchType::Local)?
            .delete()?;

        Ok(())
    }

    pub fn fetch(&self) -> Result<(), Error> {
        let strs = self.repo.find_remote("origin")?.fetch_refspecs()?;
        let test = strs.iter().filter_map(|x| x).collect::<Vec<_>>();

        if let Err(e) = self.repo.find_remote("origin")?.fetch(&test, None, None) {
            let asd = format!("{:?}", e);
        }

        Ok(())
    }

    pub fn has_local_branch(&self, branch_name: &str) -> Result<(), Error> {
        self.repo
            .find_branch(branch_name, git2::BranchType::Local)?;

        Ok(())
    }

    fn get_branch_type(&self, branch_name: &str) -> Result<git2::BranchType, Error> {
        let components = branch_name.split('/').collect::<Vec<_>>();

        match components.len() {
            0 => Err(Error::ZeroSizedBranchName),
            1 => Ok(git2::BranchType::Local),
            _ => {
                if self.repo.find_remote(&components[0]).is_ok() {
                    Ok(git2::BranchType::Remote)
                } else {
                    Ok(git2::BranchType::Local)
                }
            }
        }
    }

    fn checkout_local(&self, branch_name: &str, obj: &git2::Object<'_>) -> Result<bool, Error> {
        self.repo.checkout_tree(obj, None)?;

        let branch_str = format!("refs/heads/{}", branch_name);
        let branch_ref = self.repo.find_reference(&branch_str)?;

        self.repo
            .set_head(branch_ref.name().ok_or(Error::GenericError)?)?;

        Ok(true)
    }

    fn checkout_remote(&self, obj: &git2::Object<'_>) -> Result<bool, Error> {
        let head_id = self.repo.head()?.peel(git2::ObjectType::Any)?.id();

        if head_id == obj.id() {
            return Ok(false);
        }

        self.repo.set_head_detached(obj.id())?;
        self.repo.reset(obj, git2::ResetType::Hard, None)?;

        Ok(true)
    }
}
<commit_msg>Supply default credential callback<commit_after>use crate::{Error, Reference, Statuses};
use git2;
use std::path::{Path, PathBuf};

pub struct GitRepo {
    path: PathBuf,
    repo: git2::Repository,
}

unsafe impl Send for GitRepo {}

impl GitRepo {
    pub fn open<P>(path: P) -> Result<Self, Error>
    where
        P: Into<PathBuf>,
        P: AsRef<Path>,
    {
        let owned_path = path.into();
        let git_repo = git2::Repository::open(&owned_path)?;

        let repo = Self {
            path: owned_path,
            repo: git_repo,
        };

        Ok(repo)
    }

    pub fn path(&self) -> &Path {
        &self.path
    }

    pub fn statuses(&self) -> Result<Statuses<'_>, Error> {
        let mut opts = git2::StatusOptions::new();

        opts.include_ignored(false)
            .include_untracked(true)
            .recurse_untracked_dirs(true)
            .include_unreadable_as_untracked(true)
            .disable_pathspec_match(true)
            .exclude_submodules(true);

        self.repo
            .statuses(Some(&mut opts))
            .map(|x| x.into())
            .map_err(|x| x.into())
    }

    pub fn reset(&self) -> Result<Reference, Error> {
        let head = self.repo.head()?;
        let obj = head.peel(git2::ObjectType::Any)?;

        self.repo.reset(&obj, git2::ResetType::Hard, None)?;

        Reference::from_ref(&head)
    }

    pub fn checkout(&self, branch_name: &str) -> Result<bool, Error> {
        let branch_type = self.get_branch_type(branch_name)?;
        let branch = self.repo.find_branch(branch_name, branch_type)?;
        let obj = branch.get().peel(git2::ObjectType::Commit)?;

        match branch_type {
            git2::BranchType::Local => self.checkout_local(branch_name, &obj),
            git2::BranchType::Remote => self.checkout_remote(&obj),
        }
    }

    pub fn delete_local_branch(&self, branch_name: &str) -> Result<(), Error> {
        self.repo
            .find_branch(branch_name, git2::BranchType::Local)?
            .delete()?;

        Ok(())
    }

    pub fn fetch(&self) -> Result<(), Error> {
        let mut options = {
            let mut remote_callbacks = git2::RemoteCallbacks::new();
            remote_callbacks.credentials(
                |_s: &str,
                 _os: Option<&str>,
                 _ct: git2::CredentialType|
                 -> Result<git2::Cred, git2::Error> { git2::Cred::default() },
            );

            let mut o = git2::FetchOptions::new();
            o.remote_callbacks(remote_callbacks);
            o
        };

        let refspecs = self.repo.find_remote("origin")?.fetch_refspecs()?;
        let refspec_collection = refspecs.iter().filter_map(|x| x).collect::<Vec<_>>();

        if let Err(e) =
            self.repo
                .find_remote("origin")?
                .fetch(&refspec_collection, Some(&mut options), None)
        {
            let asd = format!("{:?}", e);
            return Err(Error::GenericError);
        }

        Ok(())
    }

    pub fn has_local_branch(&self, branch_name: &str) -> Result<(), Error> {
        self.repo
            .find_branch(branch_name, git2::BranchType::Local)?;

        Ok(())
    }

    fn get_branch_type(&self, branch_name: &str) -> Result<git2::BranchType, Error> {
        let components = branch_name.split('/').collect::<Vec<_>>();

        match components.len() {
            0 => Err(Error::ZeroSizedBranchName),
            1 => Ok(git2::BranchType::Local),
            _ => {
                if self.repo.find_remote(&components[0]).is_ok() {
                    Ok(git2::BranchType::Remote)
                } else {
                    Ok(git2::BranchType::Local)
                }
            }
        }
    }

    fn checkout_local(&self, branch_name: &str, obj: &git2::Object<'_>) -> Result<bool, Error> {
        self.repo.checkout_tree(obj, None)?;

        let branch_str = format!("refs/heads/{}", branch_name);
        let branch_ref = self.repo.find_reference(&branch_str)?;

        self.repo
            .set_head(branch_ref.name().ok_or(Error::GenericError)?)?;

        Ok(true)
    }

    fn checkout_remote(&self, obj: &git2::Object<'_>) -> Result<bool, Error> {
        let head_id = self.repo.head()?.peel(git2::ObjectType::Any)?.id();

        if head_id == obj.id() {
            return Ok(false);
        }

        self.repo.set_head_detached(obj.id())?;
        self.repo.reset(obj, git2::ResetType::Hard, None)?;

        Ok(true)
    }
}
<|endoftext|>


<commit_before>use circle::Circle;
use fx32::Fx32;
use fx32::Fx32Small;
use ray2::Ray2;
use vec2::Vec2;
use wide_line::WideLine;

use std::cmp;

use std::io::Error;
use std::io::prelude::*;
use std::io::BufWriter;
use std::fs::File;

#[derive (Clone, Copy)]
pub enum Ray2TraceResult {
	Hit (Fx32, Vec2 <Fx32>, Vec2 <Fx32Small>),
	Miss,
}

pub fn fold_closer_result (a: Ray2TraceResult, b: Ray2TraceResult) -> Ray2TraceResult {
	match a {
		Ray2TraceResult::Miss => {
			return b;
		},
		Ray2TraceResult::Hit (a_t, ..) => {
			match b {
				Ray2TraceResult::Miss => {
					return a;
				},
				Ray2TraceResult::Hit (b_t, ..) => {
					if a_t < b_t {
						return a;
					}
					else {
						return b;
					}
				}
			}
		},
	}
}

pub fn write_vec2 <T> (writer: &mut T, v: &Vec2 <Fx32>) where T: Write {
	write! (writer, "v {} 0 {}\n", v.x.to_f64 () / 256.0, v.y.to_f64 () / 256.0).unwrap ();
}

pub fn apply_dt (ray: &Ray2, dt: Fx32Small) -> Ray2 {
	Ray2 {
		start: ray.start,
		dir: ray.dir * dt,
	}
}

pub fn test_ray_trace () -> Result <(), Error> {
	let scale = 1;
	//let scale_fx = Fx32::from_int (scale);

	let obstacle = vec! [
	Circle {
		center: Vec2 {x: Fx32::from_q (133, scale), y: Fx32::from_q (512 - 34, scale)},
		radius: Fx32::from_q (20, scale),
	},
	Circle {
		center: Vec2 {x: Fx32::from_q (256, scale), y: Fx32::from_q (501, scale)},
		radius: Fx32::from_q (20, scale),
	},
	Circle {
		center: Vec2 {x: Fx32::from_q (404, scale), y: Fx32::from_q (501, scale)},
		radius: Fx32::from_q (20, scale),
	},
	];

	let lines = vec! [
	WideLine {
		start: obstacle [0].center,
		end: obstacle [1].center,
		radius: Fx32::from_q (20, scale),
	},
	WideLine {
		start: obstacle [1].center,
		end: obstacle [2].center,
		radius: Fx32::from_q (20, scale),
	},
	];

	let mut num_bounces = 0;
	let mut num_ticks = 0;

	let inv_dt = 4;
	let gravity = Vec2::<Fx32> {
		x: Fx32::from_q (0, 1),
		y: Fx32::from_q (2, 1),
	};

	let obj_file = try!(File::create("lines.obj"));
	let mut writer = BufWriter::new (obj_file);

	let mut vertex_i = 1;
	let mut polyline_start = vertex_i;

	for x in 66..202 {
		let x = x * 2;
		let mut particle = Ray2 {
			start: Vec2 {
				x: Fx32::from_q (x * 2 + 1, scale * 2),
				y: Fx32::from_q (0, scale)
			},
			dir: Vec2 {
				x: Fx32::from_q (0, scale),
				y: Fx32::from_q (1, scale),
			},
		};

		write_vec2 (&mut writer, &particle.start);
		vertex_i += 1;

		let dt = Fx32::from_q (1, inv_dt).to_small ();

		for _ in 0..500 {
			let trace_result = {
				let point_results = obstacle.iter ().map (|obstacle| ray_trace_circle_2 (&apply_dt (&particle, dt), obstacle));

				let line_results = lines.iter ().map (|line| ray_trace_line (&apply_dt (&particle, dt), line));

				point_results.chain (line_results).fold ( Ray2TraceResult::Miss, fold_closer_result)
			};

			match trace_result {
				Ray2TraceResult::Miss => {
					//let air_drag = Fx32 { x: particle.dir.length_sq ().x / -16384 };
					//let air_force = particle.dir * air_drag;
					let new_dir = particle.dir + gravity * dt;// + Vec2::<Fx32>::from (air_force * dt);
					let sum_dir = particle.dir + new_dir;
					let average_dir = Vec2::<Fx32> {
						x: Fx32 { x: sum_dir.x.x / 2 },
						y: Fx32 { x: sum_dir.y.x / 2 },
					};

					particle.start = particle.start + (average_dir * dt);
					particle.dir = new_dir;
				},
				Ray2TraceResult::Hit (_, ccd_pos, normal) => {
					particle.start = ccd_pos;
					particle.dir = particle.dir.reflect (normal) * Fx32::from_q (1023, 1024);
					//particle.dir = normal;
					num_bounces += 1;
				},
			};

			write_vec2 (&mut writer, &particle.start);
			vertex_i += 1;

			num_ticks += 1;

			if particle.start.y > 768 {
				break;
			}
		}

		for i in polyline_start..vertex_i - 1 {
			try! (write! (writer, "f {} {}\n", i, i + 1));
		}
		polyline_start = vertex_i
	}

	println! ("num_bounces: {}", num_bounces);
	println! ("num_ticks: {}", num_ticks);

	Ok (())
}

pub struct Basis2 {
	pub x: Vec2 <Fx32Small>,
	pub y: Vec2 <Fx32Small>,
}

// Constructs a basis to ray space
// Such that the ray is the X axis
pub fn get_ray_basis (ray: &Ray2, ray_length: Fx32) -> Basis2 {
	let basis_x_big = if ray_length == 0 {
		ray.dir
	}
	else {
		ray.dir / ray_length
	};

	Basis2 {
		x: basis_x_big.to_small (),
		y: basis_x_big.cross ().to_small (),
	}
}

impl Basis2 {
	pub fn to_space (&self, v: &Vec2 <Fx32>) -> Vec2 <Fx32> {
		Vec2::<Fx32> {
			x: *v * self.x,
			y: *v * self.y,
		}
	}

	pub fn from_space (&self, v: &Vec2 <Fx32>) -> Vec2 <Fx32> {
		Vec2::<Fx32> {
			x: (v.x * self.x.x) + (v.y * self.y.x),
			y: (v.x * self.x.y) + (v.y * self.y.y),
		}
	}
}

pub fn ray_trace_line (ray: &Ray2, line: &WideLine) -> Ray2TraceResult {
	if line.start == line.end {
		// Line has zero length and so zero collision area
		// If we run through the math we may get a 0 / 0 result
		// so just drop it now
		return Ray2TraceResult::Miss;
	}

	let margin = Fx32::from_q (1, 256);

	let line_tangent: Vec2 <Fx32> = line.end - line.start;
	let line_tangent = Vec2::<Fx32> {
		x: line_tangent.x * Fx32::from_q (1, 256),
		y: line_tangent.y * Fx32::from_q (1, 256),
	};
	let line_normal = line_tangent.cross ().normalized ();

	let sdf: Fx32 = (ray.start - line.start) * line_normal;

	// Flip the normal so it's towards the ray
	// This will allow us to extrude the correct side
	let line_normal = if sdf > 0 {
		line_normal
	}
	else {
		-line_normal
	};

	let big_normal: Vec2 <Fx32> = line_normal.into ();

	let along = (ray.start - line.start) * line_tangent;

	if sdf.abs () <= line.radius && along > 0 && along < (line.end - line.start) * line_tangent {
		// Ray has already started inside and we should push it out
		let towards = -Fx32::from (ray.dir * line_normal);

		let safe_point = ray.start + big_normal * (line.radius - sdf.abs () + margin);

		if towards > 0 {
			// Ray is moving deeper inside - Pop it out and reflect it
			return Ray2TraceResult::Hit (
				Fx32::from_int (0),
				safe_point,
				line_normal,
			);
		}
		else {
			// Ray is moving out - Pop it out but consume its timestep
			return Ray2TraceResult::Hit (
				Fx32::from_int (1),
				safe_point,
				line_normal,
			);
		}
	}

	let extrude_vector = line.radius * Vec2::<Fx32>::from (line_normal);
	// Extrude the line
	let line = WideLine {
		start: line.start + extrude_vector,
		end: line.end + extrude_vector,
		radius: Fx32::from_int (0),
	};

	let ray_length = ray.dir.length ();

	if ray_length == 0 {
		return Ray2TraceResult::Miss;
	}

	let basis = get_ray_basis (ray, ray_length);

	// Transform the line to ray space
	let line = WideLine {
		start: basis.to_space (&(line.start - ray.start)),
		end: basis.to_space (&(line.end - ray.start)),
		radius: line.radius,
	};

	// Line will have zero y difference resulting in a divide by zero
	if line.start.y == line.end.y {
		return Ray2TraceResult::Miss;
	}

	// Apply SAT
	if line.start.y >= 0 && line.end.y >= 0 {
		return Ray2TraceResult::Miss;
	}
	else if line.start.y <= 0 && line.end.y <= 0 {
		return Ray2TraceResult::Miss;
	}

	// If we get here, we know that the obstacle line crosses our ray somewhere

	// Note: Lines must not have 0 length
	let obstacle_t = (-line.start.y) / (line.end.y - line.start.y);

	assert! (obstacle_t >= 0);
	assert! (obstacle_t <= 1, format!("{:?}", ray_length));

	let crossing_x = line.start.x * (Fx32::from_int (1) - obstacle_t) + line.end.x * obstacle_t;

	if crossing_x < 0 || crossing_x > ray_length {
		return Ray2TraceResult::Miss;
	}

	// The line segments intersect
	let t = crossing_x / ray_length;

	let safe_point = ray.start + ray.dir * t + big_normal * (line.radius + margin);

	return Ray2TraceResult::Hit (
		t,
		safe_point,
		line_normal,
	);
}

pub fn ray_trace_circle_2 (ray: &Ray2, circle: &Circle) -> Ray2TraceResult {
	let ray_length = ray.dir.length ();
	let basis = get_ray_basis (ray, ray_length);

	let center_in_ray_space = basis.to_space (&(circle.center - ray.start));

	if center_in_ray_space.x < 0 {
		return Ray2TraceResult::Miss;
	}

	if center_in_ray_space.x > ray_length + circle.radius {
		return Ray2TraceResult::Miss;
	}

	if center_in_ray_space.y.abs () >= circle.radius {
		// Prevents a negative root later on
		return Ray2TraceResult::Miss;
	}

	let ray_space_x = center_in_ray_space.x - (circle.radius.square () - center_in_ray_space.y.square ()).sqrt ();

	if ray_space_x > ray_length || ray_length == 0 {
		return Ray2TraceResult::Miss;
	}

	let t = ray_space_x / ray_length;
	let ccd_pos = ray.start + ray.dir * t;

	if t <= 1 {
		return Ray2TraceResult::Hit (
			Fx32 { x: cmp::max (t.x, Fx32::from_int (0).x) },
			ccd_pos,
			((ccd_pos - circle.center) / circle.radius).to_small (),
		);
	}
	else {
		return Ray2TraceResult::Miss;
	}
}
<commit_msg>So close! Only a couple rays messing up<commit_after>use circle::Circle;
use fx32::Fx32;
use fx32::Fx32Small;
use ray2::Ray2;
use vec2::Vec2;
use wide_line::WideLine;

use std::cmp;

use std::io::Error;
use std::io::prelude::*;
use std::io::BufWriter;
use std::fs::File;

#[derive (Clone, Copy)]
pub enum Ray2TraceResult {
	Hit (Fx32, Vec2 <Fx32>, Vec2 <Fx32Small>),
	Miss,
}

pub fn fold_closer_result (a: Ray2TraceResult, b: Ray2TraceResult) -> Ray2TraceResult {
	match a {
		Ray2TraceResult::Miss => {
			return b;
		},
		Ray2TraceResult::Hit (a_t, ..) => {
			match b {
				Ray2TraceResult::Miss => {
					return a;
				},
				Ray2TraceResult::Hit (b_t, ..) => {
					if a_t < b_t {
						return a;
					}
					else {
						return b;
					}
				}
			}
		},
	}
}

pub fn write_vec2 <T> (writer: &mut T, v: &Vec2 <Fx32>) where T: Write {
	write! (writer, "v {} 0 {}\n", v.x.to_f64 () / 256.0, v.y.to_f64 () / 256.0).unwrap ();
}

pub fn apply_dt (ray: &Ray2, dt: Fx32Small) -> Ray2 {
	Ray2 {
		start: ray.start,
		dir: ray.dir * dt,
	}
}

pub fn test_ray_trace () -> Result <(), Error> {
	let scale = 1;
	//let scale_fx = Fx32::from_int (scale);

	let obstacle = vec! [
	Circle {
		center: Vec2 {x: Fx32::from_q (40, scale), y: Fx32::from_q (470 - 34, scale)},
		radius: Fx32::from_q (20, scale),
	},
	Circle {
		center: Vec2 {x: Fx32::from_q (256, scale), y: Fx32::from_q (512, scale)},
		radius: Fx32::from_q (20, scale),
	},
	Circle {
		center: Vec2 {x: Fx32::from_q (480, scale), y: Fx32::from_q (460, scale)},
		radius: Fx32::from_q (20, scale),
	},
	];

	let lines = vec! [
	WideLine {
		start: obstacle [0].center,
		end: obstacle [1].center,
		radius: Fx32::from_q (20, scale),
	},
	WideLine {
		start: obstacle [1].center,
		end: obstacle [2].center,
		radius: Fx32::from_q (20, scale),
	},
	];

	let mut num_bounces = 0;
	let mut num_ticks = 0;

	let inv_dt = 4;
	let gravity = Vec2::<Fx32> {
		x: Fx32::from_q (0, 1),
		y: Fx32::from_q (2, 1),
	};

	let obj_file = try!(File::create("lines.obj"));
	let mut writer = BufWriter::new (obj_file);

	let mut vertex_i = 1;
	let mut polyline_start = vertex_i;

	for x in 0..256 {
		let x = x * 2;
		let mut particle = Ray2 {
			start: Vec2 {
				x: Fx32::from_q (x * 2 + 1, scale * 2),
				y: Fx32::from_q (0, scale)
			},
			dir: Vec2 {
				x: Fx32::from_q (0, scale),
				y: Fx32::from_q (1, scale),
			},
		};

		write_vec2 (&mut writer, &particle.start);
		vertex_i += 1;

		let dt = Fx32::from_q (1, inv_dt).to_small ();

		for _ in 0..500 {
			let trace_result = {
				let point_results = obstacle.iter ().map (|obstacle| ray_trace_circle_2 (&apply_dt (&particle, dt), obstacle));

				let line_results = lines.iter ().map (|line| ray_trace_line (&apply_dt (&particle, dt), line));

				point_results.chain (line_results).fold ( Ray2TraceResult::Miss, fold_closer_result)
			};

			match trace_result {
				Ray2TraceResult::Miss => {
					//let air_drag = Fx32 { x: particle.dir.length_sq ().x / -16384 };
					//let air_force = particle.dir * air_drag;
					let new_dir = particle.dir + gravity * dt;// + Vec2::<Fx32>::from (air_force * dt);
					let sum_dir = particle.dir + new_dir;
					let average_dir = Vec2::<Fx32> {
						x: Fx32 { x: sum_dir.x.x / 2 },
						y: Fx32 { x: sum_dir.y.x / 2 },
					};

					particle.start = particle.start + (average_dir * dt);
					particle.dir = new_dir;
				},
				Ray2TraceResult::Hit (_, ccd_pos, normal) => {
					particle.start = ccd_pos;
					particle.dir = particle.dir.reflect (normal) * Fx32::from_q (768, 1024);
					//particle.dir = normal;
					num_bounces += 1;
				},
			};

			write_vec2 (&mut writer, &particle.start);
			vertex_i += 1;

			num_ticks += 1;

			if particle.start.y > 768 {
				break;
			}
		}

		for i in polyline_start..vertex_i - 1 {
			try! (write! (writer, "f {} {}\n", i, i + 1));
		}
		polyline_start = vertex_i
	}

	println! ("num_bounces: {}", num_bounces);
	println! ("num_ticks: {}", num_ticks);

	Ok (())
}

pub struct Basis2 {
	pub x: Vec2 <Fx32Small>,
	pub y: Vec2 <Fx32Small>,
}

// Constructs a basis to ray space
// Such that the ray is the X axis
pub fn get_ray_basis (ray: &Ray2, ray_length: Fx32) -> Basis2 {
	let basis_x_big = if ray_length == 0 {
		ray.dir
	}
	else {
		ray.dir / ray_length
	};

	Basis2 {
		x: basis_x_big.to_small (),
		y: basis_x_big.cross ().to_small (),
	}
}

impl Basis2 {
	pub fn to_space (&self, v: &Vec2 <Fx32>) -> Vec2 <Fx32> {
		Vec2::<Fx32> {
			x: *v * self.x,
			y: *v * self.y,
		}
	}

	pub fn from_space (&self, v: &Vec2 <Fx32>) -> Vec2 <Fx32> {
		Vec2::<Fx32> {
			x: (v.x * self.x.x) + (v.y * self.y.x),
			y: (v.x * self.x.y) + (v.y * self.y.y),
		}
	}
}

pub fn ray_trace_line (ray: &Ray2, line: &WideLine) -> Ray2TraceResult {
	if line.start == line.end {
		// Line has zero length and so zero collision area
		// If we run through the math we may get a 0 / 0 result
		// so just drop it now
		return Ray2TraceResult::Miss;
	}

	let margin = Fx32::from_q (1, 256);

	let line_tangent: Vec2 <Fx32> = line.end - line.start;
	let line_tangent = Vec2::<Fx32> {
		x: line_tangent.x * Fx32::from_q (1, 256),
		y: line_tangent.y * Fx32::from_q (1, 256),
	};
	let line_normal = line_tangent.cross ().normalized ();

	let sdf: Fx32 = (ray.start - line.start) * line_normal;

	// Flip the normal so it's towards the ray
	// This will allow us to extrude the correct side
	let line_normal = if sdf > 0 {
		line_normal
	}
	else {
		-line_normal
	};

	let big_normal: Vec2 <Fx32> = line_normal.into ();

	let along = (ray.start - line.start) * line_tangent;

	if sdf.abs () <= line.radius + margin && along > 0 && along < (line.end - line.start) * line_tangent {
		// Ray has already started inside and we should push it out
		let towards = -Fx32::from (ray.dir * line_normal);

		let safe_point = ray.start + big_normal * (line.radius - sdf.abs () + margin);

		if towards > 0 {
			// Ray is moving deeper inside - Pop it out and reflect it
			return Ray2TraceResult::Hit (
				Fx32::from_int (0),
				safe_point,
				line_normal,
			);
		}
		else {
			// Ray is moving out - Pop it out but consume its timestep
			return Ray2TraceResult::Hit (
				Fx32::from_int (1),
				safe_point,
				line_normal,
			);
		}
	}

	let extrude_vector = line.radius * Vec2::<Fx32>::from (line_normal);
	// Extrude the line
	let line = WideLine {
		start: line.start + extrude_vector,
		end: line.end + extrude_vector,
		radius: Fx32::from_int (0),
	};

	let ray_length = ray.dir.length ();

	if ray_length == 0 {
		return Ray2TraceResult::Miss;
	}

	let basis = get_ray_basis (ray, ray_length);

	// Transform the line to ray space
	let line = WideLine {
		start: basis.to_space (&(line.start - ray.start)),
		end: basis.to_space (&(line.end - ray.start)),
		radius: line.radius,
	};

	// Line will have zero y difference resulting in a divide by zero
	if line.start.y == line.end.y {
		return Ray2TraceResult::Miss;
	}

	// Apply SAT
	if line.start.y >= 0 && line.end.y >= 0 {
		return Ray2TraceResult::Miss;
	}
	else if line.start.y <= 0 && line.end.y <= 0 {
		return Ray2TraceResult::Miss;
	}

	// If we get here, we know that the obstacle line crosses our ray somewhere

	// Note: Lines must not have 0 length
	let obstacle_t = (-line.start.y) / (line.end.y - line.start.y);

	assert! (obstacle_t >= 0);
	assert! (obstacle_t <= 1, format!("{:?}", ray_length));

	let crossing_x = line.start.x * (Fx32::from_int (1) - obstacle_t) + line.end.x * obstacle_t;

	if crossing_x < 0 || crossing_x > ray_length {
		return Ray2TraceResult::Miss;
	}

	// The line segments intersect
	let t = crossing_x / ray_length;

	let safe_point = ray.start + ray.dir * t + big_normal * (line.radius + margin);

	return Ray2TraceResult::Hit (
		t,
		safe_point,
		line_normal,
	);
}

pub fn ray_trace_circle_2 (ray: &Ray2, circle: &Circle) -> Ray2TraceResult {
	let ray_length = ray.dir.length ();
	let basis = get_ray_basis (ray, ray_length);

	let center_in_ray_space = basis.to_space (&(circle.center - ray.start));

	if center_in_ray_space.x < 0 {
		return Ray2TraceResult::Miss;
	}

	if center_in_ray_space.x > ray_length + circle.radius {
		return Ray2TraceResult::Miss;
	}

	if center_in_ray_space.y.abs () >= circle.radius {
		// Prevents a negative root later on
		return Ray2TraceResult::Miss;
	}

	let ray_space_x = center_in_ray_space.x - (circle.radius.square () - center_in_ray_space.y.square ()).sqrt ();

	if ray_space_x > ray_length || ray_length == 0 {
		return Ray2TraceResult::Miss;
	}

	let t = ray_space_x / ray_length;
	let ccd_pos = ray.start + ray.dir * t;

	if t <= 1 {
		return Ray2TraceResult::Hit (
			Fx32 { x: cmp::max (t.x, Fx32::from_int (0).x) },
			ccd_pos,
			((ccd_pos - circle.center) / circle.radius).to_small (),
		);
	}
	else {
		return Ray2TraceResult::Miss;
	}
}
<|endoftext|>


<commit_before>pub use amq_protocol::protocol::BasicProperties;

use amq_protocol::protocol::AMQPClass;
use amq_protocol::frame::AMQPFrame;
use crossbeam_channel::Sender;
use log::error;

use std::result;
use std::collections::{HashMap, HashSet, VecDeque};

use crate::api::{Answer, ChannelState};
use crate::error::{Error, ErrorKind};
use crate::message::BasicGetMessage;
use crate::queue::Queue;

#[derive(Debug)]
pub struct Channel {
  pub id:             u16,
  pub state:          ChannelState,
  pub send_flow:      bool,
  pub receive_flow:   bool,
  pub queues:         HashMap<String, Queue>,
  pub prefetch_size:  u32,
  pub prefetch_count: u16,
  pub confirm:        bool,
  pub acked:          HashSet<u64>,
  pub nacked:         HashSet<u64>,
  pub unacked:        HashSet<u64>,
  pub awaiting:       VecDeque<Answer>,
      delivery_tag:   u64,
      frame_sender:   Sender<AMQPFrame>,
}

impl Channel {
  pub fn new(channel_id: u16, frame_sender: Sender<AMQPFrame>) -> Channel {
    Channel {
      id:             channel_id,
      state:          ChannelState::Initial,
      send_flow:      true,
      receive_flow:   true,
      queues:         HashMap::new(),
      prefetch_size:  0,
      prefetch_count: 0,
      confirm:        false,
      acked:          HashSet::new(),
      nacked:         HashSet::new(),
      unacked:        HashSet::new(),
      awaiting:       VecDeque::new(),
      delivery_tag:   1,
      frame_sender,
    }
  }

  /// verifies if the channel's state is the one passed as argument
  pub fn check_state(&self, state: ChannelState) -> result::Result<(), Error> {
    if self.state == state {
      Ok(())
    } else {
      Err(ErrorKind::InvalidState {
        expected: state,
        actual:   self.state.clone(),
      }.into())
    }
  }

  #[doc(hidden)]
  pub fn send_method_frame(&mut self, method: AMQPClass) {
    self.send_frame(AMQPFrame::Method(self.id, method));
  }

  #[doc(hidden)]
  pub fn send_frame(&mut self, frame: AMQPFrame) {
    // We always hold a reference to the receiver so it's safe to unwrap
    self.frame_sender.send(frame).unwrap();
  }

  /// gets the next message corresponding to a queue, in response to a basic.get
  ///
  /// If there is no message, the method will return None
  pub fn next_basic_get_message(&mut self, queue_name: &str) -> Option<BasicGetMessage> {
      self.queues.get_mut(queue_name).and_then(|queue| queue.next_basic_get_message())
  }

  #[doc(hidden)]
  pub fn handle_content_header_frame(&mut self, size: u64, properties: BasicProperties) {
    if let ChannelState::WillReceiveContent(queue_name, consumer_tag) = self.state.clone() {
      if size > 0 {
        self.state = ChannelState::ReceivingContent(queue_name.clone(), consumer_tag.clone(), size as usize);
      } else {
        self.state = ChannelState::Connected;
      }
      if let Some(ref mut q) = self.queues.get_mut(&queue_name) {
        if let Some(ref consumer_tag) = consumer_tag {
          if let Some(ref mut cs) = q.consumers.get_mut(consumer_tag) {
            cs.set_delivery_properties(properties);
            if size == 0 {
              cs.new_delivery_complete();
            }
          }
        } else {
          q.set_delivery_properties(properties);
          if size == 0 {
            q.new_delivery_complete();
          }
        }
      }
    } else {
      self.state = ChannelState::Error;
    }
  }

  #[doc(hidden)]
  pub fn handle_body_frame(&mut self, payload: Vec<u8>) {
    let payload_size = payload.len();

    if let ChannelState::ReceivingContent(queue_name, opt_consumer_tag, remaining_size) = self.state.clone() {
      if remaining_size >= payload_size {
        if let Some(ref mut q) = self.queues.get_mut(&queue_name) {
          if let Some(ref consumer_tag) = opt_consumer_tag {
            if let Some(ref mut cs) = q.consumers.get_mut(consumer_tag) {
              cs.receive_delivery_content(payload);
              if remaining_size == payload_size {
                cs.new_delivery_complete();
              }
            }
          } else {
            q.receive_delivery_content(payload);
            if remaining_size == payload_size {
              q.new_delivery_complete();
            }
          }
        }

        if remaining_size == payload_size {
          self.state = ChannelState::Connected;
        } else {
          self.state = ChannelState::ReceivingContent(queue_name, opt_consumer_tag, remaining_size - payload_size);
        }
      } else {
        error!("body frame too large");
        self.state = ChannelState::Error;
      }
    } else {
      self.state = ChannelState::Error;
    }
  }

  pub fn is_connected(&self) -> bool {
    self.state != ChannelState::Initial && self.state != ChannelState::Closed && self.state != ChannelState::Error
  }

  pub fn next_delivery_tag(&mut self) -> u64 {
    let tag = self.delivery_tag;
    self.delivery_tag += 1;
    if self.delivery_tag == 0 {
      self.delivery_tag = 1;
    }
    tag
  }

  pub fn ack(&mut self, delivery_tag: u64) -> Result<(), Error> {
    self.drop_unacked(delivery_tag)?;
    self.acked.insert(delivery_tag);
    Ok(())
  }

  pub fn nack(&mut self, delivery_tag: u64) -> Result<(), Error> {
    self.drop_unacked(delivery_tag)?;
    self.nacked.insert(delivery_tag);
    Ok(())
  }

  fn drop_unacked(&mut self, delivery_tag: u64) -> Result<(), Error> {
    if !self.unacked.remove(&delivery_tag) {
      return Err(ErrorKind::PreconditionFailed.into());
    }
    Ok(())
  }
}
<commit_msg>async: introduce ChannelHandle<commit_after>pub use amq_protocol::protocol::BasicProperties;

use amq_protocol::protocol::AMQPClass;
use amq_protocol::frame::AMQPFrame;
use crossbeam_channel::Sender;
use log::error;

use std::result;
use std::collections::{HashMap, HashSet, VecDeque};

use crate::api::{Answer, ChannelState};
use crate::error::{Error, ErrorKind};
use crate::message::BasicGetMessage;
use crate::queue::Queue;

#[derive(Clone, Debug)]
pub struct ChannelHandle {
  pub id:             u16,
      frame_sender:   Sender<AMQPFrame>,
}

#[derive(Debug)]
pub struct Channel {
  pub id:             u16,
  pub state:          ChannelState,
  pub send_flow:      bool,
  pub receive_flow:   bool,
  pub queues:         HashMap<String, Queue>,
  pub prefetch_size:  u32,
  pub prefetch_count: u16,
  pub confirm:        bool,
  pub acked:          HashSet<u64>,
  pub nacked:         HashSet<u64>,
  pub unacked:        HashSet<u64>,
  pub awaiting:       VecDeque<Answer>,
      delivery_tag:   u64,
      frame_sender:   Sender<AMQPFrame>,
}

impl Channel {
  pub fn new(channel_id: u16, frame_sender: Sender<AMQPFrame>) -> Channel {
    Channel {
      id:             channel_id,
      state:          ChannelState::Initial,
      send_flow:      true,
      receive_flow:   true,
      queues:         HashMap::new(),
      prefetch_size:  0,
      prefetch_count: 0,
      confirm:        false,
      acked:          HashSet::new(),
      nacked:         HashSet::new(),
      unacked:        HashSet::new(),
      awaiting:       VecDeque::new(),
      delivery_tag:   1,
      frame_sender,
    }
  }

  pub fn handle(&self) -> ChannelHandle {
    ChannelHandle {
      id:           self.id,
      frame_sender: self.frame_sender.clone(),
    }
  }

  /// verifies if the channel's state is the one passed as argument
  pub fn check_state(&self, state: ChannelState) -> result::Result<(), Error> {
    if self.state == state {
      Ok(())
    } else {
      Err(ErrorKind::InvalidState {
        expected: state,
        actual:   self.state.clone(),
      }.into())
    }
  }

  #[doc(hidden)]
  pub fn send_method_frame(&mut self, method: AMQPClass) {
    self.send_frame(AMQPFrame::Method(self.id, method));
  }

  #[doc(hidden)]
  pub fn send_frame(&mut self, frame: AMQPFrame) {
    // We always hold a reference to the receiver so it's safe to unwrap
    self.frame_sender.send(frame).unwrap();
  }

  /// gets the next message corresponding to a queue, in response to a basic.get
  ///
  /// If there is no message, the method will return None
  pub fn next_basic_get_message(&mut self, queue_name: &str) -> Option<BasicGetMessage> {
      self.queues.get_mut(queue_name).and_then(|queue| queue.next_basic_get_message())
  }

  #[doc(hidden)]
  pub fn handle_content_header_frame(&mut self, size: u64, properties: BasicProperties) {
    if let ChannelState::WillReceiveContent(queue_name, consumer_tag) = self.state.clone() {
      if size > 0 {
        self.state = ChannelState::ReceivingContent(queue_name.clone(), consumer_tag.clone(), size as usize);
      } else {
        self.state = ChannelState::Connected;
      }
      if let Some(ref mut q) = self.queues.get_mut(&queue_name) {
        if let Some(ref consumer_tag) = consumer_tag {
          if let Some(ref mut cs) = q.consumers.get_mut(consumer_tag) {
            cs.set_delivery_properties(properties);
            if size == 0 {
              cs.new_delivery_complete();
            }
          }
        } else {
          q.set_delivery_properties(properties);
          if size == 0 {
            q.new_delivery_complete();
          }
        }
      }
    } else {
      self.state = ChannelState::Error;
    }
  }

  #[doc(hidden)]
  pub fn handle_body_frame(&mut self, payload: Vec<u8>) {
    let payload_size = payload.len();

    if let ChannelState::ReceivingContent(queue_name, opt_consumer_tag, remaining_size) = self.state.clone() {
      if remaining_size >= payload_size {
        if let Some(ref mut q) = self.queues.get_mut(&queue_name) {
          if let Some(ref consumer_tag) = opt_consumer_tag {
            if let Some(ref mut cs) = q.consumers.get_mut(consumer_tag) {
              cs.receive_delivery_content(payload);
              if remaining_size == payload_size {
                cs.new_delivery_complete();
              }
            }
          } else {
            q.receive_delivery_content(payload);
            if remaining_size == payload_size {
              q.new_delivery_complete();
            }
          }
        }

        if remaining_size == payload_size {
          self.state = ChannelState::Connected;
        } else {
          self.state = ChannelState::ReceivingContent(queue_name, opt_consumer_tag, remaining_size - payload_size);
        }
      } else {
        error!("body frame too large");
        self.state = ChannelState::Error;
      }
    } else {
      self.state = ChannelState::Error;
    }
  }

  pub fn is_connected(&self) -> bool {
    self.state != ChannelState::Initial && self.state != ChannelState::Closed && self.state != ChannelState::Error
  }

  pub fn next_delivery_tag(&mut self) -> u64 {
    let tag = self.delivery_tag;
    self.delivery_tag += 1;
    if self.delivery_tag == 0 {
      self.delivery_tag = 1;
    }
    tag
  }

  pub fn ack(&mut self, delivery_tag: u64) -> Result<(), Error> {
    self.drop_unacked(delivery_tag)?;
    self.acked.insert(delivery_tag);
    Ok(())
  }

  pub fn nack(&mut self, delivery_tag: u64) -> Result<(), Error> {
    self.drop_unacked(delivery_tag)?;
    self.nacked.insert(delivery_tag);
    Ok(())
  }

  fn drop_unacked(&mut self, delivery_tag: u64) -> Result<(), Error> {
    if !self.unacked.remove(&delivery_tag) {
      return Err(ErrorKind::PreconditionFailed.into());
    }
    Ok(())
  }
}
<|endoftext|>