<commit_before>#![deny(missing_docs)]
#![warn(rust_2018_idioms)]
#![doc(html_root_url = "https://docs.rs/amq-protocol-tcp/5.0.0-beta.4/")]

//! # AMQP URI TCP connection handling
//!
//! amq-protocol-tcp is a library aiming at providing tools to help
//! connecting to an AMQP URI

use amq_protocol_uri::{AMQPScheme, AMQPUri};
use log::{trace, warn};
use mio::{Events, Interest, Poll, Token};
use tcp_stream::HandshakeError;

use std::io;

/// Re-export TcpStream
pub use tcp_stream::{Identity, TcpStream};

/// Trait providing a method to connect to a TcpStream
pub trait AMQPUriTcpExt {
    /// connect to a TcpStream
    fn connect<S, F: FnOnce(TcpStream, AMQPUri, Option<(Poll, Token)>) -> S>(
        self,
        f: F,
    ) -> io::Result<S>
    where
        Self: Sized,
    {
        self.connect_full(f, None, None)
    }
    /// connect to a TcpStream, registering it to the given Poll with the given Token to handle the
    /// handshake process. You should reregister it afterwards to better fit your needs
    fn connect_full<S, F: FnOnce(TcpStream, AMQPUri, Option<(Poll, Token)>) -> S>(
        self,
        f: F,
        poll: Option<(Poll, Token)>,
        identity: Option<Identity<'_, '_>>,
    ) -> io::Result<S>;
}

impl AMQPUriTcpExt for AMQPUri {
    fn connect_full<S, F: FnOnce(TcpStream, AMQPUri, Option<(Poll, Token)>) -> S>(
        self,
        f: F,
        poll: Option<(Poll, Token)>,
        identity: Option<Identity<'_, '_>>,
    ) -> io::Result<S> {
        let uri = format!("{}:{}", self.authority.host, self.authority.port);
        trace!("Connecting to {}", uri);
        let mut stream = TcpStream::connect(uri)?;

        if let Some((poll, token)) = poll.as_ref() {
            trace!("Registering for mio events");
            poll.registry().register(
                &mut stream,
                *token,
                Interest::READABLE | Interest::WRITABLE,
            )?;
        }

        match self.scheme {
            AMQPScheme::AMQP => Ok((stream, poll)),
            AMQPScheme::AMQPS => connect_amqps(stream, &self.authority.host, poll, identity),
        }
        .map(|(s, poll)| f(s, self, poll))
    }
}

fn connect_amqps(
    stream: TcpStream,
    host: &str,
    mut poll: Option<(Poll, Token)>,
    identity: Option<Identity<'_, '_>>,
) -> io::Result<(TcpStream, Option<(Poll, Token)>)> {
    trace!("Enabling TLS");
    let mut events = Events::with_capacity(1024);
    let mut res = stream.into_tls(host, identity);

    while let Err(error) = res {
        warn!("Got error when enabling TLS: {:?}", error);
        match error {
            HandshakeError::Failure(io_err) => return Err(io_err),
            HandshakeError::WouldBlock(mid) => {
                if let Some((poll, _)) = poll.as_mut() {
                    trace!("Waiting for mio events");
                    poll.poll(&mut events, None)?;
                }
                trace!("Retrying TLS");
                res = mid.handshake()
            }
        };
    }

    trace!("TLS enabled");
    Ok((res.unwrap(), poll))
}

impl AMQPUriTcpExt for &str {
    fn connect_full<S, F: FnOnce(TcpStream, AMQPUri, Option<(Poll, Token)>) -> S>(
        self,
        f: F,
        poll: Option<(Poll, Token)>,
        identity: Option<Identity<'_, '_>>,
    ) -> io::Result<S> {
        self.parse::<AMQPUri>()
            .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?
            .connect_full(f, poll, identity)
    }
}
<commit_msg>tcp: change log level<commit_after>#![deny(missing_docs)]
#![warn(rust_2018_idioms)]
#![doc(html_root_url = "https://docs.rs/amq-protocol-tcp/5.0.0-beta.4/")]

//! # AMQP URI TCP connection handling
//!
//! amq-protocol-tcp is a library aiming at providing tools to help
//! connecting to an AMQP URI

use amq_protocol_uri::{AMQPScheme, AMQPUri};
use log::{debug, trace};
use mio::{Events, Interest, Poll, Token};
use tcp_stream::HandshakeError;

use std::io;

/// Re-export TcpStream
pub use tcp_stream::{Identity, TcpStream};

/// Trait providing a method to connect to a TcpStream
pub trait AMQPUriTcpExt {
    /// connect to a TcpStream
    fn connect<S, F: FnOnce(TcpStream, AMQPUri, Option<(Poll, Token)>) -> S>(
        self,
        f: F,
    ) -> io::Result<S>
    where
        Self: Sized,
    {
        self.connect_full(f, None, None)
    }
    /// connect to a TcpStream, registering it to the given Poll with the given Token to handle the
    /// handshake process. You should reregister it afterwards to better fit your needs
    fn connect_full<S, F: FnOnce(TcpStream, AMQPUri, Option<(Poll, Token)>) -> S>(
        self,
        f: F,
        poll: Option<(Poll, Token)>,
        identity: Option<Identity<'_, '_>>,
    ) -> io::Result<S>;
}

impl AMQPUriTcpExt for AMQPUri {
    fn connect_full<S, F: FnOnce(TcpStream, AMQPUri, Option<(Poll, Token)>) -> S>(
        self,
        f: F,
        poll: Option<(Poll, Token)>,
        identity: Option<Identity<'_, '_>>,
    ) -> io::Result<S> {
        let uri = format!("{}:{}", self.authority.host, self.authority.port);
        trace!("Connecting to {}", uri);
        let mut stream = TcpStream::connect(uri)?;

        if let Some((poll, token)) = poll.as_ref() {
            trace!("Registering for mio events");
            poll.registry().register(
                &mut stream,
                *token,
                Interest::READABLE | Interest::WRITABLE,
            )?;
        }

        match self.scheme {
            AMQPScheme::AMQP => Ok((stream, poll)),
            AMQPScheme::AMQPS => connect_amqps(stream, &self.authority.host, poll, identity),
        }
        .map(|(s, poll)| f(s, self, poll))
    }
}

fn connect_amqps(
    stream: TcpStream,
    host: &str,
    mut poll: Option<(Poll, Token)>,
    identity: Option<Identity<'_, '_>>,
) -> io::Result<(TcpStream, Option<(Poll, Token)>)> {
    trace!("Enabling TLS");
    let mut events = Events::with_capacity(1024);
    let mut res = stream.into_tls(host, identity);

    while let Err(error) = res {
        debug!("Got error when enabling TLS: {:?}", error);
        match error {
            HandshakeError::Failure(io_err) => return Err(io_err),
            HandshakeError::WouldBlock(mid) => {
                if let Some((poll, _)) = poll.as_mut() {
                    trace!("Waiting for mio events");
                    poll.poll(&mut events, None)?;
                }
                trace!("Retrying TLS");
                res = mid.handshake()
            }
        };
    }

    trace!("TLS enabled");
    Ok((res.unwrap(), poll))
}

impl AMQPUriTcpExt for &str {
    fn connect_full<S, F: FnOnce(TcpStream, AMQPUri, Option<(Poll, Token)>) -> S>(
        self,
        f: F,
        poll: Option<(Poll, Token)>,
        identity: Option<Identity<'_, '_>>,
    ) -> io::Result<S> {
        self.parse::<AMQPUri>()
            .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?
            .connect_full(f, poll, identity)
    }
}
<|endoftext|>


<commit_before>//! Module that adds fasterxml annotations to generated classes.

use backend::errors::*;
use genco::{Cons, Element, IntoTokens, Java, Quoted, Tokens};
use genco::java::{Argument, Class, DOUBLE, FLOAT, Field, INTEGER, LONG, Modifier, SHORT, imported,
                  local};
use listeners::{ClassAdded, EnumAdded, InterfaceAdded, Listeners, TupleAdded};
use std::rc::Rc;

/// @JsonSubTypes.Type annotation
struct SubTypesType<'a, 'el>(&'a Module, Tokens<'el, Java<'el>>);

impl<'a, 'el> IntoTokens<'el, Java<'el>> for SubTypesType<'a, 'el> {
    fn into_tokens(self) -> Tokens<'el, Java<'el>> {
        toks!["@", self.0.sub_type.clone(), "(", self.1.join(", "), ")"]
    }
}

/// @JsonSubTypes annotation
struct SubTypes<'a, 'el>(&'a Module, Tokens<'el, Java<'el>>);

impl<'a, 'el> IntoTokens<'el, Java<'el>> for SubTypes<'a, 'el> {
    fn into_tokens(self) -> Tokens<'el, Java<'el>> {
        let mut out: Tokens<Java> = Tokens::new();
        out.append("@");
        out.append(self.0.sub_types.clone());
        out.append("({");

        if !self.1.is_empty() {
            out.nested(self.1.join(toks![",", Element::PushSpacing]))
        }

        out.append("})");
        out
    }
}

struct TypeInfo<'a, 'el>(&'a Module, Tokens<'el, Java<'el>>);

impl<'a, 'el> IntoTokens<'el, Java<'el>> for TypeInfo<'a, 'el> {
    fn into_tokens(self) -> Tokens<'el, Java<'el>> {
        toks!["@", self.0.type_info.clone(), "(", self.1.join(", "), ")"]
    }
}

pub struct Module {
    override_: Java<'static>,
    creator: Java<'static>,
    value: Java<'static>,
    property: Java<'static>,
    sub_types: Java<'static>,
    sub_type: Java<'static>,
    type_info: Java<'static>,
    serialize: Java<'static>,
    deserialize: Java<'static>,
    deserializer: Java<'static>,
    serializer: Java<'static>,
    generator: Java<'static>,
    serializer_provider: Java<'static>,
    parser: Java<'static>,
    deserialization_context: Java<'static>,
    type_reference: Java<'static>,
    token: Java<'static>,
    string: Java<'static>,
    io_exception: Java<'static>,
}

impl Module {
    pub fn new() -> Module {
        Module {
            override_: imported("java.lang", "Override"),
            creator: imported("com.fasterxml.jackson.annotation", "JsonCreator"),
            value: imported("com.fasterxml.jackson.annotation", "JsonValue"),
            property: imported("com.fasterxml.jackson.annotation", "JsonProperty"),
            sub_types: imported("com.fasterxml.jackson.annotation", "JsonSubTypes"),
            sub_type: imported("com.fasterxml.jackson.annotation", "JsonSubTypes").path("Type"),
            type_info: imported("com.fasterxml.jackson.annotation", "JsonTypeInfo"),
            serialize: imported("com.fasterxml.jackson.databind.annotation", "JsonSerialize"),
            deserialize: imported(
                "com.fasterxml.jackson.databind.annotation",
                "JsonDeserialize",
            ),
            serializer: imported("com.fasterxml.jackson.databind", "JsonSerializer"),
            deserializer: imported("com.fasterxml.jackson.databind", "JsonDeserializer"),
            generator: imported("com.fasterxml.jackson.core", "JsonGenerator"),
            serializer_provider: imported("com.fasterxml.jackson.databind", "SerializerProvider"),
            parser: imported("com.fasterxml.jackson.core", "JsonParser"),
            deserialization_context: imported(
                "com.fasterxml.jackson.databind",
                "DeserializationContext",
            ),
            type_reference: imported("com.fasterxml.jackson.core.type", "TypeReference"),
            token: imported("com.fasterxml.jackson.core", "JsonToken"),
            string: imported("java.lang", "String"),
            io_exception: imported("java.io", "IOException"),
        }
    }

    /// RpName serialize implementation for tuples.
    fn tuple_serializer<'el>(
        &self,
        name: Cons<'el>,
        fields: &mut [Field<'el>],
    ) -> Result<Class<'el>> {
        let mut class = Class::new("Serializer");
        let ty = local(name.clone());

        class.extends = Some(self.serializer.with_arguments(vec![ty.clone()]));

        let value = Argument::new(ty.clone(), "value");
        let jgen = Argument::new(self.generator.clone(), "jgen");
        let provider = Argument::new(self.serializer_provider.clone(), "provider");

        let mut serialize = Tokens::new();

        serialize.push(toks!("@", self.override_.clone()));
        serialize.push(toks![
            "public serialize(",
            toks![value.var(), jgen.var(), provider.var()].join_spacing(),
            ") throws ",
            self.io_exception.clone(),
            " {",
        ]);

        serialize.nested({
            let mut t = Tokens::new();
            t.push(toks!["jgen.writeStartArray();"]);

            for field in fields {
                let access = toks!["value.", field.var()];

                let write = match field.ty() {
                    SHORT | LONG | INTEGER | FLOAT | DOUBLE => {
                        toks!["writeNumber(", access.clone(), ")"]
                    }
                    Java::Primitive { .. } => {
                        return Err("cannot serialize type".into());
                    }
                    class @ Java::Class { .. } => {
                        if class == self.string {
                            toks!["writeString(", access.clone(), ")"]
                        } else {
                            toks!["writeObject(", access.clone(), ")"]
                        }
                    }
                    _ => toks!["writeObject(", access.clone(), ")"],
                };

                t.push(toks!["jgen.", write, ";"]);
            }

            t.push(toks!["jgen.writeEndArray();"]);

            t
        });

        serialize.push("}");

        class.body.push(serialize);
        Ok(class)
    }

    fn deserialize_method_for_type<'el, A>(
        &self,
        ty: Java<'el>,
        parser: A,
    ) -> Result<(Option<(Tokens<'el, Java<'el>>, &'el str)>, Tokens<'el, Java<'el>>)>
    where
        A: Into<Tokens<'el, Java<'el>>>,
    {
        let p = parser.into();

        let (token, reader) = match ty {
            java @ Java::Primitive { .. } => {
                let test = toks!["!", p.clone(), ".nextToken().isNumeric()"];

                match java {
                    SHORT => (
                        Some((test, "VALUE_NUMBER_INT")),
                        toks![p, ".getShortValue()"],
                    ),
                    LONG => (
                        Some((test, "VALUE_NUMBER_INT")),
                        toks![p, ".getLongValue()"],
                    ),
                    INTEGER => {
                        (
                            Some((test, "VALUE_NUMBER_INT")),
                            toks![p, ".getIntegerValue()"],
                        )
                    }
                    FLOAT => {
                        (
                            Some((test, "VALUE_NUMBER_FLOAT")),
                            toks![p, ".getFloatValue()"],
                        )
                    }
                    DOUBLE => {
                        (
                            Some((test, "VALUE_NUMBER_FLOAT")),
                            toks![p, ".getDoubleValue()"],
                        )
                    }
                    _ => {
                        return Err("unsupported type".into());
                    }
                }
            }
            class @ Java::Class { .. } => {
                if class == self.string {
                    let test =
                        toks![p.clone(), ".nextToken() != ", self.token.clone(), ".VALUE_STRING",
                    ];
                    let token = Some((test, "VALUE_STRING"));
                    (token, toks![p, ".getText()"])
                } else {
                    let is_empty = class.arguments().map(|a| a.is_empty()).unwrap_or(true);

                    let argument = if is_empty {
                        toks![class, ".class"]
                    } else {
                        toks![
                            "new ",
                            self.type_reference.with_arguments(vec![class]),
                            "(){}",
                        ]
                    };

                    (None, toks![p, ".readValueAs(", argument, ")"])
                }
            }
            _ => {
                return Err("unsupported type".into());
            }
        };

        Ok((token, reader))
    }

    fn wrong_token<'el, C, P, T>(&self, ctxt: C, parser: P, token: T) -> Tokens<'el, Java<'el>>
    where
        C: Into<Tokens<'el, Java<'el>>>,
        P: Into<Tokens<'el, Java<'el>>>,
        T: Into<Tokens<'el, Java<'el>>>,
    {
        let mut arguments = Tokens::new();

        arguments.push(parser.into());
        arguments.push(toks![self.token.clone(), ".", token.into()]);
        arguments.push("null");

        toks![
            "throw ",
            ctxt.into(),
            ".wrongTokenException(",
            arguments.join(", "),
            ");",
        ]
    }

    /// RpName deserialize implementation for tuples.
    fn tuple_deserializer<'el>(
        &self,
        name: Cons<'el>,
        fields: &mut [Field<'el>],
    ) -> Result<Class<'el>> {
        use self::Modifier::*;

        let ty = local(name.clone());

        let parser = toks!("final ", self.parser.clone(), " parser");
        let ctxt = toks!("final ", self.deserialization_context.clone(), " ctxt");

        let mut deserialize = Tokens::new();

        deserialize.push(toks!("@", self.override_.clone()));
        deserialize.push(toks![
            "public ", ty.clone(), " deserialize(",
            toks![parser, ctxt].join_spacing(),
            ") throws ",
            self.io_exception.clone(),
            " {",
        ]);

        deserialize.nested({
            let mut body = Tokens::new();
            let current_token = toks!["parser.getCurrentToken()"];

            let mut start_array = Tokens::new();
            start_array.push(toks![
                "if (",
                current_token,
                " != ",
                self.token.clone(),
                ".START_ARRAY) {",
            ]);
            start_array.nested(self.wrong_token("ctxt", "parser", "START_ARRAY"));
            start_array.push("}");
            body.push(start_array);

            let mut arguments = Tokens::new();

            for field in fields {
                let (token, reader) = self.deserialize_method_for_type(field.ty(), "parser")?;

                if let Some((test, expected)) = token {
                    let mut field_check = Tokens::new();
                    field_check.push(toks!["if (", test, ") {"]);
                    field_check.nested(self.wrong_token("ctxt", "parser", expected));
                    field_check.push("}");
                    body.push(field_check);
                }

                let variable = toks!["v_", field.var()];
                let assign =
                    toks![
                        "final ",
                        field.ty(),
                        " ",
                        variable.clone(),
                        " = ",
                        reader,
                        ";",
                    ];
                body.push(assign);
                arguments.push(variable);
            }

            let mut end_array = Tokens::new();
            end_array.push(toks![
                "if (parser.nextToken() != ", self.token.clone(), ".END_ARRAY) {",
            ]);
            end_array.nested(self.wrong_token("ctxt", "parser", "END_ARRAY"));
            end_array.push("}");
            body.push(end_array);

            body.push(toks![
                "return new ",
                ty.clone(),
                "(",
                arguments.join(", "),
                ");",
            ]);

            body.join_line_spacing()
        });

        deserialize.push("}");

        Ok({
            let mut deserializer = Class::new("Deserializer");
            deserializer.modifiers.push(Static);
            deserializer.extends = Some(self.deserializer.with_arguments(vec![ty.clone()]));
            deserializer.body.push(deserialize);
            deserializer
        })
    }

    fn add_class_annotations<'a>(&self, names: &[Cons<'a>], spec: &mut Class<'a>) -> Result<()> {
        for (field, name) in spec.fields.iter_mut().zip(names.iter()) {
            let ann = toks!["@", self.property.clone(), "(", name.clone().quoted(), ")"];
            field.annotation(ann.clone());
        }

        for c in &mut spec.constructors {
            c.annotation(toks!["@", self.creator.clone()]);

            for (argument, name) in c.arguments.iter_mut().zip(names.iter()) {
                let ann = toks!["@", self.property.clone(), "(", name.clone().quoted(), ")"];
                argument.annotation(ann.clone());
            }
        }

        Ok(())
    }

    fn add_tuple_serialization(&self, spec: &mut Class) -> Result<()> {
        let serializer = self.tuple_serializer(spec.name(), &mut spec.fields)?;

        let serializer_type = Rc::new(format!(
            "{}.{}",
            spec.name().as_ref(),
            serializer.name().as_ref()
        ));

        spec.annotation(toks![
            self.serialize.clone(),
            "(using = ",
            serializer_type,
            ".class)",
        ]);

        spec.body.push(serializer);

        let deserializer = self.tuple_deserializer(spec.name(), &mut spec.fields)?;

        let deserializer_type = Rc::new(format!(
            "{}.{}",
            spec.name().as_ref(),
            deserializer.name().as_ref()
        ));

        let deserialize =
            toks![
            "@",
            self.deserialize.clone(),
            "(using = ",
            deserializer_type,
            ".class)",
        ];

        spec.annotation(deserialize);
        spec.body.push(deserializer);
        Ok(())
    }
}

impl Listeners for Module {
    fn class_added<'a>(&self, e: &mut ClassAdded) -> Result<()> {
        self.add_class_annotations(&e.names, &mut e.spec)?;
        Ok(())
    }

    fn tuple_added(&self, e: &mut TupleAdded) -> Result<()> {
        self.add_tuple_serialization(&mut e.spec)
    }

    fn enum_added(&self, e: &mut EnumAdded) -> Result<()> {
        e.from_value.annotation(toks!["@", self.creator.clone()]);
        e.to_value.annotation(toks!["@", self.value.clone()]);
        Ok(())
    }

    fn interface_added(&self, e: &mut InterfaceAdded) -> Result<()> {
        {
            let mut args = Tokens::new();

            args.append(toks!["use=", self.type_info.clone(), ".Id.NAME"]);
            args.append(toks!["include=", self.type_info.clone(), ".As.PROPERTY"]);
            args.append(toks!["property=", "type".quoted()]);

            e.spec.annotation(TypeInfo(self, args));
        }

        {
            let mut args = Tokens::new();

            for (key, sub_type) in &e.body.sub_types {
                for name in &sub_type.names {
                    let name = name.value().to_owned();

                    let mut a = Tokens::new();

                    a.append(toks!["name=", name.quoted()]);
                    a.append(toks![
                        "value=",
                        e.spec.name(),
                        ".",
                        key.as_str(),
                        ".class",
                    ]);

                    let arg = SubTypesType(self, a).into_tokens();
                    args.append(arg);
                }
            }

            e.spec.annotation(SubTypes(self, args));
        }

        Ok(())
    }
}
<commit_msg>[java/fasterxml] fix handling of tuples<commit_after>//! Module that adds fasterxml annotations to generated classes.

use backend::errors::*;
use genco::{Cons, Element, IntoTokens, Java, Quoted, Tokens};
use genco::java::{Argument, Class, DOUBLE, FLOAT, Field, INTEGER, LONG, Modifier, SHORT, imported,
                  local};
use listeners::{ClassAdded, EnumAdded, InterfaceAdded, Listeners, TupleAdded};
use std::rc::Rc;

/// @JsonSubTypes.Type annotation
struct SubTypesType<'a, 'el>(&'a Module, Tokens<'el, Java<'el>>);

impl<'a, 'el> IntoTokens<'el, Java<'el>> for SubTypesType<'a, 'el> {
    fn into_tokens(self) -> Tokens<'el, Java<'el>> {
        toks!["@", self.0.sub_type.clone(), "(", self.1.join(", "), ")"]
    }
}

/// @JsonSubTypes annotation
struct SubTypes<'a, 'el>(&'a Module, Tokens<'el, Java<'el>>);

impl<'a, 'el> IntoTokens<'el, Java<'el>> for SubTypes<'a, 'el> {
    fn into_tokens(self) -> Tokens<'el, Java<'el>> {
        let mut out: Tokens<Java> = Tokens::new();
        out.append("@");
        out.append(self.0.sub_types.clone());
        out.append("({");

        if !self.1.is_empty() {
            out.nested(self.1.join(toks![",", Element::PushSpacing]))
        }

        out.append("})");
        out
    }
}

struct TypeInfo<'a, 'el>(&'a Module, Tokens<'el, Java<'el>>);

impl<'a, 'el> IntoTokens<'el, Java<'el>> for TypeInfo<'a, 'el> {
    fn into_tokens(self) -> Tokens<'el, Java<'el>> {
        toks!["@", self.0.type_info.clone(), "(", self.1.join(", "), ")"]
    }
}

pub struct Module {
    override_: Java<'static>,
    creator: Java<'static>,
    value: Java<'static>,
    property: Java<'static>,
    sub_types: Java<'static>,
    sub_type: Java<'static>,
    type_info: Java<'static>,
    serialize: Java<'static>,
    deserialize: Java<'static>,
    deserializer: Java<'static>,
    serializer: Java<'static>,
    generator: Java<'static>,
    serializer_provider: Java<'static>,
    parser: Java<'static>,
    deserialization_context: Java<'static>,
    type_reference: Java<'static>,
    token: Java<'static>,
    string: Java<'static>,
    io_exception: Java<'static>,
}

impl Module {
    pub fn new() -> Module {
        Module {
            override_: imported("java.lang", "Override"),
            creator: imported("com.fasterxml.jackson.annotation", "JsonCreator"),
            value: imported("com.fasterxml.jackson.annotation", "JsonValue"),
            property: imported("com.fasterxml.jackson.annotation", "JsonProperty"),
            sub_types: imported("com.fasterxml.jackson.annotation", "JsonSubTypes"),
            sub_type: imported("com.fasterxml.jackson.annotation", "JsonSubTypes").path("Type"),
            type_info: imported("com.fasterxml.jackson.annotation", "JsonTypeInfo"),
            serialize: imported("com.fasterxml.jackson.databind.annotation", "JsonSerialize"),
            deserialize: imported(
                "com.fasterxml.jackson.databind.annotation",
                "JsonDeserialize",
            ),
            serializer: imported("com.fasterxml.jackson.databind", "JsonSerializer"),
            deserializer: imported("com.fasterxml.jackson.databind", "JsonDeserializer"),
            generator: imported("com.fasterxml.jackson.core", "JsonGenerator"),
            serializer_provider: imported("com.fasterxml.jackson.databind", "SerializerProvider"),
            parser: imported("com.fasterxml.jackson.core", "JsonParser"),
            deserialization_context: imported(
                "com.fasterxml.jackson.databind",
                "DeserializationContext",
            ),
            type_reference: imported("com.fasterxml.jackson.core.type", "TypeReference"),
            token: imported("com.fasterxml.jackson.core", "JsonToken"),
            string: imported("java.lang", "String"),
            io_exception: imported("java.io", "IOException"),
        }
    }

    /// RpName serialize implementation for tuples.
    fn tuple_serializer<'el>(
        &self,
        name: Cons<'el>,
        fields: &mut [Field<'el>],
    ) -> Result<Class<'el>> {
        use self::Modifier::*;

        let ty = local(name.clone());

        let value = Argument::new(ty.clone(), "value");
        let jgen = Argument::new(self.generator.clone(), "jgen");
        let provider = Argument::new(self.serializer_provider.clone(), "provider");

        let mut serialize = Tokens::new();

        serialize.push(toks!("@", self.override_.clone()));
        serialize.push(toks![
            "public void serialize(",
            toks![value.into_tokens(), jgen.into_tokens(), provider.into_tokens()].join(", "),
            ") throws ",
            self.io_exception.clone(),
            " {",
        ]);

        serialize.nested({
            let mut t = Tokens::new();
            t.push(toks!["jgen.writeStartArray();"]);

            for field in fields {
                let access = toks!["value.", field.var()];

                let write = match field.ty() {
                    SHORT | LONG | INTEGER | FLOAT | DOUBLE => {
                        toks!["writeNumber(", access.clone(), ")"]
                    }
                    Java::Primitive { .. } => {
                        return Err("cannot serialize type".into());
                    }
                    class @ Java::Class { .. } => {
                        if class == self.string {
                            toks!["writeString(", access.clone(), ")"]
                        } else {
                            toks!["writeObject(", access.clone(), ")"]
                        }
                    }
                    _ => toks!["writeObject(", access.clone(), ")"],
                };

                t.push(toks!["jgen.", write, ";"]);
            }

            t.push(toks!["jgen.writeEndArray();"]);

            t
        });

        serialize.push("}");

        let mut class = Class::new("Serializer");
        class.modifiers.push(Static);
        class.extends = Some(self.serializer.with_arguments(vec![ty.clone()]));
        class.body.push(serialize);
        Ok(class)
    }

    fn deserialize_method_for_type<'el, A>(
        &self,
        ty: Java<'el>,
        parser: A,
    ) -> Result<(Option<(Tokens<'el, Java<'el>>, &'el str)>, Tokens<'el, Java<'el>>)>
    where
        A: Into<Tokens<'el, Java<'el>>>,
    {
        let p = parser.into();

        let (token, reader) = match ty {
            java @ Java::Primitive { .. } => {
                let test = toks!["!", p.clone(), ".nextToken().isNumeric()"];

                match java {
                    SHORT => (
                        Some((test, "VALUE_NUMBER_INT")),
                        toks![p, ".getShortValue()"],
                    ),
                    LONG => (
                        Some((test, "VALUE_NUMBER_INT")),
                        toks![p, ".getLongValue()"],
                    ),
                    INTEGER => {
                        (
                            Some((test, "VALUE_NUMBER_INT")),
                            toks![p, ".getIntegerValue()"],
                        )
                    }
                    FLOAT => {
                        (
                            Some((test, "VALUE_NUMBER_FLOAT")),
                            toks![p, ".getFloatValue()"],
                        )
                    }
                    DOUBLE => {
                        (
                            Some((test, "VALUE_NUMBER_FLOAT")),
                            toks![p, ".getDoubleValue()"],
                        )
                    }
                    _ => {
                        return Err("unsupported type".into());
                    }
                }
            }
            class @ Java::Class { .. } => {
                if class == self.string {
                    let test =
                        toks![p.clone(), ".nextToken() != ", self.token.clone(), ".VALUE_STRING",
                    ];
                    let token = Some((test, "VALUE_STRING"));
                    (token, toks![p, ".getText()"])
                } else {
                    let is_empty = class.arguments().map(|a| a.is_empty()).unwrap_or(true);

                    let argument = if is_empty {
                        toks![class, ".class"]
                    } else {
                        toks![
                            "new ",
                            self.type_reference.with_arguments(vec![class]),
                            "(){}",
                        ]
                    };

                    (None, toks![p, ".readValueAs(", argument, ")"])
                }
            }
            _ => {
                return Err("unsupported type".into());
            }
        };

        Ok((token, reader))
    }

    fn wrong_token<'el, C, P, T>(&self, ctxt: C, parser: P, token: T) -> Tokens<'el, Java<'el>>
    where
        C: Into<Tokens<'el, Java<'el>>>,
        P: Into<Tokens<'el, Java<'el>>>,
        T: Into<Tokens<'el, Java<'el>>>,
    {
        let mut arguments = Tokens::new();

        arguments.append(parser.into());
        arguments.append(toks![self.token.clone(), ".", token.into()]);
        arguments.append("null");

        toks![
            "throw ",
            ctxt.into(),
            ".wrongTokenException(",
            arguments.join(", "),
            ");",
        ]
    }

    /// RpName deserialize implementation for tuples.
    fn tuple_deserializer<'el>(
        &self,
        name: Cons<'el>,
        fields: &mut [Field<'el>],
    ) -> Result<Class<'el>> {
        use self::Modifier::*;

        let ty = local(name.clone());

        let parser = toks!("final ", self.parser.clone(), " parser");
        let ctxt = toks!("final ", self.deserialization_context.clone(), " ctxt");

        let mut deserialize = Tokens::new();

        deserialize.push(toks!("@", self.override_.clone()));
        deserialize.push(toks![
            "public ", ty.clone(), " deserialize(",
            toks![parser, ctxt].join(", "),
            ") throws ",
            self.io_exception.clone(),
            " {",
        ]);

        deserialize.nested({
            let mut body = Tokens::new();
            let current_token = toks!["parser.getCurrentToken()"];

            let mut start_array = Tokens::new();
            start_array.push(toks![
                "if (",
                current_token,
                " != ",
                self.token.clone(),
                ".START_ARRAY) {",
            ]);
            start_array.nested(self.wrong_token("ctxt", "parser", "START_ARRAY"));
            start_array.push("}");
            body.push(start_array);

            let mut arguments = Tokens::new();

            for field in fields {
                let (token, reader) = self.deserialize_method_for_type(field.ty(), "parser")?;

                if let Some((test, expected)) = token {
                    let mut field_check = Tokens::new();
                    field_check.push(toks!["if (", test, ") {"]);
                    field_check.nested(self.wrong_token("ctxt", "parser", expected));
                    field_check.push("}");
                    body.push(field_check);
                } else {
                    body.push("parser.nextToken();");
                }

                let variable = toks!["v_", field.var()];
                let assign =
                    toks![
                        "final ",
                        field.ty(),
                        " ",
                        variable.clone(),
                        " = ",
                        reader,
                        ";",
                    ];
                body.push(assign);
                arguments.append(variable);
            }

            let mut end_array = Tokens::new();
            end_array.push(toks![
                "if (parser.nextToken() != ", self.token.clone(), ".END_ARRAY) {",
            ]);
            end_array.nested(self.wrong_token("ctxt", "parser", "END_ARRAY"));
            end_array.push("}");
            body.push(end_array);

            body.push(toks![
                "return new ",
                ty.clone(),
                "(",
                arguments.join(", "),
                ");",
            ]);

            body.join_line_spacing()
        });

        deserialize.push("}");

        Ok({
            let mut deserializer = Class::new("Deserializer");
            deserializer.modifiers.push(Static);
            deserializer.extends = Some(self.deserializer.with_arguments(vec![ty.clone()]));
            deserializer.body.push(deserialize);
            deserializer
        })
    }

    fn add_class_annotations<'a>(&self, names: &[Cons<'a>], spec: &mut Class<'a>) -> Result<()> {
        for (field, name) in spec.fields.iter_mut().zip(names.iter()) {
            let ann = toks!["@", self.property.clone(), "(", name.clone().quoted(), ")"];
            field.annotation(ann.clone());
        }

        for c in &mut spec.constructors {
            c.annotation(toks!["@", self.creator.clone()]);

            for (argument, name) in c.arguments.iter_mut().zip(names.iter()) {
                let ann = toks!["@", self.property.clone(), "(", name.clone().quoted(), ")"];
                argument.annotation(ann.clone());
            }
        }

        Ok(())
    }

    fn add_tuple_serialization(&self, spec: &mut Class) -> Result<()> {
        let serializer = self.tuple_serializer(spec.name(), &mut spec.fields)?;

        let serializer_type = Rc::new(format!(
            "{}.{}",
            spec.name().as_ref(),
            serializer.name().as_ref()
        ));

        spec.annotation(toks![
            "@",
            self.serialize.clone(),
            "(using = ",
            serializer_type,
            ".class)",
        ]);

        spec.body.push(serializer);

        let deserializer = self.tuple_deserializer(spec.name(), &mut spec.fields)?;

        let deserializer_type = Rc::new(format!(
            "{}.{}",
            spec.name().as_ref(),
            deserializer.name().as_ref()
        ));

        let deserialize =
            toks![
            "@",
            self.deserialize.clone(),
            "(using = ",
            deserializer_type,
            ".class)",
        ];

        spec.annotation(deserialize);
        spec.body.push(deserializer);
        Ok(())
    }
}

impl Listeners for Module {
    fn class_added<'a>(&self, e: &mut ClassAdded) -> Result<()> {
        self.add_class_annotations(&e.names, &mut e.spec)?;
        Ok(())
    }

    fn tuple_added(&self, e: &mut TupleAdded) -> Result<()> {
        self.add_tuple_serialization(&mut e.spec)
    }

    fn enum_added(&self, e: &mut EnumAdded) -> Result<()> {
        e.from_value.annotation(toks!["@", self.creator.clone()]);
        e.to_value.annotation(toks!["@", self.value.clone()]);
        Ok(())
    }

    fn interface_added(&self, e: &mut InterfaceAdded) -> Result<()> {
        {
            let mut args = Tokens::new();

            args.append(toks!["use=", self.type_info.clone(), ".Id.NAME"]);
            args.append(toks!["include=", self.type_info.clone(), ".As.PROPERTY"]);
            args.append(toks!["property=", "type".quoted()]);

            e.spec.annotation(TypeInfo(self, args));
        }

        {
            let mut args = Tokens::new();

            for (key, sub_type) in &e.body.sub_types {
                for name in &sub_type.names {
                    let name = name.value().to_owned();

                    let mut a = Tokens::new();

                    a.append(toks!["name=", name.quoted()]);
                    a.append(toks![
                        "value=",
                        e.spec.name(),
                        ".",
                        key.as_str(),
                        ".class",
                    ]);

                    let arg = SubTypesType(self, a).into_tokens();
                    args.append(arg);
                }
            }

            e.spec.annotation(SubTypes(self, args));
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 `multipart-async` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
use futures::{Async, Stream};

use std::borrow::Cow;
use std::error::Error;
use std::io;
use std::mem;
use std::rc::Rc;
use std::sync::Arc;

pub use display_bytes::display_bytes as show_bytes;

pub use futures::Poll;

pub type PollOpt<T, E> = Poll<Option<T>, E>;

pub fn ready<R, E, T: Into<R>>(val: T) -> Poll<R, E> {
    Ok(Async::Ready(val.into()))
}

pub fn not_ready<T, E>() -> Poll<T, E> {
    Ok(Async::NotReady)
}

pub fn error<T, E: Into<Box<Error + Send + Sync>>, E_: From<io::Error>>(e: E) -> Result<T, E_> {
    Err(io_error(e).into())
}

pub fn io_error<E: Into<Box<Error + Send + Sync>>>(e: E) -> io::Error {
    io::Error::new(io::ErrorKind::Other, e)
}

pub fn replace_default<T: Default>(dest: &mut T) -> T {
    mem::replace(dest, T::default())
}

pub struct SomeCell<T> {
    opt: Option<T>,
    err: &'static str,
}

impl<T> SomeCell<T> {
    pub fn new(val: T, err: &'static str) -> Self {
        SomeCell {
            opt: Some(val),
            err: err,
        }
    }

    pub fn try_as_ref(&self) -> io::Result<&T> {
        self.opt.as_ref().ok_or_else(|| io_error(self.err))
    }

    pub fn try_as_mut(&mut self) -> io::Result<&mut T> {
        // Sub-borrow for closure
        let err = self.err;
        self.opt.as_mut().ok_or_else(|| io_error(err))
    }

    pub fn try_take(&mut self) -> io::Result<T> {
        self.opt.take().ok_or_else(|| io_error(self.err))
    }
}

impl<S: Stream> Stream for SomeCell<S> where S::Error: From<io::Error> {
    type Item = S::Item;
    type Error = S::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.try_as_mut()?.poll()
    }
}
<commit_msg>Remove some unused code in `helpers`<commit_after>// Copyright 2017 `multipart-async` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
use futures::{Async, Stream};

use std::error::Error;
use std::io;
use std::mem;

pub use display_bytes::display_bytes as show_bytes;

pub use futures::Poll;

pub type PollOpt<T, E> = Poll<Option<T>, E>;

pub fn ready<R, E, T: Into<R>>(val: T) -> Poll<R, E> {
    Ok(Async::Ready(val.into()))
}

pub fn not_ready<T, E>() -> Poll<T, E> {
    Ok(Async::NotReady)
}

pub fn error<T, E: Into<Box<Error + Send + Sync>>, E_: From<io::Error>>(e: E) -> Result<T, E_> {
    Err(io_error(e).into())
}

pub fn io_error<E: Into<Box<Error + Send + Sync>>>(e: E) -> io::Error {
    io::Error::new(io::ErrorKind::Other, e)
}

pub fn replace_default<T: Default>(dest: &mut T) -> T {
    mem::replace(dest, T::default())
}
<|endoftext|>


<commit_before>//! History API

use std::collections::vec_deque;
use std::collections::VecDeque;
use std::fs::File;
use std::iter::DoubleEndedIterator;
use std::ops::Index;
use std::path::Path;

use super::Result;
use crate::config::{Config, HistoryDuplicates};

/// Search direction
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {
    Forward,
    Reverse,
}

/// Current state of the history.
#[derive(Default)]
pub struct History {
    entries: VecDeque<String>,
    max_len: usize,
    pub(crate) ignore_space: bool,
    pub(crate) ignore_dups: bool,
}

impl History {
    // New multiline-aware history files start with `#V2\n` and have newlines
    // and backslashes escaped in them.
    const FILE_VERSION_V2: &'static str = "#V2";

    pub fn new() -> Self {
        Self::with_config(Config::default())
    }

    pub fn with_config(config: Config) -> Self {
        Self {
            entries: VecDeque::new(),
            max_len: config.max_history_size(),
            ignore_space: config.history_ignore_space(),
            ignore_dups: config.history_duplicates() == HistoryDuplicates::IgnoreConsecutive,
        }
    }

    /// Return the history entry at position `index`, starting from 0.
    pub fn get(&self, index: usize) -> Option<&String> {
        self.entries.get(index)
    }

    /// Return the last history entry (i.e. previous command)
    pub fn last(&self) -> Option<&String> {
        self.entries.back()
    }

    /// Add a new entry in the history.
    pub fn add<S: AsRef<str> + Into<String>>(&mut self, line: S) -> bool {
        if self.max_len == 0 {
            return false;
        }
        if line.as_ref().is_empty()
            || (self.ignore_space
                && line
                    .as_ref()
                    .chars()
                    .next()
                    .map_or(true, char::is_whitespace))
        {
            return false;
        }
        if self.ignore_dups {
            if let Some(s) = self.entries.back() {
                if s == line.as_ref() {
                    return false;
                }
            }
        }
        if self.entries.len() == self.max_len {
            self.entries.pop_front();
        }
        self.entries.push_back(line.into());
        true
    }

    /// Return the number of entries in the history.
    pub fn len(&self) -> usize {
        self.entries.len()
    }

    /// Return true if the history has no entry.
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    /// Set the maximum length for the history. This function can be called even
    /// if there is already some history, the function will make sure to retain
    /// just the latest `len` elements if the new history length value is
    /// smaller than the amount of items already inside the history.
    ///
    /// Like [stifle_history](http://cnswww.cns.cwru.
    /// edu/php/chet/readline/history.html#IDX11).
    pub fn set_max_len(&mut self, len: usize) {
        self.max_len = len;
        if len == 0 {
            self.entries.clear();
            return;
        }
        loop {
            if self.entries.len() <= len {
                break;
            }
            self.entries.pop_front();
        }
    }

    /// Save the history in the specified file.
    // TODO append_history
    // http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX30
    // TODO history_truncate_file
    // http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX31
    pub fn save<P: AsRef<Path> + ?Sized>(&self, path: &P) -> Result<()> {
        use std::io::{BufWriter, Write};

        if self.is_empty() {
            return Ok(());
        }
        let old_umask = umask();
        let f = File::create(path);
        restore_umask(old_umask);
        let file = f?;
        fix_perm(&file);
        let mut wtr = BufWriter::new(file);
        wtr.write_all(Self::FILE_VERSION_V2.as_bytes())?;
        for entry in &self.entries {
            wtr.write_all(b"\n")?;
            wtr.write_all(entry.replace('\\', "\\\\").replace('\n', "\\n").as_bytes())?;
        }
        wtr.write_all(b"\n")?;
        // https://github.com/rust-lang/rust/issues/32677#issuecomment-204833485
        wtr.flush()?;
        Ok(())
    }

    /// Load the history from the specified file.
    ///
    /// # Errors
    /// Will return `Err` if path does not already exist or could not be read.
    pub fn load<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
        use std::io::{BufRead, BufReader};

        let file = File::open(&path)?;
        let rdr = BufReader::new(file);
        let mut lines = rdr.lines();
        let mut v2 = false;
        if let Some(first) = lines.next() {
            let line = first?;
            if line == Self::FILE_VERSION_V2 {
                v2 = true;
            } else {
                self.add(line);
            }
        }
        for line in lines {
            let line = if v2 {
                line?.replace("\\n", "\n").replace("\\\\", "\\")
            } else {
                line?
            };
            if line.is_empty() {
                continue;
            }
            self.add(line); // TODO truncate to MAX_LINE
        }
        Ok(())
    }

    /// Clear history
    pub fn clear(&mut self) {
        self.entries.clear()
    }

    /// Search history (start position inclusive [0, len-1]).
    ///
    /// Return the absolute index of the nearest history entry that matches
    /// `term`.
    ///
    /// Return None if no entry contains `term` between [start, len -1] for
    /// forward search
    /// or between [0, start] for reverse search.
    pub fn search(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
        let test = |entry: &String| entry.contains(term);
        self.search_match(term, start, dir, test)
    }

    /// Anchored search
    pub fn starts_with(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
        let test = |entry: &String| entry.starts_with(term);
        self.search_match(term, start, dir, test)
    }

    fn search_match<F>(&self, term: &str, start: usize, dir: Direction, test: F) -> Option<usize>
    where
        F: Fn(&String) -> bool,
    {
        if term.is_empty() || start >= self.len() {
            return None;
        }
        match dir {
            Direction::Reverse => {
                let index = self
                    .entries
                    .iter()
                    .rev()
                    .skip(self.entries.len() - 1 - start)
                    .position(test);
                index.map(|index| start - index)
            }
            Direction::Forward => {
                let index = self.entries.iter().skip(start).position(test);
                index.map(|index| index + start)
            }
        }
    }

    /// Return a forward iterator.
    pub fn iter(&self) -> Iter<'_> {
        Iter(self.entries.iter())
    }
}

impl Index<usize> for History {
    type Output = String;

    fn index(&self, index: usize) -> &String {
        &self.entries[index]
    }
}

impl<'a> IntoIterator for &'a History {
    type IntoIter = Iter<'a>;
    type Item = &'a String;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// History iterator.
pub struct Iter<'a>(vec_deque::Iter<'a, String>);

impl<'a> Iterator for Iter<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<&'a String> {
        self.0.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<&'a String> {
        self.0.next_back()
    }
}

cfg_if::cfg_if! {
    if #[cfg(any(windows, target_arch = "wasm32"))] {
        fn umask() -> u16 {
            0
        }

        fn restore_umask(_: u16) {}

        fn fix_perm(_: &File) {}
    } else if #[cfg(unix)] {
        fn umask() -> libc::mode_t {
            unsafe { libc::umask(libc::S_IXUSR | libc::S_IRWXG | libc::S_IRWXO) }
        }

        fn restore_umask(old_umask: libc::mode_t) {
            unsafe {
                libc::umask(old_umask);
            }
        }

        fn fix_perm(file: &File) {
            use std::os::unix::io::AsRawFd;
            unsafe {
                libc::fchmod(file.as_raw_fd(), libc::S_IRUSR | libc::S_IWUSR);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Direction, History};
    use crate::config::Config;
    use std::path::Path;

    fn init() -> History {
        let mut history = History::new();
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(history.add("line3"));
        history
    }

    #[test]
    fn new() {
        let history = History::new();
        assert_eq!(0, history.entries.len());
    }

    #[test]
    fn add() {
        let config = Config::builder().history_ignore_space(true).build();
        let mut history = History::with_config(config);
        assert_eq!(config.max_history_size(), history.max_len);
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(!history.add("line2"));
        assert!(!history.add(""));
        assert!(!history.add(" line3"));
    }

    #[test]
    fn set_max_len() {
        let mut history = init();
        history.set_max_len(1);
        assert_eq!(1, history.entries.len());
        assert_eq!(Some(&"line3".to_owned()), history.last());
    }

    #[test]
    fn save() {
        let mut history = init();
        assert!(history.add("line\nfour \\ abc"));
        let td = tempdir::TempDir::new_in(&Path::new("."), "histo").unwrap();
        let history_path = td.path().join(".history");

        history.save(&history_path).unwrap();
        let mut history2 = History::new();
        history2.load(&history_path).unwrap();
        for (a, b) in history.entries.iter().zip(history2.entries.iter()) {
            assert_eq!(a, b);
        }

        td.close().unwrap();
    }

    #[test]
    fn load_legacy() {
        use std::io::Write;
        let td = tempdir::TempDir::new_in(&Path::new("."), "histo").unwrap();
        let history_path = td.path().join(".history_v1");
        {
            let mut legacy = std::fs::File::create(&history_path).unwrap();
            // Some data we'd accidentally corrupt if we got the version wrong
            let data = b"\
                test\\n \\abc \\123\n\
                123\\n\\\\n\n\
                abcde
            ";
            legacy.write_all(data).unwrap();
            legacy.flush().unwrap();
        }
        let mut history = History::new();
        history.load(&history_path).unwrap();
        assert_eq!(history.entries[0], "test\\n \\abc \\123");
        assert_eq!(history.entries[1], "123\\n\\\\n");
        assert_eq!(history.entries[2], "abcde");
        td.close().unwrap();
    }

    #[test]
    fn search() {
        let history = init();
        assert_eq!(None, history.search("", 0, Direction::Forward));
        assert_eq!(None, history.search("none", 0, Direction::Forward));
        assert_eq!(None, history.search("line", 3, Direction::Forward));

        assert_eq!(Some(0), history.search("line", 0, Direction::Forward));
        assert_eq!(Some(1), history.search("line", 1, Direction::Forward));
        assert_eq!(Some(2), history.search("line3", 1, Direction::Forward));
    }

    #[test]
    fn reverse_search() {
        let history = init();
        assert_eq!(None, history.search("", 2, Direction::Reverse));
        assert_eq!(None, history.search("none", 2, Direction::Reverse));
        assert_eq!(None, history.search("line", 3, Direction::Reverse));

        assert_eq!(Some(2), history.search("line", 2, Direction::Reverse));
        assert_eq!(Some(1), history.search("line", 1, Direction::Reverse));
        assert_eq!(Some(0), history.search("line1", 1, Direction::Reverse));
    }
}
<commit_msg>Ignore test cases that fail under Miri<commit_after>//! History API

use std::collections::vec_deque;
use std::collections::VecDeque;
use std::fs::File;
use std::iter::DoubleEndedIterator;
use std::ops::Index;
use std::path::Path;

use super::Result;
use crate::config::{Config, HistoryDuplicates};

/// Search direction
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Direction {
    Forward,
    Reverse,
}

/// Current state of the history.
#[derive(Default)]
pub struct History {
    entries: VecDeque<String>,
    max_len: usize,
    pub(crate) ignore_space: bool,
    pub(crate) ignore_dups: bool,
}

impl History {
    // New multiline-aware history files start with `#V2\n` and have newlines
    // and backslashes escaped in them.
    const FILE_VERSION_V2: &'static str = "#V2";

    pub fn new() -> Self {
        Self::with_config(Config::default())
    }

    pub fn with_config(config: Config) -> Self {
        Self {
            entries: VecDeque::new(),
            max_len: config.max_history_size(),
            ignore_space: config.history_ignore_space(),
            ignore_dups: config.history_duplicates() == HistoryDuplicates::IgnoreConsecutive,
        }
    }

    /// Return the history entry at position `index`, starting from 0.
    pub fn get(&self, index: usize) -> Option<&String> {
        self.entries.get(index)
    }

    /// Return the last history entry (i.e. previous command)
    pub fn last(&self) -> Option<&String> {
        self.entries.back()
    }

    /// Add a new entry in the history.
    pub fn add<S: AsRef<str> + Into<String>>(&mut self, line: S) -> bool {
        if self.max_len == 0 {
            return false;
        }
        if line.as_ref().is_empty()
            || (self.ignore_space
                && line
                    .as_ref()
                    .chars()
                    .next()
                    .map_or(true, char::is_whitespace))
        {
            return false;
        }
        if self.ignore_dups {
            if let Some(s) = self.entries.back() {
                if s == line.as_ref() {
                    return false;
                }
            }
        }
        if self.entries.len() == self.max_len {
            self.entries.pop_front();
        }
        self.entries.push_back(line.into());
        true
    }

    /// Return the number of entries in the history.
    pub fn len(&self) -> usize {
        self.entries.len()
    }

    /// Return true if the history has no entry.
    pub fn is_empty(&self) -> bool {
        self.entries.is_empty()
    }

    /// Set the maximum length for the history. This function can be called even
    /// if there is already some history, the function will make sure to retain
    /// just the latest `len` elements if the new history length value is
    /// smaller than the amount of items already inside the history.
    ///
    /// Like [stifle_history](http://cnswww.cns.cwru.
    /// edu/php/chet/readline/history.html#IDX11).
    pub fn set_max_len(&mut self, len: usize) {
        self.max_len = len;
        if len == 0 {
            self.entries.clear();
            return;
        }
        loop {
            if self.entries.len() <= len {
                break;
            }
            self.entries.pop_front();
        }
    }

    /// Save the history in the specified file.
    // TODO append_history
    // http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX30
    // TODO history_truncate_file
    // http://cnswww.cns.cwru.edu/php/chet/readline/history.html#IDX31
    pub fn save<P: AsRef<Path> + ?Sized>(&self, path: &P) -> Result<()> {
        use std::io::{BufWriter, Write};

        if self.is_empty() {
            return Ok(());
        }
        let old_umask = umask();
        let f = File::create(path);
        restore_umask(old_umask);
        let file = f?;
        fix_perm(&file);
        let mut wtr = BufWriter::new(file);
        wtr.write_all(Self::FILE_VERSION_V2.as_bytes())?;
        for entry in &self.entries {
            wtr.write_all(b"\n")?;
            wtr.write_all(entry.replace('\\', "\\\\").replace('\n', "\\n").as_bytes())?;
        }
        wtr.write_all(b"\n")?;
        // https://github.com/rust-lang/rust/issues/32677#issuecomment-204833485
        wtr.flush()?;
        Ok(())
    }

    /// Load the history from the specified file.
    ///
    /// # Errors
    /// Will return `Err` if path does not already exist or could not be read.
    pub fn load<P: AsRef<Path> + ?Sized>(&mut self, path: &P) -> Result<()> {
        use std::io::{BufRead, BufReader};

        let file = File::open(&path)?;
        let rdr = BufReader::new(file);
        let mut lines = rdr.lines();
        let mut v2 = false;
        if let Some(first) = lines.next() {
            let line = first?;
            if line == Self::FILE_VERSION_V2 {
                v2 = true;
            } else {
                self.add(line);
            }
        }
        for line in lines {
            let line = if v2 {
                line?.replace("\\n", "\n").replace("\\\\", "\\")
            } else {
                line?
            };
            if line.is_empty() {
                continue;
            }
            self.add(line); // TODO truncate to MAX_LINE
        }
        Ok(())
    }

    /// Clear history
    pub fn clear(&mut self) {
        self.entries.clear()
    }

    /// Search history (start position inclusive [0, len-1]).
    ///
    /// Return the absolute index of the nearest history entry that matches
    /// `term`.
    ///
    /// Return None if no entry contains `term` between [start, len -1] for
    /// forward search
    /// or between [0, start] for reverse search.
    pub fn search(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
        let test = |entry: &String| entry.contains(term);
        self.search_match(term, start, dir, test)
    }

    /// Anchored search
    pub fn starts_with(&self, term: &str, start: usize, dir: Direction) -> Option<usize> {
        let test = |entry: &String| entry.starts_with(term);
        self.search_match(term, start, dir, test)
    }

    fn search_match<F>(&self, term: &str, start: usize, dir: Direction, test: F) -> Option<usize>
    where
        F: Fn(&String) -> bool,
    {
        if term.is_empty() || start >= self.len() {
            return None;
        }
        match dir {
            Direction::Reverse => {
                let index = self
                    .entries
                    .iter()
                    .rev()
                    .skip(self.entries.len() - 1 - start)
                    .position(test);
                index.map(|index| start - index)
            }
            Direction::Forward => {
                let index = self.entries.iter().skip(start).position(test);
                index.map(|index| index + start)
            }
        }
    }

    /// Return a forward iterator.
    pub fn iter(&self) -> Iter<'_> {
        Iter(self.entries.iter())
    }
}

impl Index<usize> for History {
    type Output = String;

    fn index(&self, index: usize) -> &String {
        &self.entries[index]
    }
}

impl<'a> IntoIterator for &'a History {
    type IntoIter = Iter<'a>;
    type Item = &'a String;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// History iterator.
pub struct Iter<'a>(vec_deque::Iter<'a, String>);

impl<'a> Iterator for Iter<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<&'a String> {
        self.0.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<&'a String> {
        self.0.next_back()
    }
}

cfg_if::cfg_if! {
    if #[cfg(any(windows, target_arch = "wasm32"))] {
        fn umask() -> u16 {
            0
        }

        fn restore_umask(_: u16) {}

        fn fix_perm(_: &File) {}
    } else if #[cfg(unix)] {
        fn umask() -> libc::mode_t {
            unsafe { libc::umask(libc::S_IXUSR | libc::S_IRWXG | libc::S_IRWXO) }
        }

        fn restore_umask(old_umask: libc::mode_t) {
            unsafe {
                libc::umask(old_umask);
            }
        }

        fn fix_perm(file: &File) {
            use std::os::unix::io::AsRawFd;
            unsafe {
                libc::fchmod(file.as_raw_fd(), libc::S_IRUSR | libc::S_IWUSR);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Direction, History};
    use crate::config::Config;
    use std::path::Path;

    fn init() -> History {
        let mut history = History::new();
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(history.add("line3"));
        history
    }

    #[test]
    fn new() {
        let history = History::new();
        assert_eq!(0, history.entries.len());
    }

    #[test]
    fn add() {
        let config = Config::builder().history_ignore_space(true).build();
        let mut history = History::with_config(config);
        assert_eq!(config.max_history_size(), history.max_len);
        assert!(history.add("line1"));
        assert!(history.add("line2"));
        assert!(!history.add("line2"));
        assert!(!history.add(""));
        assert!(!history.add(" line3"));
    }

    #[test]
    fn set_max_len() {
        let mut history = init();
        history.set_max_len(1);
        assert_eq!(1, history.entries.len());
        assert_eq!(Some(&"line3".to_owned()), history.last());
    }

    #[test]
    #[cfg_attr(miri, ignore)] // unsupported operation: `getcwd` not available when isolation is enabled
    fn save() {
        let mut history = init();
        assert!(history.add("line\nfour \\ abc"));
        let td = tempdir::TempDir::new_in(&Path::new("."), "histo").unwrap();
        let history_path = td.path().join(".history");

        history.save(&history_path).unwrap();
        let mut history2 = History::new();
        history2.load(&history_path).unwrap();
        for (a, b) in history.entries.iter().zip(history2.entries.iter()) {
            assert_eq!(a, b);
        }

        td.close().unwrap();
    }

    #[test]
    #[cfg_attr(miri, ignore)] // unsupported operation: `getcwd` not available when isolation is enabled
    fn load_legacy() {
        use std::io::Write;
        let td = tempdir::TempDir::new_in(&Path::new("."), "histo").unwrap();
        let history_path = td.path().join(".history_v1");
        {
            let mut legacy = std::fs::File::create(&history_path).unwrap();
            // Some data we'd accidentally corrupt if we got the version wrong
            let data = b"\
                test\\n \\abc \\123\n\
                123\\n\\\\n\n\
                abcde
            ";
            legacy.write_all(data).unwrap();
            legacy.flush().unwrap();
        }
        let mut history = History::new();
        history.load(&history_path).unwrap();
        assert_eq!(history.entries[0], "test\\n \\abc \\123");
        assert_eq!(history.entries[1], "123\\n\\\\n");
        assert_eq!(history.entries[2], "abcde");
        td.close().unwrap();
    }

    #[test]
    fn search() {
        let history = init();
        assert_eq!(None, history.search("", 0, Direction::Forward));
        assert_eq!(None, history.search("none", 0, Direction::Forward));
        assert_eq!(None, history.search("line", 3, Direction::Forward));

        assert_eq!(Some(0), history.search("line", 0, Direction::Forward));
        assert_eq!(Some(1), history.search("line", 1, Direction::Forward));
        assert_eq!(Some(2), history.search("line3", 1, Direction::Forward));
    }

    #[test]
    fn reverse_search() {
        let history = init();
        assert_eq!(None, history.search("", 2, Direction::Reverse));
        assert_eq!(None, history.search("none", 2, Direction::Reverse));
        assert_eq!(None, history.search("line", 3, Direction::Reverse));

        assert_eq!(Some(2), history.search("line", 2, Direction::Reverse));
        assert_eq!(Some(1), history.search("line", 1, Direction::Reverse));
        assert_eq!(Some(0), history.search("line1", 1, Direction::Reverse));
    }
}
<|endoftext|>


<commit_before>use std::cmp;
use std::fmt;
use std::io::{self, Write};
use std::ptr;

use tokio_io::{AsyncRead, AsyncWrite};

use http::{Http1Transaction, MessageHead, DebugTruncate};
use bytes::{BytesMut, Bytes};

const INIT_BUFFER_SIZE: usize = 8192;
pub const MAX_BUFFER_SIZE: usize = 8192 + 4096 * 100;

pub struct Buffered<T> {
    io: T,
    read_blocked: bool,
    read_buf: BytesMut,
    write_buf: WriteBuf,
}

impl<T> fmt::Debug for Buffered<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Buffered")
            .field("read_buf", &self.read_buf)
            .field("write_buf", &self.write_buf)
            .finish()
    }
}

impl<T: AsyncRead + AsyncWrite> Buffered<T> {
    pub fn new(io: T) -> Buffered<T> {
        Buffered {
            io: io,
            read_buf: BytesMut::with_capacity(0),
            write_buf: WriteBuf::new(),
            read_blocked: false,
        }
    }

    pub fn read_buf(&self) -> &[u8] {
        self.read_buf.as_ref()
    }

    pub fn consume_leading_lines(&mut self) {
        if !self.read_buf.is_empty() {
            let mut i = 0;
            while i < self.read_buf.len() {
                match self.read_buf[i] {
                    b'\r' | b'\n' => i += 1,
                    _ => break,
                }
            }
            self.read_buf.split_to(i);
        }
    }

    pub fn parse<S: Http1Transaction>(&mut self) -> ::Result<Option<MessageHead<S::Incoming>>> {
        loop {
            match try!(S::parse(&mut self.read_buf)) {
                Some(head) => {
                    //trace!("parsed {} bytes out of {}", len, self.read_buf.len());
                    return Ok(Some(head.0))
                },
                None => {
                    if self.read_buf.capacity() >= MAX_BUFFER_SIZE {
                        debug!("MAX_BUFFER_SIZE reached, closing");
                        return Err(::Error::TooLarge);
                    }
                },
            }
            self.reserve_read_buf();
            match self.read_from_io() {
                Ok(0) => {
                    trace!("parse eof");
                    //TODO: With Rust 1.14, this can be Error::from(ErrorKind)
                    return Err(io::Error::new(io::ErrorKind::UnexpectedEof, ParseEof).into());
                }
                Ok(_) => {},
                Err(e) => match e.kind() {
                    io::ErrorKind::WouldBlock => {
                        return Ok(None);
                    },
                    _ => return Err(e.into())
                }
            }
        }
    }

    fn read_from_io(&mut self) -> io::Result<usize> {
        use bytes::BufMut;
        self.read_blocked = false;
        unsafe {
            let n = match self.io.read(self.read_buf.bytes_mut()) {
                Ok(n) => n,
                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        self.read_blocked = true;
                    }
                    return Err(e)
                }
            };
            self.read_buf.advance_mut(n);
            Ok(n)
        }
    }

    fn reserve_read_buf(&mut self) {
        use bytes::BufMut;
        if self.read_buf.remaining_mut() >= INIT_BUFFER_SIZE {
            return
        }
        self.read_buf.reserve(INIT_BUFFER_SIZE);
        unsafe {
            let buf = self.read_buf.bytes_mut();
            let len = buf.len();
            ptr::write_bytes(buf.as_mut_ptr(), 0, len);
        }
    }

    pub fn buffer<B: AsRef<[u8]>>(&mut self, buf: B) -> usize {
        self.write_buf.buffer(buf.as_ref())
    }

    pub fn io_mut(&mut self) -> &mut T {
        &mut self.io
    }

    pub fn is_read_blocked(&self) -> bool {
        self.read_blocked
    }
}

impl<T: Write> Write for Buffered<T> {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        Ok(self.write_buf.buffer(data))
    }

    fn flush(&mut self) -> io::Result<()> {
        if self.write_buf.remaining() == 0 {
            self.io.flush()
        } else {
            loop {
                let n = try!(self.write_buf.write_into(&mut self.io));
                debug!("flushed {} bytes", n);
                if self.write_buf.remaining() == 0 {
                    break;
                }
            }
            self.io.flush()
        }
    }
}

pub trait MemRead {
    fn read_mem(&mut self, len: usize) -> io::Result<Bytes>;
}

impl<T: AsyncRead + AsyncWrite> MemRead for Buffered<T> {
    fn read_mem(&mut self, len: usize) -> io::Result<Bytes> {
        trace!("Buffered.read_mem read_buf={}, wanted={}", self.read_buf.len(), len);
        if !self.read_buf.is_empty() {
            let n = ::std::cmp::min(len, self.read_buf.len());
            trace!("Buffered.read_mem read_buf is not empty, slicing {}", n);
            Ok(self.read_buf.split_to(n).freeze())
        } else {
            self.reserve_read_buf();
            let n = try!(self.read_from_io());
            Ok(self.read_buf.split_to(::std::cmp::min(len, n)).freeze())
        }
    }
}

#[derive(Clone)]
pub struct Cursor<T> {
    bytes: T,
    pos: usize,
}

impl<T: AsRef<[u8]>> Cursor<T> {
    pub fn new(bytes: T) -> Cursor<T> {
        Cursor {
            bytes: bytes,
            pos: 0,
        }
    }

    pub fn is_written(&self) -> bool {
        trace!("Cursor::is_written pos = {}, len = {}", self.pos, self.bytes.as_ref().len());
        self.pos >= self.bytes.as_ref().len()
    }

    pub fn write_to<W: Write>(&mut self, dst: &mut W) -> io::Result<usize> {
        if self.remaining() == 0 {
            Ok(0)
        } else {
            dst.write(&self.bytes.as_ref()[self.pos..]).map(|n| {
                self.pos += n;
                n
            })
        }
    }

    fn remaining(&self) -> usize {
        self.bytes.as_ref().len() - self.pos
    }

    #[inline]
    pub fn buf(&self) -> &[u8] {
        &self.bytes.as_ref()[self.pos..]
    }

    #[inline]
    pub fn consume(&mut self, num: usize) {
        trace!("Cursor::consume({})", num);
        self.pos = ::std::cmp::min(self.bytes.as_ref().len(), self.pos + num);
    }
}

impl<T: AsRef<[u8]>> fmt::Debug for Cursor<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("Cursor")
            .field(&DebugTruncate(self.buf()))
            .finish()
    }
}

pub trait AtomicWrite {
    fn write_atomic(&mut self, data: &[&[u8]]) -> io::Result<usize>;
}

/*
#[cfg(not(windows))]
impl<T: Write + ::vecio::Writev> AtomicWrite for T {

    fn write_atomic(&mut self, bufs: &[&[u8]]) -> io::Result<usize> {
        self.writev(bufs)
    }

}

#[cfg(windows)]
*/
impl<T: Write> AtomicWrite for T {
    fn write_atomic(&mut self, bufs: &[&[u8]]) -> io::Result<usize> {
        if bufs.len() == 1 {
            self.write(bufs[0])
        } else {
            let vec = bufs.concat();
            self.write(&vec)
        }
    }
}
//}

// an internal buffer to collect writes before flushes
#[derive(Debug)]
struct WriteBuf(Cursor<Vec<u8>>);

impl WriteBuf {
    fn new() -> WriteBuf {
        WriteBuf(Cursor::new(Vec::new()))
    }

    fn write_into<W: Write>(&mut self, w: &mut W) -> io::Result<usize> {
        self.0.write_to(w)
    }

    fn buffer(&mut self, data: &[u8]) -> usize {
        trace!("WriteBuf::buffer() len = {:?}", data.len());
        self.maybe_reset();
        self.maybe_reserve(data.len());
        let mut vec = &mut self.0.bytes;
        let len = cmp::min(vec.capacity() - vec.len(), data.len());
        assert!(vec.capacity() - vec.len() >= len);
        unsafe {
            // in rust 1.9, we could use slice::copy_from_slice
            ptr::copy(
                data.as_ptr(),
                vec.as_mut_ptr().offset(vec.len() as isize),
                len
            );
            let new_len = vec.len() + len;
            vec.set_len(new_len);
        }
        len
    }

    fn remaining(&self) -> usize {
        self.0.remaining()
    }

    #[inline]
    fn maybe_reserve(&mut self, needed: usize) {
        let mut vec = &mut self.0.bytes;
        let cap = vec.capacity();
        if cap == 0 {
            let init = cmp::min(MAX_BUFFER_SIZE, cmp::max(INIT_BUFFER_SIZE, needed));
            trace!("WriteBuf reserving initial {}", init);
            vec.reserve(init);
        } else if cap < MAX_BUFFER_SIZE {
            vec.reserve(cmp::min(needed, MAX_BUFFER_SIZE - cap));
            trace!("WriteBuf reserved {}", vec.capacity() - cap);
        }
    }

    fn maybe_reset(&mut self) {
        if self.0.pos != 0 && self.0.remaining() == 0 {
            self.0.pos = 0;
            unsafe {
                self.0.bytes.set_len(0);
            }
        }
    }
}

#[derive(Debug)]
struct ParseEof;

impl fmt::Display for ParseEof {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("parse eof")
    }
}

impl ::std::error::Error for ParseEof {
    fn description(&self) -> &str {
        "parse eof"
    }
}

#[cfg(test)]
use std::io::Read;

#[cfg(test)]
impl<T: Read> MemRead for ::mock::AsyncIo<T> {
    fn read_mem(&mut self, len: usize) -> io::Result<Bytes> {
        let mut v = vec![0; len];
        let n = try!(self.read(v.as_mut_slice()));
        Ok(BytesMut::from(&v[..n]).freeze())
    }
}

#[test]
fn test_iobuf_write_empty_slice() {
    use mock::{AsyncIo, Buf as MockBuf};

    let mut mock = AsyncIo::new(MockBuf::new(), 256);
    mock.error(io::Error::new(io::ErrorKind::Other, "logic error"));

    let mut io_buf = Buffered::new(mock);

    // underlying io will return the logic error upon write,
    // so we are testing that the io_buf does not trigger a write
    // when there is nothing to flush
    io_buf.flush().expect("should short-circuit flush");
}

#[test]
fn test_parse_reads_until_blocked() {
    use mock::{AsyncIo, Buf as MockBuf};
    // missing last line ending
    let raw = "HTTP/1.1 200 OK\r\n";

    let mock = AsyncIo::new(MockBuf::wrap(raw.into()), raw.len());
    let mut buffered = Buffered::new(mock);
    assert_eq!(buffered.parse::<super::ClientTransaction>().unwrap(), None);
    assert!(buffered.io.blocked());
}
<commit_msg>refactor(http): combine reserve_read_buf into read_from_io<commit_after>use std::cmp;
use std::fmt;
use std::io::{self, Write};
use std::ptr;

use tokio_io::{AsyncRead, AsyncWrite};

use http::{Http1Transaction, MessageHead, DebugTruncate};
use bytes::{BytesMut, Bytes};

const INIT_BUFFER_SIZE: usize = 8192;
pub const MAX_BUFFER_SIZE: usize = 8192 + 4096 * 100;

pub struct Buffered<T> {
    io: T,
    read_blocked: bool,
    read_buf: BytesMut,
    write_buf: WriteBuf,
}

impl<T> fmt::Debug for Buffered<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Buffered")
            .field("read_buf", &self.read_buf)
            .field("write_buf", &self.write_buf)
            .finish()
    }
}

impl<T: AsyncRead + AsyncWrite> Buffered<T> {
    pub fn new(io: T) -> Buffered<T> {
        Buffered {
            io: io,
            read_buf: BytesMut::with_capacity(0),
            write_buf: WriteBuf::new(),
            read_blocked: false,
        }
    }

    pub fn read_buf(&self) -> &[u8] {
        self.read_buf.as_ref()
    }

    pub fn consume_leading_lines(&mut self) {
        if !self.read_buf.is_empty() {
            let mut i = 0;
            while i < self.read_buf.len() {
                match self.read_buf[i] {
                    b'\r' | b'\n' => i += 1,
                    _ => break,
                }
            }
            self.read_buf.split_to(i);
        }
    }

    pub fn parse<S: Http1Transaction>(&mut self) -> ::Result<Option<MessageHead<S::Incoming>>> {
        loop {
            match try!(S::parse(&mut self.read_buf)) {
                Some(head) => {
                    //trace!("parsed {} bytes out of {}", len, self.read_buf.len());
                    return Ok(Some(head.0))
                },
                None => {
                    if self.read_buf.capacity() >= MAX_BUFFER_SIZE {
                        debug!("MAX_BUFFER_SIZE reached, closing");
                        return Err(::Error::TooLarge);
                    }
                },
            }
            match self.read_from_io() {
                Ok(0) => {
                    trace!("parse eof");
                    //TODO: With Rust 1.14, this can be Error::from(ErrorKind)
                    return Err(io::Error::new(io::ErrorKind::UnexpectedEof, ParseEof).into());
                }
                Ok(_) => {},
                Err(e) => match e.kind() {
                    io::ErrorKind::WouldBlock => {
                        return Ok(None);
                    },
                    _ => return Err(e.into())
                }
            }
        }
    }

    fn read_from_io(&mut self) -> io::Result<usize> {
        use bytes::BufMut;
        // TODO: Investigate if we still need these unsafe blocks
        if self.read_buf.remaining_mut() < INIT_BUFFER_SIZE {
            self.read_buf.reserve(INIT_BUFFER_SIZE);
            unsafe { // Zero out unused memory
                let buf = self.read_buf.bytes_mut();
                let len = buf.len();
                ptr::write_bytes(buf.as_mut_ptr(), 0, len);
            }
        }
        self.read_blocked = false;
        unsafe { // Can we use AsyncRead::read_buf instead?
            let n = match self.io.read(self.read_buf.bytes_mut()) {
                Ok(n) => n,
                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        self.read_blocked = true;
                    }
                    return Err(e)
                }
            };
            self.read_buf.advance_mut(n);
            Ok(n)
        }
    }

    pub fn buffer<B: AsRef<[u8]>>(&mut self, buf: B) -> usize {
        self.write_buf.buffer(buf.as_ref())
    }

    pub fn io_mut(&mut self) -> &mut T {
        &mut self.io
    }

    pub fn is_read_blocked(&self) -> bool {
        self.read_blocked
    }
}

impl<T: Write> Write for Buffered<T> {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        Ok(self.write_buf.buffer(data))
    }

    fn flush(&mut self) -> io::Result<()> {
        if self.write_buf.remaining() == 0 {
            self.io.flush()
        } else {
            loop {
                let n = try!(self.write_buf.write_into(&mut self.io));
                debug!("flushed {} bytes", n);
                if self.write_buf.remaining() == 0 {
                    break;
                }
            }
            self.io.flush()
        }
    }
}

pub trait MemRead {
    fn read_mem(&mut self, len: usize) -> io::Result<Bytes>;
}

impl<T: AsyncRead + AsyncWrite> MemRead for Buffered<T> {
    fn read_mem(&mut self, len: usize) -> io::Result<Bytes> {
        trace!("Buffered.read_mem read_buf={}, wanted={}", self.read_buf.len(), len);
        if !self.read_buf.is_empty() {
            let n = ::std::cmp::min(len, self.read_buf.len());
            trace!("Buffered.read_mem read_buf is not empty, slicing {}", n);
            Ok(self.read_buf.split_to(n).freeze())
        } else {
            let n = try!(self.read_from_io());
            Ok(self.read_buf.split_to(::std::cmp::min(len, n)).freeze())
        }
    }
}

#[derive(Clone)]
pub struct Cursor<T> {
    bytes: T,
    pos: usize,
}

impl<T: AsRef<[u8]>> Cursor<T> {
    pub fn new(bytes: T) -> Cursor<T> {
        Cursor {
            bytes: bytes,
            pos: 0,
        }
    }

    pub fn is_written(&self) -> bool {
        trace!("Cursor::is_written pos = {}, len = {}", self.pos, self.bytes.as_ref().len());
        self.pos >= self.bytes.as_ref().len()
    }

    pub fn write_to<W: Write>(&mut self, dst: &mut W) -> io::Result<usize> {
        if self.remaining() == 0 {
            Ok(0)
        } else {
            dst.write(&self.bytes.as_ref()[self.pos..]).map(|n| {
                self.pos += n;
                n
            })
        }
    }

    fn remaining(&self) -> usize {
        self.bytes.as_ref().len() - self.pos
    }

    #[inline]
    pub fn buf(&self) -> &[u8] {
        &self.bytes.as_ref()[self.pos..]
    }

    #[inline]
    pub fn consume(&mut self, num: usize) {
        trace!("Cursor::consume({})", num);
        self.pos = ::std::cmp::min(self.bytes.as_ref().len(), self.pos + num);
    }
}

impl<T: AsRef<[u8]>> fmt::Debug for Cursor<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("Cursor")
            .field(&DebugTruncate(self.buf()))
            .finish()
    }
}

pub trait AtomicWrite {
    fn write_atomic(&mut self, data: &[&[u8]]) -> io::Result<usize>;
}

/*
#[cfg(not(windows))]
impl<T: Write + ::vecio::Writev> AtomicWrite for T {

    fn write_atomic(&mut self, bufs: &[&[u8]]) -> io::Result<usize> {
        self.writev(bufs)
    }

}

#[cfg(windows)]
*/
impl<T: Write> AtomicWrite for T {
    fn write_atomic(&mut self, bufs: &[&[u8]]) -> io::Result<usize> {
        if bufs.len() == 1 {
            self.write(bufs[0])
        } else {
            let vec = bufs.concat();
            self.write(&vec)
        }
    }
}
//}

// an internal buffer to collect writes before flushes
#[derive(Debug)]
struct WriteBuf(Cursor<Vec<u8>>);

impl WriteBuf {
    fn new() -> WriteBuf {
        WriteBuf(Cursor::new(Vec::new()))
    }

    fn write_into<W: Write>(&mut self, w: &mut W) -> io::Result<usize> {
        self.0.write_to(w)
    }

    fn buffer(&mut self, data: &[u8]) -> usize {
        trace!("WriteBuf::buffer() len = {:?}", data.len());
        self.maybe_reset();
        self.maybe_reserve(data.len());
        let mut vec = &mut self.0.bytes;
        let len = cmp::min(vec.capacity() - vec.len(), data.len());
        assert!(vec.capacity() - vec.len() >= len);
        unsafe {
            // in rust 1.9, we could use slice::copy_from_slice
            ptr::copy(
                data.as_ptr(),
                vec.as_mut_ptr().offset(vec.len() as isize),
                len
            );
            let new_len = vec.len() + len;
            vec.set_len(new_len);
        }
        len
    }

    fn remaining(&self) -> usize {
        self.0.remaining()
    }

    #[inline]
    fn maybe_reserve(&mut self, needed: usize) {
        let mut vec = &mut self.0.bytes;
        let cap = vec.capacity();
        if cap == 0 {
            let init = cmp::min(MAX_BUFFER_SIZE, cmp::max(INIT_BUFFER_SIZE, needed));
            trace!("WriteBuf reserving initial {}", init);
            vec.reserve(init);
        } else if cap < MAX_BUFFER_SIZE {
            vec.reserve(cmp::min(needed, MAX_BUFFER_SIZE - cap));
            trace!("WriteBuf reserved {}", vec.capacity() - cap);
        }
    }

    fn maybe_reset(&mut self) {
        if self.0.pos != 0 && self.0.remaining() == 0 {
            self.0.pos = 0;
            unsafe {
                self.0.bytes.set_len(0);
            }
        }
    }
}

#[derive(Debug)]
struct ParseEof;

impl fmt::Display for ParseEof {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("parse eof")
    }
}

impl ::std::error::Error for ParseEof {
    fn description(&self) -> &str {
        "parse eof"
    }
}

#[cfg(test)]
use std::io::Read;

#[cfg(test)]
impl<T: Read> MemRead for ::mock::AsyncIo<T> {
    fn read_mem(&mut self, len: usize) -> io::Result<Bytes> {
        let mut v = vec![0; len];
        let n = try!(self.read(v.as_mut_slice()));
        Ok(BytesMut::from(&v[..n]).freeze())
    }
}

#[test]
fn test_iobuf_write_empty_slice() {
    use mock::{AsyncIo, Buf as MockBuf};

    let mut mock = AsyncIo::new(MockBuf::new(), 256);
    mock.error(io::Error::new(io::ErrorKind::Other, "logic error"));

    let mut io_buf = Buffered::new(mock);

    // underlying io will return the logic error upon write,
    // so we are testing that the io_buf does not trigger a write
    // when there is nothing to flush
    io_buf.flush().expect("should short-circuit flush");
}

#[test]
fn test_parse_reads_until_blocked() {
    use mock::{AsyncIo, Buf as MockBuf};
    // missing last line ending
    let raw = "HTTP/1.1 200 OK\r\n";

    let mock = AsyncIo::new(MockBuf::wrap(raw.into()), raw.len());
    let mut buffered = Buffered::new(mock);
    assert_eq!(buffered.parse::<super::ClientTransaction>().unwrap(), None);
    assert!(buffered.io.blocked());
}
<|endoftext|>


<commit_before>extern crate allergies;

use allergies::*;

#[test]
fn test_no_allergies_means_not_allergic() {
    let allergies = Allergies::new(0);
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Peanuts));
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Cats));
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Strawberries));
}

#[test]
#[ignore]
fn test_is_allergic_to_eggs() {
    assert_eq!(true, Allergies::new(1).is_allergic_to(&Allergen::Eggs));
}

#[test]
#[ignore]
fn test_has_the_right_allergies() {
    let allergies = Allergies::new(5);
    assert_eq!(true, allergies.is_allergic_to(&Allergen::Eggs));
    assert_eq!(true, allergies.is_allergic_to(&Allergen::Shellfish));
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Strawberries));
}

#[test]
#[ignore]
fn test_no_allergies_at_all() {
    assert_eq!(Vec::<Allergen>::new(), Allergies::new(0).allergies());
}

#[test]
#[ignore]
fn test_just_to_peanuts() {
    assert_eq!(vec![Allergen::Peanuts], Allergies::new(2).allergies());
}

#[test]
#[ignore]
fn test_allergic_to_everything() {
    let all = vec![Allergen::Eggs, Allergen::Peanuts, Allergen::Shellfish,
                   Allergen::Strawberries, Allergen::Tomatoes,
                   Allergen::Chocolate, Allergen::Pollen, Allergen::Cats];
    let allergies = Allergies::new(255).allergies();

    assert_eq!(allergies.len(), all.len());

    for allergy in &all {
        assert!(allergies.contains(&allergy));
    }
}

#[test]
#[ignore]
fn test_ignore_non_allergen_score_parts() {
    assert_eq!(vec![Allergen::Eggs], Allergies::new(257).allergies());
}
<commit_msg>Update Allergies tests to canonical set (#142)<commit_after>extern crate allergies;

use allergies::*;

fn compare_allergy_vectors(expected: &Vec<Allergen>, actual: &Vec<Allergen>) {
    if !expected.iter().eq(actual.iter()) {
        panic!("Expected {:?}, got {:?}", expected, actual);
    }
}

#[test]
fn is_not_allergic_to_anything() {
    let allergies = Allergies::new(0);
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Peanuts));
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Cats));
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Strawberries));
}

#[test]
#[ignore]
fn is_allergic_to_eggs() {
    assert_eq!(true, Allergies::new(1).is_allergic_to(&Allergen::Eggs));
}

#[test]
#[ignore]
fn is_allergic_to_egg_shellfish_and_strawberries() {
    let allergies = Allergies::new(5);
    assert_eq!(true, allergies.is_allergic_to(&Allergen::Eggs));
    assert_eq!(true, allergies.is_allergic_to(&Allergen::Shellfish));
    assert_eq!(false, allergies.is_allergic_to(&Allergen::Strawberries));
}

#[test]
#[ignore]
fn no_allergies_at_all() {
    let expected: Vec<Allergen> = Vec::new();
    let allergies = Allergies::new(0).allergies();

    compare_allergy_vectors(&expected, &allergies);
}

#[test]
#[ignore]
fn allergic_to_just_eggs() {
    let expected = vec![Allergen::Eggs];
    let allergies = Allergies::new(1).allergies();

    compare_allergy_vectors(&expected, &allergies);
}

#[test]
#[ignore]
fn allergic_to_just_peanuts() {
    let expected = vec![Allergen::Peanuts];
    let allergies = Allergies::new(2).allergies();

    compare_allergy_vectors(&expected, &allergies);
}

#[test]
#[ignore]
fn allergic_to_just_strawberries() {
    let expected = vec![Allergen::Strawberries];
    let allergies = Allergies::new(8).allergies();

    compare_allergy_vectors(&expected, &allergies);
}

#[test]
#[ignore]
fn allergic_to_eggs_and_peanuts() {
    let expected = vec![Allergen::Eggs, Allergen::Peanuts];
    let allergies = Allergies::new(3).allergies();

    compare_allergy_vectors(&expected, &allergies);
}

#[test]
#[ignore]
fn allergic_to_eggs_and_shellfish() {
    let expected = vec![Allergen::Eggs, Allergen::Shellfish];
    let allergies = Allergies::new(5).allergies();

    compare_allergy_vectors(&expected, &allergies);
}

#[test]
#[ignore]
fn allergic_to_many_things() {
    let expected = vec![Allergen::Strawberries,
                        Allergen::Tomatoes,
                        Allergen::Chocolate,
                        Allergen::Pollen,
                        Allergen::Cats];
    let allergies = Allergies::new(248).allergies();

    compare_allergy_vectors(&expected, &allergies);
}

#[test]
#[ignore]
fn allergic_to_everything() {
    let expected = vec![Allergen::Eggs,
                        Allergen::Peanuts,
                        Allergen::Shellfish,
                        Allergen::Strawberries,
                        Allergen::Tomatoes,
                        Allergen::Chocolate,
                        Allergen::Pollen,
                        Allergen::Cats];
    let allergies = Allergies::new(255).allergies();

    compare_allergy_vectors(&expected, &allergies);
}

#[test]
#[ignore]
fn scores_over_255_do_not_trigger_false_positives() {
    let expected = vec![Allergen::Eggs,
                        Allergen::Shellfish,
                        Allergen::Strawberries,
                        Allergen::Tomatoes,
                        Allergen::Chocolate,
                        Allergen::Pollen,
                        Allergen::Cats];
    let allergies = Allergies::new(509).allergies();

    compare_allergy_vectors(&expected, &allergies);
}
<|endoftext|>