<commit_before>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Need non-snake case so the macro can re-use type names for variables.
#![allow(non_snake_case)]

use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

use futures::future::{maybe_done, FutureExt, MaybeDone};

pub enum SelectResult<F: Future> {
    Pending(F),
    Finished(F::Output),
}

// Macro-generate future combinators to allow for running different numbers of top-level futures in
// this FutureList. Generates the implementation of `FutureList` for the select types. For an
// explicit example this is modeled after, see `UnitFutures`.
macro_rules! generate {
    ($(
        $(#[$doc:meta])*
        ($Select:ident, <$($Fut:ident),*>),
    )*) => ($(
        #[must_use = "Combinations of futures don't do anything unless run in an executor."]
        paste::item! {
            pub(crate) struct $Select<$($Fut: Future + Unpin),*> {
                $($Fut: MaybeDone<$Fut>,)*
            }
        }

        impl<$($Fut: Future + Unpin),*> $Select<$($Fut),*> {
            paste::item! {
                pub(crate) fn new($($Fut: $Fut),*) -> $Select<$($Fut),*> {
                    $Select {
                        $($Fut: maybe_done($Fut),)*
                    }
                }
            }
        }

        impl<$($Fut: Future + Unpin),*> Future for $Select<$($Fut),*> {
            type Output = ($(SelectResult<$Fut>),*);

            fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
                let mut complete = false;
                $(
                    let $Fut = Pin::new(&mut self.$Fut);
                    // The future impls `Unpin`, use `poll_unpin` to avoid wrapping it in
                    // `Pin` to call `poll`.
                    complete |= self.$Fut.poll_unpin(cx).is_ready();
                )*

                if complete {
                    Poll::Ready(($(
                        match std::mem::replace(&mut self.$Fut, MaybeDone::Gone) {
                            MaybeDone::Future(f) => SelectResult::Pending(f),
                            MaybeDone::Done(o) => SelectResult::Finished(o),
                            MaybeDone::Gone => unreachable!(),
                        }
                    ), *))
                } else {
                    Poll::Pending
                }
            }
        }
    )*)
}

generate! {
    /// _Future for the [`select2`] function.
    (Select2, <_Fut1, _Fut2>),

    /// _Future for the [`select3`] function.
    (Select3, <_Fut1, _Fut2, _Fut3>),

    /// _Future for the [`select4`] function.
    (Select4, <_Fut1, _Fut2, _Fut3, _Fut4>),

    /// _Future for the [`select5`] function.
    (Select5, <_Fut1, _Fut2, _Fut3, _Fut4, _Fut5>),

    /// _Future for the [`select6`] function.
    (Select6, <_Fut1, _Fut2, _Fut3, _Fut4, _Fut5, _Fut6>),
}
<commit_msg>async: remove misplaced must_use attribute<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Need non-snake case so the macro can re-use type names for variables.
#![allow(non_snake_case)]

use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

use futures::future::{maybe_done, FutureExt, MaybeDone};

pub enum SelectResult<F: Future> {
    Pending(F),
    Finished(F::Output),
}

// Macro-generate future combinators to allow for running different numbers of top-level futures in
// this FutureList. Generates the implementation of `FutureList` for the select types. For an
// explicit example this is modeled after, see `UnitFutures`.
macro_rules! generate {
    ($(
        $(#[$doc:meta])*
        ($Select:ident, <$($Fut:ident),*>),
    )*) => ($(

        paste::item! {
            pub(crate) struct $Select<$($Fut: Future + Unpin),*> {
                $($Fut: MaybeDone<$Fut>,)*
            }
        }

        impl<$($Fut: Future + Unpin),*> $Select<$($Fut),*> {
            paste::item! {
                pub(crate) fn new($($Fut: $Fut),*) -> $Select<$($Fut),*> {
                    $Select {
                        $($Fut: maybe_done($Fut),)*
                    }
                }
            }
        }

        impl<$($Fut: Future + Unpin),*> Future for $Select<$($Fut),*> {
            type Output = ($(SelectResult<$Fut>),*);

            fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
                let mut complete = false;
                $(
                    let $Fut = Pin::new(&mut self.$Fut);
                    // The future impls `Unpin`, use `poll_unpin` to avoid wrapping it in
                    // `Pin` to call `poll`.
                    complete |= self.$Fut.poll_unpin(cx).is_ready();
                )*

                if complete {
                    Poll::Ready(($(
                        match std::mem::replace(&mut self.$Fut, MaybeDone::Gone) {
                            MaybeDone::Future(f) => SelectResult::Pending(f),
                            MaybeDone::Done(o) => SelectResult::Finished(o),
                            MaybeDone::Gone => unreachable!(),
                        }
                    ), *))
                } else {
                    Poll::Pending
                }
            }
        }
    )*)
}

generate! {
    /// _Future for the [`select2`] function.
    (Select2, <_Fut1, _Fut2>),

    /// _Future for the [`select3`] function.
    (Select3, <_Fut1, _Fut2, _Fut3>),

    /// _Future for the [`select4`] function.
    (Select4, <_Fut1, _Fut2, _Fut3, _Fut4>),

    /// _Future for the [`select5`] function.
    (Select5, <_Fut1, _Fut2, _Fut3, _Fut4, _Fut5>),

    /// _Future for the [`select6`] function.
    (Select6, <_Fut1, _Fut2, _Fut3, _Fut4, _Fut5, _Fut6>),
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate httparse;
extern crate mio;
extern crate net2;
extern crate num_cpus;
extern crate slab;
extern crate time;

use std::ascii::AsciiExt;
use std::env;
use std::io::{self, Read, Write};
use std::mem;
use std::net::SocketAddr;
use std::slice;
use std::str;
use std::thread;

use net2::unix::*;

use mio::tcp::{TcpStream, TcpListener};
use mio::{Poll, Token, EventSet, PollOpt, Events};
use slab::Slab;

const LISTENER: mio::Token = mio::Token(0);

struct Server<'a> {
    count: u64,
    listener: &'a TcpListener,
    connections: Slab<Connection, mio::Token>,
}

impl<'a> Server<'a> {
    fn new(listener: &'a TcpListener) -> Server<'a> {
        Server {
            count: 0,
            listener: listener,
            connections: Slab::new_starting_at(mio::Token(1), 1024),
        }
    }

    fn ready(&mut self,
             poll: &Poll,
             token: Token,
             events: EventSet) {
        debug!("{:?} {:?}", token, events);
        if token == LISTENER {
            while let Ok(Some(socket)) = self.listener.accept() {
                debug!("accepted");
                self.count += 1;
                // socket.0.set_nodelay(true).unwrap();
                let token = self.connections
                    .insert_with(move |_| Connection::new(socket.0))
                    .unwrap();
                self.try_connection(poll, token, EventSet::all());
            }
        } else {
            self.try_connection(poll, token, events);
        }
    }

    fn try_connection(&mut self, poll: &Poll, token: Token, events: EventSet) {
        let res = self.connections[token].ready(events);

        if res.is_err() || self.connections[token].closed {
            if let Err(ref e) = res {
                info!("error: {:?}\non: {:?} {:?}", e,
                       token, self.connections[token].socket);
            }
            debug!("removing");
            self.connections.remove(token);
        } else {
            self.connections[token].reregister(poll, token).unwrap();
        }
    }
}

struct Connection {
    socket: TcpStream,
    input: Vec<u8>,
    output: Output,
    keepalive: bool,
    closed: bool,
    first: bool,
    read_closed: bool,
}

struct Output {
    buf: Vec<u8>,
}

impl Connection {
    fn new(socket: TcpStream) -> Connection {
        Connection {
            socket: socket,
            input: Vec::with_capacity(2048),
            output: Output {
                buf: Vec::with_capacity(2048),
            },
            keepalive: false,
            read_closed: false,
            closed: false,
            first: true,
        }
    }

    fn ready(&mut self, events: EventSet) -> io::Result<()> {
        while events.is_readable() && !self.read_closed {
            let before = self.input.len();
            let eof = try!(read(&mut self.socket, &mut self.input));
            if eof {
                debug!("eof");
            }
            self.read_closed = eof;
            if self.input.len() == before {
                break
            }

            while self.input.len() > 0 {
                let (req, amt) = match try!(parse(&self.input)) {
                    Some(pair) => pair,
                    None => {
                        debug!("need more data for a request");
                        return Ok(())
                    }
                };
                let request = Request {
                    inner: req,
                    amt: amt,
                    data: mem::replace(&mut self.input, Vec::new()),
                };
                debug!("got a request");
                self.keepalive = request.version() >= 1;
                self.keepalive = self.keepalive || request.headers().any(|s| {
                    s.0.eq_ignore_ascii_case("connection") &&
                        s.1.eq_ignore_ascii_case(b"keep-alive")
                });

                let response = process(&request);
                response.to_bytes(&mut self.output.buf);

                self.input = request.into_input_buf();
                if !self.keepalive {
                    debug!("disabling keepalive");
                    self.read_closed = true;
                }
            }
        }

        if events.is_writable() && self.output.buf.len() > 0 {
            let done = try!(write(&mut self.socket, &mut self.output));
            if done {
                debug!("wrote response");
                if !self.keepalive || self.read_closed {
                    self.closed = true;
                }
            }
        }

        if self.read_closed && self.output.buf.len() == 0 {
            self.closed = true;
        }
        Ok(())
    }

    fn reregister(&mut self, poll: &Poll, token: Token) -> io::Result<()> {
        assert!(!self.closed);
        debug!("register");
        let events = if self.output.buf.len() > 0 {
            if self.read_closed {
                EventSet::writable()
            } else {
                EventSet::writable() | EventSet::readable()
            }
        } else {
            assert!(!self.read_closed);
            EventSet::readable()
        };
        let opts = PollOpt::edge() | PollOpt::oneshot();
        if self.first {
            self.first = false;
            poll.register(&self.socket, token, events, opts)
        } else {
            poll.reregister(&self.socket, token, events, opts)
        }
    }
}

fn process(r: &Request) -> Response {
    assert!(r.path() == "/plaintext");
    let mut r = Response::new();
    r.header("Content-Type", "text/plain; charset=UTF-8")
     .body("Hello, World!\r\n");
    return r
}

type Slice = (usize, usize);

#[allow(dead_code)]
pub struct Request {
    inner: RawRequest,
    data: Vec<u8>,
    amt: usize,
}

struct RawRequest {
    method: Slice,
    path: Slice,
    version: u8,
    headers: Vec<(Slice, Slice)>,
}

pub struct Headers<'a> {
    iter: slice::Iter<'a, (Slice, Slice)>,
    req: &'a Request,
}

impl Request {
    pub fn method(&self) -> &str {
        str::from_utf8(self.get(&self.inner.method)).unwrap()
    }

    pub fn path(&self) -> &str {
        str::from_utf8(self.get(&self.inner.path)).unwrap()
    }

    pub fn version(&self) -> u8 {
        self.inner.version
    }

    pub fn headers(&self) -> Headers {
        Headers {
            iter: self.inner.headers.iter(),
            req: self,
        }
    }

    pub fn into_input_buf(mut self) -> Vec<u8> {
        self.data.drain(..self.amt);
        self.data
    }

    fn get(&self, s: &Slice) -> &[u8] {
        &self.data[s.0..s.1]
    }
}

impl<'a> Iterator for Headers<'a> {
    type Item = (&'a str, &'a [u8]);

    fn next(&mut self) -> Option<(&'a str, &'a [u8])> {
        self.iter.next().map(|&(ref k, ref v)| {
            (str::from_utf8(self.req.get(k)).unwrap(), self.req.get(v))
        })
    }
}

fn parse(buf: &[u8]) -> io::Result<Option<(RawRequest, usize)>> {
    let mut headers = [httparse::EMPTY_HEADER; 16];
    let mut r = httparse::Request::new(&mut headers);
    let status = try!(r.parse(&buf).map_err(|_| {
        io::Error::new(io::ErrorKind::Other, "failed to parse")
    }));
    return match status {
        httparse::Status::Complete(amt) => {
            debug!("ok {:?}", String::from_utf8_lossy(&buf[..amt]));
            Ok(Some((RawRequest {
                method: slice(buf, r.method.unwrap().as_bytes()),
                path: slice(buf, r.path.unwrap().as_bytes()),
                version: r.version.unwrap(),
                headers: r.headers.iter().map(|h| {
                    (slice(buf, h.name.as_bytes()), slice(buf, &h.value))
                }).collect(),
            }, amt)))
        }
        httparse::Status::Partial => Ok(None),
    };

    fn slice(buf: &[u8], inner: &[u8]) -> Slice {
        let start = inner.as_ptr() as usize - buf.as_ptr() as usize;
        assert!(start < buf.len());
        (start, start + inner.len())
    }
}

pub struct Response {
    headers: Vec<(String, String)>,
    response: String,
}

impl Response {
    pub fn new() -> Response {
        Response {
            headers: Vec::new(),
            response: String::new(),
        }
    }

    pub fn header(&mut self, name: &str, val: &str) -> &mut Response {
        self.headers.push((name.to_string(), val.to_string()));
        self
    }

    pub fn body(&mut self, s: &str) -> &mut Response {
        self.response = s.to_string();
        self
    }

    fn to_bytes(&self, into: &mut Vec<u8>) {
        write!(into, "\
            HTTP/1.1 200 OK\r\n\
            Server: Example\r\n\
            Date: {}\r\n\
            Content-Length: {}\r\n\
        ", time::now().rfc822(), self.response.len()).unwrap();
        for &(ref k, ref v) in &self.headers {
            extend(into, k.as_bytes());
            extend(into, b": ");
            extend(into, v.as_bytes());
            extend(into, b"\r\n");
        }
        extend(into, b"\r\n");
        extend(into, self.response.as_bytes());
    }
}

// TODO: why does extend_from_slice not optimize?
fn extend(dst: &mut Vec<u8>, data: &[u8]) {
    use std::ptr;
    dst.reserve(data.len());
    let prev = dst.len();
    unsafe {
        ptr::copy_nonoverlapping(data.as_ptr(),
                                 dst.as_mut_ptr().offset(prev as isize),
                                 data.len());
        dst.set_len(prev + data.len());
    }
}

fn read(socket: &mut TcpStream, input: &mut Vec<u8>) -> io::Result<bool> {
    loop {
        match socket.read(unsafe { slice_to_end(input) }) {
            Ok(0) => return Ok(true),
            Ok(n) => {
                let len = input.len();
                unsafe { input.set_len(len + n); }
                return Ok(false)
            }
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                return Ok(false)
            }
            Err(e) => return Err(e),
        }
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        use std::slice;
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}

fn write(socket: &mut TcpStream, output: &mut Output) -> io::Result<bool> {
    assert!(output.buf.len() > 0);
    loop {
        match socket.write(&output.buf) {
            Ok(0) => {
                return Err(io::Error::new(io::ErrorKind::Other, "early eof2"))
            }
            Ok(n) => {
                output.buf.drain(..n);
                if output.buf.len() == 0 {
                    return Ok(true)
                }
            }
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                return Ok(false)
            }
            Err(e) => return Err(e),
        }
    }
}

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

    let threads = (0..num_cpus::get()).map(|_| {
        thread::spawn(|| {
            let poll = mio::Poll::new().unwrap();
            let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
            let addr = addr.parse::<SocketAddr>().unwrap();
            let socket = net2::TcpBuilder::new_v4().unwrap();
            socket.reuse_address(true).unwrap();
            socket.reuse_port(true).unwrap();
            socket.bind(&addr).unwrap();
            let listener = socket.listen(2048).unwrap();
            let listener = TcpListener::from_listener(listener, &addr).unwrap();
            poll.register(&listener,
                          LISTENER,
                          EventSet::readable(),
                          PollOpt::level()).unwrap();

            let mut events = Events::new();
            let mut server = Server::new(&listener);
            loop {
                poll.poll(&mut events, None).unwrap();

                for i in 0..events.len() {
                    let event = events.get(i).unwrap();
                    server.ready(&poll, event.token(), event.kind());
                }
            }
        })
    }).collect::<Vec<_>>();

    for thread in threads {
        thread.join().unwrap();
    }
}
<commit_msg>Update mio-multithread-unix<commit_after>#[macro_use]
extern crate log;
extern crate env_logger;
extern crate httparse;
extern crate mio;
extern crate net2;
extern crate num_cpus;
extern crate slab;
extern crate time;

use std::ascii::AsciiExt;
use std::env;
use std::fmt;
use std::io::{self, Read, Write};
use std::mem;
use std::net::SocketAddr;
use std::panic;
use std::slice;
use std::str;
use std::thread;

use net2::unix::*;

use mio::tcp::{TcpStream, TcpListener};
use mio::{Poll, Token, EventSet, PollOpt, Events};
use slab::Slab;

const LISTENER: mio::Token = mio::Token(0);

struct Server<'a> {
    count: u64,
    listener: &'a TcpListener,
    connections: Slab<Connection, mio::Token>,
}

impl<'a> Server<'a> {
    fn new(listener: &'a TcpListener) -> Server<'a> {
        Server {
            count: 0,
            listener: listener,
            connections: Slab::new_starting_at(mio::Token(1), 1024),
        }
    }

    fn ready(&mut self,
             poll: &Poll,
             token: Token,
             events: EventSet) {
        debug!("{:?} {:?}", token, events);
        if token == LISTENER {
            while let Ok(Some(socket)) = self.listener.accept() {
                debug!("accepted");
                self.count += 1;
                // socket.0.set_nodelay(true).unwrap();
                let token = self.connections
                    .insert_with(move |_| Connection::new(socket.0))
                    .unwrap();
                poll.register(&self.connections[token].socket,
                              token,
                              EventSet::readable() | EventSet::writable(),
                              PollOpt::edge()).unwrap();
                self.try_connection(token, EventSet::all());
            }
        } else {
            self.try_connection(token, events);
        }
    }

    fn try_connection(&mut self, token: Token, events: EventSet) {
        // Simulate a `catch_unwind` that a real server would do anyway
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| {
            self.connections[token].ready(events)
        })).expect("oh no it panicked!");

        if res.is_err() || self.connections[token].closed {
            if let Err(ref e) = res {
                info!("error: {:?}\non: {:?} {:?}", e,
                       token, self.connections[token].socket);
            }
            debug!("removing");
            self.connections.remove(token);
        }
    }
}

struct Connection {
    socket: TcpStream,
    input: Vec<u8>,
    output: Output,
    keepalive: bool,
    closed: bool,
    read_closed: bool,
    events: EventSet,
}

struct Output {
    buf: Vec<u8>,
}

impl Connection {
    fn new(socket: TcpStream) -> Connection {
        Connection {
            socket: socket,
            input: Vec::with_capacity(2048),
            output: Output {
                buf: Vec::with_capacity(2048),
            },
            keepalive: false,
            read_closed: false,
            closed: false,
            events: EventSet::none(),
        }
    }

    fn ready(&mut self, events: EventSet) -> io::Result<()> {
        self.events = self.events | events;
        while self.events.is_readable() && !self.read_closed {
            let before = self.input.len();
            let eof = try!(read(&mut self.socket,
                                &mut self.input,
                                &mut self.events));
            if eof {
                debug!("eof");
            }
            self.read_closed = eof;
            if self.input.len() == before {
                break
            }

            while self.input.len() > 0 {
                let (req, amt) = match try!(parse(&self.input)) {
                    Some(pair) => pair,
                    None => {
                        debug!("need more data for a request");
                        return Ok(())
                    }
                };
                let request = Request {
                    inner: req,
                    amt: amt,
                    data: mem::replace(&mut self.input, Vec::new()),
                };
                debug!("got a request");
                self.keepalive = request.version() >= 1;
                self.keepalive = self.keepalive || request.headers().any(|s| {
                    s.0.eq_ignore_ascii_case("connection") &&
                        s.1.eq_ignore_ascii_case(b"keep-alive")
                });

                let response = process(&request);
                response.to_bytes(&mut self.output.buf);

                self.input = request.into_input_buf();
                if !self.keepalive {
                    debug!("disabling keepalive");
                    self.read_closed = true;
                }
            }
        }

        if self.events.is_writable() && self.output.buf.len() > 0 {
            let done = try!(write(&mut self.socket,
                                  &mut self.output,
                                  &mut self.events));
            if done {
                debug!("wrote response");
                if !self.keepalive || self.read_closed {
                    self.closed = true;
                }
            }
        }

        if self.read_closed && self.output.buf.len() == 0 {
            self.closed = true;
        }
        Ok(())
    }
}

fn process(r: &Request) -> Response {
    assert!(r.path() == "/plaintext");
    let mut r = Response::new();
    r.header("Content-Type", "text/plain; charset=UTF-8")
     .body("Hello, World!");
    return r
}

type Slice = (usize, usize);

#[allow(dead_code)]
pub struct Request {
    inner: RawRequest,
    data: Vec<u8>,
    amt: usize,
}

struct RawRequest {
    method: Slice,
    path: Slice,
    version: u8,
    headers: Vec<(Slice, Slice)>,
}

pub struct Headers<'a> {
    iter: slice::Iter<'a, (Slice, Slice)>,
    req: &'a Request,
}

impl Request {
    pub fn method(&self) -> &str {
        str::from_utf8(self.get(&self.inner.method)).unwrap()
    }

    pub fn path(&self) -> &str {
        str::from_utf8(self.get(&self.inner.path)).unwrap()
    }

    pub fn version(&self) -> u8 {
        self.inner.version
    }

    pub fn headers(&self) -> Headers {
        Headers {
            iter: self.inner.headers.iter(),
            req: self,
        }
    }

    pub fn into_input_buf(mut self) -> Vec<u8> {
        self.data.drain(..self.amt);
        self.data
    }

    fn get(&self, s: &Slice) -> &[u8] {
        &self.data[s.0..s.1]
    }
}

impl<'a> Iterator for Headers<'a> {
    type Item = (&'a str, &'a [u8]);

    fn next(&mut self) -> Option<(&'a str, &'a [u8])> {
        self.iter.next().map(|&(ref k, ref v)| {
            (str::from_utf8(self.req.get(k)).unwrap(), self.req.get(v))
        })
    }
}

fn parse(buf: &[u8]) -> io::Result<Option<(RawRequest, usize)>> {
    let mut headers = [httparse::EMPTY_HEADER; 16];
    let mut r = httparse::Request::new(&mut headers);
    let status = try!(r.parse(&buf).map_err(|_| {
        io::Error::new(io::ErrorKind::Other, "failed to parse")
    }));
    return match status {
        httparse::Status::Complete(amt) => {
            debug!("ok {:?}", String::from_utf8_lossy(&buf[..amt]));
            Ok(Some((RawRequest {
                method: slice(buf, r.method.unwrap().as_bytes()),
                path: slice(buf, r.path.unwrap().as_bytes()),
                version: r.version.unwrap(),
                headers: r.headers.iter().map(|h| {
                    (slice(buf, h.name.as_bytes()), slice(buf, &h.value))
                }).collect(),
            }, amt)))
        }
        httparse::Status::Partial => Ok(None),
    };

    fn slice(buf: &[u8], inner: &[u8]) -> Slice {
        let start = inner.as_ptr() as usize - buf.as_ptr() as usize;
        assert!(start < buf.len());
        (start, start + inner.len())
    }
}

pub struct Response {
    headers: Vec<(String, String)>,
    response: String,
}

impl Response {
    pub fn new() -> Response {
        Response {
            headers: Vec::new(),
            response: String::new(),
        }
    }

    pub fn header(&mut self, name: &str, val: &str) -> &mut Response {
        self.headers.push((name.to_string(), val.to_string()));
        self
    }

    pub fn body(&mut self, s: &str) -> &mut Response {
        self.response = s.to_string();
        self
    }

    fn to_bytes(&self, into: &mut Vec<u8>) {
        use std::fmt::Write;

        write!(FastWrite(into), "\
            HTTP/1.1 200 OK\r\n\
            Server: Example\r\n\
            Date: {}\r\n\
            Content-Length: {}\r\n\
        ", time::now().rfc822(), self.response.len()).unwrap();
        for &(ref k, ref v) in &self.headers {
            extend(into, k.as_bytes());
            extend(into, b": ");
            extend(into, v.as_bytes());
            extend(into, b"\r\n");
        }
        extend(into, b"\r\n");
        extend(into, self.response.as_bytes());
    }
}

// TODO: impl fmt::Write for Vec<u8>
//
// Right now `write!` on `Vec<u8>` goes through io::Write and is not super
// speedy, so inline a less-crufty implementation here which doesn't go through
// io::Error.
struct FastWrite<'a>(&'a mut Vec<u8>);

impl<'a> fmt::Write for FastWrite<'a> {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        extend(self.0, s.as_bytes());
        Ok(())
    }
}

// TODO: why does extend_from_slice not optimize?
fn extend(dst: &mut Vec<u8>, data: &[u8]) {
    use std::ptr;
    dst.reserve(data.len());
    let prev = dst.len();
    unsafe {
        ptr::copy_nonoverlapping(data.as_ptr(),
                                 dst.as_mut_ptr().offset(prev as isize),
                                 data.len());
        dst.set_len(prev + data.len());
    }
}

fn read(socket: &mut TcpStream,
        input: &mut Vec<u8>,
        events: &mut EventSet) -> io::Result<bool> {
    match socket.read(unsafe { slice_to_end(input) }) {
        Ok(0) => return Ok(true),
        Ok(n) => {
            let len = input.len();
            unsafe { input.set_len(len + n); }
            return Ok(false)
        }
        Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
            *events = *events & !EventSet::readable();
            return Ok(false)
        }
        Err(e) => return Err(e),
    }

    unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
        use std::slice;
        if v.capacity() == 0 {
            v.reserve(16);
        }
        if v.capacity() == v.len() {
            v.reserve(1);
        }
        slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize),
                                  v.capacity() - v.len())
    }
}

fn write(socket: &mut TcpStream,
         output: &mut Output,
         events: &mut EventSet) -> io::Result<bool> {
    assert!(output.buf.len() > 0);
    loop {
        match socket.write(&output.buf) {
            Ok(0) => {
                return Err(io::Error::new(io::ErrorKind::Other, "early eof2"))
            }
            Ok(n) => {
                output.buf.drain(..n);
                if output.buf.len() == 0 {
                    return Ok(true)
                }
            }
            Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
                *events = *events & !EventSet::writable();
                return Ok(false)
            }
            Err(e) => return Err(e),
        }
    }
}

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

    let threads = (0..num_cpus::get()).map(|_| {
        thread::spawn(|| {
            let poll = mio::Poll::new().unwrap();
            let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
            let addr = addr.parse::<SocketAddr>().unwrap();
            let socket = net2::TcpBuilder::new_v4().unwrap();
            socket.reuse_address(true).unwrap();
            socket.reuse_port(true).unwrap();
            socket.bind(&addr).unwrap();
            let listener = socket.listen(2048).unwrap();
            let listener = TcpListener::from_listener(listener, &addr).unwrap();
            poll.register(&listener,
                          LISTENER,
                          EventSet::readable(),
                          PollOpt::level()).unwrap();

            let mut events = Events::new();
            let mut server = Server::new(&listener);
            loop {
                poll.poll(&mut events, None).unwrap();

                for i in 0..events.len() {
                    let event = events.get(i).unwrap();
                    server.ready(&poll, event.token(), event.kind());
                }
            }
        })
    }).collect::<Vec<_>>();

    for thread in threads {
        thread.join().unwrap();
    }
}
<|endoftext|>


<commit_before>use player::Next;
use db::enums;

/// The standard arena is based on the default 1v1 fight.

impl<'a> super::Arena<'a> {
    /// Simulating a fight. This function is called on a arena and uses the next_move variables of
    /// the players to know what to do in this round.
    /// Important: All next_move variables must contain a Some() entry. If the function is called
    /// and atleast one variable is holding a None, this function will panic!
    pub fn fight(&mut self) {
        // This flag is used to show that the round is "over" earlier as aspected.
        // This can be happen if pursuit was used or both pokemons are swapped.
        let mut end_of_fight = false;
        ////////////////////////////////////////////////////////////////////////////////////////////
        // Setting the switched flag in the Player structs to false and reset if a swap will be done
        ////////////////////////////////////////////////////////////////////////////////////////////
        self.get_player_one().set_switched(false);
        self.get_player_two().set_switched(false);

        ////////////////////////////////////////////////////////////////////////////////////////////
        // Handle the pursuit(ID: 228) attack
        ////////////////////////////////////////////////////////////////////////////////////////////
        match self.get_player_one()
            .get_next_move()
            .expect("Unexpected error! This field of player one shouldn`t be None at this point.") {
            Next::Move(technique, _) => {
                if technique.get_id() == 228 {
                    match self.get_player_one()
                        .get_next_move()
                        .expect("Unexpected error! This field of player one shouldn`t be None \
                                 at this point.") {
                        Next::Switch(_) => {
                            // Resolving pursuit, updating last action and last move
                            // and setting the next move to None
                            technique.resolve(self, 2);
                            // let slot =
                            //     self.get_player_one().get_attack_slot(technique.clone())
                            //         .unwrap();
                            // self.get_player_one().set_last_move(Some((technique, slot)));
                            // let old_move = self.get_player_one().get_next_move().unwrap()
                            //         .clone();
                            // self.get_player_one().set_last_action(old_move);
                            self.get_player_one().set_next_move(None);

                        }
                        _ => {}
                    }
                }
            }
            Next::Switch(_) => {
                match self.get_player_one()
                    .get_next_move()
                    .expect("Unexpected error! This field of player one shouldn`t be None at \
                             this point.") {
                    Next::Move(technique, _) => {
                        if technique.get_id() == 228 {
                            // Resolving pursuit, updating last action and last move
                            // and setting the next move to None
                            technique.resolve(self, 1);
                            // let slot =
                            //     self.get_player_two().get_attack_slot(technique.clone())
                            //         .unwrap();
                            // self.get_player_two().set_last_move(Some((technique, slot)));
                            // let old_move = self.get_player_two().get_next_move().unwrap()
                            //         .clone();
                            // self.get_player_two().set_last_action(old_move);
                            self.get_player_two().set_next_move(None);
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }
        ////////////////////////////////////////////////////////////////////////////////////////////
        // Switch Pokemon of Player One if he wants to
        ////////////////////////////////////////////////////////////////////////////////////////////
        if let Some(x) = self.get_player_one().get_next_move() {
            match x {
                Next::Switch(pkmn) => {
                    // Switch of the current pokemon + setting flag
                    self.get_player_one().set_current(pkmn.get_int());
                    self.get_player_one().set_switched(true);
                    // Updating last action and setting next move to None. Last Move isnt updated
                    // because the last action wasnt a move
                    let old_move = self.get_player_one().get_next_move().unwrap().clone();
                    self.get_player_one().set_last_action(old_move);
                    self.get_player_one().set_next_move(None);
                }
                _ => {}
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////
        // Switch Pokemon of Player Two if he wants to
        ////////////////////////////////////////////////////////////////////////////////////////////
        if let Some(x) = self.get_player_two().get_next_move() {
            match x {
                Next::Switch(pkmn) => {
                    // Switch of the current pokemon + setting flag
                    self.get_player_two().set_current(pkmn.get_int());
                    self.get_player_two().set_switched(true);
                    // Updating last action and setting next move to None. Last Move isnt updated
                    // because the last action wasnt a move
                    let old_move = self.get_player_two().get_next_move().unwrap().clone();
                    self.get_player_two().set_last_action(old_move);
                    self.get_player_two().set_next_move(None);
                }
                _ => {}
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////
        // If player one doesnt need to make a move anymore, only resolve attack of player two
        ////////////////////////////////////////////////////////////////////////////////////////////
        if self.get_player_one().get_next_move().is_none() &&
           self.get_player_two().get_next_move().is_some() {
            match self.get_player_two().get_next_move().unwrap() {
                Next::Move(x, _) => x.resolve(self, 2),
                _ => {}
            }
            end_of_fight = true;
            ////////////////////////////////////////////////////////////////////////////////////////
            // If player two doesnt need to make a move anymore, only resolve attack of player one
            ////////////////////////////////////////////////////////////////////////////////////////
        } else if self.get_player_two().get_next_move().is_none() &&
                  self.get_player_one().get_next_move().is_some() {
            match self.get_player_one().get_next_move().unwrap() {
                Next::Move(x, _) => x.resolve(self, 1),
                _ => {}
            }
            end_of_fight = true;
            ////////////////////////////////////////////////////////////////////////////////////////
            // If both player dont have a move go out of fight
            ////////////////////////////////////////////////////////////////////////////////////////
        } else if self.get_player_two().get_next_move().is_none() &&
                  self.get_player_one().get_next_move().is_some() {
            end_of_fight = true;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        // If both player want to perform an attack Priority and Speed of Pokemon will be used to
        // decide which pokemon strikes first
        ////////////////////////////////////////////////////////////////////////////////////////////
        // Variables for faster comparison. x_prio is the priority of the pokemon of player x and
        // x_speed is the attackspeed of the pokemon of player x
        if !end_of_fight {
            let one_prio;
            let one_attack;
            match self.get_player_one().get_next_move().unwrap() {
                Next::Move(attack, _) => {
                    one_prio = attack.get_priority();
                    one_attack = attack.clone();
                }
                _ => unreachable!(),
            };
            let two_prio;
            let two_attack;
            match self.get_player_two().get_next_move().unwrap() {
                Next::Move(attack, _) => {
                    two_prio = attack.get_priority();
                    two_attack = attack.clone();
                }
                _ => unreachable!(),
            };
            let mut current = self.get_player_one().get_current();
            let one_speed = self.get_player_one().get_pokemon_list()[current]
                .get_current()
                .get_stat(&enums::Stats::Speed);
            current = self.get_player_two().get_current();
            let two_speed = self.get_player_two().get_pokemon_list()[current]
                .get_current()
                .get_stat(&enums::Stats::Speed);
            ////////////////////////////////////////////////////////////////////////////////////////
            // The attack with the higher Priority starts
            ////////////////////////////////////////////////////////////////////////////////////////
            if one_prio > two_prio {
                one_attack.resolve(self, 1);
                two_attack.resolve(self, 2);
            } else if one_prio < two_prio {
                two_attack.resolve(self, 2);
                one_attack.resolve(self, 1);
            } else {
                ////////////////////////////////////////////////////////////////////////////////////
                // If the attack priority is the same the pokemon with the higher attackspeed starts
                // If the attack speed is the same, the pokemon of player one will strike first
                ////////////////////////////////////////////////////////////////////////////////////
                if one_speed >= two_speed {
                    one_attack.resolve(self, 1);
                    two_attack.resolve(self, 2);
                } else {
                    two_attack.resolve(self, 2);
                    one_attack.resolve(self, 1);
                }
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////
        // End of Turn moves like validate the weather and effects, handle poison etc.
        ////////////////////////////////////////////////////////////////////////////////////////////
        self.validate_effects_and_weather();
        // TODO: All kind of effect like sleep, paralysis, poison... arent handled yet.
    }
}
<commit_msg>resolve enum conflicts<commit_after>use player::Next;
use db::enums;

/// The standard arena is based on the default 1v1 fight.

impl<'a> super::Arena<'a> {
    /// Simulating a fight. This function is called on a arena and uses the next_move variables of
    /// the players to know what to do in this round.
    /// Important: All next_move variables must contain a Some() entry. If the function is called
    /// and atleast one variable is holding a None, this function will panic!
    pub fn fight(&mut self) {
        // This flag is used to show that the round is "over" earlier as aspected.
        // This can be happen if pursuit was used or both pokemons are swapped.
        let mut end_of_fight = false;
        ////////////////////////////////////////////////////////////////////////////////////////////
        // Setting the switched flag in the Player structs to false and reset if a swap will be done
        ////////////////////////////////////////////////////////////////////////////////////////////
        self.get_player_one().set_switched(false);
        self.get_player_two().set_switched(false);

        ////////////////////////////////////////////////////////////////////////////////////////////
        // Handle the pursuit(ID: 228) attack
        ////////////////////////////////////////////////////////////////////////////////////////////
        match self.get_player_one()
            .get_next_move()
            .expect("Unexpected error! This field of player one shouldn`t be None at this point.") {
            Next::Move(technique) => {
                if technique.get_id() == 228 {
                    match self.get_player_one()
                        .get_next_move()
                        .expect("Unexpected error! This field of player one shouldn`t be None \
                                 at this point.") {
                        Next::Switch(_) => {
                            // Resolving pursuit, updating last action and last move
                            // and setting the next move to None
                            technique.resolve(self, 2);
                            // let slot =
                            //     self.get_player_one().get_attack_slot(technique.clone())
                            //         .unwrap();
                            // self.get_player_one().set_last_move(Some((technique, slot)));
                            // let old_move = self.get_player_one().get_next_move().unwrap()
                            //         .clone();
                            // self.get_player_one().set_last_action(old_move);
                            self.get_player_one().set_next_move(None);

                        }
                        _ => {}
                    }
                }
            }
            Next::Switch(_) => {
                match self.get_player_one()
                    .get_next_move()
                    .expect("Unexpected error! This field of player one shouldn`t be None at \
                             this point.") {
                    Next::Move(technique) => {
                        if technique.get_id() == 228 {
                            // Resolving pursuit, updating last action and last move
                            // and setting the next move to None
                            technique.resolve(self, 1);
                            // let slot =
                            //     self.get_player_two().get_attack_slot(technique.clone())
                            //         .unwrap();
                            // self.get_player_two().set_last_move(Some((technique, slot)));
                            // let old_move = self.get_player_two().get_next_move().unwrap()
                            //         .clone();
                            // self.get_player_two().set_last_action(old_move);
                            self.get_player_two().set_next_move(None);
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }
        ////////////////////////////////////////////////////////////////////////////////////////////
        // Switch Pokemon of Player One if he wants to
        ////////////////////////////////////////////////////////////////////////////////////////////
        if let Some(x) = self.get_player_one().get_next_move() {
            match x {
                Next::Switch(pkmn) => {
                    // Switch of the current pokemon + setting flag
                    self.get_player_one().set_current(pkmn.get_int());
                    self.get_player_one().set_switched(true);
                    // Updating last action and setting next move to None. Last Move isnt updated
                    // because the last action wasnt a move
                    let old_move = self.get_player_one().get_next_move().unwrap().clone();
                    self.get_player_one().set_last_action(old_move);
                    self.get_player_one().set_next_move(None);
                }
                _ => {}
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////
        // Switch Pokemon of Player Two if he wants to
        ////////////////////////////////////////////////////////////////////////////////////////////
        if let Some(x) = self.get_player_two().get_next_move() {
            match x {
                Next::Switch(pkmn) => {
                    // Switch of the current pokemon + setting flag
                    self.get_player_two().set_current(pkmn.get_int());
                    self.get_player_two().set_switched(true);
                    // Updating last action and setting next move to None. Last Move isnt updated
                    // because the last action wasnt a move
                    let old_move = self.get_player_two().get_next_move().unwrap().clone();
                    self.get_player_two().set_last_action(old_move);
                    self.get_player_two().set_next_move(None);
                }
                _ => {}
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////
        // If player one doesnt need to make a move anymore, only resolve attack of player two
        ////////////////////////////////////////////////////////////////////////////////////////////
        if self.get_player_one().get_next_move().is_none() &&
           self.get_player_two().get_next_move().is_some() {
            match self.get_player_two().get_next_move().unwrap() {
                Next::Move(x, _) => x.resolve(self, 2),
                _ => {}
            }
            end_of_fight = true;
            ////////////////////////////////////////////////////////////////////////////////////////
            // If player two doesnt need to make a move anymore, only resolve attack of player one
            ////////////////////////////////////////////////////////////////////////////////////////
        } else if self.get_player_two().get_next_move().is_none() &&
                  self.get_player_one().get_next_move().is_some() {
            match self.get_player_one().get_next_move().unwrap() {
                Next::Move(x, _) => x.resolve(self, 1),
                _ => {}
            }
            end_of_fight = true;
            ////////////////////////////////////////////////////////////////////////////////////////
            // If both player dont have a move go out of fight
            ////////////////////////////////////////////////////////////////////////////////////////
        } else if self.get_player_two().get_next_move().is_none() &&
                  self.get_player_one().get_next_move().is_some() {
            end_of_fight = true;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        // If both player want to perform an attack Priority and Speed of Pokemon will be used to
        // decide which pokemon strikes first
        ////////////////////////////////////////////////////////////////////////////////////////////
        // Variables for faster comparison. x_prio is the priority of the pokemon of player x and
        // x_speed is the attackspeed of the pokemon of player x
        if !end_of_fight {
            let one_prio;
            let one_attack;
            match self.get_player_one().get_next_move().unwrap() {
                Next::Move(attack, _) => {
                    one_prio = attack.get_priority();
                    one_attack = attack.clone();
                }
                _ => unreachable!(),
            };
            let two_prio;
            let two_attack;
            match self.get_player_two().get_next_move().unwrap() {
                Next::Move(attack, _) => {
                    two_prio = attack.get_priority();
                    two_attack = attack.clone();
                }
                _ => unreachable!(),
            };
            let mut current = self.get_player_one().get_current();
            let one_speed = self.get_player_one().get_pokemon_list()[current]
                .get_current()
                .get_stat(&enums::Stats::Speed);
            current = self.get_player_two().get_current();
            let two_speed = self.get_player_two().get_pokemon_list()[current]
                .get_current()
                .get_stat(&enums::Stats::Speed);
            ////////////////////////////////////////////////////////////////////////////////////////
            // The attack with the higher Priority starts
            ////////////////////////////////////////////////////////////////////////////////////////
            if one_prio > two_prio {
                one_attack.resolve(self, 1);
                two_attack.resolve(self, 2);
            } else if one_prio < two_prio {
                two_attack.resolve(self, 2);
                one_attack.resolve(self, 1);
            } else {
                ////////////////////////////////////////////////////////////////////////////////////
                // If the attack priority is the same the pokemon with the higher attackspeed starts
                // If the attack speed is the same, the pokemon of player one will strike first
                ////////////////////////////////////////////////////////////////////////////////////
                if one_speed >= two_speed {
                    one_attack.resolve(self, 1);
                    two_attack.resolve(self, 2);
                } else {
                    two_attack.resolve(self, 2);
                    one_attack.resolve(self, 1);
                }
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////
        // End of Turn moves like validate the weather and effects, handle poison etc.
        ////////////////////////////////////////////////////////////////////////////////////////////
        self.validate_effects_and_weather();
        // TODO: All kind of effect like sleep, paralysis, poison... arent handled yet.
    }
}
<|endoftext|>


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

#[cfg(test)]
mod test {
    use crate::{ast::*, compilation_top_level::*, souffle::souffle_interface::*};
    use std::fs;
    use crate::utils::*;

    // This dependency is used for generating keypairs.
    use crate::signing::tink_interface::*;

    #[test]
  fn test_signature_exporting() {
        utils::create_bazeltest_output_paths(vec!["test_keys", "test_outputs"]);
        store_new_keypair_cleartext(
            &utils::get_resolved_path("test_keys/principal1_pub.json"),
            &utils::get_resolved_path("test_keys/principal1_priv.json"),
        );

        compile("exporting", "test_inputs", "test_outputs", "");

        let deser_claim = deserialize_from_file(
            &utils::get_resolved_path("test_outputs/prin1_statement1.obj")).unwrap();

        assert!(verify_claim(
            &utils::get_resolved_path("test_keys/principal1_pub.json"),
            &utils::get_resolved_path("test_outputs/prin1_statement1.sig"),
            &deser_claim
        )
        .is_ok());
    }
}
<commit_msg>Fix a directory setup bug in test_export_signatures rust test. (#441)<commit_after>/*
 * Copyright 2021 The Raksha Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#[cfg(test)]
mod test {
    use crate::{ast::*, compilation_top_level::*, souffle::souffle_interface::*};
    use std::fs;
    use crate::utils::*;

    // This dependency is used for generating keypairs.
    use crate::signing::tink_interface::*;

    #[test]
  fn test_signature_exporting() {
        utils::setup_directories_for_bazeltest(
            vec!["test_inputs"], vec!["test_keys", "test_outputs"]);
        store_new_keypair_cleartext(
            &utils::get_resolved_path("test_keys/principal1_pub.json"),
            &utils::get_resolved_path("test_keys/principal1_priv.json"),
        );

        compile("exporting", "test_inputs", "test_outputs", "");

        let deser_claim = deserialize_from_file(
            &utils::get_resolved_path("test_outputs/prin1_statement1.obj")).unwrap();

        assert!(verify_claim(
            &utils::get_resolved_path("test_keys/principal1_pub.json"),
            &utils::get_resolved_path("test_outputs/prin1_statement1.sig"),
            &deser_claim
        )
        .is_ok());
    }
}
<|endoftext|>


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

//! service records for identify port mapping for specific services on a host

use serialize::binary::*;
use error::*;
use rr::domain::Name;

/// [RFC 2782, DNS SRV RR, February 2000](https://tools.ietf.org/html/rfc2782)
///
/// Introductory example
///
///  If a SRV-cognizant LDAP client wants to discover a LDAP server that
///  supports TCP protocol and provides LDAP service for the domain
///  example.com., it does a lookup of
///
/// _ldap._tcp.example.com
///
///  as described in [ARM].  The example zone file near the end of this
///  memo contains answering RRs for an SRV query.
///
///  Note: LDAP is chosen as an example for illustrative purposes only,
///  and the LDAP examples used in this document should not be considered
///  a definitive statement on the recommended way for LDAP to use SRV
///  records. As described in the earlier applicability section, consult
///  the appropriate LDAP documents for the recommended procedures.
///
/// The format of the SRV RR
///
///  Here is the format of the SRV RR, whose DNS type code is 33:
///
/// _Service._Proto.Name TTL Class SRV Priority Weight Port Target
///
/// (There is an example near the end of this document.)
///
///  Service
/// The symbolic name of the desired service, as defined in Assigned
/// Numbers [STD 2] or locally.  An underscore (_) is prepended to
/// the service identifier to avoid collisions with DNS labels that
/// occur in nature.
///
/// Some widely used services, notably POP, don't have a single
/// universal name.  If Assigned Numbers names the service
/// indicated, that name is the only name which is legal for SRV
/// lookups.  The Service is case insensitive.
///
///  Proto
/// The symbolic name of the desired protocol, with an underscore
/// (_) prepended to prevent collisions with DNS labels that occur
/// in nature.  _TCP and _UDP are at present the most useful values
/// for this field, though any name defined by Assigned Numbers or
/// locally may be used (as for Service).  The Proto is case
/// insensitive.
///
///  Name
/// The domain this RR refers to.  The SRV RR is unique in that the
/// name one searches for is not this name; the example near the end
/// shows this clearly.
///
///  TTL
/// Standard DNS meaning [RFC 1035].
///
///  Class
/// Standard DNS meaning [RFC 1035].   SRV records occur in the IN
/// Class.
///
/// ```
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct SRV {
    priority: u16,
    weight: u16,
    port: u16,
    target: Name,
}

impl SRV {
    /// Creates a new SRV record data.
    ///
    /// # Arguments
    ///
    /// * `priority` - lower values have a higher priority and clients will attempt to use these
    ///                first.
    /// * `weight` - for servers with the same priority, higher weights will be chosen more often.
    /// * `port` - the socket port number on which the service is listening.
    /// * `target` - like CNAME, this is the target domain name to which the service is associated.
    ///
    /// # Return value
    ///
    /// The newly constructed SRV record data.
    pub fn new(priority: u16, weight: u16, port: u16, target: Name) -> SRV {
        SRV {
            priority: priority,
            weight: weight,
            port: port,
            target: target,
        }
    }

    /// ```text
    ///  Priority
    /// The priority of this target host.  A client MUST attempt to
    /// contact the target host with the lowest-numbered priority it can
    /// reach; target hosts with the same priority SHOULD be tried in an
    /// order defined by the weight field.  The range is 0-65535.  This
    /// is a 16 bit unsigned integer in network byte order.
    /// ```
    pub fn priority(&self) -> u16 {
        self.priority
    }

    /// ```text
    ///  Weight
    /// A server selection mechanism.  The weight field specifies a
    /// relative weight for entries with the same priority. Larger
    /// weights SHOULD be given a proportionately higher probability of
    /// being selected. The range of this number is 0-65535.  This is a
    /// 16 bit unsigned integer in network byte order.  Domain
    /// administrators SHOULD use Weight 0 when there isn't any server
    /// selection to do, to make the RR easier to read for humans (less
    /// noisy).  In the presence of records containing weights greater
    /// than 0, records with weight 0 should have a very small chance of
    /// being selected.
    ///
    /// In the absence of a protocol whose specification calls for the
    /// use of other weighting information, a client arranges the SRV
    /// RRs of the same Priority in the order in which target hosts,
    /// specified by the SRV RRs, will be contacted. The following
    /// algorithm SHOULD be used to order the SRV RRs of the same
    /// priority:
    ///
    /// To select a target to be contacted next, arrange all SRV RRs
    /// (that have not been ordered yet) in any order, except that all
    /// those with weight 0 are placed at the beginning of the list.
    ///
    /// Compute the sum of the weights of those RRs, and with each RR
    /// associate the running sum in the selected order. Then choose a
    /// uniform random number between 0 and the sum computed
    /// (inclusive), and select the RR whose running sum value is the
    /// first in the selected order which is greater than or equal to
    /// the random number selected. The target host specified in the
    /// selected SRV RR is the next one to be contacted by the client.
    /// Remove this SRV RR from the set of the unordered SRV RRs and
    /// apply the described algorithm to the unordered SRV RRs to select
    /// the next target host.  Continue the ordering process until there
    /// are no unordered SRV RRs.  This process is repeated for each
    /// Priority.
    /// ```
    pub fn weight(&self) -> u16 {
        self.weight
    }

    /// ```text
    ///  Port
    /// The port on this target host of this service.  The range is 0-
    /// 65535.  This is a 16 bit unsigned integer in network byte order.
    /// This is often as specified in Assigned Numbers but need not be.
    ///
    /// ```
    pub fn port(&self) -> u16 {
        self.port
    }

    /// ```text
    ///  Target
    /// The domain name of the target host.  There MUST be one or more
    /// address records for this name, the name MUST NOT be an alias (in
    /// the sense of RFC 1034 or RFC 2181).  Implementors are urged, but
    /// not required, to return the address record(s) in the Additional
    /// Data section.  Unless and until permitted by future standards
    /// action, name compression is not to be used for this field.
    ///
    /// A Target of "." means that the service is decidedly not
    /// available at this domain.
    /// ```
    pub fn target(&self) -> &Name {
        &self.target
    }
}

/// Read the RData from the given Decoder
pub fn read(decoder: &mut BinDecoder) -> ProtoResult<SRV> {
    // SRV { priority: u16, weight: u16, port: u16, target: Name, },
    Ok(SRV::new(
        decoder.read_u16()?,
        decoder.read_u16()?,
        decoder.read_u16()?,
        Name::read(decoder)?,
    ))
}

/// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
///
/// This is accurate for all currently known name records.
///
/// ```text
/// 6.2.  Canonical RR Form
///
///    For the purposes of DNS security, the canonical form of an RR is the
///    wire format of the RR where:
///
///    ...
///
///    3.  if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
///        HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
///        SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase
///        US-ASCII letters in the DNS names contained within the RDATA are replaced
///        by the corresponding lowercase US-ASCII letters;
/// ```
pub fn emit(encoder: &mut BinEncoder, srv: &SRV) -> ProtoResult<()> {
    let is_canonical_names = encoder.is_canonical_names();

    encoder.emit_u16(srv.priority())?;
    encoder.emit_u16(srv.weight())?;
    encoder.emit_u16(srv.port())?;
    srv.target()
        .emit_with_lowercase(encoder, is_canonical_names)?;
    Ok(())
}

#[test]
fn test() {
    use std::str::FromStr;

    let rdata = SRV::new(
        1,
        2,
        3,
        Name::from_str("_dns._tcp.example.com").unwrap(),
    );

    let mut bytes = Vec::new();
    let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
    assert!(emit(&mut encoder, &rdata).is_ok());
    let bytes = encoder.into_bytes();

    println!("bytes: {:?}", bytes);

    let mut decoder: BinDecoder = BinDecoder::new(bytes);
    let read_rdata = read(&mut decoder);
    assert!(
        read_rdata.is_ok(),
        format!("error decoding: {:?}", read_rdata.unwrap_err())
    );
    assert_eq!(rdata, read_rdata.unwrap());
}
<commit_msg>fix srv.rs doc string<commit_after>/*
 * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//! service records for identify port mapping for specific services on a host

use serialize::binary::*;
use error::*;
use rr::domain::Name;

/// [RFC 2782, DNS SRV RR, February 2000](https://tools.ietf.org/html/rfc2782)
///
/// ```text
/// Introductory example
///
///  If a SRV-cognizant LDAP client wants to discover a LDAP server that
///  supports TCP protocol and provides LDAP service for the domain
///  example.com., it does a lookup of
///
/// _ldap._tcp.example.com
///
///  as described in [ARM].  The example zone file near the end of this
///  memo contains answering RRs for an SRV query.
///
///  Note: LDAP is chosen as an example for illustrative purposes only,
///  and the LDAP examples used in this document should not be considered
///  a definitive statement on the recommended way for LDAP to use SRV
///  records. As described in the earlier applicability section, consult
///  the appropriate LDAP documents for the recommended procedures.
///
/// The format of the SRV RR
///
///  Here is the format of the SRV RR, whose DNS type code is 33:
///
/// _Service._Proto.Name TTL Class SRV Priority Weight Port Target
///
/// (There is an example near the end of this document.)
///
///  Service
/// The symbolic name of the desired service, as defined in Assigned
/// Numbers [STD 2] or locally.  An underscore (_) is prepended to
/// the service identifier to avoid collisions with DNS labels that
/// occur in nature.
///
/// Some widely used services, notably POP, don't have a single
/// universal name.  If Assigned Numbers names the service
/// indicated, that name is the only name which is legal for SRV
/// lookups.  The Service is case insensitive.
///
///  Proto
/// The symbolic name of the desired protocol, with an underscore
/// (_) prepended to prevent collisions with DNS labels that occur
/// in nature.  _TCP and _UDP are at present the most useful values
/// for this field, though any name defined by Assigned Numbers or
/// locally may be used (as for Service).  The Proto is case
/// insensitive.
///
///  Name
/// The domain this RR refers to.  The SRV RR is unique in that the
/// name one searches for is not this name; the example near the end
/// shows this clearly.
///
///  TTL
/// Standard DNS meaning [RFC 1035].
///
///  Class
/// Standard DNS meaning [RFC 1035].   SRV records occur in the IN
/// Class.
///
/// ```
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct SRV {
    priority: u16,
    weight: u16,
    port: u16,
    target: Name,
}

impl SRV {
    /// Creates a new SRV record data.
    ///
    /// # Arguments
    ///
    /// * `priority` - lower values have a higher priority and clients will attempt to use these
    ///                first.
    /// * `weight` - for servers with the same priority, higher weights will be chosen more often.
    /// * `port` - the socket port number on which the service is listening.
    /// * `target` - like CNAME, this is the target domain name to which the service is associated.
    ///
    /// # Return value
    ///
    /// The newly constructed SRV record data.
    pub fn new(priority: u16, weight: u16, port: u16, target: Name) -> SRV {
        SRV {
            priority: priority,
            weight: weight,
            port: port,
            target: target,
        }
    }

    /// ```text
    ///  Priority
    /// The priority of this target host.  A client MUST attempt to
    /// contact the target host with the lowest-numbered priority it can
    /// reach; target hosts with the same priority SHOULD be tried in an
    /// order defined by the weight field.  The range is 0-65535.  This
    /// is a 16 bit unsigned integer in network byte order.
    /// ```
    pub fn priority(&self) -> u16 {
        self.priority
    }

    /// ```text
    ///  Weight
    /// A server selection mechanism.  The weight field specifies a
    /// relative weight for entries with the same priority. Larger
    /// weights SHOULD be given a proportionately higher probability of
    /// being selected. The range of this number is 0-65535.  This is a
    /// 16 bit unsigned integer in network byte order.  Domain
    /// administrators SHOULD use Weight 0 when there isn't any server
    /// selection to do, to make the RR easier to read for humans (less
    /// noisy).  In the presence of records containing weights greater
    /// than 0, records with weight 0 should have a very small chance of
    /// being selected.
    ///
    /// In the absence of a protocol whose specification calls for the
    /// use of other weighting information, a client arranges the SRV
    /// RRs of the same Priority in the order in which target hosts,
    /// specified by the SRV RRs, will be contacted. The following
    /// algorithm SHOULD be used to order the SRV RRs of the same
    /// priority:
    ///
    /// To select a target to be contacted next, arrange all SRV RRs
    /// (that have not been ordered yet) in any order, except that all
    /// those with weight 0 are placed at the beginning of the list.
    ///
    /// Compute the sum of the weights of those RRs, and with each RR
    /// associate the running sum in the selected order. Then choose a
    /// uniform random number between 0 and the sum computed
    /// (inclusive), and select the RR whose running sum value is the
    /// first in the selected order which is greater than or equal to
    /// the random number selected. The target host specified in the
    /// selected SRV RR is the next one to be contacted by the client.
    /// Remove this SRV RR from the set of the unordered SRV RRs and
    /// apply the described algorithm to the unordered SRV RRs to select
    /// the next target host.  Continue the ordering process until there
    /// are no unordered SRV RRs.  This process is repeated for each
    /// Priority.
    /// ```
    pub fn weight(&self) -> u16 {
        self.weight
    }

    /// ```text
    ///  Port
    /// The port on this target host of this service.  The range is 0-
    /// 65535.  This is a 16 bit unsigned integer in network byte order.
    /// This is often as specified in Assigned Numbers but need not be.
    ///
    /// ```
    pub fn port(&self) -> u16 {
        self.port
    }

    /// ```text
    ///  Target
    /// The domain name of the target host.  There MUST be one or more
    /// address records for this name, the name MUST NOT be an alias (in
    /// the sense of RFC 1034 or RFC 2181).  Implementors are urged, but
    /// not required, to return the address record(s) in the Additional
    /// Data section.  Unless and until permitted by future standards
    /// action, name compression is not to be used for this field.
    ///
    /// A Target of "." means that the service is decidedly not
    /// available at this domain.
    /// ```
    pub fn target(&self) -> &Name {
        &self.target
    }
}

/// Read the RData from the given Decoder
pub fn read(decoder: &mut BinDecoder) -> ProtoResult<SRV> {
    // SRV { priority: u16, weight: u16, port: u16, target: Name, },
    Ok(SRV::new(
        decoder.read_u16()?,
        decoder.read_u16()?,
        decoder.read_u16()?,
        Name::read(decoder)?,
    ))
}

/// [RFC 4034](https://tools.ietf.org/html/rfc4034#section-6), DNSSEC Resource Records, March 2005
///
/// This is accurate for all currently known name records.
///
/// ```text
/// 6.2.  Canonical RR Form
///
///    For the purposes of DNS security, the canonical form of an RR is the
///    wire format of the RR where:
///
///    ...
///
///    3.  if the type of the RR is NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR,
///        HINFO, MINFO, MX, HINFO, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX,
///        SRV, DNAME, A6, RRSIG, or (rfc6840 removes NSEC), all uppercase
///        US-ASCII letters in the DNS names contained within the RDATA are replaced
///        by the corresponding lowercase US-ASCII letters;
/// ```
pub fn emit(encoder: &mut BinEncoder, srv: &SRV) -> ProtoResult<()> {
    let is_canonical_names = encoder.is_canonical_names();

    encoder.emit_u16(srv.priority())?;
    encoder.emit_u16(srv.weight())?;
    encoder.emit_u16(srv.port())?;
    srv.target()
        .emit_with_lowercase(encoder, is_canonical_names)?;
    Ok(())
}

#[test]
fn test() {
    use std::str::FromStr;

    let rdata = SRV::new(
        1,
        2,
        3,
        Name::from_str("_dns._tcp.example.com").unwrap(),
    );

    let mut bytes = Vec::new();
    let mut encoder: BinEncoder = BinEncoder::new(&mut bytes);
    assert!(emit(&mut encoder, &rdata).is_ok());
    let bytes = encoder.into_bytes();

    println!("bytes: {:?}", bytes);

    let mut decoder: BinDecoder = BinDecoder::new(bytes);
    let read_rdata = read(&mut decoder);
    assert!(
        read_rdata.is_ok(),
        format!("error decoding: {:?}", read_rdata.unwrap_err())
    );
    assert_eq!(rdata, read_rdata.unwrap());
}
<|endoftext|>


<commit_before>//! Library to read and write protocol buffers data.

// TODO: add docs
//#![deny(missing_docs)]

#![cfg_attr(rustc_nightly, feature(specialization))]

#[cfg(feature = "bytes")]
extern crate bytes;
#[cfg(feature = "with-serde")]
extern crate serde;
#[macro_use]
#[cfg(feature = "with-serde")]

extern crate serde_derive;
pub use crate::clear::Clear;
pub use crate::core::parse_from_bytes;
#[cfg(feature = "bytes")]
pub use crate::core::parse_from_carllerche_bytes;
pub use crate::core::parse_from_reader;
pub use crate::core::Message;
pub use crate::enums::ProtobufEnum;
pub use crate::enums::ProtobufEnumOrUnknown;
pub use crate::oneof::Oneof;
pub use crate::repeated::RepeatedField;
pub use crate::singular::SingularField;
pub use crate::singular::SingularPtrField;
pub use crate::stream::CodedInputStream;
pub use crate::stream::CodedOutputStream;
pub use crate::unknown::UnknownFields;
pub use crate::unknown::UnknownFieldsIter;
pub use crate::unknown::UnknownValue;
pub use crate::unknown::UnknownValueRef;
pub use crate::unknown::UnknownValues;
pub use crate::unknown::UnknownValuesIter;
pub mod wire_format;
pub use cached_size::CachedSize;
#[cfg(feature = "bytes")]
pub use crate::chars::Chars;
pub use crate::error::ProtobufError;
pub use crate::error::ProtobufResult;

pub use crate::reflect::types;

// generated
pub mod descriptor;
// TODO: move plugin to mod codegen
pub mod plugin;
pub mod rustproto;

mod clear;
mod core;
mod enums;
pub mod error;
pub mod ext;
pub mod json;
mod lazy;
mod oneof;
pub mod prelude;
pub mod reflect;
mod repeated;
pub mod rt;
mod singular;
pub mod stream;
pub mod text_format;
pub mod well_known_types;

// used by test
#[cfg(test)]
#[path = "../../protobuf-test-common/src/hex.rs"]
mod hex;

mod cached_size;
mod chars;
mod paginate;
mod unknown;
mod varint;
mod zigzag;

mod misc;

mod buf_read_iter;

// so `use protobuf::*` could work in mod descriptor and well_known_types
mod protobuf {
    pub use crate::cached_size::CachedSize;
    pub use crate::clear::Clear;
    pub use crate::core::*;
    pub use crate::descriptor;
    pub use crate::enums::ProtobufEnum;
    pub use crate::enums::ProtobufEnumOrUnknown;
    pub use crate::error::*;
    pub use crate::ext;
    pub use crate::oneof::Oneof;
    pub use crate::reflect;
    pub use crate::reflect::types;
    pub use crate::repeated::RepeatedField;
    pub use crate::rt;
    pub use crate::singular::SingularField;
    pub use crate::singular::SingularPtrField;
    pub use crate::stream::*;
    pub use crate::text_format;
    pub use crate::unknown::UnknownFields;
    pub use crate::unknown::UnknownFieldsIter;
    pub use crate::unknown::UnknownValue;
    pub use crate::unknown::UnknownValueRef;
    pub use crate::unknown::UnknownValues;
    pub use crate::unknown::UnknownValuesIter;
    pub use crate::well_known_types;
    pub use crate::wire_format;
}
<commit_msg>protobuf::protobuf mod is no longer needed<commit_after>//! Library to read and write protocol buffers data.

// TODO: add docs
//#![deny(missing_docs)]

#![cfg_attr(rustc_nightly, feature(specialization))]

#[cfg(feature = "bytes")]
extern crate bytes;
#[cfg(feature = "with-serde")]
extern crate serde;
#[macro_use]
#[cfg(feature = "with-serde")]

extern crate serde_derive;
pub use crate::clear::Clear;
pub use crate::core::parse_from_bytes;
#[cfg(feature = "bytes")]
pub use crate::core::parse_from_carllerche_bytes;
pub use crate::core::parse_from_reader;
pub use crate::core::Message;
pub use crate::enums::ProtobufEnum;
pub use crate::enums::ProtobufEnumOrUnknown;
pub use crate::oneof::Oneof;
pub use crate::repeated::RepeatedField;
pub use crate::singular::SingularField;
pub use crate::singular::SingularPtrField;
pub use crate::stream::CodedInputStream;
pub use crate::stream::CodedOutputStream;
pub use crate::unknown::UnknownFields;
pub use crate::unknown::UnknownFieldsIter;
pub use crate::unknown::UnknownValue;
pub use crate::unknown::UnknownValueRef;
pub use crate::unknown::UnknownValues;
pub use crate::unknown::UnknownValuesIter;
pub mod wire_format;
pub use cached_size::CachedSize;
#[cfg(feature = "bytes")]
pub use crate::chars::Chars;
pub use crate::error::ProtobufError;
pub use crate::error::ProtobufResult;

pub use crate::reflect::types;

// generated
pub mod descriptor;
// TODO: move plugin to mod codegen
pub mod plugin;
pub mod rustproto;

mod clear;
mod core;
mod enums;
pub mod error;
pub mod ext;
pub mod json;
mod lazy;
mod oneof;
pub mod prelude;
pub mod reflect;
mod repeated;
pub mod rt;
mod singular;
pub mod stream;
pub mod text_format;
pub mod well_known_types;

// used by test
#[cfg(test)]
#[path = "../../protobuf-test-common/src/hex.rs"]
mod hex;

mod cached_size;
mod chars;
mod paginate;
mod unknown;
mod varint;
mod zigzag;

mod misc;

mod buf_read_iter;
<|endoftext|>


<commit_before>//! # Integration tests.
//!
//! These tests are run on our executable to make sure that all the
//! command-line options work correctly.

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};

static TEST_ID: AtomicUsize = ATOMIC_USIZE_INIT;

/// This code is inspired by the `WorkDir` pattern that BurntSushi uses to
/// test CLI tools like `ripgrep` and `xsv`.
struct WorkDir {
    bin: PathBuf,
    dir: PathBuf,
}

impl WorkDir {
    fn new(test_name: &str) -> WorkDir {
        let mut bin_dir = env::current_exe()
            .expect("Could not find executable")
            .parent()
            .expect("Could not find parent directory for executable")
            .to_path_buf();
        if bin_dir.ends_with("deps") {
            bin_dir.pop();
        }
        let id = TEST_ID.fetch_add(1, Ordering::SeqCst);
        let dir = bin_dir.join("vobsub2png-tests")
            .join(test_name)
            .join(format!("{}", id));
        if dir.exists() {
            fs::remove_dir_all(&dir)
                .expect("Could not remove test output directory");
        }
        fs::create_dir_all(&dir)
            .expect("Could not create test output directory");
        WorkDir {
            bin: bin_dir.join("vobsub2png"),
            dir: dir,
        }
    }

    fn cmd(&self) -> process::Command {
        let mut cmd = process::Command::new(&self.bin);
        cmd.current_dir(&self.dir);
        cmd
    }

    fn fixture<P: AsRef<Path>>(&self, path: P) -> PathBuf {
        let cwd = env::current_dir().expect("Could not get current dir");
        fs::canonicalize(cwd.join(path))
            .expect("Could not canonicalize path")
    }

    fn expect_path<P: AsRef<Path>>(&self, path: P) {
        let path = self.dir.join(path);
        assert!(path.exists(), format!("{} exists", path.display()));
    }
}

#[test]
fn generates_png_and_json_files() {
    let workdir = WorkDir::new("generates_png_and_json_files");
    let status = workdir.cmd()
        .arg("-o")
        .arg("out")
        .arg(workdir.fixture("../fixtures/example.idx"))
        .status()
        .expect("could not run command");
    assert!(status.success());
    workdir.expect_path("out/index.json");
    workdir.expect_path("out/0000.png");
    workdir.expect_path("out/0001.png");
}

#[test]
fn defaults_out_dir_based_on_input_name() {
    let workdir = WorkDir::new("defaults_out_dir_based_on_input_name");
    let status = workdir.cmd()
        .arg(workdir.fixture("../fixtures/example.idx"))
        .status()
        .expect("could not run command");
    assert!(status.success());
    workdir.expect_path("example_subtitles/index.json");
    workdir.expect_path("example_subtitles/0000.png");
    workdir.expect_path("example_subtitles/0001.png");
}
<commit_msg>Work around create_dir_all race condition<commit_after>//! # Integration tests.
//!
//! These tests are run on our executable to make sure that all the
//! command-line options work correctly.

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
use std::thread;
use std::time;

static TEST_ID: AtomicUsize = ATOMIC_USIZE_INIT;

/// This code is inspired by the `WorkDir` pattern that BurntSushi uses to
/// test CLI tools like `ripgrep` and `xsv`.
struct WorkDir {
    bin: PathBuf,
    dir: PathBuf,
}

impl WorkDir {
    fn new(test_name: &str) -> WorkDir {
        let mut bin_dir = env::current_exe()
            .expect("Could not find executable")
            .parent()
            .expect("Could not find parent directory for executable")
            .to_path_buf();
        if bin_dir.ends_with("deps") {
            bin_dir.pop();
        }
        let id = TEST_ID.fetch_add(1, Ordering::SeqCst);
        let dir = bin_dir.join("vobsub2png-tests")
            .join(test_name)
            .join(format!("{}", id));
        if dir.exists() {
            fs::remove_dir_all(&dir)
                .expect("Could not remove test output directory");
        }

        // Work around https://github.com/rust-lang/rust/issues/33707.
        let mut err = None;
        for _ in 0..10 {
            match fs::create_dir_all(&dir) {
                Ok(_) => {
                    err = None;
                    break;
                }
                Err(e) => {
                    err = Some(e);
                }
            }
            thread::sleep(time::Duration::from_millis(500));
        }
        if let Some(e) = err {
            panic!("Could not create test output directory: {}", e);
        }

        WorkDir {
            bin: bin_dir.join("vobsub2png"),
            dir: dir,
        }
    }

    fn cmd(&self) -> process::Command {
        let mut cmd = process::Command::new(&self.bin);
        cmd.current_dir(&self.dir);
        cmd
    }

    fn fixture<P: AsRef<Path>>(&self, path: P) -> PathBuf {
        let cwd = env::current_dir().expect("Could not get current dir");
        fs::canonicalize(cwd.join(path))
            .expect("Could not canonicalize path")
    }

    fn expect_path<P: AsRef<Path>>(&self, path: P) {
        let path = self.dir.join(path);
        assert!(path.exists(), format!("{} exists", path.display()));
    }
}

#[test]
fn generates_png_and_json_files() {
    let workdir = WorkDir::new("generates_png_and_json_files");
    let status = workdir.cmd()
        .arg("-o")
        .arg("out")
        .arg(workdir.fixture("../fixtures/example.idx"))
        .status()
        .expect("could not run command");
    assert!(status.success());
    workdir.expect_path("out/index.json");
    workdir.expect_path("out/0000.png");
    workdir.expect_path("out/0001.png");
}

#[test]
fn defaults_out_dir_based_on_input_name() {
    let workdir = WorkDir::new("defaults_out_dir_based_on_input_name");
    let status = workdir.cmd()
        .arg(workdir.fixture("../fixtures/example.idx"))
        .status()
        .expect("could not run command");
    assert!(status.success());
    workdir.expect_path("example_subtitles/index.json");
    workdir.expect_path("example_subtitles/0000.png");
    workdir.expect_path("example_subtitles/0001.png");
}
<|endoftext|>


<commit_before>extern crate diesel;
extern crate dotenv;

use diesel::migrations::run_pending_migrations;
use diesel::pg::PgConnection;
use diesel::prelude::*;
use dotenv::dotenv;
use std::env;

fn main() {
    println!("cargo:rerun-if-env-changed=TEST_DATABASE_URL");
    println!("cargo:rerun-if-changed=build.rs");
    if env::var("PROFILE") == Ok("debug".into()) {
        let _ = dotenv();
        if let Ok(database_url) = env::var("TEST_DATABASE_URL") {
            let connection = PgConnection::establish(&database_url).expect(
                "Could not connect to TEST_DATABASE_URL",
            );
            run_pending_migrations(&connection).expect("Error running migrations");
        }
    }
}
<commit_msg>Ensure the build script is run when migrations are added<commit_after>extern crate diesel;
extern crate dotenv;

use diesel::migrations::run_pending_migrations;
use diesel::pg::PgConnection;
use diesel::prelude::*;
use dotenv::dotenv;
use std::env;

fn main() {
    println!("cargo:rerun-if-env-changed=TEST_DATABASE_URL");
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=migrations/");
    if env::var("PROFILE") == Ok("debug".into()) {
        let _ = dotenv();
        if let Ok(database_url) = env::var("TEST_DATABASE_URL") {
            let connection = PgConnection::establish(&database_url).expect(
                "Could not connect to TEST_DATABASE_URL",
            );
            run_pending_migrations(&connection).expect("Error running migrations");
        }
    }
}
<|endoftext|>


<commit_before>extern crate gl_generator;

use gl_generator::{Registry, Api, Profile, Fallbacks};
use std::env;
use std::fs::File;
use std::path::Path;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();

    let dest = Path::new(&out_dir);

    let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();

    Registry::new(Api::Gl, (4, 5), Profile::Core, Fallbacks::All, ["GL_EXT_texture_filter_anisotropic"])
        .write_bindings(gl_generator::StructGenerator, &mut file)
        .unwrap();
}
<commit_msg>Added GL_ARB_draw_buffers_blend<commit_after>extern crate gl_generator;

use gl_generator::{Registry, Api, Profile, Fallbacks};
use std::env;
use std::fs::File;
use std::path::Path;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();

    let dest = Path::new(&out_dir);

    let mut file = File::create(&dest.join("gl_bindings.rs")).unwrap();

    Registry::new(Api::Gl, (4, 5), Profile::Core, Fallbacks::All, [
        "GL_EXT_texture_filter_anisotropic",
        "GL_ARB_draw_buffers_blend",
        ])
        .write_bindings(gl_generator::StructGenerator, &mut file)
        .unwrap();
}
<|endoftext|>