<commit_before>use ErrorCode;

use std::sync::mpsc::Receiver;
use std::time::Duration;

pub struct ResultHandler {}

impl ResultHandler {
    pub fn empty(err: ErrorCode, receiver: Receiver<ErrorCode>) -> Result<(), ErrorCode> {
        err.try_err()?;
        match receiver.recv() {
            Ok(err) => err.try_err(),
            Err(e) => Err(ErrorCode::from(e))
        }
    }

    pub fn empty_timeout(err: ErrorCode, receiver: Receiver<ErrorCode>, timeout: Duration) -> Result<(), ErrorCode> {
        err.try_err()?;

        match receiver.recv_timeout(timeout) {
            Ok(err) => err.try_err(),
            Err(e) => Err(ErrorCode::from(e))
        }
    }

    pub fn one<T>(err: ErrorCode, receiver: Receiver<(ErrorCode, T)>) -> Result<T, ErrorCode> {
        err.try_err()?;

        let res = receiver.recv();
        match res {
            Ok((err, val)) => {
                err.try_err()?;
                Ok(val)
            },
            Err(e) => {
                error!("An error was received {:?}", e);
                Err(ErrorCode::Success)
            }
        }
//        let (err, val) = receiver.recv()?;
//
//        err.try_err()?;
//
//        Ok(val)
    }

    pub fn one_timeout<T>(err: ErrorCode, receiver: Receiver<(ErrorCode, T)>, timeout: Duration) -> Result<T, ErrorCode> {
        err.try_err()?;

        match receiver.recv_timeout(timeout) {
            Ok((err, val)) =>  {
                err.try_err()?;
                Ok(val)
            },
            Err(e) => Err(ErrorCode::from(e))
        }
    }

    pub fn two<T1, T2>(err: ErrorCode, receiver: Receiver<(ErrorCode, T1, T2)>) -> Result<(T1, T2), ErrorCode> {
        err.try_err()?;

        let (err, val, val2) = receiver.recv()?;

        err.try_err()?;

        Ok((val, val2))
    }

    pub fn two_timeout<T1, T2>(err: ErrorCode, receiver: Receiver<(ErrorCode, T1, T2)>, timeout: Duration) -> Result<(T1, T2), ErrorCode> {
        err.try_err()?;

        match receiver.recv_timeout(timeout) {
            Ok((err, val1, val2)) =>  {
                err.try_err()?;
                Ok((val1, val2))
            },
            Err(e) => Err(ErrorCode::from(e))
        }
    }

    pub fn three<T1, T2, T3>(err: ErrorCode, receiver: Receiver<(ErrorCode, T1, T2, T3)>) -> Result<(T1, T2, T3), ErrorCode> {
        err.try_err()?;

        let (err, val, val2, val3) = receiver.recv()?;

        err.try_err()?;

        Ok((val, val2, val3))
    }

    pub fn three_timeout<T1, T2, T3>(err: ErrorCode, receiver: Receiver<(ErrorCode, T1, T2, T3)>, timeout: Duration) -> Result<(T1, T2, T3), ErrorCode> {
        err.try_err()?;

        match receiver.recv_timeout(timeout) {
            Ok((err, val1, val2, val3)) =>  {
                err.try_err()?;
                Ok((val1, val2, val3))
            },
            Err(e) => Err(ErrorCode::from(e))
        }
    }
}
<commit_msg>Print error message<commit_after>use ErrorCode;

use std::sync::mpsc::Receiver;
use std::time::Duration;

pub struct ResultHandler {}

impl ResultHandler {
    pub fn empty(err: ErrorCode, receiver: Receiver<ErrorCode>) -> Result<(), ErrorCode> {
        err.try_err()?;
        match receiver.recv() {
            Ok(err) => err.try_err(),
            Err(e) => Err(ErrorCode::from(e))
        }
    }

    pub fn empty_timeout(err: ErrorCode, receiver: Receiver<ErrorCode>, timeout: Duration) -> Result<(), ErrorCode> {
        err.try_err()?;

        match receiver.recv_timeout(timeout) {
            Ok(err) => err.try_err(),
            Err(e) => Err(ErrorCode::from(e))
        }
    }

    pub fn one<T>(err: ErrorCode, receiver: Receiver<(ErrorCode, T)>) -> Result<T, ErrorCode> {
        err.try_err()?;

        let res = receiver.recv();
        match res {
            Ok((err, val)) => {
                err.try_err()?;
                Ok(val)
            },
            Err(e) => {
                println!("An error was received {:?}", e);
                Err(ErrorCode::Success)
            }
        }
//        let (err, val) = receiver.recv()?;
//
//        err.try_err()?;
//
//        Ok(val)
    }

    pub fn one_timeout<T>(err: ErrorCode, receiver: Receiver<(ErrorCode, T)>, timeout: Duration) -> Result<T, ErrorCode> {
        err.try_err()?;

        match receiver.recv_timeout(timeout) {
            Ok((err, val)) =>  {
                err.try_err()?;
                Ok(val)
            },
            Err(e) => Err(ErrorCode::from(e))
        }
    }

    pub fn two<T1, T2>(err: ErrorCode, receiver: Receiver<(ErrorCode, T1, T2)>) -> Result<(T1, T2), ErrorCode> {
        err.try_err()?;

        let (err, val, val2) = receiver.recv()?;

        err.try_err()?;

        Ok((val, val2))
    }

    pub fn two_timeout<T1, T2>(err: ErrorCode, receiver: Receiver<(ErrorCode, T1, T2)>, timeout: Duration) -> Result<(T1, T2), ErrorCode> {
        err.try_err()?;

        match receiver.recv_timeout(timeout) {
            Ok((err, val1, val2)) =>  {
                err.try_err()?;
                Ok((val1, val2))
            },
            Err(e) => Err(ErrorCode::from(e))
        }
    }

    pub fn three<T1, T2, T3>(err: ErrorCode, receiver: Receiver<(ErrorCode, T1, T2, T3)>) -> Result<(T1, T2, T3), ErrorCode> {
        err.try_err()?;

        let (err, val, val2, val3) = receiver.recv()?;

        err.try_err()?;

        Ok((val, val2, val3))
    }

    pub fn three_timeout<T1, T2, T3>(err: ErrorCode, receiver: Receiver<(ErrorCode, T1, T2, T3)>, timeout: Duration) -> Result<(T1, T2, T3), ErrorCode> {
        err.try_err()?;

        match receiver.recv_timeout(timeout) {
            Ok((err, val1, val2, val3)) =>  {
                err.try_err()?;
                Ok((val1, val2, val3))
            },
            Err(e) => Err(ErrorCode::from(e))
        }
    }
}
<|endoftext|>


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

#![deny(warnings)]

#![feature(iter_arith)]
#![feature(rustc_private)]
#![feature(rustdoc)]

extern crate rustdoc;
extern crate rustc_back;

use std::env;
use std::error::Error;
use std::process;
use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
use subcommand::Subcommand;
use term::Term;

mod term;
mod error;
mod book;

mod subcommand;
mod help;
mod build;
mod serve;
mod test;

static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;

fn main() {
    let mut term = Term::new();
    let cmd: Vec<_> = env::args().collect();

    if cmd.len() <= 1 {
        help::usage()
    } else {
        match subcommand::parse_name(&cmd[1][..]) {
            Some(mut subcmd) => {
                match subcmd.parse_args(&cmd[..cmd.len()-1]) {
                    Ok(_) => {
                        match subcmd.execute(&mut term) {
                            Ok(_) => (),
                            Err(err) => {
                                term.err(&format!("error: {}", err));
                            }
                        }
                    }
                    Err(err) => {
                        println!("{}", err.description());
                        println!("");
                        subcmd.usage();
                    }
                }
            }
            None => {
                println!("Unrecognized command '{}'.", cmd[1]);
                println!("");
                help::usage();
            }
        }
    }
    process::exit(EXIT_STATUS.load(Ordering::SeqCst) as i32);
}
<commit_msg>rustbook: Make `main` a public function<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(warnings)]

#![feature(iter_arith)]
#![feature(rustc_private)]
#![feature(rustdoc)]

extern crate rustdoc;
extern crate rustc_back;

use std::env;
use std::error::Error;
use std::process;
use std::sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
use subcommand::Subcommand;
use term::Term;

mod term;
mod error;
mod book;

mod subcommand;
mod help;
mod build;
mod serve;
mod test;

static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;

pub fn main() {
    let mut term = Term::new();
    let cmd: Vec<_> = env::args().collect();

    if cmd.len() <= 1 {
        help::usage()
    } else {
        match subcommand::parse_name(&cmd[1][..]) {
            Some(mut subcmd) => {
                match subcmd.parse_args(&cmd[..cmd.len()-1]) {
                    Ok(_) => {
                        match subcmd.execute(&mut term) {
                            Ok(_) => (),
                            Err(err) => {
                                term.err(&format!("error: {}", err));
                            }
                        }
                    }
                    Err(err) => {
                        println!("{}", err.description());
                        println!("");
                        subcmd.usage();
                    }
                }
            }
            None => {
                println!("Unrecognized command '{}'.", cmd[1]);
                println!("");
                help::usage();
            }
        }
    }
    process::exit(EXIT_STATUS.load(Ordering::SeqCst) as i32);
}
<|endoftext|>


<commit_before>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! This is the developer documentation of Oak, if you do not intend to contribute, please read the [user manual](http://hyc.io/oak) instead. This library proposes a syntax extension for a parser generator based on [Parsing Expression Grammar (PEG)](https://en.wikipedia.org/wiki/Parsing_expression_grammar). It aims at simplifying the construction of the AST by typing the parsing rules. This is an experimental library.

#![feature(convert, rustc_private, plugin_registrar, quote, box_syntax, vec_push_all, drain, str_escape)]
#![crate_name = "oak"]

extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;

use front::parser;

mod ast;
mod front;
mod middle;
mod back;
mod rust;
mod identifier;
mod monad;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
  reg.register_syntax_extension(
    rust::token::intern("grammar"),
    rust::SyntaxExtension::IdentTT(Box::new(expand), None, false));
}

fn expand<'cx>(cx: &'cx mut rust::ExtCtxt, _sp: rust::Span, grammar_name: rust::Ident,
  tts: Vec<rust::TokenTree>) -> Box<rust::MacResult + 'cx>
{
  parse(cx, grammar_name, tts)
}

fn parse<'cx>(cx: &'cx mut rust::ExtCtxt, grammar_name: rust::Ident,
  tts: Vec<rust::TokenTree>) -> Box<rust::MacResult + 'cx>
{
  let mut parser = parser::Parser::new(cx.parse_sess(), cx.cfg(), tts, grammar_name);
  let ast = parser.parse_grammar();
  let cx: &'cx rust::ExtCtxt = cx;
  middle::analyse(cx, ast)
    .and_next(|ast| back::compile(cx, ast))
    .unwrap_or_else(|| {
      cx.parse_sess.span_diagnostic.handler.abort_if_errors();
      rust::DummyResult::any(rust::DUMMY_SP)
    })
}
<commit_msg>[Compilation error] Must abort if any error occurs during the parsing step.<commit_after>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! This is the developer documentation of Oak, if you do not intend to contribute, please read the [user manual](http://hyc.io/oak) instead. This library proposes a syntax extension for a parser generator based on [Parsing Expression Grammar (PEG)](https://en.wikipedia.org/wiki/Parsing_expression_grammar). It aims at simplifying the construction of the AST by typing the parsing rules. This is an experimental library.

#![feature(convert, rustc_private, plugin_registrar, quote, box_syntax, vec_push_all, drain, str_escape)]
#![crate_name = "oak"]

extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;

use front::parser;

mod ast;
mod front;
mod middle;
mod back;
mod rust;
mod identifier;
mod monad;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
  reg.register_syntax_extension(
    rust::token::intern("grammar"),
    rust::SyntaxExtension::IdentTT(Box::new(expand), None, false));
}

fn expand<'cx>(cx: &'cx mut rust::ExtCtxt, _sp: rust::Span, grammar_name: rust::Ident,
  tts: Vec<rust::TokenTree>) -> Box<rust::MacResult + 'cx>
{
  parse(cx, grammar_name, tts)
}

fn abort_if_errors(cx: &rust::ExtCtxt) {
  cx.parse_sess.span_diagnostic.handler.abort_if_errors();
}

fn parse<'cx>(cx: &'cx mut rust::ExtCtxt, grammar_name: rust::Ident,
  tts: Vec<rust::TokenTree>) -> Box<rust::MacResult + 'cx>
{
  let mut parser = parser::Parser::new(cx.parse_sess(), cx.cfg(), tts, grammar_name);
  let ast = parser.parse_grammar();
  abort_if_errors(cx);
  let cx: &'cx rust::ExtCtxt = cx;
  middle::analyse(cx, ast)
    .and_next(|ast| back::compile(cx, ast))
    .unwrap_or_else(|| {
      abort_if_errors(cx);
      rust::DummyResult::any(rust::DUMMY_SP)
    })
}
<|endoftext|>


<commit_before>//! Contains `XmlEvent` datatype, instances of which are consumed by the writer.

use std::borrow::Cow;

use name::Name;
use attribute::Attribute;
use common::XmlVersion;
use namespace::{Namespace, NS_NO_PREFIX};

/// A part of an XML output stream.
///
/// Objects of this enum are consumed by `EventWriter`. They correspond to different parts of
/// an XML document.
pub enum XmlEvent<'a> {
    /// Corresponds to XML document declaration.
    ///
    /// This event should always be written before any other event. If it is not written
    /// at all, a default XML declaration will be outputted if the corresponding option
    /// is set in the configuration. Otherwise an error will be returned.
    StartDocument {
        /// XML version.
        ///
        /// Defaults to `XmlVersion::Version10`.
        version: XmlVersion,

        /// XML document encoding.
        ///
        /// Defaults to `Some("UTF-8")`.
        encoding: Option<&'a str>,

        /// XML standalone declaration.
        ///
        /// Defaults to `None`.
        standalone: Option<bool>
    },

    /// Denotes an XML processing instruction.
    ProcessingInstruction {
        /// Processing instruction target.
        name: &'a str,

        /// Processing instruction content.
        data: Option<&'a str>
    },

    /// Denotes a beginning of an XML element.
    StartElement {
        /// Qualified name of the element.
        name: Name<'a>,

        /// A list of attributes associated with the element.
        ///
        /// Currently attributes are not checked for duplicates (TODO). Attribute values
        /// will be escaped, and all characters invalid for attribute values like `"` or `<`
        /// will be changed into character entities.
        attributes: Cow<'a, [Attribute<'a>]>,

        /// Contents of the namespace mapping at this point of the document.
        ///
        /// This mapping will be inspected for "new" entries, and if at this point of the document
        /// a particular pair of prefix and namespace URI is already defined, no namespace
        /// attributes will be emitted.
        namespace: Cow<'a, Namespace>,
    },

    /// Denotes an end of an XML element.
    EndElement {
        /// Optional qualified name of the element.
        ///
        /// If `None`, then it is assumed that the element name should be the last valid one.
        /// If `Some` and element names tracking is enabled, then the writer will check it for
        /// correctness.
        name: Option<Name<'a>>
    },

    /// Denotes CDATA content.
    ///
    /// This event contains unparsed data, and no escaping will be performed when writing it
    /// to the output stream.
    CData(&'a str),

    /// Denotes a comment.
    ///
    /// The string will be checked for invalid sequences and error will be returned by the
    /// write operation
    Comment(&'a str),

    /// Denotes character data outside of tags.
    ///
    /// Contents of this event will be escaped if `perform_escaping` option is enabled,
    /// that is, every character invalid for PCDATA will appear as a character entity.
    Characters(&'a str)
}

impl<'a> XmlEvent<'a> {
    /// Returns an writer event for a processing instruction.
    #[inline]
    pub fn processing_instruction(name: &'a str, data: Option<&'a str>) -> XmlEvent<'a> {
        XmlEvent::ProcessingInstruction { name: name, data: data }
    }

    /// Returns a builder for a starting element.
    ///
    /// This builder can then be used to tweak attributes and namespace starting at
    /// this element.
    #[inline]
    pub fn start_element<S>(name: S) -> StartElementBuilder<'a> where S: Into<Name<'a>> {
        StartElementBuilder {
            name: name.into(),
            attributes: Vec::new(),
            namespace: Namespace::empty().into()
        }
    }

    /// Returns a builder for an closing element.
    ///
    /// This method, unline `start_element()`, does not accept a name because by default
    /// the writer is able to determine it automatically. However, when this functionality
    /// is disabled, it is possible to specify the name with `name()` method on the builder.
    #[inline]
    pub fn end_element() -> EndElementBuilder<'a> {
        EndElementBuilder { name: None }
    }

    /// Returns a CDATA event.
    ///
    /// Naturally, the provided string won't be escaped, except for closing CDATA token `]]>`
    /// (depending on the configuration).
    #[inline]
    pub fn cdata(data: &'a str) -> XmlEvent<'a> { XmlEvent::CData(data) }

    /// Returns a regular characters (PCDATA) event.
    ///
    /// All offending symbols, in particular, `&` and `<`, will be escaped by the writer.
    #[inline]
    pub fn characters(data: &'a str) -> XmlEvent<'a> { XmlEvent::Characters(data) }

    /// Returns a comment event.
    #[inline]
    pub fn comment(data: &'a str) -> XmlEvent<'a> { XmlEvent::Comment(data) }
}

impl<'a> From<&'a str> for XmlEvent<'a> {
    #[inline]
    fn from(s: &'a str) -> XmlEvent<'a> { XmlEvent::Characters(s) }
}

pub struct EndElementBuilder<'a> {
    name: Option<Name<'a>>
}

/// A builder for a closing element event.
impl<'a> EndElementBuilder<'a> {
    /// Sets the name of this closing element.
    ///
    /// Usually the writer is able to determine closing element names automatically. If
    /// this functionality is enabled (by default it is), then this name is checked for correctness.
    /// It is possible, however, to disable such behavior; then the user must ensure that
    /// closing element name is correct manually.
    #[inline]
    pub fn name<N>(mut self, name: N) -> EndElementBuilder<'a> where N: Into<Name<'a>> {
        self.name = Some(name.into());
        self
    }
}

impl<'a> From<EndElementBuilder<'a>> for XmlEvent<'a> {
    fn from(b: EndElementBuilder<'a>) -> XmlEvent<'a> {
        XmlEvent::EndElement { name: b.name }
    }
}

/// A builder for a starting element event.
pub struct StartElementBuilder<'a> {
    name: Name<'a>,
    attributes: Vec<Attribute<'a>>,
    namespace: Namespace
}

impl<'a> StartElementBuilder<'a> {
    /// Sets an attribute value of this element to the given string.
    ///
    /// This method can be used to add attributes to the starting element. Name is a qualified
    /// name; its namespace is ignored, but its prefix is checked for correctness, that is,
    /// it is checked that the prefix is bound to some namespace in the current context.
    ///
    /// Currently attributes are not checked for duplicates. Note that duplicate attributes
    /// are a violation of XML document well-formedness.
    ///
    /// The writer checks that you don't specify reserved prefix names, for example `xmlns`.
    #[inline]
    pub fn attr<N>(mut self, name: N, value: &'a str) -> StartElementBuilder<'a>
        where N: Into<Name<'a>>
    {
        self.attributes.push(Attribute::new(name.into(), value));
        self
    }

    /// Adds a namespace to the current namespace context.
    ///
    /// If no namespace URI was bound to the provided prefix at this point of the document,
    /// then the mapping from the prefix to the provided namespace URI will be written as
    /// a part of this element attribute set.
    ///
    /// If the same namespace URI was bound to the provided prefix at this point of the document,
    /// then no namespace attributes will be emitted.
    ///
    /// If some other namespace URI was bound to the provided prefix at this point of the document,
    /// then another binding will be added as a part of this element attribute set, shadowing
    /// the outer binding.
    #[inline]
    pub fn ns<S1, S2>(mut self, prefix: S1, uri: S2) -> StartElementBuilder<'a>
        where S1: Into<String>, S2: Into<String>
    {
        self.namespace.put(prefix, uri);
        self
    }

    /// Adds a default namespace mapping to the current namespace context.
    ///
    /// Same rules as for `ns()` are also valid for the default namespace mapping.
    #[inline]
    pub fn default_ns<S>(mut self, uri: S) -> StartElementBuilder<'a>
        where S: Into<String>
    {
        self.namespace.put(NS_NO_PREFIX, uri);
        self
    }
}

impl<'a> From<StartElementBuilder<'a>> for XmlEvent<'a> {
    #[inline]
    fn from(b: StartElementBuilder<'a>) -> XmlEvent<'a> {
        XmlEvent::StartElement {
            name: b.name,
            attributes: Cow::Owned(b.attributes),
            namespace: Cow::Owned(b.namespace)
        }
    }
}
<commit_msg>Add Debug to writer::XmlEvent<commit_after>//! Contains `XmlEvent` datatype, instances of which are consumed by the writer.

use std::borrow::Cow;

use name::Name;
use attribute::Attribute;
use common::XmlVersion;
use namespace::{Namespace, NS_NO_PREFIX};

/// A part of an XML output stream.
///
/// Objects of this enum are consumed by `EventWriter`. They correspond to different parts of
/// an XML document.
#[derive(Debug)]
pub enum XmlEvent<'a> {
    /// Corresponds to XML document declaration.
    ///
    /// This event should always be written before any other event. If it is not written
    /// at all, a default XML declaration will be outputted if the corresponding option
    /// is set in the configuration. Otherwise an error will be returned.
    StartDocument {
        /// XML version.
        ///
        /// Defaults to `XmlVersion::Version10`.
        version: XmlVersion,

        /// XML document encoding.
        ///
        /// Defaults to `Some("UTF-8")`.
        encoding: Option<&'a str>,

        /// XML standalone declaration.
        ///
        /// Defaults to `None`.
        standalone: Option<bool>
    },

    /// Denotes an XML processing instruction.
    ProcessingInstruction {
        /// Processing instruction target.
        name: &'a str,

        /// Processing instruction content.
        data: Option<&'a str>
    },

    /// Denotes a beginning of an XML element.
    StartElement {
        /// Qualified name of the element.
        name: Name<'a>,

        /// A list of attributes associated with the element.
        ///
        /// Currently attributes are not checked for duplicates (TODO). Attribute values
        /// will be escaped, and all characters invalid for attribute values like `"` or `<`
        /// will be changed into character entities.
        attributes: Cow<'a, [Attribute<'a>]>,

        /// Contents of the namespace mapping at this point of the document.
        ///
        /// This mapping will be inspected for "new" entries, and if at this point of the document
        /// a particular pair of prefix and namespace URI is already defined, no namespace
        /// attributes will be emitted.
        namespace: Cow<'a, Namespace>,
    },

    /// Denotes an end of an XML element.
    EndElement {
        /// Optional qualified name of the element.
        ///
        /// If `None`, then it is assumed that the element name should be the last valid one.
        /// If `Some` and element names tracking is enabled, then the writer will check it for
        /// correctness.
        name: Option<Name<'a>>
    },

    /// Denotes CDATA content.
    ///
    /// This event contains unparsed data, and no escaping will be performed when writing it
    /// to the output stream.
    CData(&'a str),

    /// Denotes a comment.
    ///
    /// The string will be checked for invalid sequences and error will be returned by the
    /// write operation
    Comment(&'a str),

    /// Denotes character data outside of tags.
    ///
    /// Contents of this event will be escaped if `perform_escaping` option is enabled,
    /// that is, every character invalid for PCDATA will appear as a character entity.
    Characters(&'a str)
}

impl<'a> XmlEvent<'a> {
    /// Returns an writer event for a processing instruction.
    #[inline]
    pub fn processing_instruction(name: &'a str, data: Option<&'a str>) -> XmlEvent<'a> {
        XmlEvent::ProcessingInstruction { name: name, data: data }
    }

    /// Returns a builder for a starting element.
    ///
    /// This builder can then be used to tweak attributes and namespace starting at
    /// this element.
    #[inline]
    pub fn start_element<S>(name: S) -> StartElementBuilder<'a> where S: Into<Name<'a>> {
        StartElementBuilder {
            name: name.into(),
            attributes: Vec::new(),
            namespace: Namespace::empty().into()
        }
    }

    /// Returns a builder for an closing element.
    ///
    /// This method, unline `start_element()`, does not accept a name because by default
    /// the writer is able to determine it automatically. However, when this functionality
    /// is disabled, it is possible to specify the name with `name()` method on the builder.
    #[inline]
    pub fn end_element() -> EndElementBuilder<'a> {
        EndElementBuilder { name: None }
    }

    /// Returns a CDATA event.
    ///
    /// Naturally, the provided string won't be escaped, except for closing CDATA token `]]>`
    /// (depending on the configuration).
    #[inline]
    pub fn cdata(data: &'a str) -> XmlEvent<'a> { XmlEvent::CData(data) }

    /// Returns a regular characters (PCDATA) event.
    ///
    /// All offending symbols, in particular, `&` and `<`, will be escaped by the writer.
    #[inline]
    pub fn characters(data: &'a str) -> XmlEvent<'a> { XmlEvent::Characters(data) }

    /// Returns a comment event.
    #[inline]
    pub fn comment(data: &'a str) -> XmlEvent<'a> { XmlEvent::Comment(data) }
}

impl<'a> From<&'a str> for XmlEvent<'a> {
    #[inline]
    fn from(s: &'a str) -> XmlEvent<'a> { XmlEvent::Characters(s) }
}

pub struct EndElementBuilder<'a> {
    name: Option<Name<'a>>
}

/// A builder for a closing element event.
impl<'a> EndElementBuilder<'a> {
    /// Sets the name of this closing element.
    ///
    /// Usually the writer is able to determine closing element names automatically. If
    /// this functionality is enabled (by default it is), then this name is checked for correctness.
    /// It is possible, however, to disable such behavior; then the user must ensure that
    /// closing element name is correct manually.
    #[inline]
    pub fn name<N>(mut self, name: N) -> EndElementBuilder<'a> where N: Into<Name<'a>> {
        self.name = Some(name.into());
        self
    }
}

impl<'a> From<EndElementBuilder<'a>> for XmlEvent<'a> {
    fn from(b: EndElementBuilder<'a>) -> XmlEvent<'a> {
        XmlEvent::EndElement { name: b.name }
    }
}

/// A builder for a starting element event.
pub struct StartElementBuilder<'a> {
    name: Name<'a>,
    attributes: Vec<Attribute<'a>>,
    namespace: Namespace
}

impl<'a> StartElementBuilder<'a> {
    /// Sets an attribute value of this element to the given string.
    ///
    /// This method can be used to add attributes to the starting element. Name is a qualified
    /// name; its namespace is ignored, but its prefix is checked for correctness, that is,
    /// it is checked that the prefix is bound to some namespace in the current context.
    ///
    /// Currently attributes are not checked for duplicates. Note that duplicate attributes
    /// are a violation of XML document well-formedness.
    ///
    /// The writer checks that you don't specify reserved prefix names, for example `xmlns`.
    #[inline]
    pub fn attr<N>(mut self, name: N, value: &'a str) -> StartElementBuilder<'a>
        where N: Into<Name<'a>>
    {
        self.attributes.push(Attribute::new(name.into(), value));
        self
    }

    /// Adds a namespace to the current namespace context.
    ///
    /// If no namespace URI was bound to the provided prefix at this point of the document,
    /// then the mapping from the prefix to the provided namespace URI will be written as
    /// a part of this element attribute set.
    ///
    /// If the same namespace URI was bound to the provided prefix at this point of the document,
    /// then no namespace attributes will be emitted.
    ///
    /// If some other namespace URI was bound to the provided prefix at this point of the document,
    /// then another binding will be added as a part of this element attribute set, shadowing
    /// the outer binding.
    #[inline]
    pub fn ns<S1, S2>(mut self, prefix: S1, uri: S2) -> StartElementBuilder<'a>
        where S1: Into<String>, S2: Into<String>
    {
        self.namespace.put(prefix, uri);
        self
    }

    /// Adds a default namespace mapping to the current namespace context.
    ///
    /// Same rules as for `ns()` are also valid for the default namespace mapping.
    #[inline]
    pub fn default_ns<S>(mut self, uri: S) -> StartElementBuilder<'a>
        where S: Into<String>
    {
        self.namespace.put(NS_NO_PREFIX, uri);
        self
    }
}

impl<'a> From<StartElementBuilder<'a>> for XmlEvent<'a> {
    #[inline]
    fn from(b: StartElementBuilder<'a>) -> XmlEvent<'a> {
        XmlEvent::StartElement {
            name: b.name,
            attributes: Cow::Owned(b.attributes),
            namespace: Cow::Owned(b.namespace)
        }
    }
}
<|endoftext|>


<commit_before>#[doc(str = "

Implements the RCU dom-sharing model.  This model allows for a single
writer and any number of readers, but the writer must be able to
control and manage the lifetimes of the reader(s).  For simplicity I
will describe the impl as though there were a single reader.

The basic idea is that every object in the RCU pool has both a reader
view and a writer view.  The writer always sees the writer view, which
contains the most up-to-date values.  The reader uses the reader view,
which contains the values as of the point where the reader was forked.
When the writer joins the reader, the reader view will be synchronized
with the writer view.

Internally, the way this works is using a copy-on-write scheme.  Each
RCU node maintains two pointers (`rd_ptr` and `wr_ptr`).  Assuming
that readers are active, when a writer wants to modify a node, it
first copies the reader's data into a new pointer.  Any writes that
occur after that point (but before the reader is joined) will operate
on this same copy.  When the reader is joined, any nodes which the
writer modified will free the stale reader data and update the reader
pointer to be the same as the writer pointer.

# Using the RCU APIs as a writer

You must first create a `scope` object.  The scope object manages the
memory and the RCU operations.  RCU'd objects of some sendable type
`T` are not referenced directly but rather through a `handle<T>`.  To
create a new RCU object, you use `scope.handle(t)` where `t` is some
initial value of type `T`.  To write to an RCU object, use
`scope.wr()` and to read from it use `scope.rd()`. Be sure not to use
the various `reader_methods`.

Handles can be freely sent between tasks but the RCU scope cannot.  It
must stay with the writer task.  You are responsible for correctly
invoking `reader_forked()` and `reader_joined()` to keep the RCU scope
abreast of when the reader is active.  Failure to do so will lead to
race conditions or worse.

# Using the RCU APIs as a reader

Import the `reader_methods` impl.  When you receive a handle, you can
invoke `h.rd { |v| ... }` and so forth.  There is also a piece of
auxiliary data that can be optionally associated with each handle.

Note: if the type `T` contains mutable fields, then there is nothing
to stop the reader from mutating those fields in the `rd()` method.
Do not do this.  It will lead to race conditions.

# Auxiliary data

Readers can associate a piece of auxiliary data of type `A` along with
main nodes.  This is convenient but dangerous: it is the reader's job
to ensure that this data remains live independent of the RCU nodes
themselves.

")];

import ptr::extensions;

export handle;
export reader_methods;
export writer_methods;
export scope;

type scope_data<T:send,A> = {
    mut layout_active: bool,
    mut free_list: [handle<T,A>],
    mut first_dirty: handle<T,A>
};

resource scope_rsrc<T:send,A>(d: scope_data<T,A>) {
    unsafe {
        for d.free_list.each { |h| free_handle(h); }
    }
}

type scope<T:send,A> = @scope_rsrc<T,A>;

type handle_data<T:send,A> = {mut rd_ptr: *T,
                              mut wr_ptr: *T,
                              mut rd_aux: *A,
                              mut next_dirty: handle<T,A>};
enum handle<T:send,A> {
    _handle(*handle_data<T,A>)
}

impl private_methods<T:send,A> for handle<T,A> {
    fn rd_ptr() -> *T unsafe { (**self).rd_ptr }
    fn wr_ptr() -> *T unsafe { (**self).wr_ptr }
    fn rd_aux() -> *A unsafe { (**self).rd_aux }
    fn next_dirty() -> handle<T,A> unsafe { (**self).next_dirty }

    fn set_rd_ptr(t: *T) unsafe { (**self).rd_ptr = t; }
    fn set_wr_ptr(t: *T) unsafe { (**self).wr_ptr = t; }
    fn set_rd_aux(t: *A) unsafe { (**self).rd_aux = t; }
    fn set_next_dirty(+h: handle<T,A>) unsafe { (**self).next_dirty = h; }

    fn is_null() -> bool { (*self).is_null() }
    fn is_not_null() -> bool { (*self).is_not_null() }
}

impl reader_methods<T:send,A> for handle<T,A> {
    #[doc(str = "access the reader's view of the handle's data")]
    fn rd<U>(f: fn(T) -> U) -> U unsafe {
        f(*self.rd_ptr())
    }

    #[doc(str = "true if auxiliary data is associated with this handle")]
    fn has_aux() -> bool unsafe {
        self.rd_aux().is_not_null()
    }

    #[doc(str = "set the auxiliary data associated with this handle.

    **Warning:** the reader is responsible for keeping this data live!
    ")]
    fn set_aux(p: @A) unsafe {
        let p2 = p;
        unsafe::forget(p2); // Bump the reference count.

        (**self).rd_aux = ptr::addr_of(*p);
    }

    #[doc(str = "access the auxiliary data associated with this handle.")]
    fn aux<U>(f: fn(A) -> U) -> U unsafe {
        assert self.has_aux();
        f(*self.rd_aux())
    }
}

impl private_methods<T:send,A> for scope<T,A> {
    fn clone(v: *T) -> *T unsafe {
        let n: *mut T =
            unsafe::reinterpret_cast(
                libc::calloc(sys::size_of::<T>(), 1u));

        // n.b.: this assignment will run the drop glue for <T,A>.
        // *Hopefully* the fact that everything is initialized to NULL
        // by calloc will make this ok.  We may have to make the take
        // glue be tolerant.
        *n = unsafe{*v};

        ret unsafe::reinterpret_cast(n);
    }
}

unsafe fn free<T:send>(t: *T) {
    let _x <- *unsafe::reinterpret_cast::<*T,*mut T>(t);
    libc::free(unsafe::reinterpret_cast(t));
}

unsafe fn free_handle<T:send,A>(h: handle<T,A>) {
    free(h.rd_ptr());
    if h.wr_ptr() != h.rd_ptr() { free(h.wr_ptr()); }
}

fn null_handle<T:send,A>() -> handle<T,A> {
    _handle(ptr::null())
}

fn scope<T:send,A>() -> scope<T,A> {
    @scope_rsrc({mut layout_active: false,
                 mut free_list: [],
                 mut first_dirty: null_handle()})
}

impl writer_methods<T:send,A> for scope<T,A> {
    fn is_reader_forked() -> bool {
        self.layout_active
    }

    fn reader_forked() {
        assert !self.layout_active;
        assert self.first_dirty.is_null();
        self.layout_active = true;
    }

    fn reader_joined() unsafe {
        assert self.layout_active;

        if self.first_dirty.is_not_null() {
            let mut handle = self.first_dirty;
            while (*handle).is_not_null() {
                free(handle.rd_ptr());

                handle.set_rd_ptr(handle.wr_ptr());
                let next_handle = handle.next_dirty();
                handle.set_next_dirty(null_handle());
                handle = next_handle;
            }
            self.first_dirty = null_handle();
        }

        assert self.first_dirty.is_null();
        self.layout_active = false;
    }

    fn rd<U>(h: handle<T,A>, f: fn(T) -> U) -> U unsafe {
        // Use the wr_ptr, which may be more up to date than the
        // rd_ptr or may not
        f(*h.wr_ptr())
    }

    fn wr<U>(h: handle<T,A>, f: fn(T) -> U) -> U unsafe {
        if self.layout_active && h.rd_ptr() == h.wr_ptr() {
            #debug["marking handle %? as dirty", h];
            h.set_wr_ptr(self.clone(h.rd_ptr()));
            h.set_next_dirty(self.first_dirty);
            self.first_dirty = h;
        }
        f(*h.wr_ptr())
    }

    fn handle(v: T) -> handle<T,A> unsafe {
        let d: *handle_data<T,A> =
            unsafe::reinterpret_cast(
                libc::malloc(sys::size_of::<handle_data<T,A>>()));
        (*d).rd_ptr = self.clone(ptr::addr_of(v));
        (*d).wr_ptr = (*d).rd_ptr;
        (*d).rd_aux = ptr::null();
        (*d).next_dirty = null_handle();
        let h = _handle(d);
        self.free_list += [h];
        ret h;
    }
}

#[cfg(test)]
mod test {

    type animal = {name: str, species: species};
    enum species {
        chicken(~chicken),
        bull(~bull)
    }
    type chicken = {mut eggs_per_day:uint};
    type bull = {mut horns:uint};

    type processed = {flag: bool};

    type animal_scope = scope<animal, processed>;

    #[test]
    fn handles_get_freed() {
        let s: animal_scope = scope();
        s.handle({name:"henrietta", species:chicken(~{mut eggs_per_day:22u})});
        s.handle({name:"ferdinand", species:bull(~{mut horns:3u})});
    }

    fn mutate(a: animal) {
        alt a.species {
          chicken(c) { c.eggs_per_day += 1u; }
          bull(c) { c.horns += 1u; }
        }
    }

    fn read_characteristic(a: animal) -> uint {
        alt a.species {
          chicken(c) { c.eggs_per_day }
          bull(c) { c.horns }
        }
    }

    #[test]
    fn interspersed_execution() {
        let s: animal_scope = scope();
        let henrietta =
            s.handle({name:"henrietta",
                      species:chicken(~{mut eggs_per_day:0u})});
        let ferdinand =
            s.handle({name:"ferdinand",
                      species:bull(~{mut horns:0u})});

        let iter1 = 3u;
        let iter2 = 22u;
        let read_port = comm::port();
        let read_chan = comm::chan(read_port);

        // fire up a reader task
        uint::range(0u, iter1) { |i|
            s.reader_forked();
            let wait_chan = task::spawn_listener {|wait_port|
                uint::range(0u, iter2) { |_i|
                    comm::send(read_chan, henrietta.rd(read_characteristic));
                    comm::send(read_chan, ferdinand.rd(read_characteristic));
                    comm::recv(wait_port);
                }
            };

            let hrc = henrietta.rd(read_characteristic);
            assert hrc == (i * iter2);

            let frc = ferdinand.rd(read_characteristic);
            assert frc == i * iter2;

            uint::range(0u, iter2) { |_i|
                assert hrc == comm::recv(read_port);
                s.wr(henrietta, mutate);
                assert frc == comm::recv(read_port);
                s.wr(ferdinand, mutate);
                comm::send(wait_chan, ());
            }
            s.reader_joined();
        }

        assert henrietta.rd(read_characteristic) == iter1 * iter2;
        assert ferdinand.rd(read_characteristic) == iter1 * iter2;
    }

}
<commit_msg>Fix for kind system changes<commit_after>#[doc(str = "

Implements the RCU dom-sharing model.  This model allows for a single
writer and any number of readers, but the writer must be able to
control and manage the lifetimes of the reader(s).  For simplicity I
will describe the impl as though there were a single reader.

The basic idea is that every object in the RCU pool has both a reader
view and a writer view.  The writer always sees the writer view, which
contains the most up-to-date values.  The reader uses the reader view,
which contains the values as of the point where the reader was forked.
When the writer joins the reader, the reader view will be synchronized
with the writer view.

Internally, the way this works is using a copy-on-write scheme.  Each
RCU node maintains two pointers (`rd_ptr` and `wr_ptr`).  Assuming
that readers are active, when a writer wants to modify a node, it
first copies the reader's data into a new pointer.  Any writes that
occur after that point (but before the reader is joined) will operate
on this same copy.  When the reader is joined, any nodes which the
writer modified will free the stale reader data and update the reader
pointer to be the same as the writer pointer.

# Using the RCU APIs as a writer

You must first create a `scope` object.  The scope object manages the
memory and the RCU operations.  RCU'd objects of some sendable type
`T` are not referenced directly but rather through a `handle<T>`.  To
create a new RCU object, you use `scope.handle(t)` where `t` is some
initial value of type `T`.  To write to an RCU object, use
`scope.wr()` and to read from it use `scope.rd()`. Be sure not to use
the various `reader_methods`.

Handles can be freely sent between tasks but the RCU scope cannot.  It
must stay with the writer task.  You are responsible for correctly
invoking `reader_forked()` and `reader_joined()` to keep the RCU scope
abreast of when the reader is active.  Failure to do so will lead to
race conditions or worse.

# Using the RCU APIs as a reader

Import the `reader_methods` impl.  When you receive a handle, you can
invoke `h.rd { |v| ... }` and so forth.  There is also a piece of
auxiliary data that can be optionally associated with each handle.

Note: if the type `T` contains mutable fields, then there is nothing
to stop the reader from mutating those fields in the `rd()` method.
Do not do this.  It will lead to race conditions.

# Auxiliary data

Readers can associate a piece of auxiliary data of type `A` along with
main nodes.  This is convenient but dangerous: it is the reader's job
to ensure that this data remains live independent of the RCU nodes
themselves.

")];

import ptr::extensions;

export handle;
export reader_methods;
export writer_methods;
export scope;

type scope_data<T:send,A> = {
    mut layout_active: bool,
    mut free_list: [handle<T,A>],
    mut first_dirty: handle<T,A>
};

resource scope_rsrc<T:send,A>(d: scope_data<T,A>) {
    unsafe {
        for d.free_list.each { |h| free_handle(h); }
    }
}

type scope<T:send,A> = @scope_rsrc<T,A>;

type handle_data<T:send,A> = {mut rd_ptr: *T,
                              mut wr_ptr: *T,
                              mut rd_aux: *A,
                              mut next_dirty: handle<T,A>};
enum handle<T:send,A> {
    _handle(*handle_data<T,A>)
}

impl private_methods<T:send,A> for handle<T,A> {
    fn rd_ptr() -> *T unsafe { (**self).rd_ptr }
    fn wr_ptr() -> *T unsafe { (**self).wr_ptr }
    fn rd_aux() -> *A unsafe { (**self).rd_aux }
    fn next_dirty() -> handle<T,A> unsafe { (**self).next_dirty }

    fn set_rd_ptr(t: *T) unsafe { (**self).rd_ptr = t; }
    fn set_wr_ptr(t: *T) unsafe { (**self).wr_ptr = t; }
    fn set_rd_aux(t: *A) unsafe { (**self).rd_aux = t; }
    fn set_next_dirty(+h: handle<T,A>) unsafe { (**self).next_dirty = h; }

    fn is_null() -> bool { (*self).is_null() }
    fn is_not_null() -> bool { (*self).is_not_null() }
}

impl reader_methods<T:send,A> for handle<T,A> {
    #[doc(str = "access the reader's view of the handle's data")]
    fn rd<U>(f: fn(T) -> U) -> U unsafe {
        f(*self.rd_ptr())
    }

    #[doc(str = "true if auxiliary data is associated with this handle")]
    fn has_aux() -> bool unsafe {
        self.rd_aux().is_not_null()
    }

    #[doc(str = "set the auxiliary data associated with this handle.

    **Warning:** the reader is responsible for keeping this data live!
    ")]
    fn set_aux(p: @A) unsafe {
        let p2 = p;
        unsafe::forget(p2); // Bump the reference count.

        (**self).rd_aux = ptr::addr_of(*p);
    }

    #[doc(str = "access the auxiliary data associated with this handle.")]
    fn aux<U>(f: fn(A) -> U) -> U unsafe {
        assert self.has_aux();
        f(*self.rd_aux())
    }
}

impl private_methods<T: copy send,A> for scope<T,A> {
    fn clone(v: *T) -> *T unsafe {
        let n: *mut T =
            unsafe::reinterpret_cast(
                libc::calloc(sys::size_of::<T>(), 1u));

        // n.b.: this assignment will run the drop glue for <T,A>.
        // *Hopefully* the fact that everything is initialized to NULL
        // by calloc will make this ok.  We may have to make the take
        // glue be tolerant.
        *n = unsafe{*v};

        ret unsafe::reinterpret_cast(n);
    }
}

unsafe fn free<T:send>(t: *T) {
    let _x <- *unsafe::reinterpret_cast::<*T,*mut T>(t);
    libc::free(unsafe::reinterpret_cast(t));
}

unsafe fn free_handle<T:send,A>(h: handle<T,A>) {
    free(h.rd_ptr());
    if h.wr_ptr() != h.rd_ptr() { free(h.wr_ptr()); }
}

fn null_handle<T:send,A>() -> handle<T,A> {
    _handle(ptr::null())
}

fn scope<T:send,A>() -> scope<T,A> {
    @scope_rsrc({mut layout_active: false,
                 mut free_list: [],
                 mut first_dirty: null_handle()})
}

impl writer_methods<T:copy send,A> for scope<T,A> {
    fn is_reader_forked() -> bool {
        self.layout_active
    }

    fn reader_forked() {
        assert !self.layout_active;
        assert self.first_dirty.is_null();
        self.layout_active = true;
    }

    fn reader_joined() unsafe {
        assert self.layout_active;

        if self.first_dirty.is_not_null() {
            let mut handle = self.first_dirty;
            while (*handle).is_not_null() {
                free(handle.rd_ptr());

                handle.set_rd_ptr(handle.wr_ptr());
                let next_handle = handle.next_dirty();
                handle.set_next_dirty(null_handle());
                handle = next_handle;
            }
            self.first_dirty = null_handle();
        }

        assert self.first_dirty.is_null();
        self.layout_active = false;
    }

    fn rd<U>(h: handle<T,A>, f: fn(T) -> U) -> U unsafe {
        // Use the wr_ptr, which may be more up to date than the
        // rd_ptr or may not
        f(*h.wr_ptr())
    }

    fn wr<U>(h: handle<T,A>, f: fn(T) -> U) -> U unsafe {
        if self.layout_active && h.rd_ptr() == h.wr_ptr() {
            #debug["marking handle %? as dirty", h];
            h.set_wr_ptr(self.clone(h.rd_ptr()));
            h.set_next_dirty(self.first_dirty);
            self.first_dirty = h;
        }
        f(*h.wr_ptr())
    }

    fn handle(v: T) -> handle<T,A> unsafe {
        let d: *handle_data<T,A> =
            unsafe::reinterpret_cast(
                libc::malloc(sys::size_of::<handle_data<T,A>>()));
        (*d).rd_ptr = self.clone(ptr::addr_of(v));
        (*d).wr_ptr = (*d).rd_ptr;
        (*d).rd_aux = ptr::null();
        (*d).next_dirty = null_handle();
        let h = _handle(d);
        self.free_list += [h];
        ret h;
    }
}

#[cfg(test)]
mod test {

    type animal = {name: str, species: species};
    enum species {
        chicken(~chicken),
        bull(~bull)
    }
    type chicken = {mut eggs_per_day:uint};
    type bull = {mut horns:uint};

    type processed = {flag: bool};

    type animal_scope = scope<animal, processed>;

    #[test]
    fn handles_get_freed() {
        let s: animal_scope = scope();
        s.handle({name:"henrietta", species:chicken(~{mut eggs_per_day:22u})});
        s.handle({name:"ferdinand", species:bull(~{mut horns:3u})});
    }

    fn mutate(a: animal) {
        alt a.species {
          chicken(c) { c.eggs_per_day += 1u; }
          bull(c) { c.horns += 1u; }
        }
    }

    fn read_characteristic(a: animal) -> uint {
        alt a.species {
          chicken(c) { c.eggs_per_day }
          bull(c) { c.horns }
        }
    }

    #[test]
    fn interspersed_execution() {
        let s: animal_scope = scope();
        let henrietta =
            s.handle({name:"henrietta",
                      species:chicken(~{mut eggs_per_day:0u})});
        let ferdinand =
            s.handle({name:"ferdinand",
                      species:bull(~{mut horns:0u})});

        let iter1 = 3u;
        let iter2 = 22u;
        let read_port = comm::port();
        let read_chan = comm::chan(read_port);

        // fire up a reader task
        uint::range(0u, iter1) { |i|
            s.reader_forked();
            let wait_chan = task::spawn_listener {|wait_port|
                uint::range(0u, iter2) { |_i|
                    comm::send(read_chan, henrietta.rd(read_characteristic));
                    comm::send(read_chan, ferdinand.rd(read_characteristic));
                    comm::recv(wait_port);
                }
            };

            let hrc = henrietta.rd(read_characteristic);
            assert hrc == (i * iter2);

            let frc = ferdinand.rd(read_characteristic);
            assert frc == i * iter2;

            uint::range(0u, iter2) { |_i|
                assert hrc == comm::recv(read_port);
                s.wr(henrietta, mutate);
                assert frc == comm::recv(read_port);
                s.wr(ferdinand, mutate);
                comm::send(wait_chan, ());
            }
            s.reader_joined();
        }

        assert henrietta.rd(read_characteristic) == iter1 * iter2;
        assert ferdinand.rd(read_characteristic) == iter1 * iter2;
    }

}
<|endoftext|>


<commit_before>use crate::utils;
use crate::utils::sugg::Sugg;
use crate::utils::{match_type, paths, span_lint_and_sugg};
use if_chain::if_chain;

use rustc_errors::Applicability;
use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, PatKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint};

use std::marker::PhantomData;

declare_clippy_lint! {
    /// **What it does:**
    /// Lints usage of  `if let Some(v) = ... { y } else { x }` which is more
    /// idiomatically done with `Option::map_or` (if the else bit is a simple
    /// expression) or `Option::map_or_else` (if the else bit is a longer
    /// block).
    ///
    /// **Why is this bad?**
    /// Using the dedicated functions of the Option type is clearer and
    /// more concise than an if let expression.
    ///
    /// **Known problems:**
    /// This lint uses whether the block is just an expression or if it has
    /// more statements to decide whether to use `Option::map_or` or
    /// `Option::map_or_else`. If you have a single expression which calls
    /// an expensive function, then it would be more efficient to use
    /// `Option::map_or_else`, but this lint would suggest `Option::map_or`.
    ///
    /// Also, this lint uses a deliberately conservative metric for checking
    /// if the inside of either body contains breaks or continues which will
    /// cause it to not suggest a fix if either block contains a loop with
    /// continues or breaks contained within the loop.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     5
    /// };
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     let y = do_complicated_function();
    ///     y*y
    /// };
    /// ```
    ///
    /// should be
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// let _ = optional.map_or(5, |foo| foo);
    /// let _ = optional.map_or_else(||{
    ///     let y = do_complicated_function;
    ///     y*y
    /// }, |foo| foo);
    /// ```
    pub OPTION_IF_LET_ELSE,
    style,
    "reimplementation of Option::map_or"
}

declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]);

/// Returns true iff the given expression is the result of calling `Result::ok`
fn is_result_ok(cx: &LateContext<'_, '_>, expr: &'_ Expr<'_>) -> bool {
    if let ExprKind::MethodCall(ref path, _, &[ref receiver]) = &expr.kind {
        path.ident.name.to_ident_string() == "ok" && match_type(cx, &cx.tables.expr_ty(&receiver), &paths::RESULT)
    } else {
        false
    }
}

/// A struct containing information about occurences of the
/// `if let Some(..) = .. else` construct that this lint detects.
struct OptionIfLetElseOccurence {
    option: String,
    method_sugg: String,
    some_expr: String,
    none_expr: String,
    wrap_braces: bool,
}

struct ReturnBreakContinueVisitor<'tcx> {
    seen_return_break_continue: bool,
    phantom_data: PhantomData<&'tcx bool>,
}
impl<'tcx> ReturnBreakContinueVisitor<'tcx> {
    fn new() -> ReturnBreakContinueVisitor<'tcx> {
        ReturnBreakContinueVisitor {
            seen_return_break_continue: false,
            phantom_data: PhantomData,
        }
    }
}
impl<'tcx> Visitor<'tcx> for ReturnBreakContinueVisitor<'tcx> {
    type Map = Map<'tcx>;
    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }

    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
        if self.seen_return_break_continue {
            // No need to look farther if we've already seen one of them
            return;
        }
        match &ex.kind {
            ExprKind::Ret(..) | ExprKind::Break(..) | ExprKind::Continue(..) => {
                self.seen_return_break_continue = true;
            },
            // Something special could be done here to handle while or for loop
            // desugaring, as this will detect a break if there's a while loop
            // or a for loop inside the expression.
            _ => {
                rustc_hir::intravisit::walk_expr(self, ex);
            },
        }
    }
}

fn contains_return_break_continue<'tcx>(expression: &'tcx Expr<'tcx>) -> bool {
    let mut recursive_visitor: ReturnBreakContinueVisitor<'tcx> = ReturnBreakContinueVisitor::new();
    recursive_visitor.visit_expr(expression);
    recursive_visitor.seen_return_break_continue
}

/// Extracts the body of a given arm. If the arm contains only an expression,
/// then it returns the expression. Otherwise, it returns the entire block
fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> {
    if let ExprKind::Block(
        Block {
            stmts: statements,
            expr: Some(expr),
            ..
        },
        _,
    ) = &arm.body.kind
    {
        if let [] = statements {
            Some(&expr)
        } else {
            Some(&arm.body)
        }
    } else {
        None
    }
}

/// If this is the else body of an if/else expression, then we need to wrap
/// it in curcly braces. Otherwise, we don't.
fn should_wrap_in_braces(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
    utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| {
        if let Some(Expr {
            kind:
                ExprKind::Match(
                    _,
                    arms,
                    MatchSource::IfDesugar {
                        contains_else_clause: true,
                    }
                    | MatchSource::IfLetDesugar {
                        contains_else_clause: true,
                    },
                ),
            ..
        }) = parent.expr
        {
            expr.hir_id == arms[1].body.hir_id
        } else {
            false
        }
    })
}

fn format_option_in_sugg(cx: &LateContext<'_, '_>, cond_expr: &Expr<'_>, as_ref: bool, as_mut: bool) -> String {
    format!(
        "{}{}",
        Sugg::hir(cx, cond_expr, "..").maybe_par(),
        if as_mut {
            ".as_mut()"
        } else if as_ref {
            ".as_ref()"
        } else {
            ""
        }
    )
}

/// If this expression is the option if let/else construct we're detecting, then
/// this function returns an `OptionIfLetElseOccurence` struct with details if
/// this construct is found, or None if this construct is not found.
fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -> Option<OptionIfLetElseOccurence> {
    if_chain! {
        if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly
        if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind;
        if arms.len() == 2;
        if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already
        if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind;
        if utils::match_qpath(struct_qpath, &paths::OPTION_SOME);
        if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind;
        if !contains_return_break_continue(arms[0].body);
        if !contains_return_break_continue(arms[1].body);
        then {
            let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" };
            let some_body = extract_body_from_arm(&arms[0])?;
            let none_body = extract_body_from_arm(&arms[1])?;
            let method_sugg = match &none_body.kind {
                ExprKind::Block(..) => "map_or_else",
                _ => "map_or",
            };
            let capture_name = id.name.to_ident_string();
            let wrap_braces = should_wrap_in_braces(cx, expr);
            let (as_ref, as_mut) = match &cond_expr.kind {
                ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
                ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
                _ => (bind_annotation == &BindingAnnotation::Ref, bind_annotation == &BindingAnnotation::RefMut),
            };
            let cond_expr = match &cond_expr.kind {
                // Pointer dereferencing happens automatically, so we can omit it in the suggestion
                ExprKind::Unary(UnOp::UnDeref, expr) | ExprKind::AddrOf(_, _, expr) => expr,
                _ => cond_expr,
            };
            Some(OptionIfLetElseOccurence {
                option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut),
                method_sugg: method_sugg.to_string(),
                some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir(cx, some_body, "..")),
                none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")),
                wrap_braces,
            })
        } else {
            None
        }
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
        if let Some(detection) = detect_option_if_let_else(cx, expr) {
            span_lint_and_sugg(
                cx,
                OPTION_IF_LET_ELSE,
                expr.span,
                format!("use Option::{} instead of an if let/else", detection.method_sugg).as_str(),
                "try",
                format!(
                    "{}{}.{}({}, {}){}",
                    if detection.wrap_braces { "{ " } else { "" },
                    detection.option,
                    detection.method_sugg,
                    detection.none_expr,
                    detection.some_expr,
                    if detection.wrap_braces { " }" } else { "" },
                ),
                Applicability::MachineApplicable,
            );
        }
    }
}
<commit_msg>Don't lint if contains a macro<commit_after>use crate::utils;
use crate::utils::sugg::Sugg;
use crate::utils::{match_type, paths, span_lint_and_sugg};
use if_chain::if_chain;

use rustc_errors::Applicability;
use rustc_hir::intravisit::{NestedVisitorMap, Visitor};
use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, PatKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:**
    /// Lints usage of  `if let Some(v) = ... { y } else { x }` which is more
    /// idiomatically done with `Option::map_or` (if the else bit is a simple
    /// expression) or `Option::map_or_else` (if the else bit is a longer
    /// block).
    ///
    /// **Why is this bad?**
    /// Using the dedicated functions of the Option type is clearer and
    /// more concise than an if let expression.
    ///
    /// **Known problems:**
    /// This lint uses whether the block is just an expression or if it has
    /// more statements to decide whether to use `Option::map_or` or
    /// `Option::map_or_else`. If you have a single expression which calls
    /// an expensive function, then it would be more efficient to use
    /// `Option::map_or_else`, but this lint would suggest `Option::map_or`.
    ///
    /// Also, this lint uses a deliberately conservative metric for checking
    /// if the inside of either body contains breaks or continues which will
    /// cause it to not suggest a fix if either block contains a loop with
    /// continues or breaks contained within the loop.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     5
    /// };
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     let y = do_complicated_function();
    ///     y*y
    /// };
    /// ```
    ///
    /// should be
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// let _ = optional.map_or(5, |foo| foo);
    /// let _ = optional.map_or_else(||{
    ///     let y = do_complicated_function;
    ///     y*y
    /// }, |foo| foo);
    /// ```
    pub OPTION_IF_LET_ELSE,
    style,
    "reimplementation of Option::map_or"
}

declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]);

/// Returns true iff the given expression is the result of calling `Result::ok`
fn is_result_ok(cx: &LateContext<'_, '_>, expr: &'_ Expr<'_>) -> bool {
    if let ExprKind::MethodCall(ref path, _, &[ref receiver]) = &expr.kind {
        path.ident.name.to_ident_string() == "ok" && match_type(cx, &cx.tables.expr_ty(&receiver), &paths::RESULT)
    } else {
        false
    }
}

/// A struct containing information about occurences of the
/// `if let Some(..) = .. else` construct that this lint detects.
struct OptionIfLetElseOccurence {
    option: String,
    method_sugg: String,
    some_expr: String,
    none_expr: String,
    wrap_braces: bool,
}

struct ReturnBreakContinueMacroVisitor {
    seen_return_break_continue: bool,
}
impl ReturnBreakContinueMacroVisitor {
    fn new() -> ReturnBreakContinueMacroVisitor {
        ReturnBreakContinueMacroVisitor {
            seen_return_break_continue: false,
        }
    }
}
impl<'tcx> Visitor<'tcx> for ReturnBreakContinueMacroVisitor {
    type Map = Map<'tcx>;
    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
        NestedVisitorMap::None
    }

    fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
        if self.seen_return_break_continue {
            // No need to look farther if we've already seen one of them
            return;
        }
        match &ex.kind {
            ExprKind::Ret(..) | ExprKind::Break(..) | ExprKind::Continue(..) => {
                self.seen_return_break_continue = true;
            },
            // Something special could be done here to handle while or for loop
            // desugaring, as this will detect a break if there's a while loop
            // or a for loop inside the expression.
            _ => {
                if utils::in_macro(ex.span) {
                    self.seen_return_break_continue = true;
                } else {
                    rustc_hir::intravisit::walk_expr(self, ex);
                }
            },
        }
    }
}

fn contains_return_break_continue_macro(expression: &Expr<'_>) -> bool {
    let mut recursive_visitor = ReturnBreakContinueMacroVisitor::new();
    recursive_visitor.visit_expr(expression);
    recursive_visitor.seen_return_break_continue
}

/// Extracts the body of a given arm. If the arm contains only an expression,
/// then it returns the expression. Otherwise, it returns the entire block
fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> {
    if let ExprKind::Block(
        Block {
            stmts: statements,
            expr: Some(expr),
            ..
        },
        _,
    ) = &arm.body.kind
    {
        if let [] = statements {
            Some(&expr)
        } else {
            Some(&arm.body)
        }
    } else {
        None
    }
}

/// If this is the else body of an if/else expression, then we need to wrap
/// it in curcly braces. Otherwise, we don't.
fn should_wrap_in_braces(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
    utils::get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| {
        if let Some(Expr {
            kind:
                ExprKind::Match(
                    _,
                    arms,
                    MatchSource::IfDesugar {
                        contains_else_clause: true,
                    }
                    | MatchSource::IfLetDesugar {
                        contains_else_clause: true,
                    },
                ),
            ..
        }) = parent.expr
        {
            expr.hir_id == arms[1].body.hir_id
        } else {
            false
        }
    })
}

fn format_option_in_sugg(cx: &LateContext<'_, '_>, cond_expr: &Expr<'_>, as_ref: bool, as_mut: bool) -> String {
    format!(
        "{}{}",
        Sugg::hir(cx, cond_expr, "..").maybe_par(),
        if as_mut {
            ".as_mut()"
        } else if as_ref {
            ".as_ref()"
        } else {
            ""
        }
    )
}

/// If this expression is the option if let/else construct we're detecting, then
/// this function returns an `OptionIfLetElseOccurence` struct with details if
/// this construct is found, or None if this construct is not found.
fn detect_option_if_let_else<'a>(cx: &LateContext<'_, 'a>, expr: &'a Expr<'a>) -> Option<OptionIfLetElseOccurence> {
    if_chain! {
        if !utils::in_macro(expr.span); // Don't lint macros, because it behaves weirdly
        if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind;
        if arms.len() == 2;
        if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already
        if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind;
        if utils::match_qpath(struct_qpath, &paths::OPTION_SOME);
        if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind;
        if !contains_return_break_continue_macro(arms[0].body);
        if !contains_return_break_continue_macro(arms[1].body);
        then {
            let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" };
            let some_body = extract_body_from_arm(&arms[0])?;
            let none_body = extract_body_from_arm(&arms[1])?;
            let method_sugg = match &none_body.kind {
                ExprKind::Block(..) => "map_or_else",
                _ => "map_or",
            };
            let capture_name = id.name.to_ident_string();
            let wrap_braces = should_wrap_in_braces(cx, expr);
            let (as_ref, as_mut) = match &cond_expr.kind {
                ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
                ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
                _ => (bind_annotation == &BindingAnnotation::Ref, bind_annotation == &BindingAnnotation::RefMut),
            };
            let cond_expr = match &cond_expr.kind {
                // Pointer dereferencing happens automatically, so we can omit it in the suggestion
                ExprKind::Unary(UnOp::UnDeref, expr) | ExprKind::AddrOf(_, _, expr) => expr,
                _ => cond_expr,
            };
            Some(OptionIfLetElseOccurence {
                option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut),
                method_sugg: method_sugg.to_string(),
                some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir(cx, some_body, "..")),
                none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")),
                wrap_braces,
            })
        } else {
            None
        }
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OptionIfLetElse {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
        if let Some(detection) = detect_option_if_let_else(cx, expr) {
            span_lint_and_sugg(
                cx,
                OPTION_IF_LET_ELSE,
                expr.span,
                format!("use Option::{} instead of an if let/else", detection.method_sugg).as_str(),
                "try",
                format!(
                    "{}{}.{}({}, {}){}",
                    if detection.wrap_braces { "{ " } else { "" },
                    detection.option,
                    detection.method_sugg,
                    detection.none_expr,
                    detection.some_expr,
                    if detection.wrap_braces { " }" } else { "" },
                ),
                Applicability::MachineApplicable,
            );
        }
    }
}
<|endoftext|>


<commit_before>extern crate xml;
extern crate rustc_serialize;

use std;

pub struct Decoder {
    tree: std::vec::IntoIter<FlatTree>,
}

impl Decoder {
    pub fn new<T: std::io::Read>(body: T) -> Decoder {
        Decoder { tree: Tree::new(body).map(flatten_tree).unwrap_or(vec![].into_iter()) }
    }

    fn peel_named_layer(&mut self, name: &str) -> Result<(), Error> {
        if let Some(FlatTree::Node(key, length)) = self.tree.next() {
            if key == name && length == 1 {
                return Ok(());
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn peel_layer(&mut self) -> Result<(String, usize), Error> {
        if let Some(FlatTree::Node(key, length)) = self.tree.next() {
            if key == "value" && length == 1 {
                if let Some(FlatTree::Node(key, length)) = self.tree.next() {
                    return Ok((key, length));
                }
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    pub fn peel_response_body(&mut self) -> Result<(), Error> {
        try!(self.peel_named_layer("methodResponse"));
        try!(self.peel_named_layer("params"));
        try!(self.peel_named_layer("param"));
        Ok(())
    }
}

impl rustc_serialize::Decoder for Decoder {
    type Error = Error;

    fn read_nil(&mut self) -> Result<(), Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_usize(&mut self) -> Result<usize, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_u64(&mut self) -> Result<u64, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_u32(&mut self) -> Result<u32, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_u16(&mut self) -> Result<u16, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_u8(&mut self) -> Result<u8, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_isize(&mut self) -> Result<isize, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_i64(&mut self) -> Result<i64, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_i32(&mut self) -> Result<i32, Self::Error> {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && (key == "i4" || key == "int") {
            if let Some(FlatTree::Leaf(value)) = self.tree.next() {
                return Ok(try!(value.parse::<i32>()));
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_i16(&mut self) -> Result<i16, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_i8(&mut self) -> Result<i8, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_bool(&mut self) -> Result<bool, Self::Error> {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && key == "boolean" {
            if let Some(FlatTree::Leaf(value)) = self.tree.next() {
                return Ok(try!(value.parse::<i32>()) != 0);
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_f64(&mut self) -> Result<f64, Self::Error> {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && key == "double" {
            if let Some(FlatTree::Leaf(value)) = self.tree.next() {
                return Ok(try!(value.parse::<f64>()));
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_f32(&mut self) -> Result<f32, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_char(&mut self) -> Result<char, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_str(&mut self) -> Result<String, Self::Error> {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && key == "string" {
            if let Some(FlatTree::Leaf(value)) = self.tree.next() {
                return Ok(value);
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_enum<T, F>(&mut self, _: &str, _: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_enum_variant<T, F>(&mut self, _: &[&str], _: F) -> Result<T, Self::Error>
        where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_enum_variant_arg<T, F>(&mut self, _: usize, _: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_enum_struct_variant<T, F>(&mut self, _: &[&str], _: F) -> Result<T, Self::Error>
        where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_enum_struct_variant_field<T, F>(&mut self,
                                            _: &str,
                                            _: usize,
                                            _: F)
                                            -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_struct<T, F>(&mut self, _: &str, size: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        self.read_tuple(size, f)
    }

    fn read_struct_field<T, F>(&mut self, _: &str, _: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        f(self)
    }

    fn read_tuple<T, F>(&mut self, _: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && key == "array" {
            if let Some(FlatTree::Node(key, _)) = self.tree.next() {
                if key == "data" {
                    return f(self);
                }
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_tuple_arg<T, F>(&mut self, _: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        f(self)
    }

    fn read_tuple_struct<T, F>(&mut self, _: &str, size: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        self.read_tuple(size, f)
    }

    fn read_tuple_struct_arg<T, F>(&mut self, _: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        f(self)
    }

    fn read_option<T, F>(&mut self, _: F) -> Result<T, Self::Error>
        where F: FnMut(&mut Self, bool) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error>
    {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && key == "array" {
            if let Some(FlatTree::Node(key, length)) = self.tree.next() {
                if key == "data" {
                    return f(self, length);
                }
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_seq_elt<T, F>(&mut self, _: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        f(self)
    }

    fn read_map<T, F>(&mut self, _: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_map_elt_key<T, F>(&mut self, _: usize, _: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_map_elt_val<T, F>(&mut self, _: usize, _: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn error(&mut self, err: &str) -> Self::Error {
        Error::Decoding(err.to_owned())
    }
}

enum Node {
    Open(String),
    Data(String),
    Close(String),
}

enum Tree {
    Leaf(String),
    Node(String, Vec<Tree>),
}

enum FlatTree {
    Leaf(String),
    Node(String, usize),
}

fn flatten_tree(tree: Tree) -> std::vec::IntoIter<FlatTree> {
    match tree {
        Tree::Leaf(value) => vec![FlatTree::Leaf(value)].into_iter(),
        Tree::Node(key, children) => {
            let mut result = vec![FlatTree::Node(key, children.len())];
            for child in children.into_iter().map(flatten_tree) {
                for node in child {
                    result.push(node);
                }
            }
            result.into_iter()
        }
    }
}

impl Tree {
    fn new<T: std::io::Read>(body: T) -> Result<Tree, Error> {
        try!(parse_tree(&mut xml::EventReader::new(body))).ok_or(Error::UnsupportedDataFormat)
    }
}

fn parse_tree<T: std::io::Read>(reader: &mut xml::EventReader<T>) -> Result<Option<Tree>, Error> {
    match try!(next_node(reader)) {
        Node::Close(..) => Ok(None),
        Node::Data(value) => Ok(Some(Tree::Leaf(value))),
        Node::Open(name) => {
            Ok(Some(Tree::Node(name, {
                let mut children = Vec::<Tree>::new();
                while let Some(node) = try!(parse_tree(reader)) {
                    children.push(node);
                }
                children
            })))
        }
    }
}

fn next_node<T: std::io::Read>(reader: &mut xml::EventReader<T>) -> Result<Node, Error> {
    match try!(reader.next()) {
        xml::reader::XmlEvent::StartElement { name, .. } => Ok(Node::Open(name.local_name)),
        xml::reader::XmlEvent::Characters(value) => Ok(Node::Data(value)),
        xml::reader::XmlEvent::EndElement { name } => Ok(Node::Close(name.local_name)),
        _ => next_node(reader),
    }
}

#[derive(Debug)]
pub enum Error {
    XmlRead(xml::reader::Error),
    UnsupportedDataFormat,
    Decoding(String),
    ParseInt(std::num::ParseIntError),
    ParseFloat(std::num::ParseFloatError),
}

impl From<xml::reader::Error> for Error {
    fn from(err: xml::reader::Error) -> Error {
        Error::XmlRead(err)
    }
}

impl From<std::num::ParseIntError> for Error {
    fn from(err: std::num::ParseIntError) -> Error {
        Error::ParseInt(err)
    }
}

impl From<std::num::ParseFloatError> for Error {
    fn from(err: std::num::ParseFloatError) -> Error {
        Error::ParseFloat(err)
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::XmlRead(ref err) => write!(f, "XML reading error: {}", err),
            Error::UnsupportedDataFormat => write!(f, "Unencodable data provided"),
            Error::Decoding(ref err) => write!(f, "Internal error while decoding: {}", err),
            Error::ParseInt(ref err) => write!(f, "Int parsing error: {}", err),
            Error::ParseFloat(ref err) => write!(f, "Float parsing error: {}", err),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::XmlRead(ref err) => err.description(),
            Error::UnsupportedDataFormat => "Unencodable data provided",
            Error::Decoding(..) => "Internal error while decoding",
            Error::ParseInt(ref err) => err.description(),
            Error::ParseFloat(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::XmlRead(ref err) => Some(err),
            Error::UnsupportedDataFormat => None,
            Error::Decoding(..) => None,
            Error::ParseInt(ref err) => Some(err),
            Error::ParseFloat(ref err) => Some(err),
        }
    }
}
<commit_msg>Fix handling of empty strings<commit_after>extern crate xml;
extern crate rustc_serialize;

use std;

pub struct Decoder {
    tree: std::vec::IntoIter<FlatTree>,
}

impl Decoder {
    pub fn new<T: std::io::Read>(body: T) -> Decoder {
        Decoder { tree: Tree::new(body).map(flatten_tree).unwrap_or(vec![].into_iter()) }
    }

    fn peel_named_layer(&mut self, name: &str) -> Result<(), Error> {
        if let Some(FlatTree::Node(key, length)) = self.tree.next() {
            if key == name && length == 1 {
                return Ok(());
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn peel_layer(&mut self) -> Result<(String, usize), Error> {
        if let Some(FlatTree::Node(key, length)) = self.tree.next() {
            if key == "value" && length == 1 {
                if let Some(FlatTree::Node(key, length)) = self.tree.next() {
                    return Ok((key, length));
                }
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    pub fn peel_response_body(&mut self) -> Result<(), Error> {
        try!(self.peel_named_layer("methodResponse"));
        try!(self.peel_named_layer("params"));
        try!(self.peel_named_layer("param"));
        Ok(())
    }
}

impl rustc_serialize::Decoder for Decoder {
    type Error = Error;

    fn read_nil(&mut self) -> Result<(), Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_usize(&mut self) -> Result<usize, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_u64(&mut self) -> Result<u64, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_u32(&mut self) -> Result<u32, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_u16(&mut self) -> Result<u16, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_u8(&mut self) -> Result<u8, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_isize(&mut self) -> Result<isize, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_i64(&mut self) -> Result<i64, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_i32(&mut self) -> Result<i32, Self::Error> {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && (key == "i4" || key == "int") {
            if let Some(FlatTree::Leaf(value)) = self.tree.next() {
                return Ok(try!(value.parse::<i32>()));
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_i16(&mut self) -> Result<i16, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_i8(&mut self) -> Result<i8, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_bool(&mut self) -> Result<bool, Self::Error> {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && key == "boolean" {
            if let Some(FlatTree::Leaf(value)) = self.tree.next() {
                return Ok(try!(value.parse::<i32>()) != 0);
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_f64(&mut self) -> Result<f64, Self::Error> {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && key == "double" {
            if let Some(FlatTree::Leaf(value)) = self.tree.next() {
                return Ok(try!(value.parse::<f64>()));
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_f32(&mut self) -> Result<f32, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_char(&mut self) -> Result<char, Self::Error> {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_str(&mut self) -> Result<String, Self::Error> {
        let (key, length) = try!(self.peel_layer());
        if key == "string" {
            if length == 1 {
                if let Some(FlatTree::Leaf(value)) = self.tree.next() {
                    return Ok(value);
                }
            } else if length == 0 {
                return Ok("".to_owned());
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_enum<T, F>(&mut self, _: &str, _: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_enum_variant<T, F>(&mut self, _: &[&str], _: F) -> Result<T, Self::Error>
        where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_enum_variant_arg<T, F>(&mut self, _: usize, _: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_enum_struct_variant<T, F>(&mut self, _: &[&str], _: F) -> Result<T, Self::Error>
        where F: FnMut(&mut Self, usize) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_enum_struct_variant_field<T, F>(&mut self,
                                            _: &str,
                                            _: usize,
                                            _: F)
                                            -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_struct<T, F>(&mut self, _: &str, size: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        self.read_tuple(size, f)
    }

    fn read_struct_field<T, F>(&mut self, _: &str, _: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        f(self)
    }

    fn read_tuple<T, F>(&mut self, _: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && key == "array" {
            if let Some(FlatTree::Node(key, _)) = self.tree.next() {
                if key == "data" {
                    return f(self);
                }
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_tuple_arg<T, F>(&mut self, _: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        f(self)
    }

    fn read_tuple_struct<T, F>(&mut self, _: &str, size: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        self.read_tuple(size, f)
    }

    fn read_tuple_struct_arg<T, F>(&mut self, _: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        f(self)
    }

    fn read_option<T, F>(&mut self, _: F) -> Result<T, Self::Error>
        where F: FnMut(&mut Self, bool) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_seq<T, F>(&mut self, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error>
    {
        let (key, length) = try!(self.peel_layer());
        if length == 1 && key == "array" {
            if let Some(FlatTree::Node(key, length)) = self.tree.next() {
                if key == "data" {
                    return f(self, length);
                }
            }
        }
        Err(Error::UnsupportedDataFormat)
    }

    fn read_seq_elt<T, F>(&mut self, _: usize, f: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        f(self)
    }

    fn read_map<T, F>(&mut self, _: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self, usize) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_map_elt_key<T, F>(&mut self, _: usize, _: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn read_map_elt_val<T, F>(&mut self, _: usize, _: F) -> Result<T, Self::Error>
        where F: FnOnce(&mut Self) -> Result<T, Self::Error>
    {
        Err(Error::UnsupportedDataFormat)
    }

    fn error(&mut self, err: &str) -> Self::Error {
        Error::Decoding(err.to_owned())
    }
}

enum Node {
    Open(String),
    Data(String),
    Close(String),
}

enum Tree {
    Leaf(String),
    Node(String, Vec<Tree>),
}

enum FlatTree {
    Leaf(String),
    Node(String, usize),
}

fn flatten_tree(tree: Tree) -> std::vec::IntoIter<FlatTree> {
    match tree {
        Tree::Leaf(value) => vec![FlatTree::Leaf(value)].into_iter(),
        Tree::Node(key, children) => {
            let mut result = vec![FlatTree::Node(key, children.len())];
            for child in children.into_iter().map(flatten_tree) {
                for node in child {
                    result.push(node);
                }
            }
            result.into_iter()
        }
    }
}

impl Tree {
    fn new<T: std::io::Read>(body: T) -> Result<Tree, Error> {
        try!(parse_tree(&mut xml::EventReader::new(body))).ok_or(Error::UnsupportedDataFormat)
    }
}

fn parse_tree<T: std::io::Read>(reader: &mut xml::EventReader<T>) -> Result<Option<Tree>, Error> {
    match try!(next_node(reader)) {
        Node::Close(..) => Ok(None),
        Node::Data(value) => Ok(Some(Tree::Leaf(value))),
        Node::Open(name) => {
            Ok(Some(Tree::Node(name, {
                let mut children = Vec::<Tree>::new();
                while let Some(node) = try!(parse_tree(reader)) {
                    children.push(node);
                }
                children
            })))
        }
    }
}

fn next_node<T: std::io::Read>(reader: &mut xml::EventReader<T>) -> Result<Node, Error> {
    match try!(reader.next()) {
        xml::reader::XmlEvent::StartElement { name, .. } => Ok(Node::Open(name.local_name)),
        xml::reader::XmlEvent::Characters(value) => Ok(Node::Data(value)),
        xml::reader::XmlEvent::EndElement { name } => Ok(Node::Close(name.local_name)),
        _ => next_node(reader),
    }
}

#[derive(Debug)]
pub enum Error {
    XmlRead(xml::reader::Error),
    UnsupportedDataFormat,
    Decoding(String),
    ParseInt(std::num::ParseIntError),
    ParseFloat(std::num::ParseFloatError),
}

impl From<xml::reader::Error> for Error {
    fn from(err: xml::reader::Error) -> Error {
        Error::XmlRead(err)
    }
}

impl From<std::num::ParseIntError> for Error {
    fn from(err: std::num::ParseIntError) -> Error {
        Error::ParseInt(err)
    }
}

impl From<std::num::ParseFloatError> for Error {
    fn from(err: std::num::ParseFloatError) -> Error {
        Error::ParseFloat(err)
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::XmlRead(ref err) => write!(f, "XML reading error: {}", err),
            Error::UnsupportedDataFormat => write!(f, "Unencodable data provided"),
            Error::Decoding(ref err) => write!(f, "Internal error while decoding: {}", err),
            Error::ParseInt(ref err) => write!(f, "Int parsing error: {}", err),
            Error::ParseFloat(ref err) => write!(f, "Float parsing error: {}", err),
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::XmlRead(ref err) => err.description(),
            Error::UnsupportedDataFormat => "Unencodable data provided",
            Error::Decoding(..) => "Internal error while decoding",
            Error::ParseInt(ref err) => err.description(),
            Error::ParseFloat(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::XmlRead(ref err) => Some(err),
            Error::UnsupportedDataFormat => None,
            Error::Decoding(..) => None,
            Error::ParseInt(ref err) => Some(err),
            Error::ParseFloat(ref err) => Some(err),
        }
    }
}
<|endoftext|>