<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Hooks for for the RPC system.
//!
//! Roughly corresponds to capability.h in the C++ implementation.

use any_pointer;
use private::capability::{ClientHook, ParamsHook, RequestHook, ResponseHook, ResultsHook};

#[cfg(feature = "rpc")]
pub type Promise<T,E> = ::gj::Promise<T,E>;

/// This fake Promise struct is defined so that the generated code for interfaces
/// can typecheck even if the "rpc" feature is not enabled.
#[cfg(not(feature = "rpc"))]
pub struct Promise<T,E>(::std::result::Result<T,E>);

#[cfg(not(feature = "rpc"))]
impl <T,E> Promise<T,E> {
    pub fn ok(v: T) -> Promise<T,E> {
        Promise(Ok(v))
    }
    pub fn err(e: E) -> Promise<T,E> {
        Promise(Err(e))
    }
    pub fn map<F, R>(self, _func: F) -> Promise<R, E>
        where F: FnOnce(T) -> Result<R, E>,
    {
        unimplemented!()
    }
}

#[must_use]
pub struct RemotePromise<Results> where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a> + 'static {
    pub promise: Promise<Response<Results>, ::Error>,
    pub pipeline: Results::Pipeline,
}

pub struct ReaderCapTable {
    pub hooks: Vec<Option<Box<ClientHook>>>
}

impl ReaderCapTable {
    pub fn new(hooks: Vec<Option<Box<ClientHook>>>) -> ReaderCapTable {
        ReaderCapTable { hooks: hooks }
    }

    // Do I need an Imbueable trait?
    pub fn imbue<'a, T>(&'a self) -> T {
        &self.hooks;
        unimplemented!();
    }
}

pub struct Response<Results> {
    pub marker: ::std::marker::PhantomData<Results>,
    pub hook: Box<ResponseHook>,
}

impl <Results> Response<Results>
    where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a>
{
    pub fn new(hook: Box<ResponseHook>) -> Response<Results> {
        Response { marker: ::std::marker::PhantomData, hook: hook }
    }
    pub fn get<'a>(&'a self) -> ::Result<<Results as ::traits::Owned<'a>>::Reader> {
        try!(self.hook.get()).get_as()
    }
}

pub struct Request<Params, Results> {
    pub marker: ::std::marker::PhantomData<(Params, Results)>,
    pub hook: Box<RequestHook>
}

impl <Params, Results> Request <Params, Results>
    where Params: for<'a> ::traits::Owned<'a>
{
    pub fn new(hook: Box<RequestHook>) -> Request <Params, Results> {
        Request { hook: hook, marker: ::std::marker::PhantomData }
    }

    pub fn get<'a>(&'a mut self) -> <Params as ::traits::Owned<'a>>::Builder {
        self.hook.get().init_as()
    }
}

#[cfg(feature = "rpc")]
impl <Params, Results> Request <Params, Results>
where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a> + 'static,
      <Results as ::traits::Pipelined>::Pipeline: FromTypelessPipeline
{
    pub fn send(self) -> RemotePromise<Results> {
        let RemotePromise {promise, pipeline, ..} = self.hook.send();
        let typed_promise = promise.map(|response| {
            Ok(Response {hook: response.hook,
                        marker: ::std::marker::PhantomData})
        });
        RemotePromise { promise: typed_promise,
                        pipeline: FromTypelessPipeline::new(pipeline)
                      }
    }
}

pub struct Params<T> {
    pub marker: ::std::marker::PhantomData<T>,
    pub hook: Box<ParamsHook>,
}

impl <T> Params <T> {
    pub fn new(hook: Box<ParamsHook>) -> Params<T> {
        Params { marker: ::std::marker::PhantomData, hook: hook }
    }
    pub fn get<'a>(&'a self) -> <T as ::traits::Owned<'a>>::Reader
        where T: ::traits::Owned<'a>
    {
        self.hook.get().unwrap().get_as().unwrap()
    }
}

pub struct Results<T> {
    pub marker: ::std::marker::PhantomData<T>,
    pub hook: Box<ResultsHook>,
}

impl <T> Results<T> {
    pub fn new(hook: Box<ResultsHook>) -> Results<T> {
        Results { marker: ::std::marker::PhantomData, hook: hook }
    }

    pub fn get<'a>(&'a mut self) -> <T as ::traits::Owned<'a>>::Builder
        where T: ::traits::Owned<'a>
    {
        self.hook.get().unwrap().get_as().unwrap()
    }
}

pub trait FromTypelessPipeline {
    fn new (typeless: any_pointer::Pipeline) -> Self;
}

pub trait FromClientHook {
    fn new(Box<ClientHook>) -> Self;
}

pub struct Client {
    pub hook: Box<ClientHook>
}

impl Client {
    pub fn new(hook: Box<ClientHook>) -> Client {
        Client { hook : hook }
    }

    pub fn new_call<Params, Results>(&self,
                                     interface_id : u64,
                                     method_id : u16,
                                     size_hint : Option<::MessageSize>)
                                     -> Request<Params, Results> {
        let typeless = self.hook.new_call(interface_id, method_id, size_hint);
        Request { hook: typeless.hook, marker: ::std::marker::PhantomData }
    }
}

pub trait Server {
    fn dispatch_call(&mut self, interface_id: u64, method_id: u16,
                     params: Params<any_pointer::Owned>,
                     results: Results<any_pointer::Owned>)
                     -> Promise<Results<any_pointer::Owned>, ::Error>;
}

<commit_msg>A request should not get re-initted on get().<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Hooks for for the RPC system.
//!
//! Roughly corresponds to capability.h in the C++ implementation.

use any_pointer;
use private::capability::{ClientHook, ParamsHook, RequestHook, ResponseHook, ResultsHook};

#[cfg(feature = "rpc")]
pub type Promise<T,E> = ::gj::Promise<T,E>;

/// This fake Promise struct is defined so that the generated code for interfaces
/// can typecheck even if the "rpc" feature is not enabled.
#[cfg(not(feature = "rpc"))]
pub struct Promise<T,E>(::std::result::Result<T,E>);

#[cfg(not(feature = "rpc"))]
impl <T,E> Promise<T,E> {
    pub fn ok(v: T) -> Promise<T,E> {
        Promise(Ok(v))
    }
    pub fn err(e: E) -> Promise<T,E> {
        Promise(Err(e))
    }
    pub fn map<F, R>(self, _func: F) -> Promise<R, E>
        where F: FnOnce(T) -> Result<R, E>,
    {
        unimplemented!()
    }
}

#[must_use]
pub struct RemotePromise<Results> where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a> + 'static {
    pub promise: Promise<Response<Results>, ::Error>,
    pub pipeline: Results::Pipeline,
}

pub struct ReaderCapTable {
    pub hooks: Vec<Option<Box<ClientHook>>>
}

impl ReaderCapTable {
    pub fn new(hooks: Vec<Option<Box<ClientHook>>>) -> ReaderCapTable {
        ReaderCapTable { hooks: hooks }
    }

    // Do I need an Imbueable trait?
    pub fn imbue<'a, T>(&'a self) -> T {
        &self.hooks;
        unimplemented!();
    }
}

pub struct Response<Results> {
    pub marker: ::std::marker::PhantomData<Results>,
    pub hook: Box<ResponseHook>,
}

impl <Results> Response<Results>
    where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a>
{
    pub fn new(hook: Box<ResponseHook>) -> Response<Results> {
        Response { marker: ::std::marker::PhantomData, hook: hook }
    }
    pub fn get<'a>(&'a self) -> ::Result<<Results as ::traits::Owned<'a>>::Reader> {
        try!(self.hook.get()).get_as()
    }
}

pub struct Request<Params, Results> {
    pub marker: ::std::marker::PhantomData<(Params, Results)>,
    pub hook: Box<RequestHook>
}

impl <Params, Results> Request <Params, Results>
    where Params: for<'a> ::traits::Owned<'a>
{
    pub fn new(hook: Box<RequestHook>) -> Request <Params, Results> {
        Request { hook: hook, marker: ::std::marker::PhantomData }
    }

    pub fn get<'a>(&'a mut self) -> <Params as ::traits::Owned<'a>>::Builder {
        self.hook.get().get_as().unwrap()
    }
}

#[cfg(feature = "rpc")]
impl <Params, Results> Request <Params, Results>
where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a> + 'static,
      <Results as ::traits::Pipelined>::Pipeline: FromTypelessPipeline
{
    pub fn send(self) -> RemotePromise<Results> {
        let RemotePromise {promise, pipeline, ..} = self.hook.send();
        let typed_promise = promise.map(|response| {
            Ok(Response {hook: response.hook,
                        marker: ::std::marker::PhantomData})
        });
        RemotePromise { promise: typed_promise,
                        pipeline: FromTypelessPipeline::new(pipeline)
                      }
    }
}

pub struct Params<T> {
    pub marker: ::std::marker::PhantomData<T>,
    pub hook: Box<ParamsHook>,
}

impl <T> Params <T> {
    pub fn new(hook: Box<ParamsHook>) -> Params<T> {
        Params { marker: ::std::marker::PhantomData, hook: hook }
    }
    pub fn get<'a>(&'a self) -> <T as ::traits::Owned<'a>>::Reader
        where T: ::traits::Owned<'a>
    {
        self.hook.get().unwrap().get_as().unwrap()
    }
}

pub struct Results<T> {
    pub marker: ::std::marker::PhantomData<T>,
    pub hook: Box<ResultsHook>,
}

impl <T> Results<T> {
    pub fn new(hook: Box<ResultsHook>) -> Results<T> {
        Results { marker: ::std::marker::PhantomData, hook: hook }
    }

    pub fn get<'a>(&'a mut self) -> <T as ::traits::Owned<'a>>::Builder
        where T: ::traits::Owned<'a>
    {
        self.hook.get().unwrap().get_as().unwrap()
    }
}

pub trait FromTypelessPipeline {
    fn new (typeless: any_pointer::Pipeline) -> Self;
}

pub trait FromClientHook {
    fn new(Box<ClientHook>) -> Self;
}

pub struct Client {
    pub hook: Box<ClientHook>
}

impl Client {
    pub fn new(hook: Box<ClientHook>) -> Client {
        Client { hook : hook }
    }

    pub fn new_call<Params, Results>(&self,
                                     interface_id : u64,
                                     method_id : u16,
                                     size_hint : Option<::MessageSize>)
                                     -> Request<Params, Results> {
        let typeless = self.hook.new_call(interface_id, method_id, size_hint);
        Request { hook: typeless.hook, marker: ::std::marker::PhantomData }
    }
}

pub trait Server {
    fn dispatch_call(&mut self, interface_id: u64, method_id: u16,
                     params: Params<any_pointer::Owned>,
                     results: Results<any_pointer::Owned>)
                     -> Promise<Results<any_pointer::Owned>, ::Error>;
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use builtins::Builtin;
use word::Word;

pub struct Dictionary {
    items: HashMap<String, Word>,
}

impl Dictionary {
    pub fn get(&self, name: &str) -> Option<Word> {
        if let Some(word) = self.items.get(name) {
            Some(word.clone())
        } else if let Ok(num) = name.parse::<i32>() {
            Some(Word::Int(num))
        } else if let Ok(num) = name.parse::<f32>() {
            Some(Word::Float(num))
        } else {
            None
        }
    }
    pub fn set(&mut self, name: &str, value: Word) {
        if self.items.contains_key(name) {
            // XXX display debug message another way
            println!("Redefined {}", name);
        }
        self.items.insert(name.to_owned(), value);
    }
}

impl Default for Dictionary {
    fn default() -> Dictionary {
        let mut dict = HashMap::new();
        dict.insert(".\"".to_owned(), Word::Dotquote);
        dict.insert(".".to_owned(), Word::Builtin(Builtin::Dot));
        dict.insert("+".to_owned(), Word::Builtin(Builtin::Plus));
        dict.insert("-".to_owned(), Word::Builtin(Builtin::Minus));
        dict.insert("*".to_owned(), Word::Builtin(Builtin::Times));
        dict.insert("/".to_owned(), Word::Builtin(Builtin::Divide));
        dict.insert("=".to_owned(), Word::Builtin(Builtin::Equal));
        dict.insert("<".to_owned(), Word::Builtin(Builtin::LessThan));
        dict.insert(">".to_owned(), Word::Builtin(Builtin::GreaterThan));
        dict.insert("<=".to_owned(), Word::Builtin(Builtin::LessEqual));
        dict.insert(">=".to_owned(), Word::Builtin(Builtin::GreaterEqual));
        dict.insert(":".to_owned(), Word::Colon);
        dict.insert(";".to_owned(), Word::Semicolon);
        dict.insert("if".to_owned(), Word::If);
        dict.insert("then".to_owned(), Word::Then);
        dict.insert("else".to_owned(), Word::Else);
        dict.insert("(".to_owned(), Word::Parenthesis);
        Dictionary { items: dict }
    }
}
<commit_msg>Make lookup in dictionary case insensitive<commit_after>use std::collections::HashMap;
use builtins::Builtin;
use word::Word;

pub struct Dictionary {
    items: HashMap<String, Word>,
}

impl Dictionary {
    pub fn get(&self, name: &str) -> Option<Word> {
        // Make lookup case insensitive
        let uppername = name.to_uppercase();
        if let Some(word) = self.items.get(&uppername) {
            Some(word.clone())
        } else if let Ok(num) = name.parse::<i32>() {
            Some(Word::Int(num))
        } else if let Ok(num) = name.parse::<f32>() {
            Some(Word::Float(num))
        } else {
            None
        }
    }
    pub fn set(&mut self, name: &str, value: Word) {
        if self.items.contains_key(name) {
            // XXX display debug message another way
            println!("Redefined {}", name);
        }
        // Make lookup case insensitive
        self.items.insert(name.to_uppercase(), value);
    }
}

impl Default for Dictionary {
    fn default() -> Dictionary {
        let mut dict = HashMap::new();
        dict.insert(".\"".to_owned(), Word::Dotquote);
        dict.insert(".".to_owned(), Word::Builtin(Builtin::Dot));
        dict.insert("+".to_owned(), Word::Builtin(Builtin::Plus));
        dict.insert("-".to_owned(), Word::Builtin(Builtin::Minus));
        dict.insert("*".to_owned(), Word::Builtin(Builtin::Times));
        dict.insert("/".to_owned(), Word::Builtin(Builtin::Divide));
        dict.insert("=".to_owned(), Word::Builtin(Builtin::Equal));
        dict.insert("<".to_owned(), Word::Builtin(Builtin::LessThan));
        dict.insert(">".to_owned(), Word::Builtin(Builtin::GreaterThan));
        dict.insert("<=".to_owned(), Word::Builtin(Builtin::LessEqual));
        dict.insert(">=".to_owned(), Word::Builtin(Builtin::GreaterEqual));
        dict.insert(":".to_owned(), Word::Colon);
        dict.insert(";".to_owned(), Word::Semicolon);
        dict.insert("if".to_owned(), Word::If);
        dict.insert("then".to_owned(), Word::Then);
        dict.insert("else".to_owned(), Word::Else);
        dict.insert("(".to_owned(), Word::Parenthesis);
        Dictionary { items: dict }
    }
}
<|endoftext|>


<commit_before>//! Hyphenating iterators.

use std::borrow::Cow;

use unicode_segmentation::UnicodeSegmentation;

use language::{Corpus};
use utilia::{Interspersable, Intersperse};

pub trait Hyphenation<Hyphenator> where Hyphenator : Iterator {
    /// Returns the indices of valid hyphenation points within the text.
    fn opportunities(self, corp: &Corpus) -> Vec<usize>;

    /// Returns an iterator over segments of the text separated by valid
    /// hyphenation points.
    ///
    /// When iterating over a word, such segments coincide with orthographic
    /// syllables. Note that, in some orthographies, the syllables of a hyphenated
    /// word are not necessarily substrings of the original word.
    fn hyphenate(self, corp: &Corpus) -> Hyphenator;
}

/// The `Standard` hyphenator iterates over a string, returning slices
/// delimited by string boundaries and valid hyphenation points.
///
/// For individual words, such slices coincide with orthographic syllables.
#[derive(Clone, Debug)]
pub struct Standard<'a> {
    text: &'a str,
    opportunities: Vec<usize>,
    prior: usize,
    i: usize
}

impl<'a> Standard<'a> {
    /// Inserts a soft hyphen at hyphenation points.
    pub fn punctuate(self) -> Intersperse<Self> {
        self.intersperse("\u{ad}")
    }

    /// Inserts a given string at hyphenation points.
    pub fn punctuate_with(self, mark: &'a str) -> Intersperse<Self> {
        self.intersperse(mark)
    }
}

impl<'a> Iterator for Standard<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        let start = self.prior;
        let i = self.i;

        match self.opportunities.get(i) {
            Some(&end) => {
                self.prior = end;
                self.i = i + 1;
                Some(&self.text[start .. end])
            },
            None => {
                if i <= self.opportunities.len() {
                    self.i = i + 1;
                    Some(&self.text[start ..])
                } else {
                    None
                }
            }
        }
    }
}

impl<'a> Hyphenation<Standard<'a>> for &'a str {
    /// Returns the byte indices of valid hyphenation points within the string.
    fn opportunities(self, corp: &Corpus) -> Vec<usize> {
        let (l_min, r_min) = (corp.left_min, corp.right_min);
        let length_min = l_min + r_min;

        if self.chars().count() < length_min {
            return vec![];
        }

        let by_word = self.split_word_bound_indices();

        by_word.flat_map(|(i, word)| {
            let pts = match corp.exceptions.iter()
                                .filter_map(|exs| exs.score(word))
                                .next() {
                    Some(vec) => Cow::Borrowed(vec),
                    None => Cow::Owned(corp.patterns.score(word))
            }.into_owned();
            let length = pts.len();
            let l = l_min;
            let r = if length >= length_min { length - l_min - r_min + 1 } else { 0 };

            word.char_indices().skip(l)
                .zip(pts.into_iter().skip(l).take(r))
                .filter(|&(_, p)| p % 2 != 0)
                .map(move |((i1, _), _)| i1 + i)
        }).collect()
    }

    /// Returns an iterator over string slices separated by valid hyphenation
    /// points.
    fn hyphenate(self, corp: &Corpus) -> Standard<'a> {
        let os = self.opportunities(corp);

        Standard {
            text: self,
            opportunities: os,
            prior: 0,
            i: 0
        }
    }
}
<commit_msg>Code trivialities<commit_after>//! Hyphenating iterators.

use std::borrow::Cow;

use unicode_segmentation::UnicodeSegmentation;

use language::{Corpus};
use utilia::{Interspersable, Intersperse};

pub trait Hyphenation<Hyphenator> where Hyphenator : Iterator {
    /// Returns the indices of valid hyphenation points within the text.
    fn opportunities(self, corp: &Corpus) -> Vec<usize>;

    /// Returns an iterator over segments of the text separated by valid
    /// hyphenation points.
    ///
    /// When iterating over a word, such segments coincide with orthographic
    /// syllables. Note that, in some orthographies, the syllables of a hyphenated
    /// word are not necessarily substrings of the original word.
    fn hyphenate(self, corp: &Corpus) -> Hyphenator;
}

/// The `Standard` hyphenator iterates over a string, returning slices
/// delimited by string boundaries and valid hyphenation points.
///
/// For individual words, such slices coincide with orthographic syllables.
#[derive(Clone, Debug)]
pub struct Standard<'a> {
    text: &'a str,
    opportunities: Vec<usize>,
    prior: usize,
    i: usize
}

impl<'a> Standard<'a> {
    /// Inserts a soft hyphen at hyphenation points.
    pub fn punctuate(self) -> Intersperse<Self> {
        self.intersperse("\u{ad}")
    }

    /// Inserts a given string at hyphenation points.
    pub fn punctuate_with(self, mark: &'a str) -> Intersperse<Self> {
        self.intersperse(mark)
    }
}

impl<'a> Iterator for Standard<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        let start = self.prior;
        let i = self.i;

        match self.opportunities.get(i) {
            Some(&end) => {
                self.prior = end;
                self.i = i + 1;
                Some(&self.text[start .. end])
            },
            None => {
                if i <= self.opportunities.len() {
                    self.i = i + 1;
                    Some(&self.text[start ..])
                } else {
                    None
                }
            }
        }
    }
}

impl<'a> Hyphenation<Standard<'a>> for &'a str {
    /// Returns the byte indices of valid hyphenation points within the string.
    fn opportunities(self, corp: &Corpus) -> Vec<usize> {
        let (l_min, r_min) = (corp.left_min, corp.right_min);
        let length_min = l_min + r_min;

        if self.chars().count() < length_min {
            return vec![];
        }

        let by_word = self.split_word_bound_indices();

        by_word.flat_map(|(i, word)| {
            let pts = match corp.exceptions.iter()
                                .filter_map(|exs| exs.score(word))
                                .next() {
                    Some(vec) => Cow::Borrowed(vec),
                    None => Cow::Owned(corp.patterns.score(word))
            }.into_owned();
            let length = pts.len();
            let l = l_min;
            let r = if length >= length_min { length - l_min - r_min + 1 } else { 0 };

            word.char_indices().skip(l)
                .zip(pts.into_iter().skip(l).take(r))
                .filter(|&(_, p)| p % 2 != 0)
                .map(move |((i1, _), _)| i1 + i)
        }).collect()
    }

    /// Returns an iterator over string slices separated by valid hyphenation
    /// points.
    fn hyphenate(self, corp: &Corpus) -> Standard<'a> {
        Standard {
            text: self,
            opportunities: self.opportunities(corp),
            prior: 0,
            i: 0
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core;

#[deriving(Eq, IterBytes)]
pub struct EnumSet<E> {
    bits: uint
}

pub trait CLike {
    pub fn to_uint(&self) -> uint;
    pub fn from_uint(uint) -> Self;
}

fn bit<E:CLike>(e: E) -> uint {
    1 << e.to_uint()
}

pub impl<E:CLike> EnumSet<E> {
    fn empty() -> EnumSet<E> {
        EnumSet {bits: 0}
    }

    fn is_empty(&self) -> bool {
        self.bits == 0
    }

    fn intersects(&self, e: EnumSet<E>) -> bool {
        (self.bits & e.bits) != 0
    }

    fn contains(&self, e: EnumSet<E>) -> bool {
        (self.bits & e.bits) == e.bits
    }

    fn add(&mut self, e: E) {
        self.bits |= bit(e);
    }

    fn plus(&self, e: E) -> EnumSet<E> {
        EnumSet {bits: self.bits | bit(e)}
    }

    fn contains_elem(&self, e: E) -> bool {
        (self.bits & bit(e)) != 0
    }

    fn each(&self, f: &fn(E) -> bool) {
        let mut bits = self.bits;
        let mut index = 0;
        while bits != 0 {
            if (bits & 1) != 0 {
                let e = CLike::from_uint(index);
                if !f(e) {
                    return;
                }
            }
            index += 1;
            bits >>= 1;
        }
    }
}

impl<E:CLike> core::Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
    fn sub(&self, e: &EnumSet<E>) -> EnumSet<E> {
        EnumSet {bits: self.bits & !e.bits}
    }
}

impl<E:CLike> core::BitOr<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
    fn bitor(&self, e: &EnumSet<E>) -> EnumSet<E> {
        EnumSet {bits: self.bits | e.bits}
    }
}

impl<E:CLike> core::BitAnd<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
    fn bitand(&self, e: &EnumSet<E>) -> EnumSet<E> {
        EnumSet {bits: self.bits & e.bits}
    }
}
<commit_msg>rustc: Add EnumSet tests<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core;

#[deriving(Eq, IterBytes)]
pub struct EnumSet<E> {
    bits: uint
}

pub trait CLike {
    pub fn to_uint(&self) -> uint;
    pub fn from_uint(uint) -> Self;
}

fn bit<E:CLike>(e: E) -> uint {
    1 << e.to_uint()
}

pub impl<E:CLike> EnumSet<E> {
    fn empty() -> EnumSet<E> {
        EnumSet {bits: 0}
    }

    fn is_empty(&self) -> bool {
        self.bits == 0
    }

    fn intersects(&self, e: EnumSet<E>) -> bool {
        (self.bits & e.bits) != 0
    }

    fn contains(&self, e: EnumSet<E>) -> bool {
        (self.bits & e.bits) == e.bits
    }

    fn add(&mut self, e: E) {
        self.bits |= bit(e);
    }

    fn contains_elem(&self, e: E) -> bool {
        (self.bits & bit(e)) != 0
    }

    fn each(&self, f: &fn(E) -> bool) {
        let mut bits = self.bits;
        let mut index = 0;
        while bits != 0 {
            if (bits & 1) != 0 {
                let e = CLike::from_uint(index);
                if !f(e) {
                    return;
                }
            }
            index += 1;
            bits >>= 1;
        }
    }
}

impl<E:CLike> core::Sub<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
    fn sub(&self, e: &EnumSet<E>) -> EnumSet<E> {
        EnumSet {bits: self.bits & !e.bits}
    }
}

impl<E:CLike> core::BitOr<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
    fn bitor(&self, e: &EnumSet<E>) -> EnumSet<E> {
        EnumSet {bits: self.bits | e.bits}
    }
}

impl<E:CLike> core::BitAnd<EnumSet<E>, EnumSet<E>> for EnumSet<E> {
    fn bitand(&self, e: &EnumSet<E>) -> EnumSet<E> {
        EnumSet {bits: self.bits & e.bits}
    }
}

#[cfg(test)]
mod test {
    use core;
    use core::iter;
    use util::enum_set::*;

    #[deriving(Eq)]
    enum Foo {
        A, B, C
    }

    impl CLike for Foo {
        pub fn to_uint(&self) -> uint {
            *self as uint
        }

        pub fn from_uint(v: uint) -> Foo {
            unsafe { cast::transmute(v) }
        }
    }

    #[test]
    fn test_empty() {
        let e: EnumSet<Foo> = EnumSet::empty();
        assert!(e.is_empty());
    }

    ///////////////////////////////////////////////////////////////////////////
    // intersect

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1: EnumSet<Foo> = EnumSet::empty();
        let e2: EnumSet<Foo> = EnumSet::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1: EnumSet<Foo> = EnumSet::empty();

        let mut e2: EnumSet<Foo> = EnumSet::empty();
        e2.add(A);
        e2.add(B);
        e2.add(C);

        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let mut e1: EnumSet<Foo> = EnumSet::empty();
        e1.add(A);

        let mut e2: EnumSet<Foo> = EnumSet::empty();
        e2.add(B);

        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let mut e1: EnumSet<Foo> = EnumSet::empty();
        e1.add(A);

        let mut e2: EnumSet<Foo> = EnumSet::empty();
        e2.add(A);
        e2.add(B);

        assert!(e1.intersects(e2));
    }

    ///////////////////////////////////////////////////////////////////////////
    // contains and contains_elem

    #[test]
    fn test_contains() {
        let mut e1: EnumSet<Foo> = EnumSet::empty();
        e1.add(A);

        let mut e2: EnumSet<Foo> = EnumSet::empty();
        e2.add(A);
        e2.add(B);

        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
    }

    #[test]
    fn test_contains_elem() {
        let mut e1: EnumSet<Foo> = EnumSet::empty();
        e1.add(A);
        assert!(e1.contains_elem(A));
        assert!(!e1.contains_elem(B));
        assert!(!e1.contains_elem(C));

        e1.add(A);
        e1.add(B);
        assert!(e1.contains_elem(A));
        assert!(e1.contains_elem(B));
        assert!(!e1.contains_elem(C));
    }

    ///////////////////////////////////////////////////////////////////////////
    // each

    #[test]
    fn test_each() {
        let mut e1: EnumSet<Foo> = EnumSet::empty();

        assert_eq!(~[], iter::to_vec(|f| e1.each(f)))

        e1.add(A);
        assert_eq!(~[A], iter::to_vec(|f| e1.each(f)))

        e1.add(C);
        assert_eq!(~[A,C], iter::to_vec(|f| e1.each(f)))

        e1.add(C);
        assert_eq!(~[A,C], iter::to_vec(|f| e1.each(f)))

        e1.add(B);
        assert_eq!(~[A,B,C], iter::to_vec(|f| e1.each(f)))
    }

    ///////////////////////////////////////////////////////////////////////////
    // operators

    #[test]
    fn test_operators() {
        let mut e1: EnumSet<Foo> = EnumSet::empty();
        e1.add(A);
        e1.add(C);

        let mut e2: EnumSet<Foo> = EnumSet::empty();
        e2.add(B);
        e2.add(C);

        let e_union = e1 | e2;
        assert_eq!(~[A,B,C], iter::to_vec(|f| e_union.each(f)))

        let e_intersection = e1 & e2;
        assert_eq!(~[C], iter::to_vec(|f| e_intersection.each(f)))

        let e_subtract = e1 - e2;
        assert_eq!(~[A], iter::to_vec(|f| e_subtract.each(f)))
    }
}
<|endoftext|>


<commit_before>//! Functions to aid the `Api::to_tokens` method.

use proc_macro2::{Span, TokenStream};
use quote::quote;
use std::collections::BTreeSet;
use syn::{
    AngleBracketedGenericArguments, GenericArgument, Ident, Lifetime,
    ParenthesizedGenericArguments, PathArguments, Type, TypeArray, TypeBareFn, TypeGroup,
    TypeParen, TypePath, TypePtr, TypeReference, TypeSlice, TypeTuple,
};

use crate::api::{metadata::Metadata, request::Request};

pub fn collect_lifetime_ident(lifetimes: &mut BTreeSet<Lifetime>, ty: &Type) {
    match ty {
        Type::Path(TypePath { path, .. }) => {
            for seg in &path.segments {
                match &seg.arguments {
                    PathArguments::AngleBracketed(AngleBracketedGenericArguments {
                        args, ..
                    }) => {
                        for gen in args {
                            if let GenericArgument::Type(ty) = gen {
                                collect_lifetime_ident(lifetimes, &ty);
                            } else if let GenericArgument::Lifetime(lt) = gen {
                                lifetimes.insert(lt.clone());
                            }
                        }
                    }
                    PathArguments::Parenthesized(ParenthesizedGenericArguments {
                        inputs, ..
                    }) => {
                        for ty in inputs {
                            collect_lifetime_ident(lifetimes, ty);
                        }
                    }
                    _ => {}
                }
            }
        }
        Type::Reference(TypeReference { elem, lifetime, .. }) => {
            collect_lifetime_ident(lifetimes, &*elem);
            if let Some(lt) = lifetime {
                lifetimes.insert(lt.clone());
            }
        }
        Type::Tuple(TypeTuple { elems, .. }) => {
            for ty in elems {
                collect_lifetime_ident(lifetimes, ty);
            }
        }
        Type::Paren(TypeParen { elem, .. }) => collect_lifetime_ident(lifetimes, &*elem),
        Type::Group(TypeGroup { elem, .. }) => collect_lifetime_ident(lifetimes, &*elem),
        Type::Ptr(TypePtr { elem, .. }) => collect_lifetime_ident(lifetimes, &*elem),
        Type::Slice(TypeSlice { elem, .. }) => collect_lifetime_ident(lifetimes, &*elem),
        Type::Array(TypeArray { elem, .. }) => collect_lifetime_ident(lifetimes, &*elem),
        Type::BareFn(TypeBareFn {
            lifetimes: Some(syn::BoundLifetimes { lifetimes: fn_lifetimes, .. }),
            ..
        }) => {
            for lt in fn_lifetimes {
                let syn::LifetimeDef { lifetime, .. } = lt;
                lifetimes.insert(lifetime.clone());
            }
        }
        _ => {}
    }
}

/// Generates a `TokenStream` of lifetime identifiers `<'lifetime>`.
pub fn generics_to_tokens<'a, I: Iterator<Item = &'a Lifetime>>(lifetimes: I) -> TokenStream {
    let lifetimes = lifetimes.collect::<Vec<_>>();
    if lifetimes.is_empty() {
        TokenStream::new()
    } else {
        let lifetimes = quote! { #( #lifetimes ),* };
        quote! { < #lifetimes > }
    }
}

/// The first item in the tuple generates code for the request path from
/// the `Metadata` and `Request` structs. The second item in the returned tuple
/// is the code to generate a Request struct field created from any segments
/// of the path that start with ":".
///
/// The first `TokenStream` returned is the constructed url path. The second `TokenStream` is
/// used for implementing `TryFrom<http::Request<Vec<u8>>>`, from path strings deserialized to Ruma
/// types.
pub(crate) fn request_path_string_and_parse(
    request: &Request,
    metadata: &Metadata,
) -> (TokenStream, TokenStream) {
    if request.has_path_fields() {
        let path_string = metadata.path.value();

        assert!(path_string.starts_with('/'), "path needs to start with '/'");
        assert!(
            path_string.chars().filter(|c| *c == ':').count() == request.path_field_count(),
            "number of declared path parameters needs to match amount of placeholders in path"
        );

        let format_call = {
            let mut format_string = path_string.clone();
            let mut format_args = Vec::new();

            while let Some(start_of_segment) = format_string.find(':') {
                // ':' should only ever appear at the start of a segment
                assert_eq!(&format_string[start_of_segment - 1..start_of_segment], "/");

                let end_of_segment = match format_string[start_of_segment..].find('/') {
                    Some(rel_pos) => start_of_segment + rel_pos,
                    None => format_string.len(),
                };

                let path_var = Ident::new(
                    &format_string[start_of_segment + 1..end_of_segment],
                    Span::call_site(),
                );
                format_args.push(quote! {
                    ::ruma_api::exports::percent_encoding::utf8_percent_encode(
                        &self.#path_var.to_string(),
                        ::ruma_api::exports::percent_encoding::NON_ALPHANUMERIC,
                    )
                });
                format_string.replace_range(start_of_segment..end_of_segment, "{}");
            }

            quote! {
                format_args!(#format_string, #(#format_args),*)
            }
        };

        let path_fields =
            path_string[1..].split('/').enumerate().filter(|(_, s)| s.starts_with(':')).map(
                |(i, segment)| {
                    let path_var = &segment[1..];
                    let path_var_ident = Ident::new(path_var, Span::call_site());
                    quote! {
                        #path_var_ident: {
                            use ::ruma_api::error::RequestDeserializationError;

                            let segment = path_segments.get(#i).unwrap().as_bytes();
                            let decoded = ::ruma_api::try_deserialize!(
                                request,
                                ::ruma_api::exports::percent_encoding::percent_decode(segment)
                                    .decode_utf8(),
                            );

                            ::ruma_api::try_deserialize!(request, ::std::convert::TryFrom::try_from(&*decoded))
                        }
                    }
                },
            );

        (format_call, quote! { #(#path_fields,)* })
    } else {
        (quote! { metadata.path.to_owned() }, TokenStream::new())
    }
}

/// The function determines the type of query string that needs to be built
/// and then builds it using `ruma_serde::urlencoded::to_string`.
pub(crate) fn build_query_string(request: &Request) -> TokenStream {
    if let Some(field) = request.query_map_field() {
        let field_name = field.ident.as_ref().expect("expected field to have identifier");

        quote!({
            // This function exists so that the compiler will throw an
            // error when the type of the field with the query_map
            // attribute doesn't implement IntoIterator<Item = (String, String)>
            //
            // This is necessary because the ruma_serde::urlencoded::to_string
            // call will result in a runtime error when the type cannot be
            // encoded as a list key-value pairs (?key1=value1&key2=value2)
            //
            // By asserting that it implements the iterator trait, we can
            // ensure that it won't fail.
            fn assert_trait_impl<T>(_: &T)
            where
                T: ::std::iter::IntoIterator<Item = (::std::string::String, ::std::string::String)>,
            {}

            let request_query = RequestQuery(self.#field_name);
            assert_trait_impl(&request_query.0);

            format_args!(
                "?{}",
                ::ruma_api::exports::ruma_serde::urlencoded::to_string(request_query)?
            )
        })
    } else if request.has_query_fields() {
        let request_query_init_fields = request.request_query_init_fields();

        quote!({
            let request_query = RequestQuery {
                #request_query_init_fields
            };

            format_args!(
                "?{}",
                ::ruma_api::exports::ruma_serde::urlencoded::to_string(request_query)?
            )
        })
    } else {
        quote! { "" }
    }
}

/// Deserialize the query string.
pub(crate) fn extract_request_query(request: &Request) -> TokenStream {
    if request.query_map_field().is_some() {
        quote! {
            let request_query = ::ruma_api::try_deserialize!(
                request,
                ::ruma_api::exports::ruma_serde::urlencoded::from_str(
                    &request.uri().query().unwrap_or("")
                ),
            );
        }
    } else if request.has_query_fields() {
        let request_query_type = if request.has_query_lifetimes() {
            quote! { IncomingRequestQuery }
        } else {
            quote! { RequestQuery }
        };
        quote! {
            let request_query: #request_query_type = ::ruma_api::try_deserialize!(
                request,
                ::ruma_api::exports::ruma_serde::urlencoded::from_str(
                    &request.uri().query().unwrap_or("")
                ),
            );
        }
    } else {
        TokenStream::new()
    }
}

/// Generates the code to initialize a `Request`.
///
/// Used to construct an `http::Request`s body.
pub(crate) fn build_request_body(request: &Request) -> TokenStream {
    if let Some(field) = request.newtype_raw_body_field() {
        let field_name = field.ident.as_ref().expect("expected field to have an identifier");
        quote!(self.#field_name)
    } else if request.has_body_fields() || request.newtype_body_field().is_some() {
        let request_body_initializers = if let Some(field) = request.newtype_body_field() {
            let field_name = field.ident.as_ref().expect("expected field to have an identifier");
            quote! { (self.#field_name) }
        } else {
            let initializers = request.request_body_init_fields();
            quote! { { #initializers } }
        };

        quote! {
            {
                let request_body = RequestBody #request_body_initializers;
                ::ruma_api::exports::serde_json::to_vec(&request_body)?
            }
        }
    } else {
        quote!(Vec::new())
    }
}

pub(crate) fn parse_request_body(request: &Request) -> TokenStream {
    if let Some(field) = request.newtype_body_field() {
        let field_name = field.ident.as_ref().expect("expected field to have an identifier");
        quote! {
            #field_name: request_body.0,
        }
    } else if let Some(field) = request.newtype_raw_body_field() {
        let field_name = field.ident.as_ref().expect("expected field to have an identifier");
        quote! {
            #field_name: request.into_body(),
        }
    } else {
        request.request_init_body_fields()
    }
}

pub(crate) fn req_res_meta_word<T>(
    attr_kind: &str,
    field: &syn::Field,
    newtype_body_field: &mut Option<syn::Field>,
    body_field_kind: T,
    raw_field_kind: T,
) -> syn::Result<T> {
    if let Some(f) = &newtype_body_field {
        let mut error = syn::Error::new_spanned(field, "There can only be one newtype body field");
        error.combine(syn::Error::new_spanned(f, "Previous newtype body field"));
        return Err(error);
    }

    *newtype_body_field = Some(field.clone());
    Ok(match attr_kind {
        "body" => body_field_kind,
        "raw_body" => raw_field_kind,
        _ => unreachable!(),
    })
}

pub(crate) fn req_res_name_value<T>(
    name: Ident,
    value: Ident,
    header: &mut Option<Ident>,
    field_kind: T,
) -> syn::Result<T> {
    if name != "header" {
        return Err(syn::Error::new_spanned(
            name,
            "Invalid #[ruma_api] argument with value, expected `header`",
        ));
    }

    *header = Some(value);
    Ok(field_kind)
}

pub(crate) fn is_valid_endpoint_path(string: &str) -> bool {
    string.as_bytes().iter().all(|b| (0x21..=0x7E).contains(b))
}
<commit_msg>Use full type with Outgoing trait for request query deserialization<commit_after>//! Functions to aid the `Api::to_tokens` method.

use proc_macro2::{Span, TokenStream};
use quote::quote;
use std::collections::BTreeSet;
use syn::{
    AngleBracketedGenericArguments, GenericArgument, Ident, Lifetime,
    ParenthesizedGenericArguments, PathArguments, Type, TypeArray, TypeBareFn, TypeGroup,
    TypeParen, TypePath, TypePtr, TypeReference, TypeSlice, TypeTuple,
};

use crate::api::{metadata::Metadata, request::Request};

pub fn collect_lifetime_ident(lifetimes: &mut BTreeSet<Lifetime>, ty: &Type) {
    match ty {
        Type::Path(TypePath { path, .. }) => {
            for seg in &path.segments {
                match &seg.arguments {
                    PathArguments::AngleBracketed(AngleBracketedGenericArguments {
                        args, ..
                    }) => {
                        for gen in args {
                            if let GenericArgument::Type(ty) = gen {
                                collect_lifetime_ident(lifetimes, &ty);
                            } else if let GenericArgument::Lifetime(lt) = gen {
                                lifetimes.insert(lt.clone());
                            }
                        }
                    }
                    PathArguments::Parenthesized(ParenthesizedGenericArguments {
                        inputs, ..
                    }) => {
                        for ty in inputs {
                            collect_lifetime_ident(lifetimes, ty);
                        }
                    }
                    _ => {}
                }
            }
        }
        Type::Reference(TypeReference { elem, lifetime, .. }) => {
            collect_lifetime_ident(lifetimes, &*elem);
            if let Some(lt) = lifetime {
                lifetimes.insert(lt.clone());
            }
        }
        Type::Tuple(TypeTuple { elems, .. }) => {
            for ty in elems {
                collect_lifetime_ident(lifetimes, ty);
            }
        }
        Type::Paren(TypeParen { elem, .. }) => collect_lifetime_ident(lifetimes, &*elem),
        Type::Group(TypeGroup { elem, .. }) => collect_lifetime_ident(lifetimes, &*elem),
        Type::Ptr(TypePtr { elem, .. }) => collect_lifetime_ident(lifetimes, &*elem),
        Type::Slice(TypeSlice { elem, .. }) => collect_lifetime_ident(lifetimes, &*elem),
        Type::Array(TypeArray { elem, .. }) => collect_lifetime_ident(lifetimes, &*elem),
        Type::BareFn(TypeBareFn {
            lifetimes: Some(syn::BoundLifetimes { lifetimes: fn_lifetimes, .. }),
            ..
        }) => {
            for lt in fn_lifetimes {
                let syn::LifetimeDef { lifetime, .. } = lt;
                lifetimes.insert(lifetime.clone());
            }
        }
        _ => {}
    }
}

/// Generates a `TokenStream` of lifetime identifiers `<'lifetime>`.
pub fn generics_to_tokens<'a, I: Iterator<Item = &'a Lifetime>>(lifetimes: I) -> TokenStream {
    let lifetimes = lifetimes.collect::<Vec<_>>();
    if lifetimes.is_empty() {
        TokenStream::new()
    } else {
        let lifetimes = quote! { #( #lifetimes ),* };
        quote! { < #lifetimes > }
    }
}

/// The first item in the tuple generates code for the request path from
/// the `Metadata` and `Request` structs. The second item in the returned tuple
/// is the code to generate a Request struct field created from any segments
/// of the path that start with ":".
///
/// The first `TokenStream` returned is the constructed url path. The second `TokenStream` is
/// used for implementing `TryFrom<http::Request<Vec<u8>>>`, from path strings deserialized to Ruma
/// types.
pub(crate) fn request_path_string_and_parse(
    request: &Request,
    metadata: &Metadata,
) -> (TokenStream, TokenStream) {
    if request.has_path_fields() {
        let path_string = metadata.path.value();

        assert!(path_string.starts_with('/'), "path needs to start with '/'");
        assert!(
            path_string.chars().filter(|c| *c == ':').count() == request.path_field_count(),
            "number of declared path parameters needs to match amount of placeholders in path"
        );

        let format_call = {
            let mut format_string = path_string.clone();
            let mut format_args = Vec::new();

            while let Some(start_of_segment) = format_string.find(':') {
                // ':' should only ever appear at the start of a segment
                assert_eq!(&format_string[start_of_segment - 1..start_of_segment], "/");

                let end_of_segment = match format_string[start_of_segment..].find('/') {
                    Some(rel_pos) => start_of_segment + rel_pos,
                    None => format_string.len(),
                };

                let path_var = Ident::new(
                    &format_string[start_of_segment + 1..end_of_segment],
                    Span::call_site(),
                );
                format_args.push(quote! {
                    ::ruma_api::exports::percent_encoding::utf8_percent_encode(
                        &self.#path_var.to_string(),
                        ::ruma_api::exports::percent_encoding::NON_ALPHANUMERIC,
                    )
                });
                format_string.replace_range(start_of_segment..end_of_segment, "{}");
            }

            quote! {
                format_args!(#format_string, #(#format_args),*)
            }
        };

        let path_fields =
            path_string[1..].split('/').enumerate().filter(|(_, s)| s.starts_with(':')).map(
                |(i, segment)| {
                    let path_var = &segment[1..];
                    let path_var_ident = Ident::new(path_var, Span::call_site());
                    quote! {
                        #path_var_ident: {
                            use ::ruma_api::error::RequestDeserializationError;

                            let segment = path_segments.get(#i).unwrap().as_bytes();
                            let decoded = ::ruma_api::try_deserialize!(
                                request,
                                ::ruma_api::exports::percent_encoding::percent_decode(segment)
                                    .decode_utf8(),
                            );

                            ::ruma_api::try_deserialize!(request, ::std::convert::TryFrom::try_from(&*decoded))
                        }
                    }
                },
            );

        (format_call, quote! { #(#path_fields,)* })
    } else {
        (quote! { metadata.path.to_owned() }, TokenStream::new())
    }
}

/// The function determines the type of query string that needs to be built
/// and then builds it using `ruma_serde::urlencoded::to_string`.
pub(crate) fn build_query_string(request: &Request) -> TokenStream {
    if let Some(field) = request.query_map_field() {
        let field_name = field.ident.as_ref().expect("expected field to have identifier");

        quote!({
            // This function exists so that the compiler will throw an
            // error when the type of the field with the query_map
            // attribute doesn't implement IntoIterator<Item = (String, String)>
            //
            // This is necessary because the ruma_serde::urlencoded::to_string
            // call will result in a runtime error when the type cannot be
            // encoded as a list key-value pairs (?key1=value1&key2=value2)
            //
            // By asserting that it implements the iterator trait, we can
            // ensure that it won't fail.
            fn assert_trait_impl<T>(_: &T)
            where
                T: ::std::iter::IntoIterator<Item = (::std::string::String, ::std::string::String)>,
            {}

            let request_query = RequestQuery(self.#field_name);
            assert_trait_impl(&request_query.0);

            format_args!(
                "?{}",
                ::ruma_api::exports::ruma_serde::urlencoded::to_string(request_query)?
            )
        })
    } else if request.has_query_fields() {
        let request_query_init_fields = request.request_query_init_fields();

        quote!({
            let request_query = RequestQuery {
                #request_query_init_fields
            };

            format_args!(
                "?{}",
                ::ruma_api::exports::ruma_serde::urlencoded::to_string(request_query)?
            )
        })
    } else {
        quote! { "" }
    }
}

/// Deserialize the query string.
pub(crate) fn extract_request_query(request: &Request) -> TokenStream {
    if request.query_map_field().is_some() {
        quote! {
            let request_query = ::ruma_api::try_deserialize!(
                request,
                ::ruma_api::exports::ruma_serde::urlencoded::from_str(
                    &request.uri().query().unwrap_or("")
                ),
            );
        }
    } else if request.has_query_fields() {
        quote! {
            let request_query: <RequestQuery as ::ruma_api::Outgoing>::Incoming = ::ruma_api::try_deserialize!(
                request,
                ::ruma_api::exports::ruma_serde::urlencoded::from_str(
                    &request.uri().query().unwrap_or("")
                ),
            );
        }
    } else {
        TokenStream::new()
    }
}

/// Generates the code to initialize a `Request`.
///
/// Used to construct an `http::Request`s body.
pub(crate) fn build_request_body(request: &Request) -> TokenStream {
    if let Some(field) = request.newtype_raw_body_field() {
        let field_name = field.ident.as_ref().expect("expected field to have an identifier");
        quote!(self.#field_name)
    } else if request.has_body_fields() || request.newtype_body_field().is_some() {
        let request_body_initializers = if let Some(field) = request.newtype_body_field() {
            let field_name = field.ident.as_ref().expect("expected field to have an identifier");
            quote! { (self.#field_name) }
        } else {
            let initializers = request.request_body_init_fields();
            quote! { { #initializers } }
        };

        quote! {
            {
                let request_body = RequestBody #request_body_initializers;
                ::ruma_api::exports::serde_json::to_vec(&request_body)?
            }
        }
    } else {
        quote!(Vec::new())
    }
}

pub(crate) fn parse_request_body(request: &Request) -> TokenStream {
    if let Some(field) = request.newtype_body_field() {
        let field_name = field.ident.as_ref().expect("expected field to have an identifier");
        quote! {
            #field_name: request_body.0,
        }
    } else if let Some(field) = request.newtype_raw_body_field() {
        let field_name = field.ident.as_ref().expect("expected field to have an identifier");
        quote! {
            #field_name: request.into_body(),
        }
    } else {
        request.request_init_body_fields()
    }
}

pub(crate) fn req_res_meta_word<T>(
    attr_kind: &str,
    field: &syn::Field,
    newtype_body_field: &mut Option<syn::Field>,
    body_field_kind: T,
    raw_field_kind: T,
) -> syn::Result<T> {
    if let Some(f) = &newtype_body_field {
        let mut error = syn::Error::new_spanned(field, "There can only be one newtype body field");
        error.combine(syn::Error::new_spanned(f, "Previous newtype body field"));
        return Err(error);
    }

    *newtype_body_field = Some(field.clone());
    Ok(match attr_kind {
        "body" => body_field_kind,
        "raw_body" => raw_field_kind,
        _ => unreachable!(),
    })
}

pub(crate) fn req_res_name_value<T>(
    name: Ident,
    value: Ident,
    header: &mut Option<Ident>,
    field_kind: T,
) -> syn::Result<T> {
    if name != "header" {
        return Err(syn::Error::new_spanned(
            name,
            "Invalid #[ruma_api] argument with value, expected `header`",
        ));
    }

    *header = Some(value);
    Ok(field_kind)
}

pub(crate) fn is_valid_endpoint_path(string: &str) -> bool {
    string.as_bytes().iter().all(|b| (0x21..=0x7E).contains(b))
}
<|endoftext|>


<commit_before>#![feature(test)]
#![feature(tool_lints)]

use std::env;

#[macro_export]
macro_rules! get_version_info {
    () => {{
        let major = env!("CARGO_PKG_VERSION_MAJOR").parse::<u8>().unwrap();
        let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap();
        let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u16>().unwrap();
        let crate_name = String::from(env!("CARGO_PKG_NAME"));

        let host_compiler = $crate::get_channel();
        let commit_hash = option_env!("GIT_HASH").map(|s| s.to_string());
        let commit_date = option_env!("COMMIT_DATE").map(|s| s.to_string());

        VersionInfo {
            major,
            minor,
            patch,
            host_compiler,
            commit_hash,
            commit_date,
            crate_name,
        }
    }};
}

// some code taken and adapted from RLS and cargo
pub struct VersionInfo {
    pub major: u8,
    pub minor: u8,
    pub patch: u16,
    pub host_compiler: Option<String>,
    pub commit_hash: Option<String>,
    pub commit_date: Option<String>,
    pub crate_name: String,
}

impl std::fmt::Display for VersionInfo {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.commit_hash.is_some() {
            write!(
                f,
                "{} {}.{}.{} ({} {})",
                self.crate_name,
                self.major,
                self.minor,
                self.patch,
                self.commit_hash.clone().unwrap_or_default().trim(),
                self.commit_date.clone().unwrap_or_default().trim(),
            )?;
        } else {
            write!(f, "{} {}.{}.{}", self.crate_name, self.major, self.minor, self.patch)?;
        }

        Ok(())
    }
}

impl std::fmt::Debug for VersionInfo {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "VersionInfo {{ crate_name: \"{}\", major: {}, minor: {}, patch: {}",
            self.crate_name, self.major, self.minor, self.patch,
        )?;
        if self.commit_hash.is_some() {
            write!(
                f,
                ", commit_hash: \"{}\", commit_date: \"{}\" }}",
                self.commit_hash.clone().unwrap_or_default().trim(),
                self.commit_date.clone().unwrap_or_default().trim()
            )?;
        } else {
            write!(f, " }}")?;
        }

        Ok(())
    }
}

pub fn get_channel() -> Option<String> {
    if let Ok(channel) = env::var("CFG_RELEASE_CHANNEL") {
        Some(channel)
    } else {
        // we could ask ${RUSTC} -Vv and do some parsing and find out
        Some(String::from("nightly"))
    }
}

pub fn get_commit_hash() -> Option<String> {
    std::process::Command::new("git")
        .args(&["rev-parse", "--short", "HEAD"])
        .output()
        .ok()
        .and_then(|r| String::from_utf8(r.stdout).ok())
}

pub fn get_commit_date() -> Option<String> {
    std::process::Command::new("git")
        .args(&["log", "-1", "--date=short", "--pretty=format:%cd"])
        .output()
        .ok()
        .and_then(|r| String::from_utf8(r.stdout).ok())
}

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

    #[test]
    fn test_struct_local() {
        let vi = get_version_info!();
        assert_eq!(vi.major, 0);
        assert_eq!(vi.minor, 1);
        assert_eq!(vi.patch, 0);
        assert_eq!(vi.crate_name, "rustc_tools_util");
        // hard to make positive tests for these since they will always change
        assert!(vi.commit_hash.is_none());
        assert!(vi.commit_date.is_none());
    }

    #[test]
    fn test_display_local() {
        let vi = get_version_info!();
        assert_eq!(vi.to_string(), "rustc_tools_util 0.1.0");
    }

    #[test]
    fn test_debug_local() {
        let vi = get_version_info!();
        let s = format!("{:?}", vi);
        assert_eq!(
            s,
            "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 1, patch: 0 }"
        );
    }

}
<commit_msg>rustc_tools_util: remove test and tool_lints features, both are actually unused.<commit_after>use std::env;

#[macro_export]
macro_rules! get_version_info {
    () => {{
        let major = env!("CARGO_PKG_VERSION_MAJOR").parse::<u8>().unwrap();
        let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap();
        let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u16>().unwrap();
        let crate_name = String::from(env!("CARGO_PKG_NAME"));

        let host_compiler = $crate::get_channel();
        let commit_hash = option_env!("GIT_HASH").map(|s| s.to_string());
        let commit_date = option_env!("COMMIT_DATE").map(|s| s.to_string());

        VersionInfo {
            major,
            minor,
            patch,
            host_compiler,
            commit_hash,
            commit_date,
            crate_name,
        }
    }};
}

// some code taken and adapted from RLS and cargo
pub struct VersionInfo {
    pub major: u8,
    pub minor: u8,
    pub patch: u16,
    pub host_compiler: Option<String>,
    pub commit_hash: Option<String>,
    pub commit_date: Option<String>,
    pub crate_name: String,
}

impl std::fmt::Display for VersionInfo {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        if self.commit_hash.is_some() {
            write!(
                f,
                "{} {}.{}.{} ({} {})",
                self.crate_name,
                self.major,
                self.minor,
                self.patch,
                self.commit_hash.clone().unwrap_or_default().trim(),
                self.commit_date.clone().unwrap_or_default().trim(),
            )?;
        } else {
            write!(f, "{} {}.{}.{}", self.crate_name, self.major, self.minor, self.patch)?;
        }

        Ok(())
    }
}

impl std::fmt::Debug for VersionInfo {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "VersionInfo {{ crate_name: \"{}\", major: {}, minor: {}, patch: {}",
            self.crate_name, self.major, self.minor, self.patch,
        )?;
        if self.commit_hash.is_some() {
            write!(
                f,
                ", commit_hash: \"{}\", commit_date: \"{}\" }}",
                self.commit_hash.clone().unwrap_or_default().trim(),
                self.commit_date.clone().unwrap_or_default().trim()
            )?;
        } else {
            write!(f, " }}")?;
        }

        Ok(())
    }
}

pub fn get_channel() -> Option<String> {
    if let Ok(channel) = env::var("CFG_RELEASE_CHANNEL") {
        Some(channel)
    } else {
        // we could ask ${RUSTC} -Vv and do some parsing and find out
        Some(String::from("nightly"))
    }
}

pub fn get_commit_hash() -> Option<String> {
    std::process::Command::new("git")
        .args(&["rev-parse", "--short", "HEAD"])
        .output()
        .ok()
        .and_then(|r| String::from_utf8(r.stdout).ok())
}

pub fn get_commit_date() -> Option<String> {
    std::process::Command::new("git")
        .args(&["log", "-1", "--date=short", "--pretty=format:%cd"])
        .output()
        .ok()
        .and_then(|r| String::from_utf8(r.stdout).ok())
}

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

    #[test]
    fn test_struct_local() {
        let vi = get_version_info!();
        assert_eq!(vi.major, 0);
        assert_eq!(vi.minor, 1);
        assert_eq!(vi.patch, 0);
        assert_eq!(vi.crate_name, "rustc_tools_util");
        // hard to make positive tests for these since they will always change
        assert!(vi.commit_hash.is_none());
        assert!(vi.commit_date.is_none());
    }

    #[test]
    fn test_display_local() {
        let vi = get_version_info!();
        assert_eq!(vi.to_string(), "rustc_tools_util 0.1.0");
    }

    #[test]
    fn test_debug_local() {
        let vi = get_version_info!();
        let s = format!("{:?}", vi);
        assert_eq!(
            s,
            "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 1, patch: 0 }"
        );
    }

}
<|endoftext|>


<commit_before>/// Minimal example for getting sdl2 and wgpu working together with raw-window-handle.
///
/// TODO: update wgpu and this example after https://github.com/gfx-rs/wgpu/pull/462 ships

extern crate glsl_to_spirv;
extern crate libc;
#[cfg(target_os = "macos")]
extern crate objc;
extern crate raw_window_handle;
extern crate sdl2;
extern crate wgpu;

use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
use raw_window_handle::macos::MacOSHandle;

use sdl2::event::{Event, WindowEvent};
use sdl2::keyboard::Keycode;
use sdl2::video::Window;

/// sdl2 implements raw-window-handle correctly, but wgpu does not for macOS
/// wgpu wrongly expects an NSView to be provided by raw-window-handle, so we have to do a little more work
struct WindowWrapper<'a>(pub &'a Window);

unsafe impl<'a> HasRawWindowHandle for WindowWrapper<'a> {
    #[cfg(not(target_os = "macos"))]
    /// all non-mac platforms work correctly, so return the handle directly
    fn raw_window_handle(&self) -> RawWindowHandle {
        self.0.raw_window_handle()
    }

    #[cfg(target_os = "macos")]
    /// do some work on macOS to get the root NSView for the NSWindow returned by sdl2
    fn raw_window_handle(&self) -> RawWindowHandle {
        use objc::{msg_send, sel, sel_impl};
        use objc::runtime::Object;
        let handle = self.0.raw_window_handle();
        match handle {
            RawWindowHandle::MacOS(macos_handle) => {
                RawWindowHandle::MacOS(MacOSHandle {
                    ns_window: macos_handle.ns_window,
                    ns_view: unsafe { msg_send![macos_handle.ns_window as *mut Object, contentView] },
                    ..MacOSHandle::empty()
                })
            }
            _ => unreachable!()
        }
    }
}

fn load_glsl(code: &str, ty: glsl_to_spirv::ShaderType) -> Result<Vec<u32>, String> {
    let spirv = glsl_to_spirv::compile(&code, ty)?;
    let result = wgpu::read_spirv(spirv).map_err(|e| e.to_string())?;
    Ok(result)
}

fn main() -> Result<(), String> {
    let sdl_context = sdl2::init()?;
    let video_subsystem = sdl_context.video()?;
    let window = video_subsystem
        .window("Raw Window Handle Example", 800, 600)
        .position_centered()
        .resizable()
        .build()
        .map_err(|e| e.to_string())?;
    let (width, height) = window.size();

    let adapter_opt = wgpu::Adapter::request(&wgpu::RequestAdapterOptions {
        power_preference: wgpu::PowerPreference::Default,
        backends: wgpu::BackendBit::PRIMARY,
    });
    let adapter = match adapter_opt {
        Some(a) => a,
        None => return Err(String::from("No adapter found")),
    };

    let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
        extensions: wgpu::Extensions {
            anisotropic_filtering: false,
        },
        limits: wgpu::Limits::default(),
    });

    let vs = include_str!("shader.vert");
    let vs_spirv = &load_glsl(vs, glsl_to_spirv::ShaderType::Vertex)?;
    let vs_module = device.create_shader_module(vs_spirv);

    let fs = include_str!("shader.frag");
    let fs_spirv = &load_glsl(fs, glsl_to_spirv::ShaderType::Fragment)?;
    let fs_module = device.create_shader_module(fs_spirv);

    let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { bindings: &[] });
    let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
        layout: &bind_group_layout,
        bindings: &[],
    });
    let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
        bind_group_layouts: &[&bind_group_layout],
    });

    let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
        layout: &pipeline_layout,
        vertex_stage: wgpu::ProgrammableStageDescriptor {
            module: &vs_module,
            entry_point: "main",
        },
        fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
            module: &fs_module,
            entry_point: "main",
        }),
        rasterization_state: Some(wgpu::RasterizationStateDescriptor {
            front_face: wgpu::FrontFace::Ccw,
            cull_mode: wgpu::CullMode::None,
            depth_bias: 0,
            depth_bias_slope_scale: 0.0,
            depth_bias_clamp: 0.0,
        }),
        primitive_topology: wgpu::PrimitiveTopology::TriangleList,
        color_states: &[wgpu::ColorStateDescriptor {
            format: wgpu::TextureFormat::Bgra8UnormSrgb,
            color_blend: wgpu::BlendDescriptor::REPLACE,
            alpha_blend: wgpu::BlendDescriptor::REPLACE,
            write_mask: wgpu::ColorWrite::ALL,
        }],
        depth_stencil_state: None,
        index_format: wgpu::IndexFormat::Uint16,
        vertex_buffers: &[],
        sample_count: 1,
        sample_mask: !0,
        alpha_to_coverage_enabled: false,
    });

    // use the WindowWrapper to make sure wgpu will work on macOS
    let surface = wgpu::Surface::create(&WindowWrapper(&window));

    let mut sc_desc = wgpu::SwapChainDescriptor {
        usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
        format: wgpu::TextureFormat::Bgra8UnormSrgb,
        width,
        height,
        present_mode: wgpu::PresentMode::Vsync,
    };

    let mut swap_chain = device.create_swap_chain(&surface, &sc_desc);

    let mut event_pump = sdl_context.event_pump()?;
    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Window {
                    win_event: WindowEvent::Resized(width, height),
                    ..
                } => {
                    sc_desc.width = width as u32;
                    sc_desc.height = height as u32;
                    swap_chain = device.create_swap_chain(&surface, &sc_desc);
                }
                Event::Quit { .. }
                | Event::KeyDown {
                    keycode: Some(Keycode::Escape),
                    ..
                } => {
                    break 'running;
                }
                _ => {}
            }
        }

        let frame = swap_chain.get_next_texture();
        let mut encoder =
            device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
        {
            let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
                color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
                    attachment: &frame.view,
                    resolve_target: None,
                    load_op: wgpu::LoadOp::Clear,
                    store_op: wgpu::StoreOp::Store,
                    clear_color: wgpu::Color::GREEN,
                }],
                depth_stencil_attachment: None,
            });
            rpass.set_pipeline(&render_pipeline);
            rpass.set_bind_group(0, &bind_group, &[]);
            rpass.draw(0 .. 3, 0 .. 1);
        }

        queue.submit(&[encoder.finish()]);
    }

    Ok(())
}<commit_msg>Never trust IDE auto-imports<commit_after>/// Minimal example for getting sdl2 and wgpu working together with raw-window-handle.
///
/// TODO: update wgpu and this example after https://github.com/gfx-rs/wgpu/pull/462 ships

extern crate glsl_to_spirv;
extern crate libc;
#[cfg(target_os = "macos")]
extern crate objc;
extern crate raw_window_handle;
extern crate sdl2;
extern crate wgpu;

use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};

use sdl2::event::{Event, WindowEvent};
use sdl2::keyboard::Keycode;
use sdl2::video::Window;

/// sdl2 implements raw-window-handle correctly, but wgpu does not for macOS
/// wgpu wrongly expects an NSView to be provided by raw-window-handle, so we have to do a little more work
struct WindowWrapper<'a>(pub &'a Window);

unsafe impl<'a> HasRawWindowHandle for WindowWrapper<'a> {
    #[cfg(not(target_os = "macos"))]
    /// all non-mac platforms work correctly, so return the handle directly
    fn raw_window_handle(&self) -> RawWindowHandle {
        self.0.raw_window_handle()
    }

    #[cfg(target_os = "macos")]
    /// do some work on macOS to get the root NSView for the NSWindow returned by sdl2
    fn raw_window_handle(&self) -> RawWindowHandle {
        use objc::{msg_send, sel, sel_impl};
        use objc::runtime::Object;
        use raw_window_handle::macos::MacOSHandle;
        let handle = self.0.raw_window_handle();
        match handle {
            RawWindowHandle::MacOS(macos_handle) => {
                RawWindowHandle::MacOS(MacOSHandle {
                    ns_window: macos_handle.ns_window,
                    ns_view: unsafe { msg_send![macos_handle.ns_window as *mut Object, contentView] },
                    ..MacOSHandle::empty()
                })
            }
            _ => unreachable!()
        }
    }
}

fn load_glsl(code: &str, ty: glsl_to_spirv::ShaderType) -> Result<Vec<u32>, String> {
    let spirv = glsl_to_spirv::compile(&code, ty)?;
    let result = wgpu::read_spirv(spirv).map_err(|e| e.to_string())?;
    Ok(result)
}

fn main() -> Result<(), String> {
    let sdl_context = sdl2::init()?;
    let video_subsystem = sdl_context.video()?;
    let window = video_subsystem
        .window("Raw Window Handle Example", 800, 600)
        .position_centered()
        .resizable()
        .build()
        .map_err(|e| e.to_string())?;
    let (width, height) = window.size();

    let adapter_opt = wgpu::Adapter::request(&wgpu::RequestAdapterOptions {
        power_preference: wgpu::PowerPreference::Default,
        backends: wgpu::BackendBit::PRIMARY,
    });
    let adapter = match adapter_opt {
        Some(a) => a,
        None => return Err(String::from("No adapter found")),
    };

    let (device, mut queue) = adapter.request_device(&wgpu::DeviceDescriptor {
        extensions: wgpu::Extensions {
            anisotropic_filtering: false,
        },
        limits: wgpu::Limits::default(),
    });

    let vs = include_str!("shader.vert");
    let vs_spirv = &load_glsl(vs, glsl_to_spirv::ShaderType::Vertex)?;
    let vs_module = device.create_shader_module(vs_spirv);

    let fs = include_str!("shader.frag");
    let fs_spirv = &load_glsl(fs, glsl_to_spirv::ShaderType::Fragment)?;
    let fs_module = device.create_shader_module(fs_spirv);

    let bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { bindings: &[] });
    let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
        layout: &bind_group_layout,
        bindings: &[],
    });
    let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
        bind_group_layouts: &[&bind_group_layout],
    });

    let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
        layout: &pipeline_layout,
        vertex_stage: wgpu::ProgrammableStageDescriptor {
            module: &vs_module,
            entry_point: "main",
        },
        fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
            module: &fs_module,
            entry_point: "main",
        }),
        rasterization_state: Some(wgpu::RasterizationStateDescriptor {
            front_face: wgpu::FrontFace::Ccw,
            cull_mode: wgpu::CullMode::None,
            depth_bias: 0,
            depth_bias_slope_scale: 0.0,
            depth_bias_clamp: 0.0,
        }),
        primitive_topology: wgpu::PrimitiveTopology::TriangleList,
        color_states: &[wgpu::ColorStateDescriptor {
            format: wgpu::TextureFormat::Bgra8UnormSrgb,
            color_blend: wgpu::BlendDescriptor::REPLACE,
            alpha_blend: wgpu::BlendDescriptor::REPLACE,
            write_mask: wgpu::ColorWrite::ALL,
        }],
        depth_stencil_state: None,
        index_format: wgpu::IndexFormat::Uint16,
        vertex_buffers: &[],
        sample_count: 1,
        sample_mask: !0,
        alpha_to_coverage_enabled: false,
    });

    // use the WindowWrapper to make sure wgpu will work on macOS
    let surface = wgpu::Surface::create(&WindowWrapper(&window));

    let mut sc_desc = wgpu::SwapChainDescriptor {
        usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
        format: wgpu::TextureFormat::Bgra8UnormSrgb,
        width,
        height,
        present_mode: wgpu::PresentMode::Vsync,
    };

    let mut swap_chain = device.create_swap_chain(&surface, &sc_desc);

    let mut event_pump = sdl_context.event_pump()?;
    'running: loop {
        for event in event_pump.poll_iter() {
            match event {
                Event::Window {
                    win_event: WindowEvent::Resized(width, height),
                    ..
                } => {
                    sc_desc.width = width as u32;
                    sc_desc.height = height as u32;
                    swap_chain = device.create_swap_chain(&surface, &sc_desc);
                }
                Event::Quit { .. }
                | Event::KeyDown {
                    keycode: Some(Keycode::Escape),
                    ..
                } => {
                    break 'running;
                }
                _ => {}
            }
        }

        let frame = swap_chain.get_next_texture();
        let mut encoder =
            device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
        {
            let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
                color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
                    attachment: &frame.view,
                    resolve_target: None,
                    load_op: wgpu::LoadOp::Clear,
                    store_op: wgpu::StoreOp::Store,
                    clear_color: wgpu::Color::GREEN,
                }],
                depth_stencil_attachment: None,
            });
            rpass.set_pipeline(&render_pipeline);
            rpass.set_bind_group(0, &bind_group, &[]);
            rpass.draw(0 .. 3, 0 .. 1);
        }

        queue.submit(&[encoder.finish()]);
    }

    Ok(())
}
<|endoftext|>


<commit_before>#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate image;
extern crate bytemuck;

use std::io::Cursor;
use image::ImageResult;
use image::codecs::openexr::*;
use image::Rgba32FImage;
use image::error::LimitError;
use image::ImageError;
use image::ImageBuffer;
use image::Rgb32FImage;
use std::io::Seek;
use std::io::BufRead;

// "just dont panic"
fn roundtrip(bytes: &[u8]) -> ImageResult<()> {
    use std::io::Write;

    /// Read the file from the specified path into an `Rgba32FImage`.
    // TODO this method should probably already exist in the main image crate
    fn read_as_rgba_image(read: impl BufRead + Seek) -> ImageResult<Rgb32FImage> {

        // TODO this method should probably already exist in the main image crate
        fn decoder_to_vec<'a, T>(decoder: impl ImageDecoder<'a>) -> ImageResult<Vec<T>>
            where T: crate::traits::Primitive + bytemuck::Pod,
        {
            let mut buf = vec![num_traits::Zero::zero(); usize::try_from(decoder.total_bytes()).unwrap() / std::mem::size_of::<T>()];
            decoder.read_image(bytemuck::cast_slice_mut(buf.as_mut_slice()))?;
            Ok(buf)
        }

        let decoder = OpenExrDecoder::with_alpha_preference(read, Some(true))?;
        let (width, height) = decoder.dimensions();
        let buffer: Vec<f32> = decoder_to_vec(decoder)?;

        ImageBuffer::from_raw(width, height, buffer)

            // this should be the only reason for the "from raw" call to fail,
            // even though such a large allocation would probably cause an error much earlier
            .ok_or_else(|| ImageError::Limits(LimitError::from_kind(LimitErrorKind::InsufficientMemory)))
    }

    /// Write an `Rgba32FImage`.
    /// Assumes the writer is buffered. In most cases,
    /// you should wrap your writer in a `BufWriter` for best performance.
    // TODO this method should probably already exist in the main image crate
    fn write_rgba_image(write: impl Write/* + Seek*/, image: &Rgba32FImage) -> ImageResult<()> {
        OpenEXREncoder::new(write).write_image(
            bytemuck::cast_slice(image.as_raw().as_slice()),
            image.width(), image.height(),
            ColorType::Rgba32F
        )
    }

    let decoded_image = read_as_rgba_image(Cursor::new(bytes))?;

    let mut bytes = Vec::with_capacity(bytes.len() + 20);
    write_rgba_image(Cursor::new(&mut bytes), &decoded_image)?;
    let redecoded_image = read_as_rgba_image(Cursor::new(bytes))?;

    // if both images are valid, assert read/write consistency
    assert_eq!(decoded_image, redecoded_image, "image was valid but was not reproducible");
    Ok(())
}

fuzz_target!(|data: &[u8]| {
    let _img = roundtrip(data); // fixme not optimized away?
});
<commit_msg>simplify helper methodsfor external fuzzer test script<commit_after>#![no_main]
#[macro_use] extern crate libfuzzer_sys;
extern crate image;
extern crate bytemuck;

use std::io::Cursor;
use image::ImageResult;
use image::codecs::openexr::*;
use image::Rgba32FImage;
use image::error::LimitError;
use image::ImageError;
use image::ImageBuffer;
use image::Rgb32FImage;
use std::io::Seek;
use std::io::BufRead;

// "just dont panic"
fn roundtrip(bytes: &[u8]) -> ImageResult<()> {
    use std::io::Write;

    /// Read the file from the specified path into an `Rgba32FImage`.
    // TODO this method should probably already exist in the main image crate
    fn read_as_rgba_byte_image(read: impl BufRead + Seek) -> ImageResult<(usize,usize,Vec<u8>)> {
        let decoder = OpenExrDecoder::with_alpha_preference(read, Some(true))?;
        let (width, height) = decoder.dimensions();

        let mut buffer = vec![0; usize::try_from(decoder.total_bytes()).unwrap()];
        decoder.read_image(bytemuck::cast_slice_mut(buf.as_mut_slice()))?;

        Ok((width, height, buffer))
    }

    /// Write an `Rgba32FImage`.
    /// Assumes the writer is buffered. In most cases,
    /// you should wrap your writer in a `BufWriter` for best performance.
    // TODO this method should probably already exist in the main image crate
    fn write_rgba_image(write: impl Write/* + Seek*/, image: &Rgba32FImage) -> ImageResult<()> {
        OpenExrEncoder::new(write).write_image(
            bytemuck::cast_slice(image.as_raw().as_slice()),
            image.width(), image.height(),
            ColorType::Rgba32F
        )
    }

    let decoded_image = read_as_rgba_byte_image(Cursor::new(bytes))?;

    let mut bytes = Vec::with_capacity(bytes.len() + 20);
    write_rgba_image(Cursor::new(&mut bytes), &decoded_image)?;

    let redecoded_image = read_as_rgba_byte_image(Cursor::new(bytes))?;

    // if both images are valid, assert read/write consistency
    assert_eq!(decoded_image, redecoded_image, "image was valid but was not reproducible");
    Ok(())
}

fuzz_target!(|data: &[u8]| {
    let _img = roundtrip(data); // fixme not optimized away?
});
<|endoftext|>


<commit_before>use ra_syntax::{
    ast::{self, AstNode},
    T,
};

use crate::{utils::invert_boolean_expression, Assist, AssistCtx, AssistId};

// Assist: invert_if
//
// Apply invert_if
// This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}`
// This also works with `!=`. This assist can only be applied with the cursor
// on `if`.
//
// ```
// fn main() {
//     if<|> !y { A } else { B }
// }
// ```
// ->
// ```
// fn main() {
//     if y { B } else { A }
// }
// ```

pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> {
    let if_keyword = ctx.find_token_at_offset(T![if])?;
    let expr = ast::IfExpr::cast(if_keyword.parent())?;
    let if_range = if_keyword.text_range();
    let cursor_in_range = ctx.frange.range.is_subrange(&if_range);
    if !cursor_in_range {
        return None;
    }

    let cond = expr.condition()?.expr()?;
    let then_node = expr.then_branch()?.syntax().clone();

    if let ast::ElseBranch::Block(else_block) = expr.else_branch()? {
        let cond_range = cond.syntax().text_range();
        let flip_cond = invert_boolean_expression(cond);
        let else_node = else_block.syntax();
        let else_range = else_node.text_range();
        let then_range = then_node.text_range();
        return ctx.add_assist(AssistId("invert_if"), "Invert if", |edit| {
            edit.target(if_range);
            edit.replace(cond_range, flip_cond.syntax().text());
            edit.replace(else_range, then_node.text());
            edit.replace(then_range, else_node.text());
        });
    }

    None
}

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

    use crate::helpers::{check_assist, check_assist_not_applicable};

    #[test]
    fn invert_if_remove_inequality() {
        check_assist(
            invert_if,
            "fn f() { i<|>f x != 3 { 1 } else { 3 + 2 } }",
            "fn f() { i<|>f x == 3 { 3 + 2 } else { 1 } }",
        )
    }

    #[test]
    fn invert_if_remove_not() {
        check_assist(
            invert_if,
            "fn f() { <|>if !cond { 3 * 2 } else { 1 } }",
            "fn f() { <|>if cond { 1 } else { 3 * 2 } }",
        )
    }

    #[test]
    fn invert_if_general_case() {
        check_assist(
            invert_if,
            "fn f() { i<|>f cond { 3 * 2 } else { 1 } }",
            "fn f() { i<|>f !cond { 1 } else { 3 * 2 } }",
        )
    }

    #[test]
    fn invert_if_doesnt_apply_with_cursor_not_on_if() {
        check_assist_not_applicable(invert_if, "fn f() { if !<|>cond { 3 * 2 } else { 1 } }")
    }
}
<commit_msg>disable invert if assist for if-let to fix #3281<commit_after>use ra_syntax::{
    ast::{self, AstNode},
    T,
};

use crate::{utils::invert_boolean_expression, Assist, AssistCtx, AssistId};

// Assist: invert_if
//
// Apply invert_if
// This transforms if expressions of the form `if !x {A} else {B}` into `if x {B} else {A}`
// This also works with `!=`. This assist can only be applied with the cursor
// on `if`.
//
// ```
// fn main() {
//     if<|> !y { A } else { B }
// }
// ```
// ->
// ```
// fn main() {
//     if y { B } else { A }
// }
// ```

pub(crate) fn invert_if(ctx: AssistCtx) -> Option<Assist> {
    let if_keyword = ctx.find_token_at_offset(T![if])?;
    let expr = ast::IfExpr::cast(if_keyword.parent())?;
    let if_range = if_keyword.text_range();
    let cursor_in_range = ctx.frange.range.is_subrange(&if_range);
    if !cursor_in_range {
        return None;
    }

    // This assist should not apply for if-let.
    if expr.condition()?.pat().is_some() {
        return None;
    }

    let cond = expr.condition()?.expr()?;
    let then_node = expr.then_branch()?.syntax().clone();

    if let ast::ElseBranch::Block(else_block) = expr.else_branch()? {
        let cond_range = cond.syntax().text_range();
        let flip_cond = invert_boolean_expression(cond);
        let else_node = else_block.syntax();
        let else_range = else_node.text_range();
        let then_range = then_node.text_range();
        return ctx.add_assist(AssistId("invert_if"), "Invert if", |edit| {
            edit.target(if_range);
            edit.replace(cond_range, flip_cond.syntax().text());
            edit.replace(else_range, then_node.text());
            edit.replace(then_range, else_node.text());
        });
    }

    None
}

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

    use crate::helpers::{check_assist, check_assist_not_applicable};

    #[test]
    fn invert_if_remove_inequality() {
        check_assist(
            invert_if,
            "fn f() { i<|>f x != 3 { 1 } else { 3 + 2 } }",
            "fn f() { i<|>f x == 3 { 3 + 2 } else { 1 } }",
        )
    }

    #[test]
    fn invert_if_remove_not() {
        check_assist(
            invert_if,
            "fn f() { <|>if !cond { 3 * 2 } else { 1 } }",
            "fn f() { <|>if cond { 1 } else { 3 * 2 } }",
        )
    }

    #[test]
    fn invert_if_general_case() {
        check_assist(
            invert_if,
            "fn f() { i<|>f cond { 3 * 2 } else { 1 } }",
            "fn f() { i<|>f !cond { 1 } else { 3 * 2 } }",
        )
    }

    #[test]
    fn invert_if_doesnt_apply_with_cursor_not_on_if() {
        check_assist_not_applicable(invert_if, "fn f() { if !<|>cond { 3 * 2 } else { 1 } }")
    }

    #[test]
    fn invert_if_doesnt_apply_with_if_let() {
        check_assist_not_applicable(
            invert_if,
            "fn f() { i<|>f let Some(_) = Some(1) { 1 } else { 0 } }",
        )
    }
}
<|endoftext|>


<commit_before>use desync::scheduler::*;

use super::timeout::*;

use std::thread;
use std::time::*;
use std::sync::*;
use std::sync::mpsc::*;

#[test]
fn suspend_queue() {
    for _x in 0..1000 {
        timeout(|| {
            use futures::executor;

            let queue           = queue();
            let scheduler       = scheduler();
            let (tx, rx)        = channel();

            let pos             = Arc::new(Mutex::new(0));

            // Send the current position when the async methods run
            let pos2            = pos.clone();
            let tx2             = tx.clone();
            desync(&queue, move || { tx2.send(*pos2.lock().unwrap()).unwrap(); });

            // Suspend after the first send
            let suspended   = scheduler.suspend(&queue);
            let resumer     = executor::block_on(suspended).unwrap();

            // Send again
            let pos2 = pos.clone();
            let tx2 = tx.clone();
            desync(&queue, move || { tx2.send(*pos2.lock().unwrap()).unwrap(); });

            // Wait for the first queue to send
            assert!(rx.recv().unwrap() == 0);

            thread::yield_now();

            // Update the position and resume
            *pos.lock().unwrap() = 1;
            resumer.resume();

            // The resumption will send us a value when it occurs
            assert!(rx.recv().unwrap() == 1);
        }, 500);
    }
}

#[test]
fn suspend_queue_with_local_drain() {
    timeout(|| {
        use futures::executor;

        // Want a scheduler with 0 threads to force a 'drain on current thread' situation
        let scheduler = Arc::new(Scheduler::new());
        scheduler.set_max_threads(0);
        scheduler.despawn_threads_if_overloaded();

        let queue = scheduler.create_job_queue();

        // Job so there's something to drain
        scheduler.desync(&queue, ||{});

        // Start suspending the queue
        let suspended   = scheduler.suspend(&queue);
        let resumer     = executor::block_on(suspended).unwrap();

        // Resume after a delay
        let resume_scheduler    = scheduler.clone();
        thread::spawn(move || {
            // Wait 100ms with the queue suspended
            thread::sleep(Duration::from_millis(100));

            // Resume it
            resumer.resume();

            // The scheduler will need to be able to finish the task on a thread
            resume_scheduler.set_max_threads(1);
        });

        // Should be able to retrieve a value once the queue resumes
        assert!(scheduler.sync(&queue, || 42) == 42);
    }, 500);
}

#[test]
fn safe_to_drop_suspended_queue() {
    timeout(|| {
        use futures::executor;

        let queue       = queue();
        let scheduler   = scheduler();

        let pos         = Arc::new(Mutex::new(0));

        // Increment the position, suspend the queue, increment it again
        let pos2        = pos.clone();
        desync(&queue, move || { let mut pos2 = pos2.lock().unwrap(); *pos2 += 1 });
        let suspended   = scheduler.suspend(&queue);
        let pos2        = pos.clone();
        desync(&queue, move || { let mut pos2 = pos2.lock().unwrap(); *pos2 += 1 });

        // Wait for long enough for these events to take place and check the queue
        while *pos.lock().unwrap() == 0 {
            thread::sleep(Duration::from_millis(100));
        }
        assert!(*pos.lock().unwrap() == 1);

        // Make sure the queue is actually suspended
        executor::block_on(suspended).unwrap();
    }, 500);
}
<commit_msg>Rename test so it's easier to run independently<commit_after>use desync::scheduler::*;

use super::timeout::*;

use std::thread;
use std::time::*;
use std::sync::*;
use std::sync::mpsc::*;

#[test]
fn suspend_queue_with_background_thread() {
    for _x in 0..1000 {
        timeout(|| {
            use futures::executor;

            let queue           = queue();
            let scheduler       = scheduler();
            let (tx, rx)        = channel();

            let pos             = Arc::new(Mutex::new(0));

            // Send the current position when the async methods run
            let pos2            = pos.clone();
            let tx2             = tx.clone();
            desync(&queue, move || { tx2.send(*pos2.lock().unwrap()).unwrap(); });

            // Suspend after the first send
            let suspended   = scheduler.suspend(&queue);
            let resumer     = executor::block_on(suspended).unwrap();

            // Send again
            let pos2 = pos.clone();
            let tx2 = tx.clone();
            desync(&queue, move || { tx2.send(*pos2.lock().unwrap()).unwrap(); });

            // Wait for the first queue to send
            assert!(rx.recv().unwrap() == 0);

            thread::yield_now();

            // Update the position and resume
            *pos.lock().unwrap() = 1;
            resumer.resume();

            // The resumption will send us a value when it occurs
            assert!(rx.recv().unwrap() == 1);
        }, 500);
    }
}

#[test]
fn suspend_queue_with_local_drain() {
    timeout(|| {
        use futures::executor;

        // Want a scheduler with 0 threads to force a 'drain on current thread' situation
        let scheduler = Arc::new(Scheduler::new());
        scheduler.set_max_threads(0);
        scheduler.despawn_threads_if_overloaded();

        let queue = scheduler.create_job_queue();

        // Job so there's something to drain
        scheduler.desync(&queue, ||{});

        // Start suspending the queue
        let suspended   = scheduler.suspend(&queue);
        let resumer     = executor::block_on(suspended).unwrap();

        // Resume after a delay
        let resume_scheduler    = scheduler.clone();
        thread::spawn(move || {
            // Wait 100ms with the queue suspended
            thread::sleep(Duration::from_millis(100));

            // Resume it
            resumer.resume();

            // The scheduler will need to be able to finish the task on a thread
            resume_scheduler.set_max_threads(1);
        });

        // Should be able to retrieve a value once the queue resumes
        assert!(scheduler.sync(&queue, || 42) == 42);
    }, 500);
}

#[test]
fn safe_to_drop_suspended_queue() {
    timeout(|| {
        use futures::executor;

        let queue       = queue();
        let scheduler   = scheduler();

        let pos         = Arc::new(Mutex::new(0));

        // Increment the position, suspend the queue, increment it again
        let pos2        = pos.clone();
        desync(&queue, move || { let mut pos2 = pos2.lock().unwrap(); *pos2 += 1 });
        let suspended   = scheduler.suspend(&queue);
        let pos2        = pos.clone();
        desync(&queue, move || { let mut pos2 = pos2.lock().unwrap(); *pos2 += 1 });

        // Wait for long enough for these events to take place and check the queue
        while *pos.lock().unwrap() == 0 {
            thread::sleep(Duration::from_millis(100));
        }
        assert!(*pos.lock().unwrap() == 1);

        // Make sure the queue is actually suspended
        executor::block_on(suspended).unwrap();
    }, 500);
}
<|endoftext|>