<commit_before>// Copyright (c) 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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.

#![feature(custom_attribute, plugin)]
#![plugin(pnet_macros)]

extern crate pnet;

#[packet]
pub struct PacketWithPayload {
    banana: u8,
    #[length_fn = "length_fn"]
    var_length: Vec<u8>, //~ ERROR: length_fn must be of type &PacketWithPayloadHeader -> usize
    #[payload]
    payload: Vec<u8>
}

fn length_fn(_: ()) -> usize {
    unimplemented!()
}

fn main() {}
<commit_msg>Ignore `variable_length_fields2` test<commit_after>// Copyright (c) 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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.

// ignore-test
// ignored as this error message isn't implemented yet

#![feature(custom_attribute, plugin)]
#![plugin(pnet_macros)]

extern crate pnet;

#[packet]
pub struct PacketWithPayload {
    banana: u8,
    #[length_fn = "length_fn"]
    var_length: Vec<u8>, //~ ERROR: length_fn must be of type &PacketWithPayloadHeader -> usize
    #[payload]
    payload: Vec<u8>
}

fn length_fn(_: ()) -> usize {
    unimplemented!()
}

fn main() {}
<|endoftext|>


<commit_before>// just proving that that array update works

// https://doc.rust-lang.org/std/slice/
// http://rustbyexample.com/array.html
fn main() {
    // slicing a Vec
    let vec = vec![1, 2, 3];
    let int_slice = &vec[..];
    // coercing an array to a slice
    let str_slice: &[&str] = &["one", "two", "three"];

    let x = &mut [1, 2, 3];
    println!("x: {:?}", x);
    x[1] = 7;
    assert_eq!(x, &[1, 7, 3]);

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

    let mut arr1 = [1, 2];
    println!("arr1: {:?}", arr1);
    arr1[1] = 1;
    println!("arr1: {:?}", arr1);

    let mut vec1 = [1, 2];
    println!("vec1: {:?}", vec1);
    vec1[1] = 1;
    println!("vec1: {:?}", vec1);

    //let mut vec2 = vec![|&i| vec![0; i]; 7];
    let mut vec2 = vec![vec![0; 7]; 7];
}
<commit_msg>use case for ragged array; caveat - unstable crate core.<commit_after>// just proving that that array update works

// https://doc.rust-lang.org/std/slice/
// http://rustbyexample.com/array.html
#![feature(core)]
extern crate core;
use core::iter::FromIterator;

fn main() {
    // slicing a Vec
    let vec = vec![1, 2, 3];
    let int_slice = &vec[..];
    // coercing an array to a slice
    let str_slice: &[&str] = &["one", "two", "three"];

    let x = &mut [1, 2, 3];
    println!("x: {:?}", x);
    x[1] = 7;
    assert_eq!(x, &[1, 7, 3]);

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

    let mut arr1 = [1, 2];
    println!("arr1: {:?}", arr1);
    arr1[1] = 1;
    println!("arr1: {:?}", arr1);

    let mut vec1 = [1, 2];
    println!("vec1: {:?}", vec1);
    vec1[1] = 1;
    println!("vec1: {:?}", vec1);

    //let mut vec2 = vec![|&i| vec![0; i]; 7];
    let mut vec2 = vec![vec![0; 7]; 7];

    // how to create a ragged array
    // warning: crate core hasn't been stabilized yet
    // `#![feature(core)]`
    // `extern crate core;`
    // `use core::iter::FromIterator;`
    // is necessary
    let mut v = Vec::from_iter ((0..10) .map (|idx| vec![idx; idx * 2]));
    println!("v.len(): {} v[1].len(): {}", v.len(), v[1].len());
    println!("v: {:?}", v);
    // prints
    // v: [[], [1, 1], [2, 2, 2, 2], [3, 3, 3, 3, 3, 3], [4, 4, 4, 4, 4, 4, 4, 4], [5, 5, 5, 5, 5, 5, 5, 5, 5, 5], [6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]]
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::cell::RefCell;
use std::fmt;

use term_painter::Color::*;
use term_painter::ToStyle;

use error::Error;
use super::{FromParam, FromSegments};

use router::Route;
use http::uri::{URI, URIBuf};
use http::hyper::{header, HyperCookie, HyperHeaders, HyperRequest, HyperRequestUri};
use http::{Method, ContentType, Cookies};

/// The type for all incoming web requests.
///
/// This should be used sparingly in Rocket applications. In particular, it
/// should likely only be used when writing
/// [FromRequest](trait.FromRequest.html) implementations. It contains all of
/// the information for a given web request. This includes the HTTP method, URI,
/// cookies, headers, and more.
pub struct Request<'a> {
    /// The HTTP method associated with the request.
    pub method: Method,
    ///

    ///
	///     Unstable
    ///     (#17):
    ///     The underlying HTTP library/types are likely to change before v1.0.
    ///
    ///

    ///
    /// The data in the request.
    pub data: Vec<u8>, // FIXME: Don't read this! (bad Hyper.)
    uri: URIBuf, // FIXME: Should be URI (without Hyper).
    params: RefCell<Vec<&'static str>>,
    cookies: Cookies,
    headers: HyperHeaders, // This sucks.
    _phantom: Option<&'a str>,
}

impl<'a> Request<'a> {
    /// Retrieves and parses into `T` the `n`th dynamic parameter from the
    /// request. Returns `Error::NoKey` if `n` is greater than the number of
    /// params. Returns `Error::BadParse` if the parameter type `T` can't be
    /// parsed from the parameter.
    ///
    /// # Example
    ///
    /// To retrieve parameter `n` as some type `T` that implements
    /// [FromParam](trait.FromParam.html) inside a
    /// [FromRequest](trait.FromRequest.html) implementation:
    ///
    /// ```rust,ignore
    /// fn from_request(request: &'r Request<'c>) -> .. {
    ///     let my_param: T = request.get_param(n);
    /// }
    /// ```
    pub fn get_param<'r, T: FromParam<'r>>(&'r self, n: usize) -> Result<T, Error> {
        let params = self.params.borrow();
        if n >= params.len() {
            debug!("{} is >= param count {}", n, params.len());
            Err(Error::NoKey)
        } else {
            T::from_param(params[n]).map_err(|_| Error::BadParse)
        }
    }

    /// Returns a borrow to the cookies sent with this request. Note that
    /// `Cookie` implements internal mutability, so this method allows you to
    /// get _and_ set cookies in the given Request.
    pub fn cookies<'r>(&'r self) -> &'r Cookies {
        &self.cookies
    }

    /// Retrieves and parses into `T` all of the path segments in the request
    /// URI beginning and including the 0-indexed `i`. `T` must implement
    /// [FromSegments](trait.FromSegments.html), which is used to parse the
    /// segments.
    ///
    /// For example, if the request URI is `"/hello/there/i/am/here"`, then
    /// `request.get_segments::<T>(1)` will attempt to parse the segments
    /// `"there/i/am/here"` as type `T`.
    pub fn get_segments<'r, T: FromSegments<'r>>(&'r self, i: usize) -> Result<T, Error> {
        if i >= self.uri().segment_count() {
            debug!("{} is >= segment count {}", i, self.uri().segment_count());
            Err(Error::NoKey)
        } else {
            // TODO: Really want to do self.uri.segments().skip(i).into_inner(),
            // but the std lib doesn't implement it for Skip.
            let mut segments = self.uri.segments();
            for _ in segments.by_ref().take(i) { /* do nothing */ }

            T::from_segments(segments).map_err(|_| Error::BadParse)
        }
    }

    // FIXME: Implement a testing framework for Rocket.
    #[doc(hidden)]
    pub fn mock(method: Method, uri: &str) -> Request {
        Request {
            params: RefCell::new(vec![]),
            method: method,
            cookies: Cookies::new(&[]),
            uri: URIBuf::from(uri),
            data: vec![],
            headers: HyperHeaders::new(),
            _phantom: None,
        }
    }

    ///

    ///
	///     Unstable
    ///     (#17):
    ///     The underlying HTTP library/types are likely to change before v1.0.
    ///
    ///

    ///
    /// Returns the headers in this request.
    pub fn headers(&self) -> &HyperHeaders {
        // FIXME: Get rid of Hyper.
        &self.headers
    }

    ///

    ///
	///     Unstable
    ///     (#17):
    ///     The underlying HTTP library/types are likely to change before v1.0.
    ///
    ///

    ///
    /// Returns the Content-Type from the request. Althought you can retrieve
    /// the content-type from the headers directly, this method is considered to
    /// be more stable. If no Content-Type was specified in the request, a
    /// Content-Type of [any](struct.ContentType.html#method.any) is returned.
    pub fn content_type(&self) -> ContentType {
        let hyp_ct = self.headers().get::();
        hyp_ct.map_or(ContentType::any(), |ct| ContentType::from(&ct.0))
    }

    /// Returns the first content-type accepted by this request.
    pub fn accepts(&self) -> ContentType {
        let accept = self.headers().get::();
        accept.map_or(ContentType::any(), |accept| {
            let items = &accept.0;
            if items.len() < 1 {
                return ContentType::any();
            } else {
                return ContentType::from(items[0].item.clone());
            }
        })
    }

    /// Retrieves the URI from the request. Rocket only allows absolute URIs, so
    /// the URI will be absolute.
    pub fn uri(&self) -> URI {
        self.uri.as_uri()
    }

    #[doc(hidden)]
    pub fn set_params(&self, route: &Route) {
        // We use transmute to cast the lifetime of self.uri.as_uri() to
        // 'static. This is because that lifetime refers to the String in URIBuf
        // in this structure, which is (obviously) guaranteed to live as long as
        // the structure AS LONG AS it is not moved out or changed. AS A RESULT,
        // the `uri` fields MUST NEVER be changed once it is set.
        // TODO: Find a way to enforce these. Look at OwningRef for inspiration.
        use ::std::mem::transmute;
        *self.params.borrow_mut() = unsafe {
            transmute(route.get_params(self.uri.as_uri()))
        };
    }

    #[doc(hidden)]
    #[cfg(test)]
    pub fn set_content_type(&mut self, ct: ContentType) {
        let hyper_ct = header::ContentType(ct.into());
        self.headers.set::(hyper_ct)
    }

    /// Create a Rocket Request from a Hyper Request.
    #[doc(hidden)]
    pub fn from_hyp<'h, 'k>(hyper_req: HyperRequest<'h, 'k>)
                            -> Result<Request<'a>, String> {
        let (_, h_method, h_headers, h_uri, _, mut h_body) = hyper_req.deconstruct();

        let uri = match h_uri {
            HyperRequestUri::AbsolutePath(s) => URIBuf::from(s),
            _ => return Err(format!("Bad URI: {}", h_uri)),
        };

        let method = match Method::from_hyp(&h_method) {
            Some(m) => m,
            _ => return Err(format!("Bad method: {}", h_method)),
        };

        let cookies = match h_headers.get::<HyperCookie>() {
            // TODO: What to do about key?
            Some(cookie) => cookie.to_cookie_jar(&[]),
            None => Cookies::new(&[]),
        };

        // FIXME: GRRR.
        let mut data = vec![];
        h_body.read_to_end(&mut data).unwrap();

        let request = Request {
            params: RefCell::new(vec![]),
            method: method,
            cookies: cookies,
            uri: uri,
            data: data,
            headers: h_headers,
            _phantom: None,
        };

        Ok(request)
    }
}

impl<'r> fmt::Display for Request<'r> {
    /// Pretty prints a Request. This is primarily used by Rocket's logging
    /// infrastructure.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", Green.paint(&self.method), Blue.paint(&self.uri))
    }
}
<commit_msg>Always inline appropriate Request methods.<commit_after>use std::io::Read;
use std::cell::RefCell;
use std::fmt;

use term_painter::Color::*;
use term_painter::ToStyle;

use error::Error;
use super::{FromParam, FromSegments};

use router::Route;
use http::uri::{URI, URIBuf};
use http::hyper::{header, HyperCookie, HyperHeaders, HyperRequest, HyperRequestUri};
use http::{Method, ContentType, Cookies};

/// The type for all incoming web requests.
///
/// This should be used sparingly in Rocket applications. In particular, it
/// should likely only be used when writing
/// [FromRequest](trait.FromRequest.html) implementations. It contains all of
/// the information for a given web request. This includes the HTTP method, URI,
/// cookies, headers, and more.
pub struct Request<'a> {
    /// The HTTP method associated with the request.
    pub method: Method,
    ///

    ///
	///     Unstable
    ///     (#17):
    ///     The underlying HTTP library/types are likely to change before v1.0.
    ///
    ///

    ///
    /// The data in the request.
    pub data: Vec<u8>, // FIXME: Don't read this! (bad Hyper.)
    uri: URIBuf, // FIXME: Should be URI (without Hyper).
    params: RefCell<Vec<&'static str>>,
    cookies: Cookies,
    headers: HyperHeaders, // This sucks.
    _phantom: Option<&'a str>,
}

impl<'a> Request<'a> {
    /// Retrieves and parses into `T` the `n`th dynamic parameter from the
    /// request. Returns `Error::NoKey` if `n` is greater than the number of
    /// params. Returns `Error::BadParse` if the parameter type `T` can't be
    /// parsed from the parameter.
    ///
    /// # Example
    ///
    /// To retrieve parameter `n` as some type `T` that implements
    /// [FromParam](trait.FromParam.html) inside a
    /// [FromRequest](trait.FromRequest.html) implementation:
    ///
    /// ```rust,ignore
    /// fn from_request(request: &'r Request<'c>) -> .. {
    ///     let my_param: T = request.get_param(n);
    /// }
    /// ```
    #[inline(always)]
    pub fn get_param<'r, T: FromParam<'r>>(&'r self, n: usize) -> Result<T, Error> {
        let params = self.params.borrow();
        if n >= params.len() {
            debug!("{} is >= param count {}", n, params.len());
            Err(Error::NoKey)
        } else {
            T::from_param(params[n]).map_err(|_| Error::BadParse)
        }
    }

    /// Returns a borrow to the cookies sent with this request. Note that
    /// `Cookie` implements internal mutability, so this method allows you to
    /// get _and_ set cookies in the given Request.
    #[inline(always)]
    pub fn cookies<'r>(&'r self) -> &'r Cookies {
        &self.cookies
    }

    /// Retrieves and parses into `T` all of the path segments in the request
    /// URI beginning and including the 0-indexed `i`. `T` must implement
    /// [FromSegments](trait.FromSegments.html), which is used to parse the
    /// segments.
    ///
    /// For example, if the request URI is `"/hello/there/i/am/here"`, then
    /// `request.get_segments::<T>(1)` will attempt to parse the segments
    /// `"there/i/am/here"` as type `T`.
    pub fn get_segments<'r, T: FromSegments<'r>>(&'r self, i: usize) -> Result<T, Error> {
        if i >= self.uri().segment_count() {
            debug!("{} is >= segment count {}", i, self.uri().segment_count());
            Err(Error::NoKey)
        } else {
            // TODO: Really want to do self.uri.segments().skip(i).into_inner(),
            // but the std lib doesn't implement it for Skip.
            let mut segments = self.uri.segments();
            for _ in segments.by_ref().take(i) { /* do nothing */ }

            T::from_segments(segments).map_err(|_| Error::BadParse)
        }
    }

    // FIXME: Implement a testing framework for Rocket.
    #[doc(hidden)]
    pub fn mock(method: Method, uri: &str) -> Request {
        Request {
            params: RefCell::new(vec![]),
            method: method,
            cookies: Cookies::new(&[]),
            uri: URIBuf::from(uri),
            data: vec![],
            headers: HyperHeaders::new(),
            _phantom: None,
        }
    }

    ///

    ///
	///     Unstable
    ///     (#17):
    ///     The underlying HTTP library/types are likely to change before v1.0.
    ///
    ///

    ///
    /// Returns the headers in this request.
    #[inline(always)]
    pub fn headers(&self) -> &HyperHeaders {
        // FIXME: Get rid of Hyper.
        &self.headers
    }

    ///

    ///
	///     Unstable
    ///     (#17):
    ///     The underlying HTTP library/types are likely to change before v1.0.
    ///
    ///

    ///
    /// Returns the Content-Type from the request. Althought you can retrieve
    /// the content-type from the headers directly, this method is considered to
    /// be more stable. If no Content-Type was specified in the request, a
    /// Content-Type of [any](struct.ContentType.html#method.any) is returned.
    #[inline(always)]
    pub fn content_type(&self) -> ContentType {
        let hyp_ct = self.headers().get::();
        hyp_ct.map_or(ContentType::any(), |ct| ContentType::from(&ct.0))
    }

    /// Returns the first content-type accepted by this request.
    pub fn accepts(&self) -> ContentType {
        let accept = self.headers().get::();
        accept.map_or(ContentType::any(), |accept| {
            let items = &accept.0;
            if items.len() < 1 {
                return ContentType::any();
            } else {
                return ContentType::from(items[0].item.clone());
            }
        })
    }

    /// Retrieves the URI from the request. Rocket only allows absolute URIs, so
    /// the URI will be absolute.
    #[inline(always)]
    pub fn uri(&self) -> URI {
        self.uri.as_uri()
    }

    #[doc(hidden)]
    #[inline(always)]
    pub fn set_params(&self, route: &Route) {
        // We use transmute to cast the lifetime of self.uri.as_uri() to
        // 'static. This is because that lifetime refers to the String in URIBuf
        // in this structure, which is (obviously) guaranteed to live as long as
        // the structure AS LONG AS it is not moved out or changed. AS A RESULT,
        // the `uri` fields MUST NEVER be changed once it is set.
        // TODO: Find a way to enforce these. Look at OwningRef for inspiration.
        use ::std::mem::transmute;
        *self.params.borrow_mut() = unsafe {
            transmute(route.get_params(self.uri.as_uri()))
        };
    }

    #[doc(hidden)]
    #[cfg(test)]
    #[inline(always)]
    pub fn set_content_type(&mut self, ct: ContentType) {
        let hyper_ct = header::ContentType(ct.into());
        self.headers.set::(hyper_ct)
    }

    /// Create a Rocket Request from a Hyper Request.
    #[doc(hidden)]
    pub fn from_hyp<'h, 'k>(hyper_req: HyperRequest<'h, 'k>)
                            -> Result<Request<'a>, String> {
        let (_, h_method, h_headers, h_uri, _, mut h_body) = hyper_req.deconstruct();

        let uri = match h_uri {
            HyperRequestUri::AbsolutePath(s) => URIBuf::from(s),
            _ => return Err(format!("Bad URI: {}", h_uri)),
        };

        let method = match Method::from_hyp(&h_method) {
            Some(m) => m,
            _ => return Err(format!("Bad method: {}", h_method)),
        };

        let cookies = match h_headers.get::<HyperCookie>() {
            // TODO: What to do about key?
            Some(cookie) => cookie.to_cookie_jar(&[]),
            None => Cookies::new(&[]),
        };

        // FIXME: GRRR.
        let mut data = vec![];
        h_body.read_to_end(&mut data).unwrap();

        let request = Request {
            params: RefCell::new(vec![]),
            method: method,
            cookies: cookies,
            uri: uri,
            data: data,
            headers: h_headers,
            _phantom: None,
        };

        Ok(request)
    }
}

impl<'r> fmt::Display for Request<'r> {
    /// Pretty prints a Request. This is primarily used by Rocket's logging
    /// infrastructure.
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", Green.paint(&self.method), Blue.paint(&self.uri))
    }
}
<|endoftext|>


<commit_before>mod data;

use std::io::Read;

use super::regex::Regex;

use super::hyper::Client;
use super::hyper::header::Connection;

use super::rustc_serialize::json;
use super::rustc_serialize::json::Json;

use super::flate2::read::GzDecoder;

use google::GoogleResult;
use self::data::StackExchangeAnswerMeta;

pub struct StackExchangeApi {
    api: &'static str,
    version: &'static str,
    protocol: &'static str,
    client: Client,
}

impl StackExchangeApi {
    pub fn new() -> Self {
        StackExchangeApi {
            api: "api.stackexchange.com",
            protocol: "https",
            version: "2.2",
            client: Client::new(),
        }
    }

    pub fn fetch_answers(&self, url: &str) -> Result<Vec<StackExchangeAnswerMeta>, String> {
        let quiestion_id: &str;
        let site: &str;

        if url.contains("stackoverflow.com") {
            let re = Regex::new(r".*stackoverflow.com/questions/(?P<q_id>\d+)/").unwrap();
            let captures = re.captures(&url).unwrap();
            quiestion_id = captures.name("q_id").unwrap();
            site = "stackoverflow".into();
        } else if url.contains("stackexchange.com") {
            let re = Regex::new(r".*//(?P<site>.*).stackexchange.com/questions/(?P<q_id>\d+)/")
                         .unwrap();
            let captures = re.captures(&url).unwrap();
            quiestion_id = captures.name("q_id").unwrap();
            site = captures.name("site").unwrap();
        } else {
            return Err("Result is not related to StackExchange.".into());
        }

        let quiestion_id: u64 = quiestion_id.parse::<u64>().unwrap();

        Ok(self.query(site, quiestion_id))
    }

    fn query(&self, site: &str, quiestion_id: u64) -> Vec<StackExchangeAnswerMeta> {
        let url = format!("{}://{}/questions/{}/answers?site={}",
                          self.protocol,
                          self.api,
                          quiestion_id,
                          site);

        let mut res = self.client
                          .get(&url)
                          .header(Connection::close())
                          .send()
                          .unwrap();

        let mut buffer = Vec::new();
        res.read_to_end(&mut buffer);

        let mut gzip_decoder = GzDecoder::new(buffer.as_slice()).unwrap();
        let mut body = String::new();
        gzip_decoder.read_to_string(&mut body).unwrap();

        let response = Json::from_str(&body).unwrap();
        let data = response.as_object().unwrap();
        let items = data.get("items").unwrap().as_array().unwrap();

        let answers: Vec<StackExchangeAnswerMeta> = items.iter()
                                                         .map(|i| {
                                                             json::decode(&i.to_string()).unwrap()
                                                         })
                                                         .collect();

        answers
    }
}
<commit_msg>Removed version (by now).<commit_after>mod data;

use std::io::Read;

use super::regex::Regex;

use super::hyper::Client;
use super::hyper::header::Connection;

use super::rustc_serialize::json;
use super::rustc_serialize::json::Json;

use super::flate2::read::GzDecoder;

use google::GoogleResult;
use self::data::StackExchangeAnswerMeta;

pub struct StackExchangeApi {
    api: &'static str,
    protocol: &'static str,
    client: Client,
}

impl StackExchangeApi {
    pub fn new() -> Self {
        StackExchangeApi {
            api: "api.stackexchange.com",
            protocol: "https",
            client: Client::new(),
        }
    }

    pub fn fetch_answers(&self, url: &str) -> Result<Vec<StackExchangeAnswerMeta>, String> {
        let quiestion_id: &str;
        let site: &str;

        if url.contains("stackoverflow.com") {
            let re = Regex::new(r".*stackoverflow.com/questions/(?P<q_id>\d+)/").unwrap();
            let captures = re.captures(&url).unwrap();
            quiestion_id = captures.name("q_id").unwrap();
            site = "stackoverflow".into();
        } else if url.contains("stackexchange.com") {
            let re = Regex::new(r".*//(?P<site>.*).stackexchange.com/questions/(?P<q_id>\d+)/")
                         .unwrap();
            let captures = re.captures(&url).unwrap();
            quiestion_id = captures.name("q_id").unwrap();
            site = captures.name("site").unwrap();
        } else {
            return Err("Result is not related to StackExchange.".into());
        }

        let quiestion_id: u64 = quiestion_id.parse::<u64>().unwrap();

        Ok(self.query(site, quiestion_id))
    }

    fn query(&self, site: &str, quiestion_id: u64) -> Vec<StackExchangeAnswerMeta> {
        let url = format!("{}://{}/questions/{}/answers?site={}",
                          self.protocol,
                          self.api,
                          quiestion_id,
                          site);

        let mut res = self.client
                          .get(&url)
                          .header(Connection::close())
                          .send()
                          .unwrap();

        let mut buffer = Vec::new();
        res.read_to_end(&mut buffer);

        let mut gzip_decoder = GzDecoder::new(buffer.as_slice()).unwrap();
        let mut body = String::new();
        gzip_decoder.read_to_string(&mut body).unwrap();

        let response = Json::from_str(&body).unwrap();
        let data = response.as_object().unwrap();
        let items = data.get("items").unwrap().as_array().unwrap();

        let answers: Vec<StackExchangeAnswerMeta> = items.iter()
                                                         .map(|i| {
                                                             json::decode(&i.to_string()).unwrap()
                                                         })
                                                         .collect();

        answers
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Johan Sköld.
// License: http://opensource.org/licenses/ISC

extern crate bgfx;
extern crate glutin;

mod common;

use bgfx::*;
use common::EventQueue;
use std::cmp::max;

const LOGO: &'static [u8] = include_bytes!("assets/00-helloworld/logo.bin");

fn example(events: EventQueue) {
    let mut width: u16 = 1024;
    let mut height: u16 = 720;
    let debug = DEBUG_TEXT;
    let reset = RESET_VSYNC;

    let bgfx = bgfx::init(RendererType::Default, None, None).unwrap();
    bgfx.reset(width, height, reset);

    // Enable debug text.
    bgfx.set_debug(debug);

    // Set view 0 clear state.
    let clear = CLEAR_COLOR | CLEAR_DEPTH;
    bgfx.set_view_clear(0, clear, 0x303030ff, 1.0_f32, 0);

    while !events.handle_events(&bgfx, &mut width, &mut height, reset) {
        // Set view 0 default viewport.
        bgfx.set_view_rect(0, 0, 0, width, height);

        // This dummy draw call is here to make sure that view 0 is cleared
        // if no other draw calls are submitted to view 0.
        bgfx.touch(0);

        // Use debug font to print information about this example.
        let x: u16 = max(width / 2 / 8, 20) - 20;
        let y: u16 = max(height / 2 / 16, 6) - 6;
        bgfx.dbg_text_clear(None, None);
        bgfx.dbg_text_image(x, y, 40, 12, LOGO, 160);
        bgfx.dbg_text_print(0, 1, 0x4f, "examples/00-helloworld.rs");
        bgfx.dbg_text_print(0, 2, 0x6f, "Description: Initialization and debug text.");

        // Advance to next frame. Rendering thread will be kicked to
        // process submitted rendering primitives.
        bgfx.frame();
    }

    // bgfx will automatically be shut down when the local `bgfx` binding
    // goes out of scope.
}

fn main() {
    common::run_example(1024, 768, example);
}
<commit_msg>Fixing 00-helloworld size<commit_after>// Copyright (c) 2015, Johan Sköld.
// License: http://opensource.org/licenses/ISC

extern crate bgfx;
extern crate glutin;

mod common;

use bgfx::*;
use common::EventQueue;
use std::cmp::max;

const LOGO: &'static [u8] = include_bytes!("assets/00-helloworld/logo.bin");

fn example(events: EventQueue) {
    let mut width: u16 = 1280;
    let mut height: u16 = 720;
    let debug = DEBUG_TEXT;
    let reset = RESET_VSYNC;

    let bgfx = bgfx::init(RendererType::Default, None, None).unwrap();
    bgfx.reset(width, height, reset);

    // Enable debug text.
    bgfx.set_debug(debug);

    // Set view 0 clear state.
    let clear = CLEAR_COLOR | CLEAR_DEPTH;
    bgfx.set_view_clear(0, clear, 0x303030ff, 1.0_f32, 0);

    while !events.handle_events(&bgfx, &mut width, &mut height, reset) {
        // Set view 0 default viewport.
        bgfx.set_view_rect(0, 0, 0, width, height);

        // This dummy draw call is here to make sure that view 0 is cleared
        // if no other draw calls are submitted to view 0.
        bgfx.touch(0);

        // Use debug font to print information about this example.
        let x: u16 = max(width / 2 / 8, 20) - 20;
        let y: u16 = max(height / 2 / 16, 6) - 6;
        bgfx.dbg_text_clear(None, None);
        bgfx.dbg_text_image(x, y, 40, 12, LOGO, 160);
        bgfx.dbg_text_print(0, 1, 0x4f, "examples/00-helloworld.rs");
        bgfx.dbg_text_print(0, 2, 0x6f, "Description: Initialization and debug text.");

        // Advance to next frame. Rendering thread will be kicked to
        // process submitted rendering primitives.
        bgfx.frame();
    }

    // bgfx will automatically be shut down when the local `bgfx` binding
    // goes out of scope.
}

fn main() {
    common::run_example(1280, 720, example);
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
use test::Bencher;

use resize::Pixel::{Gray16, Gray8, RGB24};
use resize::Type::Triangle;
use resize::Type::Lanczos3;
use resize::Type::Point;
use std::fs::File;
use std::path::PathBuf;

fn get_image() -> (png::OutputInfo, Vec<u8>) {
    let root: PathBuf = env!("CARGO_MANIFEST_DIR").into();
    let decoder = png::Decoder::new(File::open(root.join("examples/tiger.png")).unwrap());
    let (info, mut reader) = decoder.read_info().unwrap();
    let mut src = vec![110; info.buffer_size()];
    reader.next_frame(&mut src).unwrap();
    (info, src)
}

#[bench]
fn precomputed_large(b: &mut Bencher) {
    let (info, src) = get_image();
    let (w1, h1) = (info.width as usize, info.height as usize);
    let (w2, h2) = (1600, 1200);
    let mut dst = vec![120; w2 * h2];

    let mut r = resize::new(w1, h1, w2, h2, Gray8, Triangle);

    b.iter(|| r.resize(&src, &mut dst));
}

#[bench]
fn tiny(b: &mut Bencher) {
    let (info, src0) = get_image();
    let (w0, h0) = (info.width as usize, info.height as usize);
    let (w1, h1) = (3200, 2400);
    let mut src1 = vec![0; w1 * h1];

    resize::new(w0, h0, w1, h1, Gray8, Triangle).resize(&src0, &mut src1);
    let (w2, h2) = (16, 12);
    let mut dst = vec![0; w2 * h2];

    let mut r = resize::new(w1, h1, w2, h2, Gray8, Lanczos3);
    b.iter(|| r.resize(&src1, &mut dst));
}

#[bench]
fn huge_stretch(b: &mut Bencher) {
    let (info, src0) = get_image();
    let (w0, h0) = (info.width as usize, info.height as usize);
    let (w1, h1) = (12, 12);
    let mut src1 = vec![0; w1 * h1];

    resize::new(w0, h0, w1, h1, Gray8, Lanczos3).resize(&src0, &mut src1);
    let (w2, h2) = (1200, 1200);
    let mut dst = vec![0; w2 * h2];

    let mut r = resize::new(w1, h1, w2, h2, Gray8, Triangle);
    b.iter(|| r.resize(&src1, &mut dst));
}

#[bench]
fn precomputed_small(b: &mut Bencher) {
    let (info, src) = get_image();
    let (w1, h1) = (info.width as usize, info.height as usize);
    let (w2, h2) = (100, 100);
    let mut dst = vec![240; w2 * h2];

    let mut r = resize::new(w1, h1, w2, h2, Gray8, Triangle);

    b.iter(|| r.resize(&src, &mut dst));
}

#[bench]
fn precomputed_small_16bit(b: &mut Bencher) {
    let (info, src) = get_image();
    let (w1, h1) = (info.width as usize, info.height as usize);
    let (w2, h2) = (100,100);
    let mut dst = vec![33; w2*h2];
    let src: Vec<_> = src.into_iter().map(|px|{
        let px = px as u16;
        (px << 8) | px
    }).collect();

    let mut r = resize::new(w1, h1, w2, h2, Gray16, Triangle);

    b.iter(|| r.resize(&src, &mut dst));
}

#[bench]
#[allow(deprecated)]
fn recomputed_small(b: &mut Bencher) {
    let (info, src) = get_image();
    let (w1, h1) = (info.width as usize, info.height as usize);
    let (w2, h2) = (100, 100);
    let mut dst = vec![99; w2 * h2];

    b.iter(|| resize::resize(w1, h1, w2, h2, Gray8, Triangle, &src, &mut dst));
}

#[bench]
#[allow(deprecated)]
fn init_lanczos(b: &mut Bencher) {
    b.iter(|| resize::new(test::black_box(100), 200, test::black_box(300), 400, RGB24, Lanczos3));
}

#[bench]
#[allow(deprecated)]
fn init_point(b: &mut Bencher) {
    b.iter(|| resize::new(test::black_box(100), 200, test::black_box(300), 400, RGB24, Point));
}
<commit_msg>More benches<commit_after>#![feature(test)]

extern crate test;
use test::Bencher;

use resize::Pixel::{Gray16, Gray8, RGB24, RGBA64};
use resize::Type::Triangle;
use resize::Type::Lanczos3;
use resize::Type::Point;
use std::fs::File;
use std::path::PathBuf;

fn get_image() -> (png::OutputInfo, Vec<u8>) {
    let root: PathBuf = env!("CARGO_MANIFEST_DIR").into();
    let decoder = png::Decoder::new(File::open(root.join("examples/tiger.png")).unwrap());
    let (info, mut reader) = decoder.read_info().unwrap();
    let mut src = vec![110; info.buffer_size()];
    reader.next_frame(&mut src).unwrap();
    (info, src)
}

#[bench]
fn precomputed_large(b: &mut Bencher) {
    let (info, src) = get_image();
    let (w1, h1) = (info.width as usize, info.height as usize);
    let (w2, h2) = (1600, 1200);
    let mut dst = vec![120; w2 * h2];

    let mut r = resize::new(w1, h1, w2, h2, Gray8, Triangle);

    b.iter(|| r.resize(&src, &mut dst));
}

#[bench]
fn tiny(b: &mut Bencher) {
    let (info, src0) = get_image();
    let (w0, h0) = (info.width as usize, info.height as usize);
    let (w1, h1) = (3200, 2400);
    let mut src1 = vec![0; w1 * h1];

    resize::new(w0, h0, w1, h1, Gray8, Triangle).resize(&src0, &mut src1);
    let (w2, h2) = (16, 12);
    let mut dst = vec![0; w2 * h2];

    let mut r = resize::new(w1, h1, w2, h2, Gray8, Lanczos3);
    b.iter(|| r.resize(&src1, &mut dst));
}

#[bench]
fn huge_stretch(b: &mut Bencher) {
    let (info, src0) = get_image();
    let (w0, h0) = (info.width as usize, info.height as usize);
    let (w1, h1) = (12, 12);
    let mut src1 = vec![0; w1 * h1];

    resize::new(w0, h0, w1, h1, Gray8, Lanczos3).resize(&src0, &mut src1);
    let (w2, h2) = (1200, 1200);
    let mut dst = vec![0; w2 * h2];

    let mut r = resize::new(w1, h1, w2, h2, Gray8, Triangle);
    b.iter(|| r.resize(&src1, &mut dst));
}

#[bench]
fn precomputed_small(b: &mut Bencher) {
    let (info, src) = get_image();
    let (w1, h1) = (info.width as usize, info.height as usize);
    let (w2, h2) = (100, 100);
    let mut dst = vec![240; w2 * h2];

    let mut r = resize::new(w1, h1, w2, h2, Gray8, Triangle);

    b.iter(|| r.resize(&src, &mut dst));
}

#[bench]
fn a_small_rgb(b: &mut Bencher) {
    let (info, src) = get_image();
    let src: Vec<_> = src.into_iter().map(|c| rgb::RGB::new(c,c,c)).collect();
    let (w1, h1) = (info.width as usize, info.height as usize);
    let (w2, h2) = (100, 100);
    let mut dst = vec![240; w2 * h2 * 3];

    let mut r = resize::new(w1, h1, w2, h2, RGB24, Triangle);

    b.iter(|| r.resize(rgb::ComponentSlice::as_slice(&src[..]), &mut dst));
}

#[bench]
fn a_small_rgba16(b: &mut Bencher) {
    let (info, src) = get_image();
    let src: Vec<_> = src.into_iter().map(|c| {
        let w = ((c as u16) << 8) | c as u16;
        rgb::RGBA::new(w,w,w,65535)
    }).collect();
    let (w1, h1) = (info.width as usize, info.height as usize);
    let (w2, h2) = (100, 100);
    let mut dst = vec![0u16; w2 * h2 * 4];

    let mut r = resize::new(w1, h1, w2, h2, RGBA64, Triangle);

    b.iter(|| r.resize(rgb::ComponentSlice::as_slice(&src[..]), &mut dst));
}

#[bench]
fn precomputed_small_16bit(b: &mut Bencher) {
    let (info, src) = get_image();
    let (w1, h1) = (info.width as usize, info.height as usize);
    let (w2, h2) = (100,100);
    let mut dst = vec![33; w2*h2];
    let src: Vec<_> = src.into_iter().map(|px|{
        let px = px as u16;
        (px << 8) | px
    }).collect();

    let mut r = resize::new(w1, h1, w2, h2, Gray16, Triangle);

    b.iter(|| r.resize(&src, &mut dst));
}

#[bench]
#[allow(deprecated)]
fn recomputed_small(b: &mut Bencher) {
    let (info, src) = get_image();
    let (w1, h1) = (info.width as usize, info.height as usize);
    let (w2, h2) = (100, 100);
    let mut dst = vec![99; w2 * h2];

    b.iter(|| resize::resize(w1, h1, w2, h2, Gray8, Triangle, &src, &mut dst));
}

#[bench]
#[allow(deprecated)]
fn init_lanczos(b: &mut Bencher) {
    b.iter(|| resize::new(test::black_box(100), 200, test::black_box(300), 400, RGB24, Lanczos3));
}

#[bench]
#[allow(deprecated)]
fn init_point(b: &mut Bencher) {
    b.iter(|| resize::new(test::black_box(100), 200, test::black_box(300), 400, RGB24, Point));
}
<|endoftext|>


<commit_before>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use translate::*;
use std::mem::transmute;
use std::mem;
use ffi as glib_ffi;
use ffi::{gpointer, gboolean};

use MainContext;
use Source;
use SourceId;

use source::Priority;

impl MainContext {
    pub fn prepare(&self) -> (bool, i32) {
        unsafe {
            let mut priority = mem::uninitialized();

            let res = from_glib(ffi::g_main_context_prepare(self.to_glib_none().0, &mut priority));

            (res, priority)
        }
    }

    pub fn find_source_by_id(&self, source_id: &SourceId) -> Option<Source> {
        unsafe {
            from_glib_none(ffi::g_main_context_find_source_by_id(self.to_glib_none().0, source_id.to_glib()))
        }
    }

    pub fn invoke<F>(&self, func: F)
    where F: FnOnce() + Send + 'static {
        self.invoke_with_priority(::PRIORITY_DEFAULT_IDLE, func);
    }

    pub fn invoke_with_priority<F>(&self, priority: Priority, func: F)
    where F: FnOnce() + Send + 'static {
        unsafe {
            let func = Box::into_raw(Box::new(Some(Box::new(func))));
            glib_ffi::g_main_context_invoke_full(self.to_glib_none().0, priority.to_glib(), Some(trampoline::<F>),
                func as gpointer, Some(destroy_closure::<F>))
        }
    }

    /// Calls closure with context configured as the thread default one.
    ///
    /// Thread default context is changed in panic-safe manner by calling
    /// [`push_thread_default`][push_thread_default] before calling closure
    /// and [`pop_thread_default`][pop_thread_default] afterwards regardless
    /// of whether closure panicked or not.
    ///
    /// [push_thread_default]: struct.MainContext.html#method.push_thread_default
    /// [pop_thread_default]: struct.MainContext.html#method.pop_thread_default
    pub fn with_thread_default<R, F: Sized>(&self, func: F) -> R
    where F: FnOnce() -> R {
        let _thread_default = ThreadDefaultContext::new(self);
        func()
    }
}

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
unsafe extern "C" fn trampoline<F: FnOnce() + Send + 'static>(func: gpointer) -> gboolean {
    let func: &mut Option<Box<F>> = transmute(func);
    let func = func.take().expect("MainContext::invoke() closure called multiple times");
    func();
    glib_ffi::G_SOURCE_REMOVE
}

unsafe extern "C" fn destroy_closure<F: FnOnce() + Send + 'static>(ptr: gpointer) {
    Box::<Option<Box<F>>>::from_raw(ptr as *mut _);
}

struct ThreadDefaultContext<'a>(&'a MainContext);

impl<'a> ThreadDefaultContext<'a> {
    fn new(ctx: &MainContext) -> ThreadDefaultContext {
        ctx.push_thread_default();
        ThreadDefaultContext(ctx)
    }
}

impl<'a> Drop for ThreadDefaultContext<'a> {
    fn drop(&mut self) {
        self.0.pop_thread_default();
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::panic;
    use std::ptr;
    use std::thread;

    #[test]
    fn test_invoke() {
        let c = MainContext::new();
        let l = ::MainLoop::new(&c, false);

        let l_clone = l.clone();
        thread::spawn(move || {
            c.invoke(move || l_clone.quit());
        });

        l.run();
    }

    fn is_same_context(a: &MainContext, b: &MainContext) -> bool {
        ptr::eq(a.to_glib_none().0, b.to_glib_none().0)
    }

    #[test]
    fn test_with_thread_default() {
        let a = MainContext::new();
        let b = MainContext::new();

        assert!(!is_same_context(&a, &b));

        a.with_thread_default(|| {
            let t = MainContext::get_thread_default().unwrap();
            assert!(is_same_context(&a, &t));

            &b.with_thread_default(|| {
                let t = MainContext::get_thread_default().unwrap();
                assert!(is_same_context(&b, &t));
            });

            let t = MainContext::get_thread_default().unwrap();
            assert!(is_same_context(&a, &t));
        });
    }

    #[test]
    fn test_with_thread_default_is_panic_safe() {
        let a = MainContext::new();
        let b = MainContext::new();

        assert!(!is_same_context(&a, &b));

        a.with_thread_default(|| {
            let t = MainContext::get_thread_default().unwrap();
            assert!(is_same_context(&a, &t));

            let result = panic::catch_unwind(|| {
                &b.with_thread_default(|| {
                    panic!();
                });
            });
            assert!(result.is_err());

            let t = MainContext::get_thread_default().unwrap();
            assert!(is_same_context(&a, &t));
        });

    }
}
<commit_msg>Don't box MainContext::invoke() closure twice<commit_after>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use translate::*;
use std::mem::transmute;
use std::mem;
use ffi as glib_ffi;
use ffi::{gpointer, gboolean};

use MainContext;
use Source;
use SourceId;

use source::Priority;

impl MainContext {
    pub fn prepare(&self) -> (bool, i32) {
        unsafe {
            let mut priority = mem::uninitialized();

            let res = from_glib(ffi::g_main_context_prepare(self.to_glib_none().0, &mut priority));

            (res, priority)
        }
    }

    pub fn find_source_by_id(&self, source_id: &SourceId) -> Option<Source> {
        unsafe {
            from_glib_none(ffi::g_main_context_find_source_by_id(self.to_glib_none().0, source_id.to_glib()))
        }
    }

    pub fn invoke<F>(&self, func: F)
    where F: FnOnce() + Send + 'static {
        self.invoke_with_priority(::PRIORITY_DEFAULT_IDLE, func);
    }

    pub fn invoke_with_priority<F>(&self, priority: Priority, func: F)
    where F: FnOnce() + Send + 'static {
        unsafe {
            let func = Box::into_raw(Box::new(Some(func)));
            glib_ffi::g_main_context_invoke_full(self.to_glib_none().0, priority.to_glib(), Some(trampoline::<F>),
                func as gpointer, Some(destroy_closure::<F>))
        }
    }

    /// Calls closure with context configured as the thread default one.
    ///
    /// Thread default context is changed in panic-safe manner by calling
    /// [`push_thread_default`][push_thread_default] before calling closure
    /// and [`pop_thread_default`][pop_thread_default] afterwards regardless
    /// of whether closure panicked or not.
    ///
    /// [push_thread_default]: struct.MainContext.html#method.push_thread_default
    /// [pop_thread_default]: struct.MainContext.html#method.pop_thread_default
    pub fn with_thread_default<R, F: Sized>(&self, func: F) -> R
    where F: FnOnce() -> R {
        let _thread_default = ThreadDefaultContext::new(self);
        func()
    }
}

#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))]
unsafe extern "C" fn trampoline<F: FnOnce() + Send + 'static>(func: gpointer) -> gboolean {
    let func: &mut Option<F> = transmute(func);
    let func = func.take().expect("MainContext::invoke() closure called multiple times");
    func();
    glib_ffi::G_SOURCE_REMOVE
}

unsafe extern "C" fn destroy_closure<F: FnOnce() + Send + 'static>(ptr: gpointer) {
    Box::<Option<F>>::from_raw(ptr as *mut _);
}

struct ThreadDefaultContext<'a>(&'a MainContext);

impl<'a> ThreadDefaultContext<'a> {
    fn new(ctx: &MainContext) -> ThreadDefaultContext {
        ctx.push_thread_default();
        ThreadDefaultContext(ctx)
    }
}

impl<'a> Drop for ThreadDefaultContext<'a> {
    fn drop(&mut self) {
        self.0.pop_thread_default();
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::panic;
    use std::ptr;
    use std::thread;

    #[test]
    fn test_invoke() {
        let c = MainContext::new();
        let l = ::MainLoop::new(&c, false);

        let l_clone = l.clone();
        thread::spawn(move || {
            c.invoke(move || l_clone.quit());
        });

        l.run();
    }

    fn is_same_context(a: &MainContext, b: &MainContext) -> bool {
        ptr::eq(a.to_glib_none().0, b.to_glib_none().0)
    }

    #[test]
    fn test_with_thread_default() {
        let a = MainContext::new();
        let b = MainContext::new();

        assert!(!is_same_context(&a, &b));

        a.with_thread_default(|| {
            let t = MainContext::get_thread_default().unwrap();
            assert!(is_same_context(&a, &t));

            &b.with_thread_default(|| {
                let t = MainContext::get_thread_default().unwrap();
                assert!(is_same_context(&b, &t));
            });

            let t = MainContext::get_thread_default().unwrap();
            assert!(is_same_context(&a, &t));
        });
    }

    #[test]
    fn test_with_thread_default_is_panic_safe() {
        let a = MainContext::new();
        let b = MainContext::new();

        assert!(!is_same_context(&a, &b));

        a.with_thread_default(|| {
            let t = MainContext::get_thread_default().unwrap();
            assert!(is_same_context(&a, &t));

            let result = panic::catch_unwind(|| {
                &b.with_thread_default(|| {
                    panic!();
                });
            });
            assert!(result.is_err());

            let t = MainContext::get_thread_default().unwrap();
            assert!(is_same_context(&a, &t));
        });

    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2019, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use crate::context::MAX_TX_SIZE;
use crate::cpu_features::CpuFeatureLevel;
use crate::predict::{native, PredictionMode, PredictionVariant};
use crate::tiling::PlaneRegionMut;
use crate::transform::TxSize;
use crate::util::AlignedArray;
use crate::Pixel;
use libc;
use std::mem::size_of;

macro_rules! decl_angular_ipred_fn {
  ($($f:ident),+) => {
    extern {
      $(
        fn $f(
          dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8,
          width: libc::c_int, height: libc::c_int, angle: libc::c_int,
        );
      )*
    }
  };
}

decl_angular_ipred_fn! {
  rav1e_ipred_dc_avx2,
  rav1e_ipred_dc_ssse3,
  rav1e_ipred_dc_128_avx2,
  rav1e_ipred_dc_128_ssse3,
  rav1e_ipred_dc_left_avx2,
  rav1e_ipred_dc_left_ssse3,
  rav1e_ipred_dc_top_avx2,
  rav1e_ipred_dc_top_ssse3,
  rav1e_ipred_h_avx2,
  rav1e_ipred_h_ssse3,
  rav1e_ipred_v_avx2,
  rav1e_ipred_v_ssse3,
  rav1e_ipred_paeth_avx2,
  rav1e_ipred_paeth_ssse3,
  rav1e_ipred_smooth_avx2,
  rav1e_ipred_smooth_ssse3,
  rav1e_ipred_smooth_h_avx2,
  rav1e_ipred_smooth_h_ssse3,
  rav1e_ipred_smooth_v_avx2,
  rav1e_ipred_smooth_v_ssse3
}

macro_rules! decl_cfl_pred_fn {
  ($($f:ident),+) => {
    extern {
      $(
        fn $f(
          dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8,
          width: libc::c_int, height: libc::c_int, ac: *const u8,
          alpha: libc::c_int,
        );
      )*
    }
  };
}

decl_cfl_pred_fn! {
  rav1e_ipred_cfl_avx2,
  rav1e_ipred_cfl_ssse3,
  rav1e_ipred_cfl_128_avx2,
  rav1e_ipred_cfl_128_ssse3,
  rav1e_ipred_cfl_left_avx2,
  rav1e_ipred_cfl_left_ssse3,
  rav1e_ipred_cfl_top_avx2,
  rav1e_ipred_cfl_top_ssse3
}

#[inline(always)]
pub fn dispatch_predict_intra<T: Pixel>(
  mode: PredictionMode, variant: PredictionVariant,
  dst: &mut PlaneRegionMut<'_, T>, tx_size: TxSize, bit_depth: usize,
  ac: &[i16], angle: isize, edge_buf: &AlignedArray<[T; 4 * MAX_TX_SIZE + 1]>,
  cpu: CpuFeatureLevel,
) {
  let call_native = |dst: &mut PlaneRegionMut<'_, T>| {
    native::dispatch_predict_intra(
      mode, variant, dst, tx_size, bit_depth, ac, angle, edge_buf, cpu,
    );
  };

  if size_of::<T>() != 1 {
    return call_native(dst);
  }

  unsafe {
    let dst_ptr = dst.data_ptr_mut() as *mut _;
    let stride = dst.plane_cfg.stride as libc::ptrdiff_t;
    let edge_ptr =
      edge_buf.array.as_ptr().offset(2 * MAX_TX_SIZE as isize) as *const _;
    let w = tx_size.width() as libc::c_int;
    let h = tx_size.height() as libc::c_int;
    let angle = angle as libc::c_int;

    if cpu >= CpuFeatureLevel::AVX2 {
      match mode {
        PredictionMode::DC_PRED => {
          (match variant {
            PredictionVariant::NONE => rav1e_ipred_dc_128_avx2,
            PredictionVariant::LEFT => rav1e_ipred_dc_left_avx2,
            PredictionVariant::TOP => rav1e_ipred_dc_top_avx2,
            PredictionVariant::BOTH => rav1e_ipred_dc_avx2,
          })(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::UV_CFL_PRED => {
          let ac_ptr = ac.as_ptr() as *const _;
          (match variant {
            PredictionVariant::NONE => rav1e_ipred_cfl_128_avx2,
            PredictionVariant::LEFT => rav1e_ipred_cfl_left_avx2,
            PredictionVariant::TOP => rav1e_ipred_cfl_top_avx2,
            PredictionVariant::BOTH => rav1e_ipred_cfl_avx2,
          })(dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle);
        }
        PredictionMode::H_PRED => {
          rav1e_ipred_h_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::V_PRED => {
          rav1e_ipred_v_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::PAETH_PRED => {
          rav1e_ipred_paeth_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_PRED => {
          rav1e_ipred_smooth_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_H_PRED => {
          rav1e_ipred_smooth_h_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_V_PRED => {
          rav1e_ipred_smooth_v_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        _ => call_native(dst),
      }
    } else if cpu >= CpuFeatureLevel::SSSE3 {
      match mode {
        PredictionMode::DC_PRED => {
          (match variant {
            PredictionVariant::NONE => rav1e_ipred_dc_128_ssse3,
            PredictionVariant::LEFT => rav1e_ipred_dc_left_ssse3,
            PredictionVariant::TOP => rav1e_ipred_dc_top_ssse3,
            PredictionVariant::BOTH => rav1e_ipred_dc_ssse3,
          })(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::UV_CFL_PRED => {
          let ac_ptr = ac.as_ptr() as *const _;
          (match variant {
            PredictionVariant::NONE => rav1e_ipred_cfl_128_ssse3,
            PredictionVariant::LEFT => rav1e_ipred_cfl_left_ssse3,
            PredictionVariant::TOP => rav1e_ipred_cfl_top_ssse3,
            PredictionVariant::BOTH => rav1e_ipred_cfl_ssse3,
          })(dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle);
        }
        PredictionMode::H_PRED => {
          rav1e_ipred_h_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::V_PRED => {
          rav1e_ipred_v_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::PAETH_PRED => {
          rav1e_ipred_paeth_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_PRED => {
          rav1e_ipred_smooth_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_H_PRED => {
          rav1e_ipred_smooth_h_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_V_PRED => {
          rav1e_ipred_smooth_v_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        _ => call_native(dst),
      }
    } else {
      call_native(dst);
    }
  }
}

#[cfg(test)]
mod test {
  use super::*;
  use crate::frame::{AsRegion, Plane};
  use crate::predict::native;
  use num_traits::*;

  #[test]
  fn pred_matches_u8() {
    let tx_size = TxSize::TX_4X4;
    let bit_depth = 8;
    let cpu = CpuFeatureLevel::default();
    let ac = [0i16; 32 * 32];

    let mut edge_buf: AlignedArray<[u8; 4 * MAX_TX_SIZE + 1]> =
      AlignedArray::uninitialized();
    for i in 0..edge_buf.array.len() {
      edge_buf.array[i] = (i + 32).saturating_sub(2 * MAX_TX_SIZE).as_();
    }

    for (mode, variant) in [
      (PredictionMode::DC_PRED, PredictionVariant::BOTH),
      (PredictionMode::DC_PRED, PredictionVariant::TOP),
      (PredictionMode::DC_PRED, PredictionVariant::LEFT),
      (PredictionMode::DC_PRED, PredictionVariant::NONE),
      (PredictionMode::V_PRED, PredictionVariant::BOTH),
      (PredictionMode::H_PRED, PredictionVariant::BOTH),
      (PredictionMode::PAETH_PRED, PredictionVariant::BOTH),
      (PredictionMode::SMOOTH_PRED, PredictionVariant::BOTH),
      (PredictionMode::SMOOTH_H_PRED, PredictionVariant::BOTH),
      (PredictionMode::SMOOTH_V_PRED, PredictionVariant::BOTH),
      (PredictionMode::D45_PRED, PredictionVariant::BOTH),
      (PredictionMode::D135_PRED, PredictionVariant::BOTH),
      (PredictionMode::D207_PRED, PredictionVariant::BOTH),
    ]
    .iter()
    {
      let angles = match mode {
        PredictionMode::D45_PRED => [
          3, 6, 9, 14, 17, 20, 23, 26, 29, 32, 36, 39, 42, 45, 48, 51, 54, 58,
          61, 64, 67, 70, 73, 76, 81, 84, 87,
        ]
        .iter(),
        PredictionMode::D135_PRED => [
          93, 96, 99, 104, 107, 110, 113, 116, 119, 122, 126, 129, 132, 135,
          138, 141, 144, 148, 151, 154, 157, 160, 163, 166, 171, 174, 177,
        ]
        .iter(),
        PredictionMode::D207_PRED => [
          183, 186, 189, 194, 197, 200, 203, 206, 209, 212, 216, 219, 222,
          225, 228, 231, 234, 238, 241, 244, 247, 250, 253, 256, 261, 264,
          267,
        ]
        .iter(),
        _ => [0].iter(),
      };
      for angle in angles {
        let expected = {
          let mut plane = Plane::wrap(vec![0u8; 4 * 4], 4);
          native::dispatch_predict_intra(
            *mode,
            *variant,
            &mut plane.as_region_mut(),
            tx_size,
            bit_depth,
            &ac,
            *angle,
            &edge_buf,
            cpu,
          );
          let mut data = [0u8; 4 * 4];
          for (v, d) in data.iter_mut().zip(plane.data[..].iter()) {
            *v = *d;
          }
          data
        };

        let mut output = Plane::wrap(vec![0u8; 4 * 4], 4);
        dispatch_predict_intra(
          *mode,
          *variant,
          &mut output.as_region_mut(),
          tx_size,
          bit_depth,
          &ac,
          *angle,
          &edge_buf,
          cpu,
        );
        assert_eq!(expected, &output.data[..]);
      }
    }
  }
}
<commit_msg>Integrate functions from ipred.asm<commit_after>// Copyright (c) 2019, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use crate::context::MAX_TX_SIZE;
use crate::cpu_features::CpuFeatureLevel;
use crate::predict::{native, PredictionMode, PredictionVariant};
use crate::tiling::PlaneRegionMut;
use crate::transform::TxSize;
use crate::util::AlignedArray;
use crate::Pixel;
use libc;
use std::mem::size_of;

macro_rules! decl_angular_ipred_fn {
  ($($f:ident),+) => {
    extern {
      $(
        fn $f(
          dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8,
          width: libc::c_int, height: libc::c_int, angle: libc::c_int,
        );
      )*
    }
  };
}

decl_angular_ipred_fn! {
  rav1e_ipred_dc_avx2,
  rav1e_ipred_dc_ssse3,
  rav1e_ipred_dc_128_avx2,
  rav1e_ipred_dc_128_ssse3,
  rav1e_ipred_dc_left_avx2,
  rav1e_ipred_dc_left_ssse3,
  rav1e_ipred_dc_top_avx2,
  rav1e_ipred_dc_top_ssse3,
  rav1e_ipred_h_avx2,
  rav1e_ipred_h_ssse3,
  rav1e_ipred_v_avx2,
  rav1e_ipred_v_ssse3,
  rav1e_ipred_paeth_avx2,
  rav1e_ipred_paeth_ssse3,
  rav1e_ipred_smooth_avx2,
  rav1e_ipred_smooth_ssse3,
  rav1e_ipred_smooth_h_avx2,
  rav1e_ipred_smooth_h_ssse3,
  rav1e_ipred_smooth_v_avx2,
  rav1e_ipred_smooth_v_ssse3,
  rav1e_ipred_z1_avx2,
  rav1e_ipred_z2_avx2,
  rav1e_ipred_z3_avx2
}

macro_rules! decl_cfl_pred_fn {
  ($($f:ident),+) => {
    extern {
      $(
        fn $f(
          dst: *mut u8, stride: libc::ptrdiff_t, topleft: *const u8,
          width: libc::c_int, height: libc::c_int, ac: *const u8,
          alpha: libc::c_int,
        );
      )*
    }
  };
}

decl_cfl_pred_fn! {
  rav1e_ipred_cfl_avx2,
  rav1e_ipred_cfl_ssse3,
  rav1e_ipred_cfl_128_avx2,
  rav1e_ipred_cfl_128_ssse3,
  rav1e_ipred_cfl_left_avx2,
  rav1e_ipred_cfl_left_ssse3,
  rav1e_ipred_cfl_top_avx2,
  rav1e_ipred_cfl_top_ssse3
}

#[inline(always)]
pub fn dispatch_predict_intra<T: Pixel>(
  mode: PredictionMode, variant: PredictionVariant,
  dst: &mut PlaneRegionMut<'_, T>, tx_size: TxSize, bit_depth: usize,
  ac: &[i16], angle: isize, edge_buf: &AlignedArray<[T; 4 * MAX_TX_SIZE + 1]>,
  cpu: CpuFeatureLevel,
) {
  let call_native = |dst: &mut PlaneRegionMut<'_, T>| {
    native::dispatch_predict_intra(
      mode, variant, dst, tx_size, bit_depth, ac, angle, edge_buf, cpu,
    );
  };

  if size_of::<T>() != 1 {
    return call_native(dst);
  }

  unsafe {
    let dst_ptr = dst.data_ptr_mut() as *mut _;
    let stride = dst.plane_cfg.stride as libc::ptrdiff_t;
    let edge_ptr =
      edge_buf.array.as_ptr().offset(2 * MAX_TX_SIZE as isize) as *const _;
    let w = tx_size.width() as libc::c_int;
    let h = tx_size.height() as libc::c_int;
    let angle = angle as libc::c_int;

    if cpu >= CpuFeatureLevel::AVX2 {
      match mode {
        PredictionMode::DC_PRED => {
          (match variant {
            PredictionVariant::NONE => rav1e_ipred_dc_128_avx2,
            PredictionVariant::LEFT => rav1e_ipred_dc_left_avx2,
            PredictionVariant::TOP => rav1e_ipred_dc_top_avx2,
            PredictionVariant::BOTH => rav1e_ipred_dc_avx2,
          })(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::UV_CFL_PRED => {
          let ac_ptr = ac.as_ptr() as *const _;
          (match variant {
            PredictionVariant::NONE => rav1e_ipred_cfl_128_avx2,
            PredictionVariant::LEFT => rav1e_ipred_cfl_left_avx2,
            PredictionVariant::TOP => rav1e_ipred_cfl_top_avx2,
            PredictionVariant::BOTH => rav1e_ipred_cfl_avx2,
          })(dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle);
        }
        PredictionMode::H_PRED => {
          rav1e_ipred_h_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::V_PRED => {
          rav1e_ipred_v_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::PAETH_PRED => {
          rav1e_ipred_paeth_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_PRED => {
          rav1e_ipred_smooth_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_H_PRED => {
          rav1e_ipred_smooth_h_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_V_PRED => {
          rav1e_ipred_smooth_v_avx2(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::D45_PRED
        | PredictionMode::D63_PRED
        | PredictionMode::D117_PRED
        | PredictionMode::D135_PRED
        | PredictionMode::D153_PRED
        | PredictionMode::D207_PRED => {
          (if angle <= 90 {
            rav1e_ipred_z1_avx2
          } else if angle < 180 {
            rav1e_ipred_z2_avx2
          } else {
            rav1e_ipred_z3_avx2
          })(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        _ => call_native(dst),
      }
    } else if cpu >= CpuFeatureLevel::SSSE3 {
      match mode {
        PredictionMode::DC_PRED => {
          (match variant {
            PredictionVariant::NONE => rav1e_ipred_dc_128_ssse3,
            PredictionVariant::LEFT => rav1e_ipred_dc_left_ssse3,
            PredictionVariant::TOP => rav1e_ipred_dc_top_ssse3,
            PredictionVariant::BOTH => rav1e_ipred_dc_ssse3,
          })(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::UV_CFL_PRED => {
          let ac_ptr = ac.as_ptr() as *const _;
          (match variant {
            PredictionVariant::NONE => rav1e_ipred_cfl_128_ssse3,
            PredictionVariant::LEFT => rav1e_ipred_cfl_left_ssse3,
            PredictionVariant::TOP => rav1e_ipred_cfl_top_ssse3,
            PredictionVariant::BOTH => rav1e_ipred_cfl_ssse3,
          })(dst_ptr, stride, edge_ptr, w, h, ac_ptr, angle);
        }
        PredictionMode::H_PRED => {
          rav1e_ipred_h_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::V_PRED => {
          rav1e_ipred_v_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::PAETH_PRED => {
          rav1e_ipred_paeth_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_PRED => {
          rav1e_ipred_smooth_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_H_PRED => {
          rav1e_ipred_smooth_h_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        PredictionMode::SMOOTH_V_PRED => {
          rav1e_ipred_smooth_v_ssse3(dst_ptr, stride, edge_ptr, w, h, angle);
        }
        _ => call_native(dst),
      }
    } else {
      call_native(dst);
    }
  }
}

#[cfg(test)]
mod test {
  use super::*;
  use crate::frame::{AsRegion, Plane};
  use crate::predict::native;
  use num_traits::*;

  #[test]
  fn pred_matches_u8() {
    let tx_size = TxSize::TX_4X4;
    let bit_depth = 8;
    let cpu = CpuFeatureLevel::default();
    let ac = [0i16; 32 * 32];

    let mut edge_buf: AlignedArray<[u8; 4 * MAX_TX_SIZE + 1]> =
      AlignedArray::uninitialized();
    for i in 0..edge_buf.array.len() {
      edge_buf.array[i] = (i + 32).saturating_sub(2 * MAX_TX_SIZE).as_();
    }

    for (mode, variant) in [
      (PredictionMode::DC_PRED, PredictionVariant::BOTH),
      (PredictionMode::DC_PRED, PredictionVariant::TOP),
      (PredictionMode::DC_PRED, PredictionVariant::LEFT),
      (PredictionMode::DC_PRED, PredictionVariant::NONE),
      (PredictionMode::V_PRED, PredictionVariant::BOTH),
      (PredictionMode::H_PRED, PredictionVariant::BOTH),
      (PredictionMode::PAETH_PRED, PredictionVariant::BOTH),
      (PredictionMode::SMOOTH_PRED, PredictionVariant::BOTH),
      (PredictionMode::SMOOTH_H_PRED, PredictionVariant::BOTH),
      (PredictionMode::SMOOTH_V_PRED, PredictionVariant::BOTH),
      (PredictionMode::D45_PRED, PredictionVariant::BOTH),
      (PredictionMode::D135_PRED, PredictionVariant::BOTH),
      (PredictionMode::D207_PRED, PredictionVariant::BOTH),
    ]
    .iter()
    {
      let angles = match mode {
        PredictionMode::D45_PRED => [
          3, 6, 9, 14, 17, 20, 23, 26, 29, 32, 36, 39, 42, 45, 48, 51, 54, 58,
          61, 64, 67, 70, 73, 76, 81, 84, 87,
        ]
        .iter(),
        PredictionMode::D135_PRED => [
          93, 96, 99, 104, 107, 110, 113, 116, 119, 122, 126, 129, 132, 135,
          138, 141, 144, 148, 151, 154, 157, 160, 163, 166, 171, 174, 177,
        ]
        .iter(),
        PredictionMode::D207_PRED => [
          183, 186, 189, 194, 197, 200, 203, 206, 209, 212, 216, 219, 222,
          225, 228, 231, 234, 238, 241, 244, 247, 250, 253, 256, 261, 264,
          267,
        ]
        .iter(),
        _ => [0].iter(),
      };
      for angle in angles {
        let expected = {
          let mut plane = Plane::wrap(vec![0u8; 4 * 4], 4);
          native::dispatch_predict_intra(
            *mode,
            *variant,
            &mut plane.as_region_mut(),
            tx_size,
            bit_depth,
            &ac,
            *angle,
            &edge_buf,
            cpu,
          );
          let mut data = [0u8; 4 * 4];
          for (v, d) in data.iter_mut().zip(plane.data[..].iter()) {
            *v = *d;
          }
          data
        };

        let mut output = Plane::wrap(vec![0u8; 4 * 4], 4);
        dispatch_predict_intra(
          *mode,
          *variant,
          &mut output.as_region_mut(),
          tx_size,
          bit_depth,
          &ac,
          *angle,
          &edge_buf,
          cpu,
        );
        assert_eq!(expected, &output.data[..]);
      }
    }
  }
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Michael Debertol <michael.debertol..AT..gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

//! Check if a file is ordered

use crate::{
    chunks::{self, Chunk},
    compare_by, open, GlobalSettings,
};
use itertools::Itertools;
use std::{
    cmp::Ordering,
    io::Read,
    iter,
    sync::mpsc::{sync_channel, Receiver, SyncSender},
    thread,
};

/// Check if the file at `path` is ordered.
///
/// # Returns
///
/// The code we should exit with.
pub fn check(path: &str, settings: &GlobalSettings) -> i32 {
    let file = open(path);
    let (recycled_sender, recycled_receiver) = sync_channel(2);
    let (loaded_sender, loaded_receiver) = sync_channel(2);
    thread::spawn({
        let settings = settings.clone();
        move || reader(file, recycled_receiver, loaded_sender, &settings)
    });
    for _ in 0..2 {
        recycled_sender
            .send(Chunk::new(vec![0; 100 * 1024], |_| Vec::new()))
            .ok();
    }

    let mut prev_chunk: Option<Chunk> = None;
    let mut line_idx = 0;
    for chunk in loaded_receiver.iter() {
        line_idx += 1;
        if let Some(prev_chunk) = prev_chunk.take() {
            // Check if the first element of the new chunk is greater than the last
            // element from the previous chunk
            let prev_last = prev_chunk.borrow_lines().last().unwrap();
            let new_first = chunk.borrow_lines().first().unwrap();

            if compare_by(prev_last, new_first, settings) == Ordering::Greater {
                if !settings.check_silent {
                    println!("sort: {}:{}: disorder: {}", path, line_idx, new_first.line);
                }
                return 1;
            }
            recycled_sender.send(prev_chunk).ok();
        }

        for (a, b) in chunk.borrow_lines().iter().tuple_windows() {
            line_idx += 1;
            if compare_by(a, b, settings) == Ordering::Greater {
                if !settings.check_silent {
                    println!("sort: {}:{}: disorder: {}", path, line_idx, b.line);
                }
                return 1;
            }
        }

        prev_chunk = Some(chunk);
    }
    0
}

/// The function running on the reader thread.
fn reader(
    mut file: Box<dyn Read + Send>,
    receiver: Receiver<Chunk>,
    sender: SyncSender<Chunk>,
    settings: &GlobalSettings,
) {
    let mut carry_over = vec![];
    for chunk in receiver.iter() {
        let (recycled_lines, recycled_buffer) = chunk.recycle();
        let should_continue = chunks::read(
            &sender,
            recycled_buffer,
            None,
            &mut carry_over,
            &mut file,
            &mut iter::empty(),
            if settings.zero_terminated {
                b'\0'
            } else {
                b'\n'
            },
            recycled_lines,
            settings,
        );
        if !should_continue {
            break;
        }
    }
}
<commit_msg>sort: better convey that the return value should be ignored<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Michael Debertol <michael.debertol..AT..gmail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

//! Check if a file is ordered

use crate::{
    chunks::{self, Chunk},
    compare_by, open, GlobalSettings,
};
use itertools::Itertools;
use std::{
    cmp::Ordering,
    io::Read,
    iter,
    sync::mpsc::{sync_channel, Receiver, SyncSender},
    thread,
};

/// Check if the file at `path` is ordered.
///
/// # Returns
///
/// The code we should exit with.
pub fn check(path: &str, settings: &GlobalSettings) -> i32 {
    let file = open(path);
    let (recycled_sender, recycled_receiver) = sync_channel(2);
    let (loaded_sender, loaded_receiver) = sync_channel(2);
    thread::spawn({
        let settings = settings.clone();
        move || reader(file, recycled_receiver, loaded_sender, &settings)
    });
    for _ in 0..2 {
        let _ = recycled_sender.send(Chunk::new(vec![0; 100 * 1024], |_| Vec::new()));
    }

    let mut prev_chunk: Option<Chunk> = None;
    let mut line_idx = 0;
    for chunk in loaded_receiver.iter() {
        line_idx += 1;
        if let Some(prev_chunk) = prev_chunk.take() {
            // Check if the first element of the new chunk is greater than the last
            // element from the previous chunk
            let prev_last = prev_chunk.borrow_lines().last().unwrap();
            let new_first = chunk.borrow_lines().first().unwrap();

            if compare_by(prev_last, new_first, settings) == Ordering::Greater {
                if !settings.check_silent {
                    println!("sort: {}:{}: disorder: {}", path, line_idx, new_first.line);
                }
                return 1;
            }
            let _ = recycled_sender.send(prev_chunk);
        }

        for (a, b) in chunk.borrow_lines().iter().tuple_windows() {
            line_idx += 1;
            if compare_by(a, b, settings) == Ordering::Greater {
                if !settings.check_silent {
                    println!("sort: {}:{}: disorder: {}", path, line_idx, b.line);
                }
                return 1;
            }
        }

        prev_chunk = Some(chunk);
    }
    0
}

/// The function running on the reader thread.
fn reader(
    mut file: Box<dyn Read + Send>,
    receiver: Receiver<Chunk>,
    sender: SyncSender<Chunk>,
    settings: &GlobalSettings,
) {
    let mut carry_over = vec![];
    for chunk in receiver.iter() {
        let (recycled_lines, recycled_buffer) = chunk.recycle();
        let should_continue = chunks::read(
            &sender,
            recycled_buffer,
            None,
            &mut carry_over,
            &mut file,
            &mut iter::empty(),
            if settings.zero_terminated {
                b'\0'
            } else {
                b'\n'
            },
            recycled_lines,
            settings,
        );
        if !should_continue {
            break;
        }
    }
}
<|endoftext|>


<commit_before>use crate::{t, VERSION};
use std::fmt::Write as _;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use std::{
    env, fmt, fs,
    io::{self, Write},
};

#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Profile {
    Compiler,
    Codegen,
    Library,
    Tools,
    User,
}

impl Profile {
    fn include_path(&self, src_path: &Path) -> PathBuf {
        PathBuf::from(format!("{}/src/bootstrap/defaults/config.{}.toml", src_path.display(), self))
    }

    pub fn all() -> impl Iterator<Item = Self> {
        use Profile::*;
        // N.B. these are ordered by how they are displayed, not alphabetically
        [Library, Compiler, Codegen, Tools, User].iter().copied()
    }

    pub fn purpose(&self) -> String {
        use Profile::*;
        match self {
            Library => "Contribute to the standard library",
            Compiler => "Contribute to the compiler itself",
            Codegen => "Contribute to the compiler, and also modify LLVM or codegen",
            Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)",
            User => "Install Rust from source",
        }
        .to_string()
    }

    pub fn all_for_help(indent: &str) -> String {
        let mut out = String::new();
        for choice in Profile::all() {
            writeln!(&mut out, "{}{}: {}", indent, choice, choice.purpose()).unwrap();
        }
        out
    }
}

impl FromStr for Profile {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "lib" | "library" => Ok(Profile::Library),
            "compiler" => Ok(Profile::Compiler),
            "llvm" | "codegen" => Ok(Profile::Codegen),
            "maintainer" | "user" => Ok(Profile::User),
            "tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => {
                Ok(Profile::Tools)
            }
            _ => Err(format!("unknown profile: '{}'", s)),
        }
    }
}

impl fmt::Display for Profile {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Profile::Compiler => write!(f, "compiler"),
            Profile::Codegen => write!(f, "codegen"),
            Profile::Library => write!(f, "library"),
            Profile::User => write!(f, "user"),
            Profile::Tools => write!(f, "tools"),
        }
    }
}

pub fn setup(src_path: &Path, profile: Profile) {
    let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);

    if cfg_file.as_ref().map_or(false, |f| f.exists()) {
        let file = cfg_file.unwrap();
        println!(
            "error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
            file.display()
        );
        println!("help: try adding `profile = \"{}\"` at the top of {}", profile, file.display());
        println!(
            "note: this will use the configuration in {}",
            profile.include_path(src_path).display()
        );
        std::process::exit(1);
    }

    let path = cfg_file.unwrap_or_else(|| "config.toml".into());
    let settings = format!(
        "# Includes one of the default files in src/bootstrap/defaults\n\
    profile = \"{}\"\n\
    changelog-seen = {}\n",
        profile, VERSION
    );
    t!(fs::write(path, settings));

    let include_path = profile.include_path(src_path);
    println!("`x.py` will now use the configuration at {}", include_path.display());

    let suggestions = match profile {
        Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
        Profile::Tools => &[
            "check",
            "build",
            "test src/test/rustdoc*",
            "test src/tools/clippy",
            "test src/tools/miri",
            "test src/tools/rustfmt",
        ],
        Profile::Library => &["check", "build", "test library/std", "doc"],
        Profile::User => &["dist", "build"],
    };

    println!();

    t!(install_git_hook_maybe(src_path));

    println!();

    println!("To get started, try one of the following commands:");
    for cmd in suggestions {
        println!("- `x.py {}`", cmd);
    }

    if profile != Profile::User {
        println!(
            "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
        );
    }
}

// Used to get the path for `Subcommand::Setup`
pub fn interactive_path() -> io::Result<Profile> {
    fn abbrev_all() -> impl Iterator<Item = ((String, String), Profile)> {
        ('a'..)
            .zip(1..)
            .map(|(letter, number)| (letter.to_string(), number.to_string()))
            .zip(Profile::all())
    }

    fn parse_with_abbrev(input: &str) -> Result<Profile, String> {
        let input = input.trim().to_lowercase();
        for ((letter, number), profile) in abbrev_all() {
            if input == letter || input == number {
                return Ok(profile);
            }
        }
        input.parse()
    }

    println!("Welcome to the Rust project! What do you want to do with x.py?");
    for ((letter, _), profile) in abbrev_all() {
        println!("{}) {}: {}", letter, profile, profile.purpose());
    }
    let template = loop {
        print!(
            "Please choose one ({}): ",
            abbrev_all().map(|((l, _), _)| l).collect::<Vec<_>>().join("/")
        );
        io::stdout().flush()?;
        let mut input = String::new();
        io::stdin().read_line(&mut input)?;
        if input.is_empty() {
            eprintln!("EOF on stdin, when expecting answer to question.  Giving up.");
            std::process::exit(1);
        }
        break match parse_with_abbrev(&input) {
            Ok(profile) => profile,
            Err(err) => {
                println!("error: {}", err);
                println!("note: press Ctrl+C to exit");
                continue;
            }
        };
    };
    Ok(template)
}

// install a git hook to automatically run tidy --bless, if they want
fn install_git_hook_maybe(src_path: &Path) -> io::Result<()> {
    let mut input = String::new();
    println!(
        "Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` on each commit
to ensure your code is up to par. If you decide later that this behavior is undesirable,
simply delete the `pre-commit` file from .git/hooks."
    );

    let should_install = loop {
        print!("Would you like to install the git hook?: [y/N] ");
        io::stdout().flush()?;
        input.clear();
        io::stdin().read_line(&mut input)?;
        break match input.trim().to_lowercase().as_str() {
            "y" | "yes" => true,
            "n" | "no" | "" => false,
            _ => {
                println!("error: unrecognized option '{}'", input.trim());
                println!("note: press Ctrl+C to exit");
                continue;
            }
        };
    };

    if should_install {
        let src = src_path.join("src").join("etc").join("pre-commit.sh");
        let git = t!(Command::new("git").args(&["rev-parse", "--git-common-dir"]).output().map(
            |output| {
                assert!(output.status.success(), "failed to run `git`");
                PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
            }
        ));
        let dst = git.join("hooks").join("pre-commit");
        match fs::hard_link(src, &dst) {
            Err(e) => println!(
                "error: could not create hook {}: do you already have the git hook installed?\n{}",
                dst.display(),
                e
            ),
            Ok(_) => println!("Linked `src/etc/pre-commit.sh` to `.git/hooks/pre-commit`"),
        };
    } else {
        println!("Ok, skipping installation!");
    }
    Ok(())
}
<commit_msg>Rollup merge of #89212 - Sl1mb0:xpy-toolchain-link, r=jyn514<commit_after>use crate::TargetSelection;
use crate::{t, VERSION};
use std::fmt::Write as _;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use std::{
    env, fmt, fs,
    io::{self, Write},
};

#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Profile {
    Compiler,
    Codegen,
    Library,
    Tools,
    User,
}

impl Profile {
    fn include_path(&self, src_path: &Path) -> PathBuf {
        PathBuf::from(format!("{}/src/bootstrap/defaults/config.{}.toml", src_path.display(), self))
    }

    pub fn all() -> impl Iterator<Item = Self> {
        use Profile::*;
        // N.B. these are ordered by how they are displayed, not alphabetically
        [Library, Compiler, Codegen, Tools, User].iter().copied()
    }

    pub fn purpose(&self) -> String {
        use Profile::*;
        match self {
            Library => "Contribute to the standard library",
            Compiler => "Contribute to the compiler itself",
            Codegen => "Contribute to the compiler, and also modify LLVM or codegen",
            Tools => "Contribute to tools which depend on the compiler, but do not modify it directly (e.g. rustdoc, clippy, miri)",
            User => "Install Rust from source",
        }
        .to_string()
    }

    pub fn all_for_help(indent: &str) -> String {
        let mut out = String::new();
        for choice in Profile::all() {
            writeln!(&mut out, "{}{}: {}", indent, choice, choice.purpose()).unwrap();
        }
        out
    }
}

impl FromStr for Profile {
    type Err = String;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "lib" | "library" => Ok(Profile::Library),
            "compiler" => Ok(Profile::Compiler),
            "llvm" | "codegen" => Ok(Profile::Codegen),
            "maintainer" | "user" => Ok(Profile::User),
            "tools" | "tool" | "rustdoc" | "clippy" | "miri" | "rustfmt" | "rls" => {
                Ok(Profile::Tools)
            }
            _ => Err(format!("unknown profile: '{}'", s)),
        }
    }
}

impl fmt::Display for Profile {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Profile::Compiler => write!(f, "compiler"),
            Profile::Codegen => write!(f, "codegen"),
            Profile::Library => write!(f, "library"),
            Profile::User => write!(f, "user"),
            Profile::Tools => write!(f, "tools"),
        }
    }
}

pub fn setup(src_path: &Path, profile: Profile) {
    let cfg_file = env::var_os("BOOTSTRAP_CONFIG").map(PathBuf::from);

    if cfg_file.as_ref().map_or(false, |f| f.exists()) {
        let file = cfg_file.unwrap();
        println!(
            "error: you asked `x.py` to setup a new config file, but one already exists at `{}`",
            file.display()
        );
        println!("help: try adding `profile = \"{}\"` at the top of {}", profile, file.display());
        println!(
            "note: this will use the configuration in {}",
            profile.include_path(src_path).display()
        );
        std::process::exit(1);
    }

    let path = cfg_file.unwrap_or_else(|| "config.toml".into());
    let settings = format!(
        "# Includes one of the default files in src/bootstrap/defaults\n\
    profile = \"{}\"\n\
    changelog-seen = {}\n",
        profile, VERSION
    );
    t!(fs::write(path, settings));

    let include_path = profile.include_path(src_path);
    println!("`x.py` will now use the configuration at {}", include_path.display());

    let build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
    let stage_path = ["build", build.rustc_target_arg(), "stage1"].join("/");

    println!();

    if !rustup_installed() && profile != Profile::User {
        println!("`rustup` is not installed; cannot link `stage1` toolchain");
    } else if stage_dir_exists(&stage_path[..]) {
        attempt_toolchain_link(&stage_path[..]);
    }

    let suggestions = match profile {
        Profile::Codegen | Profile::Compiler => &["check", "build", "test"][..],
        Profile::Tools => &[
            "check",
            "build",
            "test src/test/rustdoc*",
            "test src/tools/clippy",
            "test src/tools/miri",
            "test src/tools/rustfmt",
        ],
        Profile::Library => &["check", "build", "test library/std", "doc"],
        Profile::User => &["dist", "build"],
    };

    println!();

    t!(install_git_hook_maybe(src_path));

    println!();

    println!("To get started, try one of the following commands:");
    for cmd in suggestions {
        println!("- `x.py {}`", cmd);
    }

    if profile != Profile::User {
        println!(
            "For more suggestions, see https://rustc-dev-guide.rust-lang.org/building/suggested.html"
        );
    }
}

fn rustup_installed() -> bool {
    Command::new("rustup")
        .arg("--version")
        .stdout(std::process::Stdio::null())
        .output()
        .map_or(false, |output| output.status.success())
}

fn stage_dir_exists(stage_path: &str) -> bool {
    match fs::create_dir(&stage_path[..]) {
        Ok(_) => true,
        Err(_) => Path::new(&stage_path[..]).exists(),
    }
}

fn attempt_toolchain_link(stage_path: &str) {
    if toolchain_is_linked() {
        return;
    }

    if try_link_toolchain(&stage_path[..]) {
        println!(
            "Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain"
        );
    } else {
        println!("`rustup` failed to link stage 1 build to `stage1` toolchain");
        println!(
            "To manually link stage 1 build to `stage1` toolchain, run:\n
            `rustup toolchain link stage1 {}`",
            &stage_path[..]
        );
    }
}

fn toolchain_is_linked() -> bool {
    match Command::new("rustup")
        .args(&["toolchain", "list"])
        .stdout(std::process::Stdio::piped())
        .output()
    {
        Ok(toolchain_list) => {
            if !String::from_utf8_lossy(&toolchain_list.stdout).contains("stage1") {
                return false;
            }
            // The toolchain has already been linked.
            println!(
                "`stage1` toolchain already linked; not attempting to link `stage1` toolchain"
            );
        }
        Err(_) => {
            // In this case, we don't know if the `stage1` toolchain has been linked;
            // but `rustup` failed, so let's not go any further.
            println!(
                "`rustup` failed to list current toolchains; not attempting to link `stage1` toolchain"
            );
        }
    }
    true
}

fn try_link_toolchain(stage_path: &str) -> bool {
    Command::new("rustup")
        .stdout(std::process::Stdio::null())
        .args(&["toolchain", "link", "stage1", &stage_path[..]])
        .output()
        .map_or(false, |output| output.status.success())
}

// Used to get the path for `Subcommand::Setup`
pub fn interactive_path() -> io::Result<Profile> {
    fn abbrev_all() -> impl Iterator<Item = ((String, String), Profile)> {
        ('a'..)
            .zip(1..)
            .map(|(letter, number)| (letter.to_string(), number.to_string()))
            .zip(Profile::all())
    }

    fn parse_with_abbrev(input: &str) -> Result<Profile, String> {
        let input = input.trim().to_lowercase();
        for ((letter, number), profile) in abbrev_all() {
            if input == letter || input == number {
                return Ok(profile);
            }
        }
        input.parse()
    }

    println!("Welcome to the Rust project! What do you want to do with x.py?");
    for ((letter, _), profile) in abbrev_all() {
        println!("{}) {}: {}", letter, profile, profile.purpose());
    }
    let template = loop {
        print!(
            "Please choose one ({}): ",
            abbrev_all().map(|((l, _), _)| l).collect::<Vec<_>>().join("/")
        );
        io::stdout().flush()?;
        let mut input = String::new();
        io::stdin().read_line(&mut input)?;
        if input.is_empty() {
            eprintln!("EOF on stdin, when expecting answer to question.  Giving up.");
            std::process::exit(1);
        }
        break match parse_with_abbrev(&input) {
            Ok(profile) => profile,
            Err(err) => {
                println!("error: {}", err);
                println!("note: press Ctrl+C to exit");
                continue;
            }
        };
    };
    Ok(template)
}

// install a git hook to automatically run tidy --bless, if they want
fn install_git_hook_maybe(src_path: &Path) -> io::Result<()> {
    let mut input = String::new();
    println!(
        "Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality.
If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` on each commit
to ensure your code is up to par. If you decide later that this behavior is undesirable,
simply delete the `pre-commit` file from .git/hooks."
    );

    let should_install = loop {
        print!("Would you like to install the git hook?: [y/N] ");
        io::stdout().flush()?;
        input.clear();
        io::stdin().read_line(&mut input)?;
        break match input.trim().to_lowercase().as_str() {
            "y" | "yes" => true,
            "n" | "no" | "" => false,
            _ => {
                println!("error: unrecognized option '{}'", input.trim());
                println!("note: press Ctrl+C to exit");
                continue;
            }
        };
    };

    if should_install {
        let src = src_path.join("src").join("etc").join("pre-commit.sh");
        let git = t!(Command::new("git").args(&["rev-parse", "--git-common-dir"]).output().map(
            |output| {
                assert!(output.status.success(), "failed to run `git`");
                PathBuf::from(t!(String::from_utf8(output.stdout)).trim())
            }
        ));
        let dst = git.join("hooks").join("pre-commit");
        match fs::hard_link(src, &dst) {
            Err(e) => println!(
                "error: could not create hook {}: do you already have the git hook installed?\n{}",
                dst.display(),
                e
            ),
            Ok(_) => println!("Linked `src/etc/pre-commit.sh` to `.git/hooks/pre-commit`"),
        };
    } else {
        println!("Ok, skipping installation!");
    }
    Ok(())
}
<|endoftext|>