<commit_before>use std::{ fmt, cmp };
use std::ops::{ Bound, Range };
use std::path::Path;
use std::fs::Metadata;
use std::str::FromStr;
use std::cell::RefCell;
use smallvec::SmallVec;
use rand::{ Rng, thread_rng, distributions::Alphanumeric };
use log::*;
use hyper::{ StatusCode, Body };
use http::HeaderMap;
use headers::HeaderMapExt;
use mime::Mime;
use base64::{ URL_SAFE_NO_PAD, encode_config_buf };
use crate::common::{ err_html, fs_hash };

pub struct Entity<'a> {
    pub path: &'a Path,
    pub length: u64,
    metadata: &'a Metadata,
    etag: headers::ETag
}

pub struct Result(pub StatusCode, pub HeaderMap, pub Value);

pub enum Value {
    Error(Body),
    None,
    Range(Range<u64>),
    Multipart(String, Vec<Range<u64>>)
}

impl<'a> Entity<'a> {
    pub fn new(path: &'a Path, metadata: &'a Metadata) -> Self {
        thread_local!{
            static BUF: RefCell<String> = RefCell::new(String::with_capacity(1)); // TODO cap
        }

        let hash = fs_hash(metadata);

        let etag = BUF.with(|buf| {
            let mut buf = buf.borrow_mut();

            buf.clear();
            buf.push('"');
            encode_config_buf(&hash.to_le_bytes(), URL_SAFE_NO_PAD, &mut buf);
            buf.push('"');

            buf.parse().unwrap()
        });

        Entity {
            path, metadata, etag,
            length: metadata.len()
        }
    }

    pub fn headers(&self) -> HeaderMap {
        let mut map = HeaderMap::new();

        map.typed_insert(headers::AcceptRanges::bytes());
        let mime = mime_guess::from_path(self.path).first_or_octet_stream();
        map.typed_insert(headers::ContentType::from(mime));

        map.typed_insert(self.etag.clone());

        if let Ok(date) = self.metadata.modified() {
            map.typed_insert(headers::LastModified::from(date));
        }

        map
    }

    pub fn multipart_headers(&self, boundary: &str) -> HeaderMap {
        let mut map = HeaderMap::new();

        map.typed_insert(headers::AcceptRanges::bytes());

        // TODO https://github.com/hyperium/mime/issues/52
        let mime = Mime::from_str(format!("multipart/byteranges; boundary={}", boundary).as_str()).unwrap();
        map.typed_insert(headers::ContentType::from(mime));

        if let Ok(date) = self.metadata.modified() {
            map.typed_insert(headers::LastModified::from(date));
        }

        map
    }

    pub fn result(&self, map: &HeaderMap) -> Result {
        // TODO check it

        if let Some(ifmatch) = map.typed_get::<headers::IfMatch>() {
            if !ifmatch.precondition_passes(&self.etag) {
                return Result(
                    StatusCode::PRECONDITION_FAILED,
                    HeaderMap::new(),
                    Value::Error(Body::from("Precondition failed"))
                );
            }
        }

        if let Some(ifrange) = map.typed_get::<headers::IfRange>() {
            let mtime = self.metadata.modified()
                .map(headers::LastModified::from)
                .ok();
            if ifrange.is_modified(Some(&self.etag), mtime.as_ref()) {
                return Result(
                    StatusCode::PRECONDITION_FAILED,
                    HeaderMap::new(),
                    Value::Error(Body::from("Precondition failed"))
                );
            }
        }

        if let Some(ifnonematch) = map.typed_get::<headers::IfNoneMatch>() {
            if ifnonematch.precondition_passes(&self.etag) {
                return not_modified(format_args!("etag: {:?}", &self.etag));
            }
        }

        if let Some(time) = map.typed_get::<headers::IfModifiedSince>() {
            if let Ok(time2) = self.metadata.modified() {
                if !time.is_modified(time2) {
                    return not_modified(format_args!("{:?} vs {:?}", time, time2));
                }
            }
        }

        if let Some(ranges) = map.typed_get::<headers::Range>() {
            let length = self.length;

            let mut vec = ranges
                .iter()
                .filter_map(|(start, end)| {
                    let start = match start {
                        Bound::Excluded(x) | Bound::Included(x) => x,
                        Bound::Unbounded => 0
                    };

                    let end = match end {
                        Bound::Excluded(y) => y,
                        Bound::Included(y) => y + 1,
                        Bound::Unbounded => length,
                    };
                    let end = cmp::min(end, length);

                    if start <= end {
                        Some(start..end)
                    } else {
                        None
                    }
                })
                .collect::<SmallVec<[_; 1]>>();

            if vec.is_empty() {
                let mut map = self.headers();
                map.typed_insert(headers::ContentRange::unsatisfied_bytes(length));
                Result(
                    StatusCode::RANGE_NOT_SATISFIABLE,
                    map,
                    Value::Error(Body::from("Bad Range"))
                )
            } else if vec.len() == 1 {
                let mut map = self.headers();
                let range = &vec[0];
                map.typed_insert(headers::ContentLength(range.end - range.start));
                map.typed_insert(headers::ContentRange::bytes(range.clone(), length).unwrap());
                Result(StatusCode::PARTIAL_CONTENT, map, Value::Range(vec.pop().unwrap()))
            } else {
                let boundary = thread_rng()
                    .sample_iter(&Alphanumeric)
                    .take(12)
                    .collect::<String>();
                let map = self.multipart_headers(&boundary);
                Result(StatusCode::PARTIAL_CONTENT, map, Value::Multipart(boundary, vec.into_vec()))
            }
        } else {
            let mut map = self.headers();
            map.typed_insert(headers::ContentLength(self.length));
            Result(StatusCode::OK, map, Value::None)
        }
    }
}

pub fn not_modified(display: fmt::Arguments) -> Result {
    debug!("send/cache: {}", display);

    let map = HeaderMap::new();
    let body = err_html(format_args!("Not Modified: {}", display)).into_string();
    Result(StatusCode::NOT_MODIFIED, map, Value::Error(Body::from(body)))
}
<commit_msg>fix etag buf cap<commit_after>use std::{ fmt, cmp };
use std::ops::{ Bound, Range };
use std::path::Path;
use std::fs::Metadata;
use std::str::FromStr;
use std::cell::RefCell;
use smallvec::SmallVec;
use rand::{ Rng, thread_rng, distributions::Alphanumeric };
use log::*;
use hyper::{ StatusCode, Body };
use http::HeaderMap;
use headers::HeaderMapExt;
use mime::Mime;
use base64::{ URL_SAFE_NO_PAD, encode_config_buf };
use crate::common::{ err_html, fs_hash };

pub struct Entity<'a> {
    pub path: &'a Path,
    pub length: u64,
    metadata: &'a Metadata,
    etag: headers::ETag
}

pub struct Result(pub StatusCode, pub HeaderMap, pub Value);

pub enum Value {
    Error(Body),
    None,
    Range(Range<u64>),
    Multipart(String, Vec<Range<u64>>)
}

impl<'a> Entity<'a> {
    pub fn new(path: &'a Path, metadata: &'a Metadata) -> Self {
        thread_local!{
            static BUF: RefCell<String> = RefCell::new(String::with_capacity(16));
        }

        let hash = fs_hash(metadata);

        let etag = BUF.with(|buf| {
            let mut buf = buf.borrow_mut();

            buf.clear();
            buf.push('"');
            encode_config_buf(&hash.to_le_bytes(), URL_SAFE_NO_PAD, &mut buf);
            buf.push('"');

            buf.parse().unwrap()
        });

        Entity {
            path, metadata, etag,
            length: metadata.len()
        }
    }

    pub fn headers(&self) -> HeaderMap {
        let mut map = HeaderMap::new();

        map.typed_insert(headers::AcceptRanges::bytes());
        let mime = mime_guess::from_path(self.path).first_or_octet_stream();
        map.typed_insert(headers::ContentType::from(mime));

        map.typed_insert(self.etag.clone());

        if let Ok(date) = self.metadata.modified() {
            map.typed_insert(headers::LastModified::from(date));
        }

        map
    }

    pub fn multipart_headers(&self, boundary: &str) -> HeaderMap {
        let mut map = HeaderMap::new();

        map.typed_insert(headers::AcceptRanges::bytes());

        // TODO https://github.com/hyperium/mime/issues/52
        let mime = Mime::from_str(format!("multipart/byteranges; boundary={}", boundary).as_str()).unwrap();
        map.typed_insert(headers::ContentType::from(mime));

        if let Ok(date) = self.metadata.modified() {
            map.typed_insert(headers::LastModified::from(date));
        }

        map
    }

    pub fn result(&self, map: &HeaderMap) -> Result {
        // TODO check it

        if let Some(ifmatch) = map.typed_get::<headers::IfMatch>() {
            if !ifmatch.precondition_passes(&self.etag) {
                return Result(
                    StatusCode::PRECONDITION_FAILED,
                    HeaderMap::new(),
                    Value::Error(Body::from("Precondition failed"))
                );
            }
        }

        if let Some(ifrange) = map.typed_get::<headers::IfRange>() {
            let mtime = self.metadata.modified()
                .map(headers::LastModified::from)
                .ok();
            if ifrange.is_modified(Some(&self.etag), mtime.as_ref()) {
                return Result(
                    StatusCode::PRECONDITION_FAILED,
                    HeaderMap::new(),
                    Value::Error(Body::from("Precondition failed"))
                );
            }
        }

        if let Some(ifnonematch) = map.typed_get::<headers::IfNoneMatch>() {
            if ifnonematch.precondition_passes(&self.etag) {
                return not_modified(format_args!("etag: {:?}", &self.etag));
            }
        }

        if let Some(time) = map.typed_get::<headers::IfModifiedSince>() {
            if let Ok(time2) = self.metadata.modified() {
                if !time.is_modified(time2) {
                    return not_modified(format_args!("{:?} vs {:?}", time, time2));
                }
            }
        }

        if let Some(ranges) = map.typed_get::<headers::Range>() {
            let length = self.length;

            let mut vec = ranges
                .iter()
                .filter_map(|(start, end)| {
                    let start = match start {
                        Bound::Excluded(x) | Bound::Included(x) => x,
                        Bound::Unbounded => 0
                    };

                    let end = match end {
                        Bound::Excluded(y) => y,
                        Bound::Included(y) => y + 1,
                        Bound::Unbounded => length,
                    };
                    let end = cmp::min(end, length);

                    if start <= end {
                        Some(start..end)
                    } else {
                        None
                    }
                })
                .collect::<SmallVec<[_; 1]>>();

            if vec.is_empty() {
                let mut map = self.headers();
                map.typed_insert(headers::ContentRange::unsatisfied_bytes(length));
                Result(
                    StatusCode::RANGE_NOT_SATISFIABLE,
                    map,
                    Value::Error(Body::from("Bad Range"))
                )
            } else if vec.len() == 1 {
                let mut map = self.headers();
                let range = &vec[0];
                map.typed_insert(headers::ContentLength(range.end - range.start));
                map.typed_insert(headers::ContentRange::bytes(range.clone(), length).unwrap());
                Result(StatusCode::PARTIAL_CONTENT, map, Value::Range(vec.pop().unwrap()))
            } else {
                let boundary = thread_rng()
                    .sample_iter(&Alphanumeric)
                    .take(12)
                    .collect::<String>();
                let map = self.multipart_headers(&boundary);
                Result(StatusCode::PARTIAL_CONTENT, map, Value::Multipart(boundary, vec.into_vec()))
            }
        } else {
            let mut map = self.headers();
            map.typed_insert(headers::ContentLength(self.length));
            Result(StatusCode::OK, map, Value::None)
        }
    }
}

pub fn not_modified(display: fmt::Arguments) -> Result {
    debug!("send/cache: {}", display);

    let map = HeaderMap::new();
    let body = err_html(format_args!("Not Modified: {}", display)).into_string();
    Result(StatusCode::NOT_MODIFIED, map, Value::Error(Body::from(body)))
}
<|endoftext|>


<commit_before>use rawslice::{RawSlice, RawMutSlice, SliceRawExt};

pub struct UncheckedSlice<'a, T: 'a > {
    slice: &'a [T],
}

pub struct UncheckedMutSlice<'a, T: 'a> {
    slice: &'a mut [T],
}

pub trait SliceUncheckedExt<T> for Sized? {
    /// Gets a version of the slice where all operations aren't bounds checked
    fn unchecked<'a>(&'a self) -> UncheckedSlice<'a, T>;

    /// Gets a mutable version of the slice where all operations aren't bounds checked
    fn unchecked_mut<'a>(&'a mut self) -> UncheckedMutSlice<'a, T>;
}

impl<T> SliceUncheckedExt<T> for [T] {
    fn unchecked<'a>(&'a self) -> UncheckedSlice<'a, T> {
        UncheckedSlice::new(self)
    }

    fn unchecked_mut<'a>(&'a mut self) -> UncheckedMutSlice<'a, T> {
        UncheckedMutSlice::new(self)
    }
}

impl<'a, T> UncheckedSlice<'a, T> {
    fn new(slice: &'a [T]) -> UncheckedSlice<'a, T> {
        UncheckedSlice{ slice: slice }
    }

    fn len(&self) -> uint {
        self.slice.len()
    }

    fn as_slice(self) -> &'a [T] {
        self.slice
    }

    unsafe fn slice(&self, from: uint, to: uint) -> UncheckedSlice<'a, T> {
        UncheckedSlice::new(self.slice.as_raw().slice(from, to).as_slice())
    }

    unsafe fn slice_from(&self, from: uint) -> UncheckedSlice<'a, T> {
        self.slice(from, self.len())
    }

    unsafe fn slice_to(&self, to: uint) -> UncheckedSlice<'a, T> {
        self.slice(0, to)
    }

    unsafe fn split_at(&self, at: uint) -> (UncheckedSlice<'a, T>, UncheckedSlice<'a, T>) {
        (self.slice_to(at), self.slice_from(at))
    }

    unsafe fn get(&self, index: uint) ->  &'a T {
        self.slice.as_raw().get(index)
    }
}

impl<'a, T> UncheckedMutSlice<'a, T> {
    fn new(slice: &'a mut [T]) -> UncheckedMutSlice<'a, T> {
        UncheckedMutSlice{ slice: slice }
    }

    fn len(&self) -> uint {
        self.slice.len()
    }

    fn as_slice(self) -> &'a [T] {
        self.slice
    }

    fn as_mut_slice(self) -> &'a mut [T] {
        self.slice
    }

    unsafe fn slice(&mut self, from: uint, to: uint) -> UncheckedMutSlice<'a, T> {
        UncheckedMutSlice::new(self.slice.as_mut_raw().slice(from, to).as_mut_slice())
    }

    unsafe fn slice_from(&mut self, from: uint) -> UncheckedMutSlice<'a, T> {
        let len = self.len();
        self.slice(from, len)
    }

    unsafe fn slice_to(&mut self, to: uint) -> UncheckedMutSlice<'a, T> {
        self.slice(0, to)
    }

    unsafe fn split_at(&mut self, at: uint) ->
            (UncheckedMutSlice<'a, T>, UncheckedMutSlice<'a, T>) {
        let raw = self.slice.as_mut_raw();
        (raw.slice_to(at).as_mut_slice().unchecked_mut(),
        raw.slice_from(at).as_mut_slice().unchecked_mut())
    }

    unsafe fn get(&mut self, index: uint) ->  &'a T {
        self.slice.as_mut_raw().get_mut(index)
    }

    unsafe fn get_mut(&mut self, index: uint) ->  &'a mut T {
        self.slice.as_mut_raw().get_mut(index)
    }
}<commit_msg>cleanup<commit_after>use rawslice::{RawSlice, RawMutSlice, SliceRawExt};

pub struct UncheckedSlice<'a, T: 'a > {
    slice: &'a [T],
}

pub struct UncheckedMutSlice<'a, T: 'a> {
    slice: &'a mut [T],
}

pub trait SliceUncheckedExt<T> for Sized? {
    /// Gets a version of the slice where all operations aren't bounds checked
    fn unchecked<'a>(&'a self) -> UncheckedSlice<'a, T>;

    /// Gets a mutable version of the slice where all operations aren't bounds checked
    fn unchecked_mut<'a>(&'a mut self) -> UncheckedMutSlice<'a, T>;
}

impl<T> SliceUncheckedExt<T> for [T] {
    fn unchecked<'a>(&'a self) -> UncheckedSlice<'a, T> {
        UncheckedSlice::new(self)
    }

    fn unchecked_mut<'a>(&'a mut self) -> UncheckedMutSlice<'a, T> {
        UncheckedMutSlice::new(self)
    }
}

impl<'a, T> UncheckedSlice<'a, T> {
    /// Makes a new unchecked slice from a slice
    pub fn new(slice: &'a [T]) -> UncheckedSlice<'a, T> {
        UncheckedSlice{ slice: slice }
    }

    /// Gets the length of the slice
    pub fn len(&self) -> uint {
        self.slice.len()
    }

    /// Converts the unchecked slice back into a checked one
    pub fn as_slice(self) -> &'a [T] {
        self.slice
    }

    /// Gets a subslice of this one
    pub unsafe fn slice<'b>(&'b self, from: uint, to: uint) -> UncheckedSlice<'b, T> {
        UncheckedSlice::new(self.slice.as_raw().slice(from, to).as_slice())
    }

    /// Gets a subslice from the given index to its end
    pub unsafe fn slice_from<'b>(&'b self, from: uint) -> UncheckedSlice<'b, T> {
        self.slice(from, self.len())
    }

    /// Gets a subslice from 0 to the given index
    pub unsafe fn slice_to<'b>(&'b self, to: uint) -> UncheckedSlice<'b, T> {
        self.slice(0, to)
    }

    /// Splits the given slice into two disjoint slices at the given index
    pub unsafe fn split_at<'b>(&'b self, at: uint) -> (UncheckedSlice<'b, T>, UncheckedSlice<'b, T>) {
        (self.slice_to(at), self.slice_from(at))
    }

    /// Gets the value at the given index
    pub unsafe fn get(&self, index: uint) ->  &T {
        self.slice.as_raw().get(index)
    }
}

impl<'a, T> UncheckedMutSlice<'a, T> {
    /// Makes a new unchecked slice from a slice
    pub fn new(slice: &'a mut [T]) -> UncheckedMutSlice<'a, T> {
        UncheckedMutSlice{ slice: slice }
    }

    /// Gets the length of the slice
    pub fn len(&self) -> uint {
        self.slice.len()
    }

    /// Converts the unchecked slice back into a checked one
    pub fn as_slice(self) -> &'a [T] {
        self.slice
    }

    /// Converts the unchecked slice back into a mutable checked one
    pub fn as_mut_slice(self) -> &'a mut [T] {
        self.slice
    }

    /// Gets a subslice of this one
    pub unsafe fn slice<'b>(&'b mut self, from: uint, to: uint) -> UncheckedMutSlice<'b, T> {
        UncheckedMutSlice::new(self.slice.as_mut_raw().slice(from, to).as_mut_slice())
    }

    /// Gets a subslice from the given index to its end
    pub unsafe fn slice_from<'b>(&'b mut self, from: uint) -> UncheckedMutSlice<'b, T> {
        let len = self.len();
        self.slice(from, len)
    }

    /// Gets a subslice from 0 to the given index
    pub unsafe fn slice_to<'b>(&'b mut self, to: uint) -> UncheckedMutSlice<'b, T> {
        self.slice(0, to)
    }

    /// Splits the given slice into two disjoint slices at the given index
    pub unsafe fn split_at<'b>(&'b mut self, at: uint) ->
            (UncheckedMutSlice<'b, T>, UncheckedMutSlice<'b, T>) {
        let raw = self.slice.as_mut_raw();
        (raw.slice_to(at).as_mut_slice().unchecked_mut(),
        raw.slice_from(at).as_mut_slice().unchecked_mut())
    }

    /// Gets the value at the given index
    pub unsafe fn get(&mut self, index: uint) ->  &T {
        self.slice.as_mut_raw().get_mut(index)
    }

    /// Gets the value at the given index mutably
    pub unsafe fn get_mut(&mut self, index: uint) ->  &mut T {
        self.slice.as_mut_raw().get_mut(index)
    }
}<|endoftext|>


<commit_before>extern crate redis;
#[macro_use]
extern crate bencher;

extern crate futures;
extern crate tokio_core;

use futures::Future;
use tokio_core::reactor::Core;

use bencher::Bencher;

use redis::PipelineCommands;

fn get_client() -> redis::Client {
    redis::Client::open("redis://127.0.0.1:6379").unwrap()
}

fn bench_simple_getsetdel(b: &mut Bencher) {
    let client = get_client();
    let con = client.get_connection().unwrap();

    b.iter(|| {
        let key = "test_key";
        redis::cmd("SET").arg(key).arg(42).execute(&con);
        let _: isize = redis::cmd("GET").arg(key).query(&con).unwrap();
        redis::cmd("DEL").arg(key).execute(&con);
    });
}

fn bench_simple_getsetdel_async(b: &mut Bencher) {
    let client = get_client();
    let mut core = Core::new().unwrap();
    let con = client.get_async_connection(&core.handle());
    let mut opt_con = Some(core.run(con).unwrap());

    b.iter(|| {
        let con = opt_con.take().expect("No connection");

        let key = "test_key";
        let future = redis::cmd("SET")
            .arg(key)
            .arg(42)
            .query_async(con)
            .and_then(|(con, ())| redis::cmd("GET").arg(key).query_async(con))
            .and_then(|(con, _): (_, isize)| redis::cmd("DEL").arg(key).query_async(con));
        let (con, ()) = core.run(future).unwrap();

        opt_con = Some(con);
    });
}

fn bench_simple_getsetdel_pipeline(b: &mut Bencher) {
    let client = get_client();
    let con = client.get_connection().unwrap();

    b.iter(|| {
        let key = "test_key";
        let _: (usize,) = redis::pipe()
            .cmd("SET")
            .arg(key)
            .arg(42)
            .ignore()
            .cmd("GET")
            .arg(key)
            .cmd("DEL")
            .arg(key)
            .ignore()
            .query(&con)
            .unwrap();
    });
}

fn bench_simple_getsetdel_pipeline_precreated(b: &mut Bencher) {
    let client = get_client();
    let con = client.get_connection().unwrap();
    let key = "test_key";
    let mut pipe = redis::pipe();
    pipe.cmd("SET")
        .arg(key)
        .arg(42)
        .ignore()
        .cmd("GET")
        .arg(key)
        .cmd("DEL")
        .arg(key)
        .ignore();

    b.iter(|| {
        let _: (usize,) = pipe.query(&con).unwrap();
    });
}

fn bench_long_pipeline(b: &mut Bencher) {
    let client = get_client();
    let con = client.get_connection().unwrap();
    let mut pipe = redis::pipe();

    for _ in 0..1_000 {
        pipe.set("foo", "bar").ignore();
    }

    b.iter(|| {
        let _: () = pipe.query(&con).unwrap();
    });
}

fn bench_encode_pipeline(b: &mut Bencher) {
    b.iter(|| {
        let mut pipe = redis::pipe();

        for _ in 0..1_000 {
            pipe.set("foo", "bar").ignore();
        }
        pipe
    });
}

fn bench_encode_pipeline_nested(b: &mut Bencher) {
    b.iter(|| {
        let mut pipe = redis::pipe();

        for _ in 0..200 {
            pipe.set(
                "foo",
                ("bar", 123, b"1231279712", &["test", "test", "test"][..]),
            ).ignore();
        }
        pipe
    });
}

benchmark_group!(
    bench,
    bench_simple_getsetdel,
    bench_simple_getsetdel_async,
    bench_simple_getsetdel_pipeline,
    bench_simple_getsetdel_pipeline_precreated,
    bench_long_pipeline,
    bench_encode_pipeline,
    bench_encode_pipeline_nested
);
benchmark_main!(bench);
<commit_msg>Fix the benchmark so it uses tokio<commit_after>extern crate redis;
#[macro_use]
extern crate bencher;

extern crate futures;
extern crate tokio;

use futures::Future;
use tokio::runtime::current_thread::Runtime;

use bencher::Bencher;

use redis::PipelineCommands;

fn get_client() -> redis::Client {
    redis::Client::open("redis://127.0.0.1:6379").unwrap()
}

fn bench_simple_getsetdel(b: &mut Bencher) {
    let client = get_client();
    let con = client.get_connection().unwrap();

    b.iter(|| {
        let key = "test_key";
        redis::cmd("SET").arg(key).arg(42).execute(&con);
        let _: isize = redis::cmd("GET").arg(key).query(&con).unwrap();
        redis::cmd("DEL").arg(key).execute(&con);
    });
}

fn bench_simple_getsetdel_async(b: &mut Bencher) {
    let client = get_client();
    let mut runtime = Runtime::new().unwrap();
    let con = client.get_async_connection();
    let mut opt_con = Some(runtime.block_on(con).unwrap());

    b.iter(|| {
        let con = opt_con.take().expect("No connection");

        let key = "test_key";
        let future = redis::cmd("SET")
            .arg(key)
            .arg(42)
            .query_async(con)
            .and_then(|(con, ())| redis::cmd("GET").arg(key).query_async(con))
            .and_then(|(con, _): (_, isize)| redis::cmd("DEL").arg(key).query_async(con));
        let (con, ()) = runtime.block_on(future).unwrap();

        opt_con = Some(con);
    });
}

fn bench_simple_getsetdel_pipeline(b: &mut Bencher) {
    let client = get_client();
    let con = client.get_connection().unwrap();

    b.iter(|| {
        let key = "test_key";
        let _: (usize,) = redis::pipe()
            .cmd("SET")
            .arg(key)
            .arg(42)
            .ignore()
            .cmd("GET")
            .arg(key)
            .cmd("DEL")
            .arg(key)
            .ignore()
            .query(&con)
            .unwrap();
    });
}

fn bench_simple_getsetdel_pipeline_precreated(b: &mut Bencher) {
    let client = get_client();
    let con = client.get_connection().unwrap();
    let key = "test_key";
    let mut pipe = redis::pipe();
    pipe.cmd("SET")
        .arg(key)
        .arg(42)
        .ignore()
        .cmd("GET")
        .arg(key)
        .cmd("DEL")
        .arg(key)
        .ignore();

    b.iter(|| {
        let _: (usize,) = pipe.query(&con).unwrap();
    });
}

fn bench_long_pipeline(b: &mut Bencher) {
    let client = get_client();
    let con = client.get_connection().unwrap();
    let mut pipe = redis::pipe();

    for _ in 0..1_000 {
        pipe.set("foo", "bar").ignore();
    }

    b.iter(|| {
        let _: () = pipe.query(&con).unwrap();
    });
}

fn bench_encode_pipeline(b: &mut Bencher) {
    b.iter(|| {
        let mut pipe = redis::pipe();

        for _ in 0..1_000 {
            pipe.set("foo", "bar").ignore();
        }
        pipe
    });
}

fn bench_encode_pipeline_nested(b: &mut Bencher) {
    b.iter(|| {
        let mut pipe = redis::pipe();

        for _ in 0..200 {
            pipe.set(
                "foo",
                ("bar", 123, b"1231279712", &["test", "test", "test"][..]),
            ).ignore();
        }
        pipe
    });
}

benchmark_group!(
    bench,
    bench_simple_getsetdel,
    bench_simple_getsetdel_async,
    bench_simple_getsetdel_pipeline,
    bench_simple_getsetdel_pipeline_precreated,
    bench_long_pipeline,
    bench_encode_pipeline,
    bench_encode_pipeline_nested
);
benchmark_main!(bench);
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::rc::Rc;

use syntex_syntax::ast::{self, Attribute};
use syntex_syntax::ext::base::{
    self,
    Determinacy,
    MultiDecorator,
    MultiModifier,
    SyntaxExtension,
};
use syntex_syntax::ext::expand::Expansion;
use syntex_syntax::ext::hygiene::Mark;
use syntex_syntax::parse::token::intern;
use syntex_syntax::parse::ParseSess;

pub struct Resolver<'a> {
    session: &'a ParseSess,
    extensions: HashMap<ast::Name, Rc<SyntaxExtension>>,
}

impl<'a> Resolver<'a> {
    pub fn new(session: &'a ParseSess) -> Self {
        Resolver {
            session: session,
            extensions: HashMap::new(),
        }
    }
}

impl<'a> base::Resolver for Resolver<'a> {
    fn next_node_id(&mut self) -> ast::NodeId {
        ast::DUMMY_NODE_ID
    }
    fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }

    fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
    fn add_macro(&mut self, _scope: Mark, def: ast::MacroDef) {
        self.session.span_diagnostic.span_bug(
            def.span,
            "add_macro is not supported yet");
    }
    fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
        self.extensions.insert(ident.name, ext);
    }
    fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}

    fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute> {
        for i in 0..attrs.len() {
            let name = intern(&attrs[i].name());

            if let Some(ext) = self.extensions.get(&name) {
                match **ext {
                    MultiModifier(..) | MultiDecorator(..) => return Some(attrs.remove(i)),
                    _ => {}
                }
            }
        }
        None
    }
    fn find_extension(&mut self, _scope: Mark, name: ast::Name) -> Option<Rc<SyntaxExtension>> {
        self.extensions.get(&name).map(|ext| ext.clone())
    }
    fn find_mac(&mut self, scope: Mark, mac: &ast::Mac) -> Option<Rc<SyntaxExtension>> {
        let path = &mac.node.path;
        if path.segments.len() > 1 || path.global ||
           !path.segments[0].parameters.is_empty() {
            // NOTE: Pass macros with module separators through to the generated source.
            self.session.span_diagnostic.span_err(path.span,
                                                  "expected macro name without module separators");
            return None;
        }
        let name = path.segments[0].identifier.name;
        self.find_extension(scope, name)
    }
    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                     -> Result<Rc<SyntaxExtension>, Determinacy> {
        if path.segments.len() > 1 || path.global ||
            !path.segments[0].parameters.is_empty() {
            // NOTE: Pass macros with module separators through to the generated source.
            self.session.span_diagnostic.span_err(path.span,
                                                    "expected macro name without module separators");
            return Err(Determinacy::Undetermined);
        }
        let name = path.segments[0].identifier.name;
        let span = path.span;

        self.find_extension(scope, name).ok_or_else(|| {
            if force {
                let mut err =
                    self.session.span_diagnostic.struct_span_err(span, &format!("macro undefined: '{}!'", name));
                err.emit();
                Determinacy::Determined
            } else {
                Determinacy::Undetermined
            }
        })
    }
}
<commit_msg>Additional argument to Resolver::add_macro<commit_after>use std::collections::HashMap;
use std::rc::Rc;

use syntex_syntax::ast::{self, Attribute};
use syntex_syntax::ext::base::{
    self,
    Determinacy,
    MultiDecorator,
    MultiModifier,
    SyntaxExtension,
};
use syntex_syntax::ext::expand::Expansion;
use syntex_syntax::ext::hygiene::Mark;
use syntex_syntax::parse::token::intern;
use syntex_syntax::parse::ParseSess;

pub struct Resolver<'a> {
    session: &'a ParseSess,
    extensions: HashMap<ast::Name, Rc<SyntaxExtension>>,
}

impl<'a> Resolver<'a> {
    pub fn new(session: &'a ParseSess) -> Self {
        Resolver {
            session: session,
            extensions: HashMap::new(),
        }
    }
}

impl<'a> base::Resolver for Resolver<'a> {
    fn next_node_id(&mut self) -> ast::NodeId {
        ast::DUMMY_NODE_ID
    }
    fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }

    fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
    fn add_macro(&mut self, _scope: Mark, def: ast::MacroDef, _export: bool) {
        self.session.span_diagnostic.span_bug(
            def.span,
            "add_macro is not supported yet");
    }
    fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
        self.extensions.insert(ident.name, ext);
    }
    fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}

    fn find_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute> {
        for i in 0..attrs.len() {
            let name = intern(&attrs[i].name());

            if let Some(ext) = self.extensions.get(&name) {
                match **ext {
                    MultiModifier(..) | MultiDecorator(..) => return Some(attrs.remove(i)),
                    _ => {}
                }
            }
        }
        None
    }
    fn find_extension(&mut self, _scope: Mark, name: ast::Name) -> Option<Rc<SyntaxExtension>> {
        self.extensions.get(&name).map(|ext| ext.clone())
    }
    fn find_mac(&mut self, scope: Mark, mac: &ast::Mac) -> Option<Rc<SyntaxExtension>> {
        let path = &mac.node.path;
        if path.segments.len() > 1 || path.global ||
           !path.segments[0].parameters.is_empty() {
            // NOTE: Pass macros with module separators through to the generated source.
            self.session.span_diagnostic.span_err(path.span,
                                                  "expected macro name without module separators");
            return None;
        }
        let name = path.segments[0].identifier.name;
        self.find_extension(scope, name)
    }
    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                     -> Result<Rc<SyntaxExtension>, Determinacy> {
        if path.segments.len() > 1 || path.global ||
            !path.segments[0].parameters.is_empty() {
            // NOTE: Pass macros with module separators through to the generated source.
            self.session.span_diagnostic.span_err(path.span,
                                                    "expected macro name without module separators");
            return Err(Determinacy::Undetermined);
        }
        let name = path.segments[0].identifier.name;
        let span = path.span;

        self.find_extension(scope, name).ok_or_else(|| {
            if force {
                let mut err =
                    self.session.span_diagnostic.struct_span_err(span, &format!("macro undefined: '{}!'", name));
                err.emit();
                Determinacy::Determined
            } else {
                Determinacy::Undetermined
            }
        })
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use super::constant_value::*;
use super::directive::Directive;
use super::primitive::*;
use super::type_annotation::*;
use super::value::*;
use common::{Location, Span};
use interner::StringKey;
use std::fmt;

/// A document only consisting of executable definitions (fragments and operations).
/// This excludes schema definitions and schema extensions.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ExecutableDocument {
    pub span: Span,
    pub definitions: Vec<ExecutableDefinition>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ExecutableDefinition {
    Operation(OperationDefinition),
    Fragment(FragmentDefinition),
}

impl ExecutableDefinition {
    pub fn location(&self) -> Location {
        match self {
            ExecutableDefinition::Operation(node) => node.location,
            ExecutableDefinition::Fragment(node) => node.location,
        }
    }

    pub fn name(&self) -> Option<StringKey> {
        match self {
            ExecutableDefinition::Operation(node) => {
                if let Some(name) = &node.name {
                    Some(name.value)
                } else {
                    None
                }
            }
            ExecutableDefinition::Fragment(node) => Some(node.name.value),
        }
    }
}

impl fmt::Debug for ExecutableDefinition {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ExecutableDefinition::Operation(node) => f.write_fmt(format_args!("{:#?}", node)),
            ExecutableDefinition::Fragment(node) => f.write_fmt(format_args!("{:#?}", node)),
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct OperationDefinition {
    pub location: Location,
    pub operation: Option<(Token, OperationKind)>,
    pub name: Option<Identifier>,
    pub variable_definitions: Option<List<VariableDefinition>>,
    pub directives: Vec<Directive>,
    pub selections: List<Selection>,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum OperationKind {
    Query,
    Mutation,
    Subscription,
}

impl fmt::Display for OperationKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            OperationKind::Query => f.write_str("query"),
            OperationKind::Mutation => f.write_str("mutation"),
            OperationKind::Subscription => f.write_str("subscription"),
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct FragmentDefinition {
    pub location: Location,
    pub fragment: Token,
    pub name: Identifier,
    pub variable_definitions: Option<List<VariableDefinition>>,
    pub type_condition: TypeCondition,
    pub directives: Vec<Directive>,
    pub selections: List<Selection>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct VariableDefinition {
    pub span: Span,
    pub name: VariableIdentifier,
    pub colon: Token,
    pub type_: TypeAnnotation,
    pub default_value: Option<DefaultValue>,
    pub directives: Vec<Directive>,
}

// Primitive Types

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Alias {
    pub span: Span,
    pub alias: Identifier,
    pub colon: Token,
}

impl fmt::Display for Alias {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("{}", self.alias))
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct TypeCondition {
    pub span: Span,
    pub on: Token,
    pub type_: Identifier,
}

impl fmt::Display for TypeCondition {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("on {}", self.type_))
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct DefaultValue {
    pub span: Span,
    pub equals: Token,
    pub value: ConstantValue,
}

impl fmt::Display for DefaultValue {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("{}", self.value))
    }
}

// Selections

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Selection {
    FragmentSpread(FragmentSpread),
    InlineFragment(InlineFragment),
    LinkedField(LinkedField),
    ScalarField(ScalarField),
}

impl Selection {
    pub fn span(&self) -> Span {
        match self {
            Selection::FragmentSpread(node) => node.span,
            Selection::InlineFragment(node) => node.span,
            Selection::LinkedField(node) => node.span,
            Selection::ScalarField(node) => node.span,
        }
    }
}

impl fmt::Debug for Selection {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Selection::FragmentSpread(node) => f.write_fmt(format_args!("{:#?}", node)),
            Selection::InlineFragment(node) => f.write_fmt(format_args!("{:#?}", node)),
            Selection::LinkedField(node) => f.write_fmt(format_args!("{:#?}", node)),
            Selection::ScalarField(node) => f.write_fmt(format_args!("{:#?}", node)),
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct FragmentSpread {
    pub span: Span,
    pub spread: Token,
    pub name: Identifier,
    pub directives: Vec<Directive>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct InlineFragment {
    pub span: Span,
    pub spread: Token,
    pub type_condition: Option<TypeCondition>,
    pub directives: Vec<Directive>,
    pub selections: List<Selection>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct LinkedField {
    pub span: Span,
    pub alias: Option<Alias>,
    pub name: Identifier,
    pub arguments: Option<List<Argument>>,
    pub directives: Vec<Directive>,
    pub selections: List<Selection>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ScalarField {
    pub span: Span,
    pub alias: Option<Alias>,
    pub name: Identifier,
    pub arguments: Option<List<Argument>>,
    pub directives: Vec<Directive>,
}
<commit_msg>add utility has_directive for ExecutableDefinition nodes.<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use super::constant_value::*;
use super::directive::Directive;
use super::primitive::*;
use super::type_annotation::*;
use super::value::*;
use common::{Location, Span};
use interner::StringKey;
use std::fmt;

/// A document only consisting of executable definitions (fragments and operations).
/// This excludes schema definitions and schema extensions.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ExecutableDocument {
    pub span: Span,
    pub definitions: Vec<ExecutableDefinition>,
}

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ExecutableDefinition {
    Operation(OperationDefinition),
    Fragment(FragmentDefinition),
}

impl ExecutableDefinition {
    pub fn location(&self) -> Location {
        match self {
            ExecutableDefinition::Operation(node) => node.location,
            ExecutableDefinition::Fragment(node) => node.location,
        }
    }

    pub fn name(&self) -> Option<StringKey> {
        match self {
            ExecutableDefinition::Operation(node) => {
                if let Some(name) = &node.name {
                    Some(name.value)
                } else {
                    None
                }
            }
            ExecutableDefinition::Fragment(node) => Some(node.name.value),
        }
    }

    pub fn has_directive(&self, directive_name: StringKey) -> bool {
        match self {
            ExecutableDefinition::Operation(node) => node
                .directives
                .iter()
                .any(|d| d.name.value == directive_name),
            ExecutableDefinition::Fragment(node) => node
                .directives
                .iter()
                .any(|d| d.name.value == directive_name),
        }
    }
}

impl fmt::Debug for ExecutableDefinition {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ExecutableDefinition::Operation(node) => f.write_fmt(format_args!("{:#?}", node)),
            ExecutableDefinition::Fragment(node) => f.write_fmt(format_args!("{:#?}", node)),
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct OperationDefinition {
    pub location: Location,
    pub operation: Option<(Token, OperationKind)>,
    pub name: Option<Identifier>,
    pub variable_definitions: Option<List<VariableDefinition>>,
    pub directives: Vec<Directive>,
    pub selections: List<Selection>,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum OperationKind {
    Query,
    Mutation,
    Subscription,
}

impl fmt::Display for OperationKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            OperationKind::Query => f.write_str("query"),
            OperationKind::Mutation => f.write_str("mutation"),
            OperationKind::Subscription => f.write_str("subscription"),
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct FragmentDefinition {
    pub location: Location,
    pub fragment: Token,
    pub name: Identifier,
    pub variable_definitions: Option<List<VariableDefinition>>,
    pub type_condition: TypeCondition,
    pub directives: Vec<Directive>,
    pub selections: List<Selection>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct VariableDefinition {
    pub span: Span,
    pub name: VariableIdentifier,
    pub colon: Token,
    pub type_: TypeAnnotation,
    pub default_value: Option<DefaultValue>,
    pub directives: Vec<Directive>,
}

// Primitive Types

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Alias {
    pub span: Span,
    pub alias: Identifier,
    pub colon: Token,
}

impl fmt::Display for Alias {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("{}", self.alias))
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct TypeCondition {
    pub span: Span,
    pub on: Token,
    pub type_: Identifier,
}

impl fmt::Display for TypeCondition {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("on {}", self.type_))
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct DefaultValue {
    pub span: Span,
    pub equals: Token,
    pub value: ConstantValue,
}

impl fmt::Display for DefaultValue {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("{}", self.value))
    }
}

// Selections

#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Selection {
    FragmentSpread(FragmentSpread),
    InlineFragment(InlineFragment),
    LinkedField(LinkedField),
    ScalarField(ScalarField),
}

impl Selection {
    pub fn span(&self) -> Span {
        match self {
            Selection::FragmentSpread(node) => node.span,
            Selection::InlineFragment(node) => node.span,
            Selection::LinkedField(node) => node.span,
            Selection::ScalarField(node) => node.span,
        }
    }
}

impl fmt::Debug for Selection {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Selection::FragmentSpread(node) => f.write_fmt(format_args!("{:#?}", node)),
            Selection::InlineFragment(node) => f.write_fmt(format_args!("{:#?}", node)),
            Selection::LinkedField(node) => f.write_fmt(format_args!("{:#?}", node)),
            Selection::ScalarField(node) => f.write_fmt(format_args!("{:#?}", node)),
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct FragmentSpread {
    pub span: Span,
    pub spread: Token,
    pub name: Identifier,
    pub directives: Vec<Directive>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct InlineFragment {
    pub span: Span,
    pub spread: Token,
    pub type_condition: Option<TypeCondition>,
    pub directives: Vec<Directive>,
    pub selections: List<Selection>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct LinkedField {
    pub span: Span,
    pub alias: Option<Alias>,
    pub name: Identifier,
    pub arguments: Option<List<Argument>>,
    pub directives: Vec<Directive>,
    pub selections: List<Selection>,
}

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ScalarField {
    pub span: Span,
    pub alias: Option<Alias>,
    pub name: Identifier,
    pub arguments: Option<List<Argument>>,
    pub directives: Vec<Directive>,
}
<|endoftext|>


<commit_before>//! [GET /_matrix/federation/v1/event_auth/{roomId}/{eventId}](https://matrix.org/docs/spec/server_server/r0.1.4#get-matrix-federation-v1-event-auth-roomid-eventid)

use ruma_api::ruma_api;
use ruma_events::pdu::Pdu;
use ruma_identifiers::{EventId, RoomId};

ruma_api! {
    metadata: {
        description: "Retrieves the complete auth chain for a given event.",
        name: "get_event_authorization",
        method: GET,
        path: "/_matrix/federation/v1/event_auth/:room_id/:event_id",
        rate_limited: false,
        requires_authentication: true,
    }

    request: {
        /// The room ID to get the auth chain for.
        #[ruma_api(path)]
        pub room_id: RoomId,

        /// The event ID to get the auth chain for.
        #[ruma_api(path)]
        pub event_id: EventId,
    }

    response: {
        /// The full set of authorization events that make up the state of the room,
        /// and their authorization events, recursively.
        pub auth_chain: Vec<Pdu>,
    }
}
<commit_msg>federation-api: Wrap `Pdu` in `Raw` in get_event_authorization<commit_after>//! [GET /_matrix/federation/v1/event_auth/{roomId}/{eventId}](https://matrix.org/docs/spec/server_server/r0.1.4#get-matrix-federation-v1-event-auth-roomid-eventid)

use ruma_api::ruma_api;
use ruma_events::pdu::Pdu;
use ruma_identifiers::{EventId, RoomId};

ruma_api! {
    metadata: {
        description: "Retrieves the complete auth chain for a given event.",
        name: "get_event_authorization",
        method: GET,
        path: "/_matrix/federation/v1/event_auth/:room_id/:event_id",
        rate_limited: false,
        requires_authentication: true,
    }

    request: {
        /// The room ID to get the auth chain for.
        #[ruma_api(path)]
        pub room_id: RoomId,

        /// The event ID to get the auth chain for.
        #[ruma_api(path)]
        pub event_id: EventId,
    }

    response: {
        /// The full set of authorization events that make up the state of the room,
        /// and their authorization events, recursively.
        pub auth_chain: Vec<Raw<Pdu>>,
    }
}
<|endoftext|>


<commit_before>use ggez::graphics::DrawMode;
use ggez::{graphics, Context, GameResult};
use ggez_goodies::scene::{Scene, SceneSwitch};

use crate::game::{Game, SceneState};
use crate::input::{Axis, Button, InputEvent};
use crate::scenes::FSceneSwitch;

use super::transition::FadeStyle;
use super::{EncounterScene, Fade};
/// Scene that controls switching between various game states.
///
/// Base state that switches between the menu, practice encounter and
/// other game states, draws a black screen that allows the fade in and fade out
/// to work.
///
/// We need this as the current ggez scene stack requires a scene. The other
/// option would be to change the scene stack to not have `expects()` and raise
/// and option instead and use None to handle scene transitions.
pub struct MainScene {}

impl MainScene {
    pub fn new() -> Self {
        Self {}
    }
}

impl Scene<Game, InputEvent> for MainScene {
    fn update(&mut self, mut game: &mut Game, ctx: &mut Context) -> FSceneSwitch {
        match game.scene {
            SceneState::Menu => {
                let encounter_scene = Box::new(
                    EncounterScene::new(
                        ctx,
                        &mut game,
                        &["knight", "dagger"],
                        "wab1",
                        "wa1.t",
                    )
                    .expect("failed to init practice encounter"),
                );

                match game.next_scene {
                    SceneState::Practice => SceneSwitch::PushMultiple(vec![
                        encounter_scene,
                        Box::new(Fade::new(274, 1, FadeStyle::In)),
                    ]),
                    _ => SceneSwitch::None,
                }
            }
            _ => SceneSwitch::None,
        }
    }

    fn draw(&mut self, game: &mut Game, ctx: &mut Context) -> GameResult<()> {
        graphics::set_color(ctx, graphics::Color::new(0.0, 0.0, 0.0, 1.0))?;
        graphics::rectangle(
            ctx,
            DrawMode::Fill,
            graphics::Rect {
                x: 0.0,
                y: 0.0,
                //TODO: handle scale factor
                w: 320.0 * 3.0,
                h: 200.0 * 3.0,
            },
        );
        graphics::set_color(ctx, graphics::Color::new(1.0, 1.0, 1.0, 1.0))?;
        Ok(())
    }

    fn name(&self) -> &str {
        "Main"
    }

    fn input(&mut self, _gameworld: &mut Game, _event: InputEvent, _started: bool) {}
}
<commit_msg>return to menu after combat ends.<commit_after>use ggez::graphics::DrawMode;
use ggez::{graphics, Context, GameResult};
use ggez_goodies::scene::{Scene, SceneSwitch};

use crate::game::{Game, SceneState};
use crate::input::{Axis, Button, InputEvent};
use crate::scenes::FSceneSwitch;

use super::transition::FadeStyle;
use super::{EncounterScene, Fade, Menu};
/// Scene that controls switching between various game states.
///
/// Base state that switches between the menu, practice encounter and
/// other game states, draws a black screen that allows the fade in and fade out
/// to work.
///
/// We need this as the current ggez scene stack requires a scene. The other
/// option would be to change the scene stack to not have `expects()` and raise
/// and option instead and use None to handle scene transitions.
pub struct MainScene {}

impl MainScene {
    pub fn new() -> Self {
        Self {}
    }
}

impl Scene<Game, InputEvent> for MainScene {
    fn update(&mut self, mut game: &mut Game, ctx: &mut Context) -> FSceneSwitch {
        match game.next_scene {
            SceneState::Menu => SceneSwitch::PushMultiple(vec![
                Box::new(Menu::new(ctx, &mut game.store).expect("failed to init menu scene")),
                Box::new(Fade::new(274, 1, FadeStyle::In)),
            ]),
            SceneState::Practice => {
                let encounter_scene = Box::new(
                    EncounterScene::new(ctx, &mut game, &["knight", "dagger"], "wab1", "wa1.t")
                        .expect("failed to init practice encounter"),
                );
                game.scene = SceneState::Practice;
                SceneSwitch::PushMultiple(vec![
                    encounter_scene,
                    Box::new(Fade::new(274, 1, FadeStyle::In)),
                ])
            }
            _ => SceneSwitch::None,
        }
    }

    fn draw(&mut self, game: &mut Game, ctx: &mut Context) -> GameResult<()> {
        graphics::set_color(ctx, graphics::Color::new(0.0, 0.0, 0.0, 1.0))?;
        graphics::rectangle(
            ctx,
            DrawMode::Fill,
            graphics::Rect {
                x: 0.0,
                y: 0.0,
                //TODO: handle scale factor
                w: 320.0 * 3.0,
                h: 200.0 * 3.0,
            },
        );
        graphics::set_color(ctx, graphics::Color::new(1.0, 1.0, 1.0, 1.0))?;
        Ok(())
    }

    fn name(&self) -> &str {
        "Main"
    }

    fn input(&mut self, _gameworld: &mut Game, _event: InputEvent, _started: bool) {}
}
<|endoftext|>


<commit_before>pub mod endpoint;

pub use self::endpoint::{Endpoint, extract_endpoints};

use std::collections::{HashMap};
use std::clone::{Clone};

use super::super::error::{Result, PathfinderError};

pub struct Router {
    endpoints: HashMap<String, Box<Endpoint>>
}

impl Router {
    pub fn new(endpoints: HashMap<String, Box<Endpoint>>) -> Router {
        Router {
            endpoints: endpoints
        }
    }

    pub fn match_url(&self, url: &str) -> Result<Box<Endpoint>> {
        match self.endpoints.contains_key(url) {
            true => Ok(self.endpoints[url].clone()),
            false => Err(PathfinderError::EndpointNotFound(url.to_string()))
        }
    }
}

#[cfg(test)]
mod tests {
    use config::{get_config};
    use engine::router::{Router, Endpoint, extract_endpoints};
    use error::{Result};

    fn get_route(file_path: &str, url: &str) -> Result<Box<Endpoint>> {
        let config = get_config(file_path);
        let endpoints = extract_endpoints(config);
        let router = Box::new(Router::new(endpoints));
        router.match_url(url)
    }

    #[test]
    fn test_router_returns_endpoint_for_a_match() {
        let route = get_route(
            &"./tests/files/config_with_valid_endpoints.yaml",
            "/api/matchmaking/search"
        );

        assert_eq!(route.is_ok(), true);
        let endpoint = route.unwrap();
        assert_eq!(endpoint.get_url(), "/api/matchmaking/search");
        assert_eq!(endpoint.get_microservice(), "microservice.search");
    }

    #[test]
    fn test_router_returns_an_error_for_non_existing_endpoint() {
        let route = get_route(
            &"./tests/files/config_with_invalid_endpoints.yaml",
            "/api/matchmaking/search"
        );

        assert_eq!(route.is_err(), true);
    }
}
<commit_msg>Added documentation for router/mod.rs<commit_after>//! Routing entity for handling endpoints
//!
//! This module is intended for matching and converting a passed URLs by a client
//! in request into certain queue/topic names.
//!

pub mod endpoint;

pub use self::endpoint::{Endpoint, extract_endpoints};

use std::collections::{HashMap};
use std::clone::{Clone};

use super::super::error::{Result, PathfinderError};

/// A struct which is stores a mapping of resources that can be
/// represented in requests and transformed into certain API endpoints of
/// microservices.
///
/// # Examples
///
/// Attempt to get an endpoint with correct URL will return all expected data:
///
/// ```
/// use config::{get_config};
/// use engine::router::{Router, Endpoint, extract_endpoints};
///
/// let url = "/api/matchmaking/search";
/// let config = get_config(&"../../../tests/files/config_with_valid_endpoints.yaml");
/// let endpoints = extract_endpoints(config);
/// let router = Box::new(Router::new(endpoints))
///
/// let endpoint = route.match_url(url).unwrap();
/// assert_eq!(endpoint.get_url(), "/api/matchmaking/search");
/// assert_eq!(endpoint.get_microservice(), "microservice.search");
/// ```
///
/// For not matched URL will be returned an error:
///
/// ```
/// use config::{get_config};
/// use engine::router::{Router, Endpoint, extract_endpoints};
///
/// let url = "/api/matchmaking/search";
/// let config = get_config(&"../../../tests/files/config_with_invalid_endpoints.yaml");
/// let endpoints = extract_endpoints(config);
/// let router = Box::new(Router::new(endpoints))
///
/// assert_eq!(route.match_url(url).is_err(), true);
/// ```
///
pub struct Router {
    endpoints: HashMap<String, Box<Endpoint>>
}

impl Router {
    /// Returns a new instance of `Router` that contains a mapping for resources.
    pub fn new(endpoints: HashMap<String, Box<Endpoint>>) -> Router {
        Router {
            endpoints: endpoints
        }
    }

    /// Returns an endpoint that was found for a passed URL.
    pub fn match_url(&self, url: &str) -> Result<Box<Endpoint>> {
        match self.endpoints.contains_key(url) {
            true => Ok(self.endpoints[url].clone()),
            false => Err(PathfinderError::EndpointNotFound(url.to_string()))
        }
    }
}

#[cfg(test)]
mod tests {
    use config::{get_config};
    use engine::router::{Router, Endpoint, extract_endpoints};
    use error::{Result};

    fn get_route(file_path: &str, url: &str) -> Result<Box<Endpoint>> {
        let config = get_config(file_path);
        let endpoints = extract_endpoints(config);
        let router = Box::new(Router::new(endpoints));
        router.match_url(url)
    }

    #[test]
    fn test_router_returns_endpoint_for_a_match() {
        let route = get_route(
            &"./tests/files/config_with_valid_endpoints.yaml",
            "/api/matchmaking/search"
        );

        assert_eq!(route.is_ok(), true);
        let endpoint = route.unwrap();
        assert_eq!(endpoint.get_url(), "/api/matchmaking/search");
        assert_eq!(endpoint.get_microservice(), "microservice.search");
    }

    #[test]
    fn test_router_returns_an_error_for_non_existing_endpoint() {
        let route = get_route(
            &"./tests/files/config_with_invalid_endpoints.yaml",
            "/api/matchmaking/search"
        );

        assert_eq!(route.is_err(), true);
    }
}
<|endoftext|>


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

use std::time::Duration;

pub use base_event_token_derive::*;
use smallvec::SmallVec;

use crate::descriptor::AsRawDescriptor;
use crate::platform::EventContext;
use crate::RawDescriptor;
use crate::Result;

/// Trait that can be used to associate events with arbitrary enums when using
/// `WaitContext`.
///
/// Simple enums that have no or primitive variant data data can use the `#[derive(EventToken)]`
/// custom derive to implement this trait. See
/// [event_token_derive::event_token](../base_event_token_derive/fn.event_token.html) for details.
pub trait EventToken {
    /// Converts this token into a u64 that can be turned back into a token via `from_raw_token`.
    fn as_raw_token(&self) -> u64;

    /// Converts a raw token as returned from `as_raw_token` back into a token.
    ///
    /// It is invalid to give a raw token that was not returned via `as_raw_token` from the same
    /// `Self`. The implementation can expect that this will never happen as a result of its usage
    /// in `WaitContext`.
    fn from_raw_token(data: u64) -> Self;
}

impl EventToken for usize {
    fn as_raw_token(&self) -> u64 {
        *self as u64
    }

    fn from_raw_token(data: u64) -> Self {
        data as Self
    }
}

impl EventToken for u64 {
    fn as_raw_token(&self) -> u64 {
        *self as u64
    }

    fn from_raw_token(data: u64) -> Self {
        data as Self
    }
}

impl EventToken for u32 {
    fn as_raw_token(&self) -> u64 {
        u64::from(*self)
    }

    fn from_raw_token(data: u64) -> Self {
        data as Self
    }
}

impl EventToken for u16 {
    fn as_raw_token(&self) -> u64 {
        u64::from(*self)
    }

    fn from_raw_token(data: u64) -> Self {
        data as Self
    }
}

impl EventToken for u8 {
    fn as_raw_token(&self) -> u64 {
        u64::from(*self)
    }

    fn from_raw_token(data: u64) -> Self {
        data as Self
    }
}

impl EventToken for () {
    fn as_raw_token(&self) -> u64 {
        0
    }

    fn from_raw_token(_data: u64) -> Self {}
}

/// Represents an event that has been signaled and waited for via a wait function.
#[derive(Copy, Clone, Debug)]
pub struct TriggeredEvent<T: EventToken> {
    pub token: T,
    pub is_readable: bool,
    pub is_writable: bool,
    pub is_hungup: bool,
}

/// Represents types of events to watch for.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum EventType {
    // Used to to temporarily stop waiting for events without
    // removing the associated descriptor from the WaitContext.
    // In most cases if a descriptor no longer needs to be
    // waited on, prefer removing it entirely with
    // WaitContext#delete
    None,
    Read,
    Write,
    ReadWrite,
}

/// Used to wait for multiple objects which are eligible for waiting.
///
/// # Example
///
/// ```
/// use base::{Event, EventToken, Result, WaitContext};
///
/// #[derive(EventToken, Copy, Clone, Debug, PartialEq)]
/// enum ExampleToken {
///    SomeEvent(u32),
///    AnotherEvent,
/// }
///
/// let evt1 = Event::new()?;
/// let evt2 = Event::new()?;
/// let another_evt = Event::new()?;
///
/// let ctx: WaitContext<ExampleToken> = WaitContext::build_with(&[
///     (&evt1, ExampleToken::SomeEvent(1)),
///     (&evt2, ExampleToken::SomeEvent(2)),
///     (&another_evt, ExampleToken::AnotherEvent),
/// ])?;
///
/// // Trigger one of the `SomeEvent` events.
/// evt2.write(1)?;
///
/// // Wait for an event to fire. `wait()` will return immediately in this example because `evt2`
/// // has already been triggered, but in normal use, `wait()` will block until at least one event
/// // is signaled by another thread or process.
/// let events = ctx.wait()?;
/// let tokens: Vec<ExampleToken> = events.iter().filter(|e| e.is_readable)
///     .map(|e| e.token).collect();
/// assert_eq!(tokens, [ExampleToken::SomeEvent(2)]);
///
/// // Reset evt2 so it doesn't trigger again in the next `wait()` call.
/// let _ = evt2.read()?;
///
/// // Trigger a different event.
/// another_evt.write(1)?;
///
/// let events = ctx.wait()?;
/// let tokens: Vec<ExampleToken> = events.iter().filter(|e| e.is_readable)
///     .map(|e| e.token).collect();
/// assert_eq!(tokens, [ExampleToken::AnotherEvent]);
///
/// let _ = another_evt.read()?;
/// # Ok::<(), base::Error>(())
/// ```
pub struct WaitContext<T: EventToken>(pub(crate) EventContext<T>);

impl<T: EventToken> WaitContext<T> {
    /// Creates a new WaitContext.
    pub fn new() -> Result<WaitContext<T>> {
        EventContext::new().map(WaitContext)
    }

    /// Creates a new WaitContext with the the associated triggers.
    pub fn build_with(triggers: &[(&dyn AsRawDescriptor, T)]) -> Result<WaitContext<T>> {
        let ctx = WaitContext::new()?;
        ctx.add_many(triggers)?;
        Ok(ctx)
    }

    /// Adds a trigger to the WaitContext.
    pub fn add(&self, descriptor: &dyn AsRawDescriptor, token: T) -> Result<()> {
        self.add_for_event(descriptor, EventType::Read, token)
    }

    /// Adds a trigger to the WaitContext watching for a specific type of event
    pub fn add_for_event(
        &self,
        descriptor: &dyn AsRawDescriptor,
        event_type: EventType,
        token: T,
    ) -> Result<()> {
        self.0.add_for_event(descriptor, event_type, token)
    }

    /// Adds multiple triggers to the WaitContext.
    pub fn add_many(&self, triggers: &[(&dyn AsRawDescriptor, T)]) -> Result<()> {
        for trigger in triggers {
            self.add(trigger.0, T::from_raw_token(trigger.1.as_raw_token()))?
        }
        Ok(())
    }

    /// Modifies a trigger already added to the WaitContext. If the descriptor is
    /// already registered, its associated token will be updated.
    pub fn modify(
        &self,
        descriptor: &dyn AsRawDescriptor,
        event_type: EventType,
        token: T,
    ) -> Result<()> {
        self.0.modify(descriptor, event_type, token)
    }

    /// Removes the given handle from triggers registered in the WaitContext if
    /// present.
    pub fn delete(&self, descriptor: &dyn AsRawDescriptor) -> Result<()> {
        self.0.delete(descriptor)
    }

    /// Waits for one or more of the registered triggers to become signaled.
    pub fn wait(&self) -> Result<SmallVec<[TriggeredEvent<T>; 16]>> {
        self.wait_timeout(Duration::new(i64::MAX as u64, 0))
    }

    /// Waits for one or more of the registered triggers to become signaled, failing if no triggers
    /// are signaled before the designated timeout has elapsed.
    pub fn wait_timeout(&self, timeout: Duration) -> Result<SmallVec<[TriggeredEvent<T>; 16]>> {
        self.0.wait_timeout(timeout)
    }
}

impl<T: EventToken> AsRawDescriptor for WaitContext<T> {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.0.as_raw_descriptor()
    }
}

#[cfg(test)]
mod tests {
    use base_event_token_derive::EventToken;

    use super::*;

    #[test]
    #[allow(dead_code)]
    fn event_token_derive() {
        #[derive(EventToken)]
        enum EmptyToken {}

        #[derive(PartialEq, Debug, EventToken)]
        enum Token {
            Alpha,
            Beta,
            // comments
            Gamma(u32),
            Delta { index: usize },
            Omega,
        }

        assert_eq!(
            Token::from_raw_token(Token::Alpha.as_raw_token()),
            Token::Alpha
        );
        assert_eq!(
            Token::from_raw_token(Token::Beta.as_raw_token()),
            Token::Beta
        );
        assert_eq!(
            Token::from_raw_token(Token::Gamma(55).as_raw_token()),
            Token::Gamma(55)
        );
        assert_eq!(
            Token::from_raw_token(Token::Delta { index: 100 }.as_raw_token()),
            Token::Delta { index: 100 }
        );
        assert_eq!(
            Token::from_raw_token(Token::Omega.as_raw_token()),
            Token::Omega
        );
    }
}
<commit_msg>base: fix WaitContext doc tests<commit_after>// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::time::Duration;

pub use base_event_token_derive::*;
use smallvec::SmallVec;

use crate::descriptor::AsRawDescriptor;
use crate::platform::EventContext;
use crate::RawDescriptor;
use crate::Result;

/// Trait that can be used to associate events with arbitrary enums when using
/// `WaitContext`.
///
/// Simple enums that have no or primitive variant data data can use the `#[derive(EventToken)]`
/// custom derive to implement this trait. See
/// [event_token_derive::event_token](../base_event_token_derive/fn.event_token.html) for details.
pub trait EventToken {
    /// Converts this token into a u64 that can be turned back into a token via `from_raw_token`.
    fn as_raw_token(&self) -> u64;

    /// Converts a raw token as returned from `as_raw_token` back into a token.
    ///
    /// It is invalid to give a raw token that was not returned via `as_raw_token` from the same
    /// `Self`. The implementation can expect that this will never happen as a result of its usage
    /// in `WaitContext`.
    fn from_raw_token(data: u64) -> Self;
}

impl EventToken for usize {
    fn as_raw_token(&self) -> u64 {
        *self as u64
    }

    fn from_raw_token(data: u64) -> Self {
        data as Self
    }
}

impl EventToken for u64 {
    fn as_raw_token(&self) -> u64 {
        *self as u64
    }

    fn from_raw_token(data: u64) -> Self {
        data as Self
    }
}

impl EventToken for u32 {
    fn as_raw_token(&self) -> u64 {
        u64::from(*self)
    }

    fn from_raw_token(data: u64) -> Self {
        data as Self
    }
}

impl EventToken for u16 {
    fn as_raw_token(&self) -> u64 {
        u64::from(*self)
    }

    fn from_raw_token(data: u64) -> Self {
        data as Self
    }
}

impl EventToken for u8 {
    fn as_raw_token(&self) -> u64 {
        u64::from(*self)
    }

    fn from_raw_token(data: u64) -> Self {
        data as Self
    }
}

impl EventToken for () {
    fn as_raw_token(&self) -> u64 {
        0
    }

    fn from_raw_token(_data: u64) -> Self {}
}

/// Represents an event that has been signaled and waited for via a wait function.
#[derive(Copy, Clone, Debug)]
pub struct TriggeredEvent<T: EventToken> {
    pub token: T,
    pub is_readable: bool,
    pub is_writable: bool,
    pub is_hungup: bool,
}

/// Represents types of events to watch for.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum EventType {
    // Used to to temporarily stop waiting for events without
    // removing the associated descriptor from the WaitContext.
    // In most cases if a descriptor no longer needs to be
    // waited on, prefer removing it entirely with
    // WaitContext#delete
    None,
    Read,
    Write,
    ReadWrite,
}

/// Used to wait for multiple objects which are eligible for waiting.
///
/// # Example
///
/// ```
/// use base::{Event, EventToken, Result, WaitContext};
///
/// #[derive(EventToken, Copy, Clone, Debug, PartialEq)]
/// enum ExampleToken {
///    SomeEvent(u32),
///    AnotherEvent,
/// }
///
/// let evt1 = Event::new()?;
/// let evt2 = Event::new()?;
/// let another_evt = Event::new()?;
///
/// let ctx: WaitContext<ExampleToken> = WaitContext::build_with(&[
///     (&evt1, ExampleToken::SomeEvent(1)),
///     (&evt2, ExampleToken::SomeEvent(2)),
///     (&another_evt, ExampleToken::AnotherEvent),
/// ])?;
///
/// // Trigger one of the `SomeEvent` events.
/// evt2.signal()?;
///
/// // Wait for an event to fire. `wait()` will return immediately in this example because `evt2`
/// // has already been triggered, but in normal use, `wait()` will block until at least one event
/// // is signaled by another thread or process.
/// let events = ctx.wait()?;
/// let tokens: Vec<ExampleToken> = events.iter().filter(|e| e.is_readable)
///     .map(|e| e.token).collect();
/// assert_eq!(tokens, [ExampleToken::SomeEvent(2)]);
///
/// // Reset evt2 so it doesn't trigger again in the next `wait()` call.
/// let _ = evt2.reset()?;
///
/// // Trigger a different event.
/// another_evt.signal()?;
///
/// let events = ctx.wait()?;
/// let tokens: Vec<ExampleToken> = events.iter().filter(|e| e.is_readable)
///     .map(|e| e.token).collect();
/// assert_eq!(tokens, [ExampleToken::AnotherEvent]);
///
/// let _ = another_evt.reset()?;
/// # Ok::<(), base::Error>(())
/// ```
pub struct WaitContext<T: EventToken>(pub(crate) EventContext<T>);

impl<T: EventToken> WaitContext<T> {
    /// Creates a new WaitContext.
    pub fn new() -> Result<WaitContext<T>> {
        EventContext::new().map(WaitContext)
    }

    /// Creates a new WaitContext with the the associated triggers.
    pub fn build_with(triggers: &[(&dyn AsRawDescriptor, T)]) -> Result<WaitContext<T>> {
        let ctx = WaitContext::new()?;
        ctx.add_many(triggers)?;
        Ok(ctx)
    }

    /// Adds a trigger to the WaitContext.
    pub fn add(&self, descriptor: &dyn AsRawDescriptor, token: T) -> Result<()> {
        self.add_for_event(descriptor, EventType::Read, token)
    }

    /// Adds a trigger to the WaitContext watching for a specific type of event
    pub fn add_for_event(
        &self,
        descriptor: &dyn AsRawDescriptor,
        event_type: EventType,
        token: T,
    ) -> Result<()> {
        self.0.add_for_event(descriptor, event_type, token)
    }

    /// Adds multiple triggers to the WaitContext.
    pub fn add_many(&self, triggers: &[(&dyn AsRawDescriptor, T)]) -> Result<()> {
        for trigger in triggers {
            self.add(trigger.0, T::from_raw_token(trigger.1.as_raw_token()))?
        }
        Ok(())
    }

    /// Modifies a trigger already added to the WaitContext. If the descriptor is
    /// already registered, its associated token will be updated.
    pub fn modify(
        &self,
        descriptor: &dyn AsRawDescriptor,
        event_type: EventType,
        token: T,
    ) -> Result<()> {
        self.0.modify(descriptor, event_type, token)
    }

    /// Removes the given handle from triggers registered in the WaitContext if
    /// present.
    pub fn delete(&self, descriptor: &dyn AsRawDescriptor) -> Result<()> {
        self.0.delete(descriptor)
    }

    /// Waits for one or more of the registered triggers to become signaled.
    pub fn wait(&self) -> Result<SmallVec<[TriggeredEvent<T>; 16]>> {
        self.wait_timeout(Duration::new(i64::MAX as u64, 0))
    }

    /// Waits for one or more of the registered triggers to become signaled, failing if no triggers
    /// are signaled before the designated timeout has elapsed.
    pub fn wait_timeout(&self, timeout: Duration) -> Result<SmallVec<[TriggeredEvent<T>; 16]>> {
        self.0.wait_timeout(timeout)
    }
}

impl<T: EventToken> AsRawDescriptor for WaitContext<T> {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.0.as_raw_descriptor()
    }
}

#[cfg(test)]
mod tests {
    use base_event_token_derive::EventToken;

    use super::*;

    #[test]
    #[allow(dead_code)]
    fn event_token_derive() {
        #[derive(EventToken)]
        enum EmptyToken {}

        #[derive(PartialEq, Debug, EventToken)]
        enum Token {
            Alpha,
            Beta,
            // comments
            Gamma(u32),
            Delta { index: usize },
            Omega,
        }

        assert_eq!(
            Token::from_raw_token(Token::Alpha.as_raw_token()),
            Token::Alpha
        );
        assert_eq!(
            Token::from_raw_token(Token::Beta.as_raw_token()),
            Token::Beta
        );
        assert_eq!(
            Token::from_raw_token(Token::Gamma(55).as_raw_token()),
            Token::Gamma(55)
        );
        assert_eq!(
            Token::from_raw_token(Token::Delta { index: 100 }.as_raw_token()),
            Token::Delta { index: 100 }
        );
        assert_eq!(
            Token::from_raw_token(Token::Omega.as_raw_token()),
            Token::Omega
        );
    }
}
<|endoftext|>


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

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::process::{Command, Stdio, exit};

#[cfg(windows)]
fn find_python() -> String {
    if Command::new("python27.exe").arg("--version").output().is_ok() {
        return "python27.exe".to_owned();
    }

    if Command::new("python.exe").arg("--version").output().is_ok() {
        return "python.exe".to_owned();
    }

    panic!("Can't find python (tried python27.exe and python.exe)! Try fixing PATH or setting the PYTHON env var");
}

#[cfg(not(windows))]
fn find_python() -> String {
    if Command::new("python2.7").arg("--version").output().unwrap().status.success() {
        "python2.7"
    } else {
        "python"
    }.to_owned()
}

fn main() {
    let python = match env::var("PYTHON") {
        Ok(python_path) => python_path,
        Err(_) => find_python(),
    };
    let style = Path::new(file!()).parent().unwrap();
    let mako = style.join("Mako-0.9.1.zip");
    let template = style.join("properties.mako.rs");
    let product = if cfg!(feature = "gecko") { "gecko" } else { "servo" };
    let result = Command::new(python)
        .env("PYTHONPATH", &mako)
        .env("TEMPLATE", &template)
        .env("PRODUCT", product)
        .arg("-c")
        .arg(r#"
import os
import sys
from mako.template import Template
from mako import exceptions
try:
    print(Template(filename=os.environ['TEMPLATE'], input_encoding='utf8').render(PRODUCT=os.environ['PRODUCT'])
                                                                          .encode('utf8'))
except:
    sys.stderr.write(exceptions.text_error_template().render().encode('utf8'))
    sys.exit(1)
"#)
        .stderr(Stdio::inherit())
        .output()
        .unwrap();
    if !result.status.success() {
        exit(1)
    }
    let out = env::var("OUT_DIR").unwrap();
    File::create(&Path::new(&out).join("properties.rs")).unwrap().write_all(&result.stdout).unwrap();
}
<commit_msg>Work around a Mako bug on Windows<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::process::{Command, Stdio, exit};

#[cfg(windows)]
fn find_python() -> String {
    if Command::new("python27.exe").arg("--version").output().is_ok() {
        return "python27.exe".to_owned();
    }

    if Command::new("python.exe").arg("--version").output().is_ok() {
        return "python.exe".to_owned();
    }

    panic!("Can't find python (tried python27.exe and python.exe)! Try fixing PATH or setting the PYTHON env var");
}

#[cfg(not(windows))]
fn find_python() -> String {
    if Command::new("python2.7").arg("--version").output().unwrap().status.success() {
        "python2.7"
    } else {
        "python"
    }.to_owned()
}

fn main() {
    let python = match env::var("PYTHON") {
        Ok(python_path) => python_path,
        Err(_) => find_python(),
    };
    let style = Path::new(file!()).parent().unwrap();
    let mako = style.join("Mako-0.9.1.zip");
    let template = style.join("properties.mako.rs");
    let product = if cfg!(feature = "gecko") { "gecko" } else { "servo" };
    let result = Command::new(python)
        .env("PYTHONPATH", &mako)
        .env("TEMPLATE", &template)
        .env("PRODUCT", product)
        .arg("-c")
        .arg(r#"
import os
import sys
from mako.template import Template
from mako import exceptions
try:
    template = Template(open(os.environ['TEMPLATE'], 'rb').read(), input_encoding='utf8')
    print(template.render(PRODUCT=os.environ['PRODUCT']).encode('utf8'))
except:
    sys.stderr.write(exceptions.text_error_template().render().encode('utf8'))
    sys.exit(1)
"#)
        .stderr(Stdio::inherit())
        .output()
        .unwrap();
    if !result.status.success() {
        exit(1)
    }
    let out = env::var("OUT_DIR").unwrap();
    File::create(&Path::new(&out).join("properties.rs")).unwrap().write_all(&result.stdout).unwrap();
}
<|endoftext|>