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

#![deny(unsafe_code)]
#![crate_name = "servo_url"]
#![crate_type = "rlib"]

#[macro_use]
extern crate malloc_size_of;
#[macro_use]
extern crate malloc_size_of_derive;
#[macro_use]
extern crate serde;

pub mod origin;

pub use crate::origin::{ImmutableOrigin, MutableOrigin, OpaqueOrigin};

use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::Hasher;
use std::net::IpAddr;
use std::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};
use std::path::Path;
use std::sync::Arc;
use url::{Position, Url};

pub use url::Host;

#[derive(Clone, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)]
pub struct ServoUrl(#[ignore_malloc_size_of = "Arc"] Arc<Url>);

impl ServoUrl {
    pub fn from_url(url: Url) -> Self {
        ServoUrl(Arc::new(url))
    }

    pub fn parse_with_base(base: Option<&Self>, input: &str) -> Result<Self, url::ParseError> {
        Url::options()
            .base_url(base.map(|b| &*b.0))
            .parse(input)
            .map(Self::from_url)
    }

    pub fn into_string(self) -> String {
        Arc::try_unwrap(self.0)
            .unwrap_or_else(|s| (*s).clone())
            .into_string()
    }

    pub fn into_url(self) -> Url {
        Arc::try_unwrap(self.0).unwrap_or_else(|s| (*s).clone())
    }

    pub fn as_url(&self) -> &Url {
        &self.0
    }

    pub fn parse(input: &str) -> Result<Self, url::ParseError> {
        Url::parse(input).map(Self::from_url)
    }

    pub fn cannot_be_a_base(&self) -> bool {
        self.0.cannot_be_a_base()
    }

    pub fn domain(&self) -> Option<&str> {
        self.0.domain()
    }

    pub fn fragment(&self) -> Option<&str> {
        self.0.fragment()
    }

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

    pub fn origin(&self) -> ImmutableOrigin {
        ImmutableOrigin::new(self.0.origin())
    }

    pub fn scheme(&self) -> &str {
        self.0.scheme()
    }

    pub fn is_secure_scheme(&self) -> bool {
        let scheme = self.scheme();
        scheme == "https" || scheme == "wss"
    }

    pub fn is_chrome(&self) -> bool {
        self.scheme() == "chrome"
    }

    pub fn as_str(&self) -> &str {
        self.0.as_str()
    }

    pub fn as_mut_url(&mut self) -> &mut Url {
        Arc::make_mut(&mut self.0)
    }

    pub fn set_username(&mut self, user: &str) -> Result<(), ()> {
        self.as_mut_url().set_username(user)
    }

    pub fn set_ip_host(&mut self, addr: IpAddr) -> Result<(), ()> {
        self.as_mut_url().set_ip_host(addr)
    }

    pub fn set_password(&mut self, pass: Option<&str>) -> Result<(), ()> {
        self.as_mut_url().set_password(pass)
    }

    pub fn set_fragment(&mut self, fragment: Option<&str>) {
        self.as_mut_url().set_fragment(fragment)
    }

    pub fn username(&self) -> &str {
        self.0.username()
    }

    pub fn password(&self) -> Option<&str> {
        self.0.password()
    }

    pub fn to_file_path(&self) -> Result<::std::path::PathBuf, ()> {
        self.0.to_file_path()
    }

    pub fn host(&self) -> Option<url::Host<&str>> {
        self.0.host()
    }

    pub fn host_str(&self) -> Option<&str> {
        self.0.host_str()
    }

    pub fn port(&self) -> Option<u16> {
        self.0.port()
    }

    pub fn port_or_known_default(&self) -> Option<u16> {
        self.0.port_or_known_default()
    }

    pub fn join(&self, input: &str) -> Result<ServoUrl, url::ParseError> {
        self.0.join(input).map(Self::from_url)
    }

    pub fn path_segments(&self) -> Option<::std::str::Split<char>> {
        self.0.path_segments()
    }

    pub fn query(&self) -> Option<&str> {
        self.0.query()
    }

    pub fn from_file_path<P: AsRef<Path>>(path: P) -> Result<Self, ()> {
        Ok(Self::from_url(Url::from_file_path(path)?))
    }
}

impl fmt::Display for ServoUrl {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(formatter)
    }
}

impl fmt::Debug for ServoUrl {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        if self.0.as_str().len() > 40 {
            let hasher = DefaultHasher::new();
            let truncated: String = self.0.as_str().chars().take(40).collect();
            let result = format!("{}... ({})", truncated, hasher.finish().to_string());
            return result.fmt(formatter);
        }
        self.0.fmt(formatter)
    }
}

impl Index<RangeFull> for ServoUrl {
    type Output = str;
    fn index(&self, _: RangeFull) -> &str {
        &self.0[..]
    }
}

impl Index<RangeFrom<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: RangeFrom<Position>) -> &str {
        &self.0[range]
    }
}

impl Index<RangeTo<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: RangeTo<Position>) -> &str {
        &self.0[range]
    }
}

impl Index<Range<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: Range<Position>) -> &str {
        &self.0[range]
    }
}

impl From<Url> for ServoUrl {
    fn from(url: Url) -> Self {
        ServoUrl::from_url(url)
    }
}

impl serde::Serialize for ServoUrl {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        url_serde::serialize(&*self.0, serializer)
    }
}

impl<'de> serde::Deserialize<'de> for ServoUrl {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        url_serde::deserialize(deserializer).map(Self::from_url)
    }
}
<commit_msg>Use hex for debug url hash.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

#![deny(unsafe_code)]
#![crate_name = "servo_url"]
#![crate_type = "rlib"]

#[macro_use]
extern crate malloc_size_of;
#[macro_use]
extern crate malloc_size_of_derive;
#[macro_use]
extern crate serde;

pub mod origin;

pub use crate::origin::{ImmutableOrigin, MutableOrigin, OpaqueOrigin};

use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::Hasher;
use std::net::IpAddr;
use std::ops::{Index, Range, RangeFrom, RangeFull, RangeTo};
use std::path::Path;
use std::sync::Arc;
use url::{Position, Url};

pub use url::Host;

#[derive(Clone, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)]
pub struct ServoUrl(#[ignore_malloc_size_of = "Arc"] Arc<Url>);

impl ServoUrl {
    pub fn from_url(url: Url) -> Self {
        ServoUrl(Arc::new(url))
    }

    pub fn parse_with_base(base: Option<&Self>, input: &str) -> Result<Self, url::ParseError> {
        Url::options()
            .base_url(base.map(|b| &*b.0))
            .parse(input)
            .map(Self::from_url)
    }

    pub fn into_string(self) -> String {
        Arc::try_unwrap(self.0)
            .unwrap_or_else(|s| (*s).clone())
            .into_string()
    }

    pub fn into_url(self) -> Url {
        Arc::try_unwrap(self.0).unwrap_or_else(|s| (*s).clone())
    }

    pub fn as_url(&self) -> &Url {
        &self.0
    }

    pub fn parse(input: &str) -> Result<Self, url::ParseError> {
        Url::parse(input).map(Self::from_url)
    }

    pub fn cannot_be_a_base(&self) -> bool {
        self.0.cannot_be_a_base()
    }

    pub fn domain(&self) -> Option<&str> {
        self.0.domain()
    }

    pub fn fragment(&self) -> Option<&str> {
        self.0.fragment()
    }

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

    pub fn origin(&self) -> ImmutableOrigin {
        ImmutableOrigin::new(self.0.origin())
    }

    pub fn scheme(&self) -> &str {
        self.0.scheme()
    }

    pub fn is_secure_scheme(&self) -> bool {
        let scheme = self.scheme();
        scheme == "https" || scheme == "wss"
    }

    pub fn is_chrome(&self) -> bool {
        self.scheme() == "chrome"
    }

    pub fn as_str(&self) -> &str {
        self.0.as_str()
    }

    pub fn as_mut_url(&mut self) -> &mut Url {
        Arc::make_mut(&mut self.0)
    }

    pub fn set_username(&mut self, user: &str) -> Result<(), ()> {
        self.as_mut_url().set_username(user)
    }

    pub fn set_ip_host(&mut self, addr: IpAddr) -> Result<(), ()> {
        self.as_mut_url().set_ip_host(addr)
    }

    pub fn set_password(&mut self, pass: Option<&str>) -> Result<(), ()> {
        self.as_mut_url().set_password(pass)
    }

    pub fn set_fragment(&mut self, fragment: Option<&str>) {
        self.as_mut_url().set_fragment(fragment)
    }

    pub fn username(&self) -> &str {
        self.0.username()
    }

    pub fn password(&self) -> Option<&str> {
        self.0.password()
    }

    pub fn to_file_path(&self) -> Result<::std::path::PathBuf, ()> {
        self.0.to_file_path()
    }

    pub fn host(&self) -> Option<url::Host<&str>> {
        self.0.host()
    }

    pub fn host_str(&self) -> Option<&str> {
        self.0.host_str()
    }

    pub fn port(&self) -> Option<u16> {
        self.0.port()
    }

    pub fn port_or_known_default(&self) -> Option<u16> {
        self.0.port_or_known_default()
    }

    pub fn join(&self, input: &str) -> Result<ServoUrl, url::ParseError> {
        self.0.join(input).map(Self::from_url)
    }

    pub fn path_segments(&self) -> Option<::std::str::Split<char>> {
        self.0.path_segments()
    }

    pub fn query(&self) -> Option<&str> {
        self.0.query()
    }

    pub fn from_file_path<P: AsRef<Path>>(path: P) -> Result<Self, ()> {
        Ok(Self::from_url(Url::from_file_path(path)?))
    }
}

impl fmt::Display for ServoUrl {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(formatter)
    }
}

impl fmt::Debug for ServoUrl {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        if self.0.as_str().len() > 40 {
            let hasher = DefaultHasher::new();
            let truncated: String = self.0.as_str().chars().take(40).collect();
            let result = format!("{}... ({:x})", truncated, hasher.finish().to_string());
            return result.fmt(formatter);
        }
        self.0.fmt(formatter)
    }
}

impl Index<RangeFull> for ServoUrl {
    type Output = str;
    fn index(&self, _: RangeFull) -> &str {
        &self.0[..]
    }
}

impl Index<RangeFrom<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: RangeFrom<Position>) -> &str {
        &self.0[range]
    }
}

impl Index<RangeTo<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: RangeTo<Position>) -> &str {
        &self.0[range]
    }
}

impl Index<Range<Position>> for ServoUrl {
    type Output = str;
    fn index(&self, range: Range<Position>) -> &str {
        &self.0[range]
    }
}

impl From<Url> for ServoUrl {
    fn from(url: Url) -> Self {
        ServoUrl::from_url(url)
    }
}

impl serde::Serialize for ServoUrl {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        url_serde::serialize(&*self.0, serializer)
    }
}

impl<'de> serde::Deserialize<'de> for ServoUrl {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        url_serde::deserialize(deserializer).map(Self::from_url)
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::rc::Rc;

use hbs;
use serde::{Deserialize, Serialize};
use futures::{Future, future, Stream};
use urlencoded::Deserializer;
use url::form_urlencoded;

use rigging::Error;
use rigging::http;
use rigging::environment::Environment;
use rigging::format::*;
use rigging::method::Method;
use rigging::resource::ResourceEndpoint;

const MIME: &'static str = "text/plain; charset=utf-8";

pub struct Handlebars {
    registry: hbs::Handlebars,
}

#[derive(Serialize)]
struct Object<T: Serialize> {
    resource: T,
}

#[derive(Serialize)]
struct Objects<T: Serialize> {
    resources: T,
}

impl<T, R, M> Format<T, R, M> for Handlebars
where
    T: ResourceEndpoint,
    M: ?Sized + Method<T>,
    M::Request: for<'d> Deserialize<'d> + 'static,
    R: Serialize,
{
    type ReqFuture = Box<Future<Item = M::Request, Error = Error>>;

    fn receive_request(_: &Rc<Self>, req: http::Request, _: &mut Environment) -> Self::ReqFuture {
        let future = req.body().fold(vec![], |mut vec, chunk| -> Result<_, http::Error> {
            vec.extend(&*chunk);
            Ok(vec)
        });
        Box::new(future.then(|result| match result {
            Ok(data)    => {
                let deserializer = Deserializer::new(form_urlencoded::parse(&data));
                M::Request::deserialize(deserializer).map_err(|e| Error::from_err(e, http::StatusCode::BadRequest))
            }
            Err(e)      => Err(Error::from_err(e, http::StatusCode::InternalServerError)),
        }))
    }

    fn present_unit(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where
        M: Method<T, Response = ()>
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|_| this.registry.render(&key.to_string(), &()).map_err(|e| {
                Error::from_err(e, http::StatusCode::BadRequest)
            })) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_resource(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where M: Method<T, Response = R>,
        R: ResourceEndpoint
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|resource| this.registry.render(&key.to_string(), &Object { resource }).map_err(|e| {
                Error::from_err(e, http::StatusCode::BadRequest)
            })) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_collection(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where
        M: Method<T, Response = Vec<R>>,
        R: ResourceEndpoint
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|resources| this.registry.render(&key.to_string(), &Objects { resources }).map_err(|e| {
                Error::from_err(e, http::StatusCode::BadRequest)
            })) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_error(_: &Rc<Self>, error: Error, _: &mut Environment) -> http::BoxFuture {
        Box::new(future::ok(respond_with_err(error)))
    }
}

impl BuildFormat for Handlebars {
    fn build(templates: &[Template]) -> Result<Self, io::Error> {
        let mut hbs = Handlebars { registry: hbs::Handlebars::new() };
        for template in templates {
            hbs.registry.register_template_string(&template.key.to_string(), template.template).map_err(|_| -> io::Error { unimplemented!() })?;
        }
        Ok(hbs)
    }
}

fn respond_with(body: String) -> http::Response {
    let status = if body.len() == 0 { http::StatusCode::NoContent } else { http::StatusCode::Ok };
    http::Response::new().with_status(status)
                         .with_header(http::headers::ContentLength(body.len() as u64))
                         .with_header(http::headers::ContentType(MIME.parse().unwrap()))
                         .with_body(body)
}

fn respond_with_err(err: Error) -> http::Response {
    #[cfg(debug_assertions)]
    let body = format!("{:?}", err);
    #[cfg(not(debug_assertions))]
    let body = format!("{}", err);
    http::Response::new().with_status(err.status_code())
                         .with_header(http::headers::ContentLength(body.len() as u64))
                         .with_body(body)
}
<commit_msg>Assume an HTML MIME type for handlebars.<commit_after>use std::io;
use std::rc::Rc;

use hbs;
use serde::{Deserialize, Serialize};
use futures::{Future, future, Stream};
use urlencoded::Deserializer;
use url::form_urlencoded;

use rigging::Error;
use rigging::http;
use rigging::environment::Environment;
use rigging::format::*;
use rigging::method::Method;
use rigging::resource::ResourceEndpoint;

const MIME: &'static str = "text/html; charset=utf-8";

pub struct Handlebars {
    registry: hbs::Handlebars,
}

#[derive(Serialize)]
struct Object<T: Serialize> {
    resource: T,
}

#[derive(Serialize)]
struct Objects<T: Serialize> {
    resources: T,
}

impl<T, R, M> Format<T, R, M> for Handlebars
where
    T: ResourceEndpoint,
    M: ?Sized + Method<T>,
    M::Request: for<'d> Deserialize<'d> + 'static,
    R: Serialize,
{
    type ReqFuture = Box<Future<Item = M::Request, Error = Error>>;

    fn receive_request(_: &Rc<Self>, req: http::Request, _: &mut Environment) -> Self::ReqFuture {
        let future = req.body().fold(vec![], |mut vec, chunk| -> Result<_, http::Error> {
            vec.extend(&*chunk);
            Ok(vec)
        });
        Box::new(future.then(|result| match result {
            Ok(data)    => {
                let deserializer = Deserializer::new(form_urlencoded::parse(&data));
                M::Request::deserialize(deserializer).map_err(|e| Error::from_err(e, http::StatusCode::BadRequest))
            }
            Err(e)      => Err(Error::from_err(e, http::StatusCode::InternalServerError)),
        }))
    }

    fn present_unit(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where
        M: Method<T, Response = ()>
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|_| this.registry.render(&key.to_string(), &()).map_err(|e| {
                Error::from_err(e, http::StatusCode::BadRequest)
            })) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_resource(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where M: Method<T, Response = R>,
        R: ResourceEndpoint
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|resource| this.registry.render(&key.to_string(), &Object { resource }).map_err(|e| {
                Error::from_err(e, http::StatusCode::BadRequest)
            })) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_collection(this: &Rc<Self>, future: M::Future, key: TemplateKey, _: &mut Environment) -> http::BoxFuture
    where
        M: Method<T, Response = Vec<R>>,
        R: ResourceEndpoint
    {
        let this = this.clone();
        Box::new(future.then(move |result| {
            match result.and_then(|resources| this.registry.render(&key.to_string(), &Objects { resources }).map_err(|e| {
                Error::from_err(e, http::StatusCode::BadRequest)
            })) {
                Ok(body)    => Ok(respond_with(body)),
                Err(err)    => Ok(respond_with_err(err)),
            }
        }))
    }

    fn present_error(_: &Rc<Self>, error: Error, _: &mut Environment) -> http::BoxFuture {
        Box::new(future::ok(respond_with_err(error)))
    }
}

impl BuildFormat for Handlebars {
    fn build(templates: &[Template]) -> Result<Self, io::Error> {
        let mut hbs = Handlebars { registry: hbs::Handlebars::new() };
        for template in templates {
            hbs.registry.register_template_string(&template.key.to_string(), template.template).map_err(|_| -> io::Error { unimplemented!() })?;
        }
        Ok(hbs)
    }
}

fn respond_with(body: String) -> http::Response {
    let status = if body.len() == 0 { http::StatusCode::NoContent } else { http::StatusCode::Ok };
    http::Response::new().with_status(status)
                         .with_header(http::headers::ContentLength(body.len() as u64))
                         .with_header(http::headers::ContentType(MIME.parse().unwrap()))
                         .with_body(body)
}

fn respond_with_err(err: Error) -> http::Response {
    #[cfg(debug_assertions)]
    let body = format!("{:?}", err);
    #[cfg(not(debug_assertions))]
    let body = format!("{}", err);
    http::Response::new().with_status(err.status_code())
                         .with_header(http::headers::ContentLength(body.len() as u64))
                         .with_body(body)
}
<|endoftext|>


<commit_before>use schema::{Schema, Field};
use query::Query;
use query::BooleanQuery;
use super::logical_ast::*;
use super::user_input_ast::*;
use super::query_grammar::parse_to_ast;
use query::Occur;
use query::TermQuery;
use postings::SegmentPostingsOption;
use query::PhraseQuery;
use analyzer::SimpleTokenizer;
use analyzer::StreamingIterator;
use schema::Term;

/// Possible error that may happen when parsing a query.
#[derive(Debug, PartialEq, Eq)]
pub enum QueryParserError {
    /// Error in the query syntax
    SyntaxError,
    /// `FieldDoesNotExist(field_name: String)`
    /// The query references a field that is not in the schema
    FieldDoesNotExist(String),
    /// `ExpectedU32(field_name: String, field_value: String)`
    /// The query contains a term for a `u32`-field, but the value
    /// is not a u32.
    ExpectedU32(String, String),
    /// It is forbidden queries that are only "excluding". (e.g. -title:pop)
    AllButQueryForbidden,
    /// If no default field is declared, running a query without any
    /// field specified is forbbidden.
    NoDefaultFieldDeclared,
}

/// Tantivy's Query parser
///
/// The language covered by the current parser is extremely simple.
///
/// * simple terms: "e.g.: `Barack Obama` are simply analyzed using
///   tantivy's `StandardTokenizer`, hence becoming `["barack", "obama"]`.
///   The terms are then searched within the default terms of the query parser.
///
///   e.g. If `body` and `title` are default fields, our example terms are
///   `["title:barack", "body:barack", "title:obama", "body:obama"]`.
///   By default, all tokenized and indexed fields are default fields.
///
///   Multiple terms are handled as an `OR` : any document containing at least
///   one of the term will go through the scoring.
///
///   This behavior is slower, but is not a bad idea if the user is sorting
///   by relevance : The user typically just scans through the first few
///   documents in order of decreasing relevance and will stop when the documents
///   are not relevant anymore.
///   Making it possible to make this behavior customizable is tracked in
///   [issue #27](https://github.com/fulmicoton/tantivy/issues/27).
///
/// * negative terms: By prepending a term by a `-`, a term can be excluded
///   from the search. This is useful for disambiguating a query.
///   e.g. `apple -fruit`
///
/// * must terms: By prepending a term by a `+`, a term can be made required for the search.
///
pub struct QueryParser {
    schema: Schema,
    default_fields: Vec<Field>,
    conjunction_by_default: bool,
    analyzer: Box<SimpleTokenizer>,
}

impl QueryParser {
    /// Creates a `QueryParser`
    /// * schema - index Schema
    /// * default_fields - fields used to search if no field is specifically defined
    ///   in the query.
    pub fn new(schema: Schema, default_fields: Vec<Field>) -> QueryParser {
        QueryParser {
            schema: schema,
            default_fields: default_fields,
            conjunction_by_default: false,
            analyzer: box SimpleTokenizer,
        }
    }

    /// Set the default way to compose queries to a conjunction.
    ///
    /// By default a ,
    pub fn set_conjunction_by_default(&mut self) {
        self.conjunction_by_default = true;
    }

    /// Parse a query
    ///
    /// Note that `parse_query` returns an error if the input
    /// is not a valid query.
    ///
    /// There is currently no lenient mode for the query parser
    /// which makes it a bad choice for a public/broad user search engine.
    ///
    /// Implementing a lenient mode for this query parser is tracked
    /// in [Issue 5](https://github.com/fulmicoton/tantivy/issues/5)
    pub fn parse_query(&self, query: &str) -> Result<Box<Query>, QueryParserError> {
        let logical_ast = self.parse_query_to_logical_ast(query)?;
        Ok(convert_to_query(logical_ast))
    }

    /// Parse the user query into an AST.
    fn parse_query_to_logical_ast(&self, query: &str) -> Result<LogicalAST, QueryParserError> {
        let (user_input_ast, _remaining) =
            parse_to_ast(query).map_err(|_| QueryParserError::SyntaxError)?;
        self.compute_logical_ast(user_input_ast)
    }

    fn resolve_field_name(&self, field_name: &str) -> Result<Field, QueryParserError> {
        self.schema
            .get_field(field_name)
            .ok_or_else(|| QueryParserError::FieldDoesNotExist(String::from(field_name)))
    }

    fn compute_logical_ast(&self,
                               user_input_ast: UserInputAST)
                               -> Result<LogicalAST, QueryParserError> {
        let (occur, ast) = try!(self.compute_logical_ast_with_occur(user_input_ast));
        if occur == Occur::MustNot {
            return Err(QueryParserError::AllButQueryForbidden);
        }
        Ok(ast)
    }

    fn compute_logical_ast_for_leaf(&self,
                                    field: Field,
                                    phrase: &str)
                                    -> Result<Option<LogicalLiteral>, QueryParserError> {
        let mut token_iter = self.analyzer.tokenize(phrase);
        let mut tokens: Vec<Term> = Vec::new();
        loop {
            if let Some(token) = token_iter.next() {
                let text = token.to_string();
                // TODO Handle u32
                let term = Term::from_field_text(field, &text);
                tokens.push(term);
            } else {
                break;
            }
        }
        if tokens.is_empty() {
            Ok(None)
        } else if tokens.len() == 1 {
            Ok(Some(LogicalLiteral::Term(tokens.into_iter().next().unwrap())))
        } else {
            Ok(Some(LogicalLiteral::Phrase(tokens)))
        }
    }

    fn default_occur(&self) -> Occur {
        if self.conjunction_by_default {
            Occur::Must
        } else {
            Occur::Should
        }
    }

    fn compute_logical_ast_with_occur(&self,
                                          user_input_ast: UserInputAST)
                                          -> Result<(Occur, LogicalAST), QueryParserError> {
        match user_input_ast {
            UserInputAST::Clause(sub_queries) => {
                let default_occur = self.default_occur();
                let logical_sub_queries: Vec<(Occur, LogicalAST)> = try!(sub_queries.into_iter()
                    .map(|sub_query| self.compute_logical_ast_with_occur(*sub_query))
                    .map(|res| {
                        res.map(|(occur, sub_ast)| (compose_occur(default_occur, occur), sub_ast))
                    })
                    .collect());
                Ok((Occur::Should, LogicalAST::Clause(logical_sub_queries)))
            }
            UserInputAST::Not(subquery) => {
                let (occur, logical_sub_queries) =
                    try!(self.compute_logical_ast_with_occur(*subquery));
                Ok((compose_occur(Occur::MustNot, occur), logical_sub_queries))
            }
            UserInputAST::Must(subquery) => {
                let (occur, logical_sub_queries) =
                    try!(self.compute_logical_ast_with_occur(*subquery));
                Ok((compose_occur(Occur::Must, occur), logical_sub_queries))
            }
            UserInputAST::Leaf(literal) => {
                let term_phrases: Vec<(Field, String)> = match literal.field_name {
                    Some(ref field_name) => {
                        let field = try!(self.resolve_field_name(&field_name));
                        vec![(field, literal.phrase.clone())]
                    }
                    None => {
                        if self.default_fields.len() == 0 {
                            return Err(QueryParserError::NoDefaultFieldDeclared);
                        } else if self.default_fields.len() == 1 {
                            vec![(self.default_fields[0], literal.phrase.clone())]
                        } else {
                            self.default_fields
                                .iter()
                                .map(|default_field| (*default_field, literal.phrase.clone()))
                                .collect()
                        }
                    }
                };
                let mut asts: Vec<LogicalAST> = Vec::new();
                for (field, phrase) in term_phrases {
                    if let Some(ast) = try!(self.compute_logical_ast_for_leaf(field, &phrase)) {
                        asts.push(LogicalAST::Leaf(box ast));
                    }
                }
                let result_ast = if asts.len() == 0 {
                    panic!("not working");
                } else if asts.len() == 1 {
                    asts[0].clone()
                } else {
                    LogicalAST::Clause(asts.into_iter()
                        .map(|ast| (Occur::Should, ast))
                        .collect())
                };
                Ok((Occur::Should, result_ast))
            }
        }
    }
}

/// Compose two occur values.
fn compose_occur(left: Occur, right: Occur) -> Occur {
    match left {
        Occur::Should => right,
        Occur::Must => {
            if right == Occur::MustNot {
                Occur::MustNot
            } else {
                Occur::Must
            }
        }
        Occur::MustNot => {
            if right == Occur::MustNot {
                Occur::Must
            } else {
                Occur::MustNot
            }
        }
    }
}

fn convert_literal_to_query(logical_literal: LogicalLiteral) -> Box<Query> {
    match logical_literal {
        LogicalLiteral::Term(term) => box TermQuery::new(term, SegmentPostingsOption::Freq),
        LogicalLiteral::Phrase(terms) => box PhraseQuery::from(terms),
    }
}

fn convert_to_query(logical_ast: LogicalAST) -> Box<Query> {
    match logical_ast {
        LogicalAST::Clause(clause) => {
            let occur_subqueries = clause.into_iter()
                .map(|(occur, subquery)| (occur, convert_to_query(subquery)))
                .collect::<Vec<_>>();
            box BooleanQuery::from(occur_subqueries)
        }
        LogicalAST::Leaf(logical_literal) => convert_literal_to_query(*logical_literal),
    }
}

#[cfg(test)]
mod test {
    use schema::{SchemaBuilder, TEXT};
    use super::QueryParser;
    use super::QueryParserError;
    use super::super::logical_ast::*;

    fn parse_query_to_logical_ast(query: &str,
                                  default_conjunction: bool)
                                  -> Result<LogicalAST, QueryParserError> {
        let mut schema_builder = SchemaBuilder::default();
        let title = schema_builder.add_text_field("title", TEXT);
        let text = schema_builder.add_text_field("text", TEXT);
        let schema = schema_builder.build();
        let default_fields = vec![title, text];
        let mut query_parser = QueryParser::new(schema, default_fields);
        if default_conjunction {
            query_parser.set_conjunction_by_default();
        }
        query_parser.parse_query_to_logical_ast(query)
    }

    fn test_parse_query_to_logical_ast_helper(query: &str,
                                              expected: &str,
                                              default_conjunction: bool) {
        let query = parse_query_to_logical_ast(query, default_conjunction).unwrap();
        let query_str = format!("{:?}", query);
        assert_eq!(query_str, expected);
    }

    #[test]
    pub fn test_parse_query_to_ast_disjunction() {
        test_parse_query_to_logical_ast_helper("title:toto",
                                               "Term([0, 116, 111, 116, 111])",
                                               false);
        test_parse_query_to_logical_ast_helper("+title:toto",
                                               "Term([0, 116, 111, 116, 111])",
                                               false);
        test_parse_query_to_logical_ast_helper("+title:toto -titi",
                                               "(+Term([0, 116, 111, 116, 111]) -(Term([0, 116, \
                                                105, 116, 105]) Term([1, 116, 105, 116, 105])))",
                                               false);
        assert_eq!(parse_query_to_logical_ast("-title:toto", false).err().unwrap(),
                   QueryParserError::AllButQueryForbidden);
        test_parse_query_to_logical_ast_helper("title:a b",
                                               "(Term([0, 97]) (Term([0, 98]) Term([1, 98])))",
                                               false);
        test_parse_query_to_logical_ast_helper("title:\"a b\"",
                                               "\"[Term([0, 97]), Term([0, 98])]\"",
                                               false);
    }

    #[test]
    pub fn test_parse_query_to_ast_conjunction() {
        test_parse_query_to_logical_ast_helper("title:toto", "Term([0, 116, 111, 116, 111])", true);
        test_parse_query_to_logical_ast_helper("+title:toto",
                                               "Term([0, 116, 111, 116, 111])",
                                               true);
        test_parse_query_to_logical_ast_helper("+title:toto -titi",
                                               "(+Term([0, 116, 111, 116, 111]) -(Term([0, 116, \
                                                105, 116, 105]) Term([1, 116, 105, 116, 105])))",
                                               true);
        assert_eq!(parse_query_to_logical_ast("-title:toto", true).err().unwrap(),
                   QueryParserError::AllButQueryForbidden);
        test_parse_query_to_logical_ast_helper("title:a b",
                                               "(+Term([0, 97]) +(Term([0, 98]) Term([1, 98])))",
                                               true);
        test_parse_query_to_logical_ast_helper("title:\"a b\"",
                                               "\"[Term([0, 97]), Term([0, 98])]\"",
                                               true);
    }
}
<commit_msg>NOBUG removed useless panic<commit_after>use schema::{Schema, Field};
use query::Query;
use query::BooleanQuery;
use super::logical_ast::*;
use super::user_input_ast::*;
use super::query_grammar::parse_to_ast;
use query::Occur;
use query::TermQuery;
use postings::SegmentPostingsOption;
use query::PhraseQuery;
use analyzer::SimpleTokenizer;
use analyzer::StreamingIterator;
use schema::Term;

/// Possible error that may happen when parsing a query.
#[derive(Debug, PartialEq, Eq)]
pub enum QueryParserError {
    /// Error in the query syntax
    SyntaxError,
    /// `FieldDoesNotExist(field_name: String)`
    /// The query references a field that is not in the schema
    FieldDoesNotExist(String),
    /// `ExpectedU32(field_name: String, field_value: String)`
    /// The query contains a term for a `u32`-field, but the value
    /// is not a u32.
    ExpectedU32(String, String),
    /// It is forbidden queries that are only "excluding". (e.g. -title:pop)
    AllButQueryForbidden,
    /// If no default field is declared, running a query without any
    /// field specified is forbbidden.
    NoDefaultFieldDeclared,
}

/// Tantivy's Query parser
///
/// The language covered by the current parser is extremely simple.
///
/// * simple terms: "e.g.: `Barack Obama` are simply analyzed using
///   tantivy's `StandardTokenizer`, hence becoming `["barack", "obama"]`.
///   The terms are then searched within the default terms of the query parser.
///
///   e.g. If `body` and `title` are default fields, our example terms are
///   `["title:barack", "body:barack", "title:obama", "body:obama"]`.
///   By default, all tokenized and indexed fields are default fields.
///
///   Multiple terms are handled as an `OR` : any document containing at least
///   one of the term will go through the scoring.
///
///   This behavior is slower, but is not a bad idea if the user is sorting
///   by relevance : The user typically just scans through the first few
///   documents in order of decreasing relevance and will stop when the documents
///   are not relevant anymore.
///   Making it possible to make this behavior customizable is tracked in
///   [issue #27](https://github.com/fulmicoton/tantivy/issues/27).
///
/// * negative terms: By prepending a term by a `-`, a term can be excluded
///   from the search. This is useful for disambiguating a query.
///   e.g. `apple -fruit`
///
/// * must terms: By prepending a term by a `+`, a term can be made required for the search.
///
pub struct QueryParser {
    schema: Schema,
    default_fields: Vec<Field>,
    conjunction_by_default: bool,
    analyzer: Box<SimpleTokenizer>,
}

impl QueryParser {
    /// Creates a `QueryParser`
    /// * schema - index Schema
    /// * default_fields - fields used to search if no field is specifically defined
    ///   in the query.
    pub fn new(schema: Schema, default_fields: Vec<Field>) -> QueryParser {
        QueryParser {
            schema: schema,
            default_fields: default_fields,
            conjunction_by_default: false,
            analyzer: box SimpleTokenizer,
        }
    }

    /// Set the default way to compose queries to a conjunction.
    ///
    /// By default a ,
    pub fn set_conjunction_by_default(&mut self) {
        self.conjunction_by_default = true;
    }

    /// Parse a query
    ///
    /// Note that `parse_query` returns an error if the input
    /// is not a valid query.
    ///
    /// There is currently no lenient mode for the query parser
    /// which makes it a bad choice for a public/broad user search engine.
    ///
    /// Implementing a lenient mode for this query parser is tracked
    /// in [Issue 5](https://github.com/fulmicoton/tantivy/issues/5)
    pub fn parse_query(&self, query: &str) -> Result<Box<Query>, QueryParserError> {
        let logical_ast = self.parse_query_to_logical_ast(query)?;
        Ok(convert_to_query(logical_ast))
    }

    /// Parse the user query into an AST.
    fn parse_query_to_logical_ast(&self, query: &str) -> Result<LogicalAST, QueryParserError> {
        let (user_input_ast, _remaining) =
            parse_to_ast(query).map_err(|_| QueryParserError::SyntaxError)?;
        self.compute_logical_ast(user_input_ast)
    }

    fn resolve_field_name(&self, field_name: &str) -> Result<Field, QueryParserError> {
        self.schema
            .get_field(field_name)
            .ok_or_else(|| QueryParserError::FieldDoesNotExist(String::from(field_name)))
    }

    fn compute_logical_ast(&self,
                               user_input_ast: UserInputAST)
                               -> Result<LogicalAST, QueryParserError> {
        let (occur, ast) = try!(self.compute_logical_ast_with_occur(user_input_ast));
        if occur == Occur::MustNot {
            return Err(QueryParserError::AllButQueryForbidden);
        }
        Ok(ast)
    }

    fn compute_logical_ast_for_leaf(&self,
                                    field: Field,
                                    phrase: &str)
                                    -> Result<Option<LogicalLiteral>, QueryParserError> {
        let mut token_iter = self.analyzer.tokenize(phrase);
        let mut tokens: Vec<Term> = Vec::new();
        loop {
            if let Some(token) = token_iter.next() {
                let text = token.to_string();
                // TODO Handle u32
                let term = Term::from_field_text(field, &text);
                tokens.push(term);
            } else {
                break;
            }
        }
        if tokens.is_empty() {
            Ok(None)
        } else if tokens.len() == 1 {
            Ok(Some(LogicalLiteral::Term(tokens.into_iter().next().unwrap())))
        } else {
            Ok(Some(LogicalLiteral::Phrase(tokens)))
        }
    }

    fn default_occur(&self) -> Occur {
        if self.conjunction_by_default {
            Occur::Must
        } else {
            Occur::Should
        }
    }

    fn compute_logical_ast_with_occur(&self,
                                        user_input_ast: UserInputAST)
                                        -> Result<(Occur, LogicalAST), QueryParserError> {
        match user_input_ast {
            UserInputAST::Clause(sub_queries) => {
                let default_occur = self.default_occur();
                let logical_sub_queries: Vec<(Occur, LogicalAST)> = try!(sub_queries.into_iter()
                    .map(|sub_query| self.compute_logical_ast_with_occur(*sub_query))
                    .map(|res| {
                        res.map(|(occur, sub_ast)| (compose_occur(default_occur, occur), sub_ast))
                    })
                    .collect());
                Ok((Occur::Should, LogicalAST::Clause(logical_sub_queries)))
            }
            UserInputAST::Not(subquery) => {
                let (occur, logical_sub_queries) =
                    try!(self.compute_logical_ast_with_occur(*subquery));
                Ok((compose_occur(Occur::MustNot, occur), logical_sub_queries))
            }
            UserInputAST::Must(subquery) => {
                let (occur, logical_sub_queries) =
                    try!(self.compute_logical_ast_with_occur(*subquery));
                Ok((compose_occur(Occur::Must, occur), logical_sub_queries))
            }
            UserInputAST::Leaf(literal) => {
                let term_phrases: Vec<(Field, String)> = match literal.field_name {
                    Some(ref field_name) => {
                        let field = try!(self.resolve_field_name(&field_name));
                        vec![(field, literal.phrase.clone())]
                    }
                    None => {
                        if self.default_fields.len() == 0 {
                            return Err(QueryParserError::NoDefaultFieldDeclared);
                        } else {
                            self.default_fields
                                .iter()
                                .map(|default_field| (*default_field, literal.phrase.clone()))
                                .collect::<Vec<(Field, String)>>()
                        }
                    }
                };
                let mut asts: Vec<LogicalAST> = Vec::new();
                for (field, phrase) in term_phrases {
                    if let Some(ast) = self.compute_logical_ast_for_leaf(field, &phrase)? {
                        asts.push(LogicalAST::Leaf(box ast));
                    }
                }
                let result_ast = if asts.len() == 0 {
                    // this should never happen
                    return Err(QueryParserError::SyntaxError);
                } else if asts.len() == 1 {
                    asts[0].clone()
                } else {
                    LogicalAST::Clause(asts.into_iter()
                        .map(|ast| (Occur::Should, ast))
                        .collect())
                };
                Ok((Occur::Should, result_ast))
            }
        }
    }
}

/// Compose two occur values.
fn compose_occur(left: Occur, right: Occur) -> Occur {
    match left {
        Occur::Should => right,
        Occur::Must => {
            if right == Occur::MustNot {
                Occur::MustNot
            } else {
                Occur::Must
            }
        }
        Occur::MustNot => {
            if right == Occur::MustNot {
                Occur::Must
            } else {
                Occur::MustNot
            }
        }
    }
}

fn convert_literal_to_query(logical_literal: LogicalLiteral) -> Box<Query> {
    match logical_literal {
        LogicalLiteral::Term(term) => box TermQuery::new(term, SegmentPostingsOption::Freq),
        LogicalLiteral::Phrase(terms) => box PhraseQuery::from(terms),
    }
}

fn convert_to_query(logical_ast: LogicalAST) -> Box<Query> {
    match logical_ast {
        LogicalAST::Clause(clause) => {
            let occur_subqueries = clause.into_iter()
                .map(|(occur, subquery)| (occur, convert_to_query(subquery)))
                .collect::<Vec<_>>();
            box BooleanQuery::from(occur_subqueries)
        }
        LogicalAST::Leaf(logical_literal) => convert_literal_to_query(*logical_literal),
    }
}

#[cfg(test)]
mod test {
    use schema::{SchemaBuilder, TEXT};
    use super::QueryParser;
    use super::QueryParserError;
    use super::super::logical_ast::*;

    fn make_query_parser() -> QueryParser {
        let mut schema_builder = SchemaBuilder::default();
        let title = schema_builder.add_text_field("title", TEXT);
        let text = schema_builder.add_text_field("text", TEXT);
        let schema = schema_builder.build();
        let default_fields = vec![title, text];
        QueryParser::new(schema, default_fields)
    }

    fn parse_query_to_logical_ast(query: &str,
                                  default_conjunction: bool)
                                  -> Result<LogicalAST, QueryParserError> {
        let mut query_parser = make_query_parser();
        if default_conjunction {
            query_parser.set_conjunction_by_default();
        }
        query_parser.parse_query_to_logical_ast(query)
    }

    fn test_parse_query_to_logical_ast_helper(query: &str,
                                              expected: &str,
                                              default_conjunction: bool) {
        let query = parse_query_to_logical_ast(query, default_conjunction).unwrap();
        let query_str = format!("{:?}", query);
        assert_eq!(query_str, expected);
    }

    #[test]
    pub fn test_parse_query_simple() {
        let query_parser = make_query_parser();
        assert!(query_parser.parse_query("toto").is_ok());
    }

    #[test]
    pub fn test_parse_query_to_ast_disjunction() {
        test_parse_query_to_logical_ast_helper("title:toto",
                                               "Term([0, 116, 111, 116, 111])",
                                               false);
        test_parse_query_to_logical_ast_helper("+title:toto",
                                               "Term([0, 116, 111, 116, 111])",
                                               false);
        test_parse_query_to_logical_ast_helper("+title:toto -titi",
                                               "(+Term([0, 116, 111, 116, 111]) -(Term([0, 116, \
                                                105, 116, 105]) Term([1, 116, 105, 116, 105])))",
                                               false);
        assert_eq!(parse_query_to_logical_ast("-title:toto", false).err().unwrap(),
                   QueryParserError::AllButQueryForbidden);
        test_parse_query_to_logical_ast_helper("title:a b",
                                               "(Term([0, 97]) (Term([0, 98]) Term([1, 98])))",
                                               false);
        test_parse_query_to_logical_ast_helper("title:\"a b\"",
                                               "\"[Term([0, 97]), Term([0, 98])]\"",
                                               false);
    }

    #[test]
    pub fn test_parse_query_to_ast_conjunction() {
        test_parse_query_to_logical_ast_helper("title:toto", "Term([0, 116, 111, 116, 111])", true);
        test_parse_query_to_logical_ast_helper("+title:toto",
                                               "Term([0, 116, 111, 116, 111])",
                                               true);
        test_parse_query_to_logical_ast_helper("+title:toto -titi",
                                               "(+Term([0, 116, 111, 116, 111]) -(Term([0, 116, \
                                                105, 116, 105]) Term([1, 116, 105, 116, 105])))",
                                               true);
        assert_eq!(parse_query_to_logical_ast("-title:toto", true).err().unwrap(),
                   QueryParserError::AllButQueryForbidden);
        test_parse_query_to_logical_ast_helper("title:a b",
                                               "(+Term([0, 97]) +(Term([0, 98]) Term([1, 98])))",
                                               true);
        test_parse_query_to_logical_ast_helper("title:\"a b\"",
                                               "\"[Term([0, 97]), Term([0, 98])]\"",
                                               true);
    }
}
<|endoftext|>


<commit_before>use super::*;
use core::iter::*;

#[test]
fn test_zip_nth() {
    let xs = [0, 1, 2, 4, 5];
    let ys = [10, 11, 12];

    let mut it = xs.iter().zip(&ys);
    assert_eq!(it.nth(0), Some((&0, &10)));
    assert_eq!(it.nth(1), Some((&2, &12)));
    assert_eq!(it.nth(0), None);

    let mut it = xs.iter().zip(&ys);
    assert_eq!(it.nth(3), None);

    let mut it = ys.iter().zip(&xs);
    assert_eq!(it.nth(3), None);
}

#[test]
fn test_zip_nth_side_effects() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    let value = [1, 2, 3, 4, 5, 6]
        .iter()
        .cloned()
        .map(|n| {
            a.push(n);
            n * 10
        })
        .zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| {
            b.push(n * 100);
            n * 1000
        }))
        .skip(1)
        .nth(3);
    assert_eq!(value, Some((50, 6000)));
    assert_eq!(a, vec![1, 2, 3, 4, 5]);
    assert_eq!(b, vec![200, 300, 400, 500, 600]);
}

#[test]
fn test_zip_next_back_side_effects() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    let mut iter = [1, 2, 3, 4, 5, 6]
        .iter()
        .cloned()
        .map(|n| {
            a.push(n);
            n * 10
        })
        .zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| {
            b.push(n * 100);
            n * 1000
        }));

    // The second iterator is one item longer, so `next_back` is called on it
    // one more time.
    assert_eq!(iter.next_back(), Some((60, 7000)));
    assert_eq!(iter.next_back(), Some((50, 6000)));
    assert_eq!(iter.next_back(), Some((40, 5000)));
    assert_eq!(iter.next_back(), Some((30, 4000)));
    assert_eq!(a, vec![6, 5, 4, 3]);
    assert_eq!(b, vec![800, 700, 600, 500, 400]);
}

#[test]
fn test_zip_nth_back_side_effects() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    let value = [1, 2, 3, 4, 5, 6]
        .iter()
        .cloned()
        .map(|n| {
            a.push(n);
            n * 10
        })
        .zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| {
            b.push(n * 100);
            n * 1000
        }))
        .nth_back(3);
    assert_eq!(value, Some((30, 4000)));
    assert_eq!(a, vec![6, 5, 4, 3]);
    assert_eq!(b, vec![800, 700, 600, 500, 400]);
}

#[test]
fn test_zip_next_back_side_effects_exhausted() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    let mut iter = [1, 2, 3, 4, 5, 6]
        .iter()
        .cloned()
        .map(|n| {
            a.push(n);
            n * 10
        })
        .zip([2, 3, 4].iter().cloned().map(|n| {
            b.push(n * 100);
            n * 1000
        }));

    iter.next();
    iter.next();
    iter.next();
    iter.next();
    assert_eq!(iter.next_back(), None);
    assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
    assert_eq!(b, vec![200, 300, 400]);
}

#[test]
fn test_zip_cloned_sideffectful() {
    let xs = [CountClone::new(), CountClone::new(), CountClone::new(), CountClone::new()];
    let ys = [CountClone::new(), CountClone::new()];

    for _ in xs.iter().cloned().zip(ys.iter().cloned()) {}

    assert_eq!(&xs, &[1, 1, 1, 0][..]);
    assert_eq!(&ys, &[1, 1][..]);

    let xs = [CountClone::new(), CountClone::new()];
    let ys = [CountClone::new(), CountClone::new(), CountClone::new(), CountClone::new()];

    for _ in xs.iter().cloned().zip(ys.iter().cloned()) {}

    assert_eq!(&xs, &[1, 1][..]);
    assert_eq!(&ys, &[1, 1, 0, 0][..]);
}

#[test]
fn test_zip_map_sideffectful() {
    let mut xs = [0; 6];
    let mut ys = [0; 4];

    for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) {}

    assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]);
    assert_eq!(&ys, &[1, 1, 1, 1]);

    let mut xs = [0; 4];
    let mut ys = [0; 6];

    for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) {}

    assert_eq!(&xs, &[1, 1, 1, 1]);
    assert_eq!(&ys, &[1, 1, 1, 1, 0, 0]);
}

#[test]
fn test_zip_map_rev_sideffectful() {
    let mut xs = [0; 6];
    let mut ys = [0; 4];

    {
        let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1));
        it.next_back();
    }
    assert_eq!(&xs, &[0, 0, 0, 1, 1, 1]);
    assert_eq!(&ys, &[0, 0, 0, 1]);

    let mut xs = [0; 6];
    let mut ys = [0; 4];

    {
        let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1));
        (&mut it).take(5).count();
        it.next_back();
    }
    assert_eq!(&xs, &[1, 1, 1, 1, 1, 1]);
    assert_eq!(&ys, &[1, 1, 1, 1]);
}

#[test]
fn test_zip_nested_sideffectful() {
    let mut xs = [0; 6];
    let ys = [0; 4];

    {
        // test that it has the side effect nested inside enumerate
        let it = xs.iter_mut().map(|x| *x = 1).enumerate().zip(&ys);
        it.count();
    }
    assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]);
}

#[test]
fn test_zip_nth_back_side_effects_exhausted() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    let mut iter = [1, 2, 3, 4, 5, 6]
        .iter()
        .cloned()
        .map(|n| {
            a.push(n);
            n * 10
        })
        .zip([2, 3, 4].iter().cloned().map(|n| {
            b.push(n * 100);
            n * 1000
        }));

    iter.next();
    iter.next();
    iter.next();
    iter.next();
    assert_eq!(iter.nth_back(0), None);
    assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
    assert_eq!(b, vec![200, 300, 400]);
}

#[test]
fn test_zip_trusted_random_access_composition() {
    let a = [0, 1, 2, 3, 4];
    let b = a;
    let c = a;

    let a = a.iter().copied();
    let b = b.iter().copied();
    let mut c = c.iter().copied();
    c.next();

    let mut z1 = a.zip(b);
    assert_eq!(z1.next().unwrap(), (0, 0));

    let mut z2 = z1.zip(c);
    fn assert_trusted_random_access<T: TrustedRandomAccess>(_a: &T) {}
    assert_trusted_random_access(&z2);
    assert_eq!(z2.next().unwrap(), ((1, 1), 1));
}

#[test]
fn test_double_ended_zip() {
    let xs = [1, 2, 3, 4, 5, 6];
    let ys = [1, 2, 3, 7];
    let a = xs.iter().cloned();
    let b = ys.iter().cloned();
    let mut it = a.zip(b);
    assert_eq!(it.next(), Some((1, 1)));
    assert_eq!(it.next(), Some((2, 2)));
    assert_eq!(it.next_back(), Some((4, 7)));
    assert_eq!(it.next_back(), Some((3, 3)));
    assert_eq!(it.next(), None);
}
<commit_msg>Add test for underflow in specialized Zip's size_hint<commit_after>use super::*;
use core::iter::*;

#[test]
fn test_zip_nth() {
    let xs = [0, 1, 2, 4, 5];
    let ys = [10, 11, 12];

    let mut it = xs.iter().zip(&ys);
    assert_eq!(it.nth(0), Some((&0, &10)));
    assert_eq!(it.nth(1), Some((&2, &12)));
    assert_eq!(it.nth(0), None);

    let mut it = xs.iter().zip(&ys);
    assert_eq!(it.nth(3), None);

    let mut it = ys.iter().zip(&xs);
    assert_eq!(it.nth(3), None);
}

#[test]
fn test_zip_nth_side_effects() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    let value = [1, 2, 3, 4, 5, 6]
        .iter()
        .cloned()
        .map(|n| {
            a.push(n);
            n * 10
        })
        .zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| {
            b.push(n * 100);
            n * 1000
        }))
        .skip(1)
        .nth(3);
    assert_eq!(value, Some((50, 6000)));
    assert_eq!(a, vec![1, 2, 3, 4, 5]);
    assert_eq!(b, vec![200, 300, 400, 500, 600]);
}

#[test]
fn test_zip_next_back_side_effects() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    let mut iter = [1, 2, 3, 4, 5, 6]
        .iter()
        .cloned()
        .map(|n| {
            a.push(n);
            n * 10
        })
        .zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| {
            b.push(n * 100);
            n * 1000
        }));

    // The second iterator is one item longer, so `next_back` is called on it
    // one more time.
    assert_eq!(iter.next_back(), Some((60, 7000)));
    assert_eq!(iter.next_back(), Some((50, 6000)));
    assert_eq!(iter.next_back(), Some((40, 5000)));
    assert_eq!(iter.next_back(), Some((30, 4000)));
    assert_eq!(a, vec![6, 5, 4, 3]);
    assert_eq!(b, vec![800, 700, 600, 500, 400]);
}

#[test]
fn test_zip_nth_back_side_effects() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    let value = [1, 2, 3, 4, 5, 6]
        .iter()
        .cloned()
        .map(|n| {
            a.push(n);
            n * 10
        })
        .zip([2, 3, 4, 5, 6, 7, 8].iter().cloned().map(|n| {
            b.push(n * 100);
            n * 1000
        }))
        .nth_back(3);
    assert_eq!(value, Some((30, 4000)));
    assert_eq!(a, vec![6, 5, 4, 3]);
    assert_eq!(b, vec![800, 700, 600, 500, 400]);
}

#[test]
fn test_zip_next_back_side_effects_exhausted() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    let mut iter = [1, 2, 3, 4, 5, 6]
        .iter()
        .cloned()
        .map(|n| {
            a.push(n);
            n * 10
        })
        .zip([2, 3, 4].iter().cloned().map(|n| {
            b.push(n * 100);
            n * 1000
        }));

    iter.next();
    iter.next();
    iter.next();
    iter.next();
    assert_eq!(iter.next_back(), None);
    assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
    assert_eq!(b, vec![200, 300, 400]);
}

#[test]
fn test_zip_cloned_sideffectful() {
    let xs = [CountClone::new(), CountClone::new(), CountClone::new(), CountClone::new()];
    let ys = [CountClone::new(), CountClone::new()];

    for _ in xs.iter().cloned().zip(ys.iter().cloned()) {}

    assert_eq!(&xs, &[1, 1, 1, 0][..]);
    assert_eq!(&ys, &[1, 1][..]);

    let xs = [CountClone::new(), CountClone::new()];
    let ys = [CountClone::new(), CountClone::new(), CountClone::new(), CountClone::new()];

    for _ in xs.iter().cloned().zip(ys.iter().cloned()) {}

    assert_eq!(&xs, &[1, 1][..]);
    assert_eq!(&ys, &[1, 1, 0, 0][..]);
}

#[test]
fn test_zip_map_sideffectful() {
    let mut xs = [0; 6];
    let mut ys = [0; 4];

    for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) {}

    assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]);
    assert_eq!(&ys, &[1, 1, 1, 1]);

    let mut xs = [0; 4];
    let mut ys = [0; 6];

    for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) {}

    assert_eq!(&xs, &[1, 1, 1, 1]);
    assert_eq!(&ys, &[1, 1, 1, 1, 0, 0]);
}

#[test]
fn test_zip_map_rev_sideffectful() {
    let mut xs = [0; 6];
    let mut ys = [0; 4];

    {
        let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1));
        it.next_back();
    }
    assert_eq!(&xs, &[0, 0, 0, 1, 1, 1]);
    assert_eq!(&ys, &[0, 0, 0, 1]);

    let mut xs = [0; 6];
    let mut ys = [0; 4];

    {
        let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1));
        (&mut it).take(5).count();
        it.next_back();
    }
    assert_eq!(&xs, &[1, 1, 1, 1, 1, 1]);
    assert_eq!(&ys, &[1, 1, 1, 1]);
}

#[test]
fn test_zip_nested_sideffectful() {
    let mut xs = [0; 6];
    let ys = [0; 4];

    {
        // test that it has the side effect nested inside enumerate
        let it = xs.iter_mut().map(|x| *x = 1).enumerate().zip(&ys);
        it.count();
    }
    assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]);
}

#[test]
fn test_zip_nth_back_side_effects_exhausted() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    let mut iter = [1, 2, 3, 4, 5, 6]
        .iter()
        .cloned()
        .map(|n| {
            a.push(n);
            n * 10
        })
        .zip([2, 3, 4].iter().cloned().map(|n| {
            b.push(n * 100);
            n * 1000
        }));

    iter.next();
    iter.next();
    iter.next();
    iter.next();
    assert_eq!(iter.nth_back(0), None);
    assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
    assert_eq!(b, vec![200, 300, 400]);
}

#[test]
fn test_zip_trusted_random_access_composition() {
    let a = [0, 1, 2, 3, 4];
    let b = a;
    let c = a;

    let a = a.iter().copied();
    let b = b.iter().copied();
    let mut c = c.iter().copied();
    c.next();

    let mut z1 = a.zip(b);
    assert_eq!(z1.next().unwrap(), (0, 0));

    let mut z2 = z1.zip(c);
    fn assert_trusted_random_access<T: TrustedRandomAccess>(_a: &T) {}
    assert_trusted_random_access(&z2);
    assert_eq!(z2.next().unwrap(), ((1, 1), 1));
}

#[test]
fn test_double_ended_zip() {
    let xs = [1, 2, 3, 4, 5, 6];
    let ys = [1, 2, 3, 7];
    let a = xs.iter().cloned();
    let b = ys.iter().cloned();
    let mut it = a.zip(b);
    assert_eq!(it.next(), Some((1, 1)));
    assert_eq!(it.next(), Some((2, 2)));
    assert_eq!(it.next_back(), Some((4, 7)));
    assert_eq!(it.next_back(), Some((3, 3)));
    assert_eq!(it.next(), None);
}

#[test]
fn test_issue_82282() {
    fn overflowed_zip(arr: &[i32]) -> impl Iterator<Item = (i32, &())> {
        static UNIT_EMPTY_ARR: [(); 0] = [];

        let mapped = arr.into_iter().map(|i| *i);
        let mut zipped = mapped.zip(UNIT_EMPTY_ARR.iter());
        zipped.next();
        zipped
    }

    let arr = [1, 2, 3];
    let zip = overflowed_zip(&arr).zip(overflowed_zip(&arr));

    assert_eq!(zip.size_hint(), (0, Some(0)));
    for _ in zip {
        panic!();
    }
}
<|endoftext|>


<commit_before>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::convert;
use crate::ops::{self, ControlFlow};
use crate::result::Result;
use crate::task::Ready;

/// Indicates whether a value is available or if the current task has been
/// scheduled to receive a wakeup instead.
#[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[stable(feature = "futures_api", since = "1.36.0")]
pub enum Poll<T> {
    /// Represents that a value is immediately ready.
    #[lang = "Ready"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Ready(#[stable(feature = "futures_api", since = "1.36.0")] T),

    /// Represents that a value is not ready yet.
    ///
    /// When a function returns `Pending`, the function *must* also
    /// ensure that the current task is scheduled to be awoken when
    /// progress can be made.
    #[lang = "Pending"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Pending,
}

impl<T> Poll<T> {
    /// Maps a `Poll<T>` to `Poll<U>` by applying a function to a contained value.
    ///
    /// # Examples
    ///
    /// Converts a Poll<[String]> into a Poll<[usize]>, consuming
    /// the original:
    ///
    /// [String]: ../../std/string/struct.String.html "String"
    /// ```
    /// # use core::task::Poll;
    /// let poll_some_string = Poll::Ready(String::from("Hello, World!"));
    /// // `Poll::map` takes self *by value*, consuming `poll_some_string`
    /// let poll_some_len = poll_some_string.map(|s| s.len());
    ///
    /// assert_eq!(poll_some_len, Poll::Ready(13));
    /// ```
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map(self, f: F) -> Poll
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(t) => Poll::Ready(f(t)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Returns `true` if the poll is a [`Poll::Ready`] value.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let x: Poll<u32> = Poll::Ready(2);
    /// assert_eq!(x.is_ready(), true);
    ///
    /// let x: Poll<u32> = Poll::Pending;
    /// assert_eq!(x.is_ready(), false);
    /// ```
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_ready(&self) -> bool {
        matches!(*self, Poll::Ready(_))
    }

    /// Returns `true` if the poll is a [`Pending`] value.
    ///
    /// [`Pending`]: Poll::Pending
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let x: Poll<u32> = Poll::Ready(2);
    /// assert_eq!(x.is_pending(), false);
    ///
    /// let x: Poll<u32> = Poll::Pending;
    /// assert_eq!(x.is_pending(), true);
    /// ```
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_pending(&self) -> bool {
        !self.is_ready()
    }

    /// Extracts the successful type of a [`Poll<T>`].
    ///
    /// When combined with the `?` operator, this function will
    /// propogate any [`Poll::Pending`] values to the caller, and
    /// extract the `T` from [`Poll::Ready`].
    ///
    /// # Examples
    ///
    /// ```rust
    /// #![feature(poll_ready)]
    ///
    /// use std::task::{Context, Poll};
    /// use std::future::{self, Future};
    /// use std::pin::Pin;
    ///
    /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
    ///     let mut fut = future::ready(42);
    ///     let fut = Pin::new(&mut fut);
    ///
    ///     let num = fut.poll(cx).ready()?;
    ///     # drop(num);
    ///     // ... use num
    ///
    ///     Poll::Ready(())
    /// }
    /// ```
    #[inline]
    #[unstable(feature = "poll_ready", issue = "89780")]
    pub fn ready(self) -> Ready<T> {
        Ready(self)
    }
}

impl<T, E> Poll<Result<T, E>> {
    /// Maps a `Poll<Result<T, E>>` to `Poll<Result<U, E>>` by applying a
    /// function to a contained `Poll::Ready(Ok)` value, leaving all other
    /// variants untouched.
    ///
    /// This function can be used to compose the results of two functions.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Result<u8, _>> = Poll::Ready("12".parse());
    /// let squared = res.map_ok(|n| n * n);
    /// assert_eq!(squared, Poll::Ready(Ok(144)));
    /// ```
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_ok(self, f: F) -> Poll<Result>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Maps a `Poll::Ready<Result<T, E>>` to `Poll::Ready<Result<T, F>>` by
    /// applying a function to a contained `Poll::Ready(Err)` value, leaving all other
    /// variants untouched.
    ///
    /// This function can be used to pass through a successful result while handling
    /// an error.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Result<u8, _>> = Poll::Ready("oops".parse());
    /// let res = res.map_err(|_| 0_u8);
    /// assert_eq!(res, Poll::Ready(Err(0)));
    /// ```
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_err(self, f: F) -> Poll<Result<T, U>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
            Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
            Poll::Pending => Poll::Pending,
        }
    }
}

impl<T, E> Poll<Option<Result<T, E>>> {
    /// Maps a `Poll<Option<Result<T, E>>>` to `Poll<Option<Result<U, E>>>` by
    /// applying a function to a contained `Poll::Ready(Some(Ok))` value,
    /// leaving all other variants untouched.
    ///
    /// This function can be used to compose the results of two functions.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("12".parse()));
    /// let squared = res.map_ok(|n| n * n);
    /// assert_eq!(squared, Poll::Ready(Some(Ok(144))));
    /// ```
    #[stable(feature = "poll_map", since = "1.51.0")]
    pub fn map_ok(self, f: F) -> Poll<Option<Result>>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Maps a `Poll::Ready<Option<Result<T, E>>>` to
    /// `Poll::Ready<Option<Result<T, F>>>` by applying a function to a
    /// contained `Poll::Ready(Some(Err))` value, leaving all other variants
    /// untouched.
    ///
    /// This function can be used to pass through a successful result while handling
    /// an error.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("oops".parse()));
    /// let res = res.map_err(|_| 0_u8);
    /// assert_eq!(res, Poll::Ready(Some(Err(0))));
    /// ```
    #[stable(feature = "poll_map", since = "1.51.0")]
    pub fn map_err(self, f: F) -> Poll<Option<Result<T, U>>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T> From<T> for Poll<T> {
    /// Convert to a `Ready` variant.
    ///
    /// # Example
    ///
    /// ```
    /// # use core::task::Poll;
    /// assert_eq!(Poll::from(true), Poll::Ready(true));
    /// ```
    fn from(t: T) -> Poll<T> {
        Poll::Ready(t)
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E> ops::Try for Poll<Result<T, E>> {
    type Output = Poll<T>;
    type Residual = Result<convert::Infallible, E>;

    #[inline]
    fn from_output(c: Self::Output) -> Self {
        c.map(Ok)
    }

    #[inline]
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        match self {
            Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)),
            Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)),
            Poll::Pending => ControlFlow::Continue(Poll::Pending),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Poll<Result<T, F>> {
    #[inline]
    fn from_residual(x: Result<convert::Infallible, E>) -> Self {
        match x {
            Err(e) => Poll::Ready(Err(From::from(e))),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E> ops::Try for Poll<Option<Result<T, E>>> {
    type Output = Poll<Option<T>>;
    type Residual = Result<convert::Infallible, E>;

    #[inline]
    fn from_output(c: Self::Output) -> Self {
        c.map(|x| x.map(Ok))
    }

    #[inline]
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        match self {
            Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))),
            Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)),
            Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)),
            Poll::Pending => ControlFlow::Continue(Poll::Pending),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>>
    for Poll<Option<Result<T, F>>>
{
    #[inline]
    fn from_residual(x: Result<convert::Infallible, E>) -> Self {
        match x {
            Err(e) => Poll::Ready(Some(Err(From::from(e)))),
        }
    }
}
<commit_msg>fix minor spelling error in Poll::ready docs<commit_after>#![stable(feature = "futures_api", since = "1.36.0")]

use crate::convert;
use crate::ops::{self, ControlFlow};
use crate::result::Result;
use crate::task::Ready;

/// Indicates whether a value is available or if the current task has been
/// scheduled to receive a wakeup instead.
#[must_use = "this `Poll` may be a `Pending` variant, which should be handled"]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[stable(feature = "futures_api", since = "1.36.0")]
pub enum Poll<T> {
    /// Represents that a value is immediately ready.
    #[lang = "Ready"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Ready(#[stable(feature = "futures_api", since = "1.36.0")] T),

    /// Represents that a value is not ready yet.
    ///
    /// When a function returns `Pending`, the function *must* also
    /// ensure that the current task is scheduled to be awoken when
    /// progress can be made.
    #[lang = "Pending"]
    #[stable(feature = "futures_api", since = "1.36.0")]
    Pending,
}

impl<T> Poll<T> {
    /// Maps a `Poll<T>` to `Poll<U>` by applying a function to a contained value.
    ///
    /// # Examples
    ///
    /// Converts a Poll<[String]> into a Poll<[usize]>, consuming
    /// the original:
    ///
    /// [String]: ../../std/string/struct.String.html "String"
    /// ```
    /// # use core::task::Poll;
    /// let poll_some_string = Poll::Ready(String::from("Hello, World!"));
    /// // `Poll::map` takes self *by value*, consuming `poll_some_string`
    /// let poll_some_len = poll_some_string.map(|s| s.len());
    ///
    /// assert_eq!(poll_some_len, Poll::Ready(13));
    /// ```
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map(self, f: F) -> Poll
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(t) => Poll::Ready(f(t)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Returns `true` if the poll is a [`Poll::Ready`] value.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let x: Poll<u32> = Poll::Ready(2);
    /// assert_eq!(x.is_ready(), true);
    ///
    /// let x: Poll<u32> = Poll::Pending;
    /// assert_eq!(x.is_ready(), false);
    /// ```
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_ready(&self) -> bool {
        matches!(*self, Poll::Ready(_))
    }

    /// Returns `true` if the poll is a [`Pending`] value.
    ///
    /// [`Pending`]: Poll::Pending
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let x: Poll<u32> = Poll::Ready(2);
    /// assert_eq!(x.is_pending(), false);
    ///
    /// let x: Poll<u32> = Poll::Pending;
    /// assert_eq!(x.is_pending(), true);
    /// ```
    #[inline]
    #[rustc_const_stable(feature = "const_poll", since = "1.49.0")]
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub const fn is_pending(&self) -> bool {
        !self.is_ready()
    }

    /// Extracts the successful type of a [`Poll<T>`].
    ///
    /// When combined with the `?` operator, this function will
    /// propagate any [`Poll::Pending`] values to the caller, and
    /// extract the `T` from [`Poll::Ready`].
    ///
    /// # Examples
    ///
    /// ```rust
    /// #![feature(poll_ready)]
    ///
    /// use std::task::{Context, Poll};
    /// use std::future::{self, Future};
    /// use std::pin::Pin;
    ///
    /// pub fn do_poll(cx: &mut Context<'_>) -> Poll<()> {
    ///     let mut fut = future::ready(42);
    ///     let fut = Pin::new(&mut fut);
    ///
    ///     let num = fut.poll(cx).ready()?;
    ///     # drop(num);
    ///     // ... use num
    ///
    ///     Poll::Ready(())
    /// }
    /// ```
    #[inline]
    #[unstable(feature = "poll_ready", issue = "89780")]
    pub fn ready(self) -> Ready<T> {
        Ready(self)
    }
}

impl<T, E> Poll<Result<T, E>> {
    /// Maps a `Poll<Result<T, E>>` to `Poll<Result<U, E>>` by applying a
    /// function to a contained `Poll::Ready(Ok)` value, leaving all other
    /// variants untouched.
    ///
    /// This function can be used to compose the results of two functions.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Result<u8, _>> = Poll::Ready("12".parse());
    /// let squared = res.map_ok(|n| n * n);
    /// assert_eq!(squared, Poll::Ready(Ok(144)));
    /// ```
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_ok(self, f: F) -> Poll<Result>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(f(t))),
            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Maps a `Poll::Ready<Result<T, E>>` to `Poll::Ready<Result<T, F>>` by
    /// applying a function to a contained `Poll::Ready(Err)` value, leaving all other
    /// variants untouched.
    ///
    /// This function can be used to pass through a successful result while handling
    /// an error.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Result<u8, _>> = Poll::Ready("oops".parse());
    /// let res = res.map_err(|_| 0_u8);
    /// assert_eq!(res, Poll::Ready(Err(0)));
    /// ```
    #[stable(feature = "futures_api", since = "1.36.0")]
    pub fn map_err(self, f: F) -> Poll<Result<T, U>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Ok(t)) => Poll::Ready(Ok(t)),
            Poll::Ready(Err(e)) => Poll::Ready(Err(f(e))),
            Poll::Pending => Poll::Pending,
        }
    }
}

impl<T, E> Poll<Option<Result<T, E>>> {
    /// Maps a `Poll<Option<Result<T, E>>>` to `Poll<Option<Result<U, E>>>` by
    /// applying a function to a contained `Poll::Ready(Some(Ok))` value,
    /// leaving all other variants untouched.
    ///
    /// This function can be used to compose the results of two functions.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("12".parse()));
    /// let squared = res.map_ok(|n| n * n);
    /// assert_eq!(squared, Poll::Ready(Some(Ok(144))));
    /// ```
    #[stable(feature = "poll_map", since = "1.51.0")]
    pub fn map_ok(self, f: F) -> Poll<Option<Result>>
    where
        F: FnOnce(T) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(f(t)))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }

    /// Maps a `Poll::Ready<Option<Result<T, E>>>` to
    /// `Poll::Ready<Option<Result<T, F>>>` by applying a function to a
    /// contained `Poll::Ready(Some(Err))` value, leaving all other variants
    /// untouched.
    ///
    /// This function can be used to pass through a successful result while handling
    /// an error.
    ///
    /// # Examples
    ///
    /// ```
    /// # use core::task::Poll;
    /// let res: Poll<Option<Result<u8, _>>> = Poll::Ready(Some("oops".parse()));
    /// let res = res.map_err(|_| 0_u8);
    /// assert_eq!(res, Poll::Ready(Some(Err(0))));
    /// ```
    #[stable(feature = "poll_map", since = "1.51.0")]
    pub fn map_err(self, f: F) -> Poll<Option<Result<T, U>>>
    where
        F: FnOnce(E) -> U,
    {
        match self {
            Poll::Ready(Some(Ok(t))) => Poll::Ready(Some(Ok(t))),
            Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(f(e)))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }
}

#[stable(feature = "futures_api", since = "1.36.0")]
impl<T> From<T> for Poll<T> {
    /// Convert to a `Ready` variant.
    ///
    /// # Example
    ///
    /// ```
    /// # use core::task::Poll;
    /// assert_eq!(Poll::from(true), Poll::Ready(true));
    /// ```
    fn from(t: T) -> Poll<T> {
        Poll::Ready(t)
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E> ops::Try for Poll<Result<T, E>> {
    type Output = Poll<T>;
    type Residual = Result<convert::Infallible, E>;

    #[inline]
    fn from_output(c: Self::Output) -> Self {
        c.map(Ok)
    }

    #[inline]
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        match self {
            Poll::Ready(Ok(x)) => ControlFlow::Continue(Poll::Ready(x)),
            Poll::Ready(Err(e)) => ControlFlow::Break(Err(e)),
            Poll::Pending => ControlFlow::Continue(Poll::Pending),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Poll<Result<T, F>> {
    #[inline]
    fn from_residual(x: Result<convert::Infallible, E>) -> Self {
        match x {
            Err(e) => Poll::Ready(Err(From::from(e))),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E> ops::Try for Poll<Option<Result<T, E>>> {
    type Output = Poll<Option<T>>;
    type Residual = Result<convert::Infallible, E>;

    #[inline]
    fn from_output(c: Self::Output) -> Self {
        c.map(|x| x.map(Ok))
    }

    #[inline]
    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
        match self {
            Poll::Ready(Some(Ok(x))) => ControlFlow::Continue(Poll::Ready(Some(x))),
            Poll::Ready(Some(Err(e))) => ControlFlow::Break(Err(e)),
            Poll::Ready(None) => ControlFlow::Continue(Poll::Ready(None)),
            Poll::Pending => ControlFlow::Continue(Poll::Pending),
        }
    }
}

#[unstable(feature = "try_trait_v2", issue = "84277")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>>
    for Poll<Option<Result<T, F>>>
{
    #[inline]
    fn from_residual(x: Result<convert::Infallible, E>) -> Self {
        match x {
            Err(e) => Poll::Ready(Some(Err(From::from(e)))),
        }
    }
}
<|endoftext|>


<commit_before>//! The I/O Prelude
//!
//! The purpose of this module is to alleviate imports of many common I/O traits
//! by adding a glob import to the top of I/O heavy modules:
//!
//! ```
//! # #![allow(unused_imports)]
//! use std::io::prelude::*;
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

#[stable(feature = "rust1", since = "1.0.0")]
pub use super::{BufRead, Read, Seek, Write};
<commit_msg>Use heading style for 'The I/O Prelude' in `std::io::prelude`<commit_after>//! # The I/O Prelude
//!
//! The purpose of this module is to alleviate imports of many common I/O traits
//! by adding a glob import to the top of I/O heavy modules:
//!
//! ```
//! # #![allow(unused_imports)]
//! use std::io::prelude::*;
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

#[stable(feature = "rust1", since = "1.0.0")]
pub use super::{BufRead, Read, Seek, Write};
<|endoftext|>


<commit_before><commit_msg>Easy to make the range state cloneable<commit_after><|endoftext|>


<commit_before>#[macro_use]
extern crate enum_map;

use enum_map::{EnumMap, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;

#[derive(Copy, Clone, Debug, EnumMap, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_option_bool() {
    let mut map = enum_map! { None => 1, Some(false) => 2, Some(true) => 3};
    assert_eq!(map[None], 1);
    assert_eq!(map[Some(false)], 2);
    assert_eq!(map[Some(true)], 3);
    map[None] = 4;
    map[Some(false)] = 5;
    map[Some(true)] = 6;
    assert_eq!(map[None], 4);
    assert_eq!(map[Some(false)], 5);
    assert_eq!(map[Some(true)], 6);
    assert_eq!(map.as_slice(), [4, 5, 6]);
    assert_eq!(
        map.into_iter().collect::<Vec<_>>(),
        [(None, 4), (Some(false), 5), (Some(true), 6)]
    );
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn discriminants() {
    #[derive(Debug, EnumMap, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(EnumMap)]
    enum Example {
        A,
        B,
        C,
        D,
        E,
        F,
        G,
        H,
        I,
        J,
        K,
        L,
        M,
        N,
        O,
        P,
        Q,
        R,
        S,
        T,
        U,
        V,
        W,
        X,
        Y,
        Z,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

#[test]
fn into_iter() {
    let mut iter = enum_map! { true => 5, false => 7 }.into_iter();
    assert_eq!(iter.next(), Some((false, 7)));
    assert_eq!(iter.next(), Some((true, 5)));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.next(), None);
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }.into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn test_u8() {
    let map = enum_map! { b'a' => 4, _ => 0 };
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
}

#[derive(EnumMap)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map!{};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}
<commit_msg>Test iter_mut len<commit_after>#[macro_use]
extern crate enum_map;

use enum_map::{EnumMap, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;

#[derive(Copy, Clone, Debug, EnumMap, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_option_bool() {
    let mut map = enum_map! { None => 1, Some(false) => 2, Some(true) => 3};
    assert_eq!(map[None], 1);
    assert_eq!(map[Some(false)], 2);
    assert_eq!(map[Some(true)], 3);
    map[None] = 4;
    map[Some(false)] = 5;
    map[Some(true)] = 6;
    assert_eq!(map[None], 4);
    assert_eq!(map[Some(false)], 5);
    assert_eq!(map[Some(true)], 6);
    assert_eq!(map.as_slice(), [4, 5, 6]);
    assert_eq!(
        map.into_iter().collect::<Vec<_>>(),
        [(None, 4), (Some(false), 5), (Some(true), 6)]
    );
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn discriminants() {
    #[derive(Debug, EnumMap, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(EnumMap)]
    enum Example {
        A,
        B,
        C,
        D,
        E,
        F,
        G,
        H,
        I,
        J,
        K,
        L,
        M,
        N,
        O,
        P,
        Q,
        R,
        S,
        T,
        U,
        V,
        W,
        X,
        Y,
        Z,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iter_mut_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter_mut()
            .len(),
        3
    );
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

#[test]
fn into_iter() {
    let mut iter = enum_map! { true => 5, false => 7 }.into_iter();
    assert_eq!(iter.next(), Some((false, 7)));
    assert_eq!(iter.next(), Some((true, 5)));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.next(), None);
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }.into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn test_u8() {
    let map = enum_map! { b'a' => 4, _ => 0 };
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
}

#[derive(EnumMap)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map!{};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}
<|endoftext|>