<commit_before>// Copyright 2015 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.

// Format list-like macro invocations. These are invocations whose token trees
// can be interpreted as expressions and separated by commas.
// Note that these token trees do not actually have to be interpreted as
// expressions by the compiler. An example of an invocation we would reformat is
// foo!( x, y, z ). The token x may represent an identifier in the code, but we
// interpreted as an expression.
// Macro uses which are not-list like, such as bar!(key => val), will not be
// reformated.
// List-like invocations with parentheses will be formatted as function calls,
// and those with brackets will be formatted as array literals.

use std::thread;

use syntax::ast;
use syntax::parse::token::{Eof, Comma, Token};
use syntax::parse::{ParseSess, tts_to_parser};

use Indent;
use rewrite::RewriteContext;
use expr::{rewrite_call, rewrite_array};
use comment::FindUncommented;
use utils::wrap_str;

// We need to pass `TokenTree`s to our expression parsing thread, but they are
// not `Send`. We wrap them in a `Send` container to force our will.
// FIXME: this is a pretty terrible hack. Any other solution would be preferred.
struct ForceSend<T>(pub T);
unsafe impl<T> Send for ForceSend<T> {}

// FIXME: use the enum from libsyntax?
enum MacroStyle {
    Parens,
    Brackets,
    Braces,
}

pub fn rewrite_macro(mac: &ast::Mac,
                     context: &RewriteContext,
                     width: usize,
                     offset: Indent)
                     -> Option<String> {
    let style = macro_style(mac, context);
    let macro_name = format!("{}!", mac.node.path);

    if let MacroStyle::Braces = style {
        return None;
    } else if mac.node.tts.is_empty() {
        return if let MacroStyle::Parens = style {
            Some(format!("{}()", macro_name))
        } else {
            Some(format!("{}[]", macro_name))
        };
    }

    let wrapped_tt_vec = ForceSend(mac.node.tts.clone());
    // Wrap expression parsing logic in a thread since the libsyntax parser
    // panicks on failure, which we do not want to propagate.
    let expr_vec_result = thread::catch_panic(move || {
        let parse_session = ParseSess::new();
        let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]);
        let mut expr_vec = vec![];

        loop {
            expr_vec.push(parser.parse_expr());

            match parser.token {
                Token::Eof => break,
                Token::Comma => (),
                _ => panic!("Macro not list-like, skiping..."),
            }

            let _ = parser.bump();
        }

        expr_vec
    });
    let expr_vec = try_opt!(expr_vec_result.ok());

    match style {
        MacroStyle::Parens => {
            // Format macro invocation as function call.
            rewrite_call(context, &macro_name, &expr_vec, mac.span, width, offset)
        }
        MacroStyle::Brackets => {
            // Format macro invocation as array literal.
            let extra_offset = macro_name.len();
            let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x),
                                                 mac.span,
                                                 context,
                                                 try_opt!(width.checked_sub(extra_offset)),
                                                 offset + extra_offset));
            Some(format!("{}{}", macro_name, rewrite))
        }
        MacroStyle::Braces => {
            // Skip macro invocations with braces, for now.
            wrap_str(context.snippet(mac.span),
                     context.config.max_width,
                     width,
                     offset)
        }
    }
}

fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle {
    let snippet = context.snippet(mac.span);
    let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value());
    let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value());
    let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value());

    if paren_pos < bracket_pos && paren_pos < brace_pos {
        MacroStyle::Parens
    } else if bracket_pos < brace_pos {
        MacroStyle::Brackets
    } else {
        MacroStyle::Braces
    }
}
<commit_msg>Prevent panics on list-like macro uses with trailing commas<commit_after>// Copyright 2015 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.

// Format list-like macro invocations. These are invocations whose token trees
// can be interpreted as expressions and separated by commas.
// Note that these token trees do not actually have to be interpreted as
// expressions by the compiler. An example of an invocation we would reformat is
// foo!( x, y, z ). The token x may represent an identifier in the code, but we
// interpreted as an expression.
// Macro uses which are not-list like, such as bar!(key => val), will not be
// reformated.
// List-like invocations with parentheses will be formatted as function calls,
// and those with brackets will be formatted as array literals.

use std::thread;

use syntax::ast;
use syntax::parse::token::{Eof, Comma, Token};
use syntax::parse::{ParseSess, tts_to_parser};

use Indent;
use rewrite::RewriteContext;
use expr::{rewrite_call, rewrite_array};
use comment::FindUncommented;
use utils::wrap_str;

// We need to pass `TokenTree`s to our expression parsing thread, but they are
// not `Send`. We wrap them in a `Send` container to force our will.
// FIXME: this is a pretty terrible hack. Any other solution would be preferred.
struct ForceSend<T>(pub T);
unsafe impl<T> Send for ForceSend<T> {}

// FIXME: use the enum from libsyntax?
enum MacroStyle {
    Parens,
    Brackets,
    Braces,
}

pub fn rewrite_macro(mac: &ast::Mac,
                     context: &RewriteContext,
                     width: usize,
                     offset: Indent)
                     -> Option<String> {
    let style = macro_style(mac, context);
    let macro_name = format!("{}!", mac.node.path);

    if let MacroStyle::Braces = style {
        return None;
    } else if mac.node.tts.is_empty() {
        return if let MacroStyle::Parens = style {
            Some(format!("{}()", macro_name))
        } else {
            Some(format!("{}[]", macro_name))
        };
    }

    let wrapped_tt_vec = ForceSend(mac.node.tts.clone());
    // Wrap expression parsing logic in a thread since the libsyntax parser
    // panics on failure, which we do not want to propagate.
    // The expression vector is wrapped in an Option inside a Result.
    let expr_vec_result = thread::catch_panic(move || {
        let parse_session = ParseSess::new();
        let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]);
        let mut expr_vec = vec![];

        loop {
            expr_vec.push(parser.parse_expr());

            match parser.token {
                Token::Eof => break,
                Token::Comma => (),
                _ => panic!("Macro not list-like, skiping..."),
            }

            let _ = parser.bump();

            if parser.token == Token::Eof {
                return None;
            }
        }

        Some(expr_vec)
    });
    let expr_vec = try_opt!(try_opt!(expr_vec_result.ok()));

    match style {
        MacroStyle::Parens => {
            // Format macro invocation as function call.
            rewrite_call(context, &macro_name, &expr_vec, mac.span, width, offset)
        }
        MacroStyle::Brackets => {
            // Format macro invocation as array literal.
            let extra_offset = macro_name.len();
            let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x),
                                                 mac.span,
                                                 context,
                                                 try_opt!(width.checked_sub(extra_offset)),
                                                 offset + extra_offset));
            Some(format!("{}{}", macro_name, rewrite))
        }
        MacroStyle::Braces => {
            // Skip macro invocations with braces, for now.
            wrap_str(context.snippet(mac.span),
                     context.config.max_width,
                     width,
                     offset)
        }
    }
}

fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle {
    let snippet = context.snippet(mac.span);
    let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value());
    let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value());
    let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value());

    if paren_pos < bracket_pos && paren_pos < brace_pos {
        MacroStyle::Parens
    } else if bracket_pos < brace_pos {
        MacroStyle::Brackets
    } else {
        MacroStyle::Braces
    }
}
<|endoftext|>


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

/// Connect events to sending a message.
///
/// ## Rules
/// 1. Send `$msg` to `$other_component` when the GTK+ `$event` is emitted on `$widget`.
///
/// 2. Optionally send `$msg.0` when the GTK+ `$event` is emitted on `$widget`.
/// Return `$msg.1` in the GTK+ callback.
/// This variant gives more control to the caller since it expects a `$msg` returning `(Option<MSG>,
/// ReturnValue)` where the `ReturnValue` is the value to return in the GTK+ callback.
/// Option<MSG> can be None if no message needs to be emitted.
///
/// 3. Send `$msg` when the GTK+ `$event` is emitted on `$widget`.
///
/// 4. Send `$msg` to `$widget` when the `$message` is received on `$stream`.
#[macro_export]
macro_rules! connect {
    // Connect to a GTK+ widget event, sending a message to another widget.
    ($widget:expr, $event:ident($($args:pat),*), $other_component:expr, $msg:expr) => {
        connect_stream!($widget, $event($($args),*), $other_component.stream(), $msg);
    };

    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), return $msg:expr) => {{
        connect_stream!(return $relm.stream(), $widget, $event($($args),*), $msg);
    }};

    // Connect to a GTK+ widget event.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
        let stream = $relm.stream().clone();
        let _ = $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    }};

    // Connect to a message reception.
    // TODO: create another macro rule accepting multiple patterns.
    ($src_component:ident @ $message:pat, $dst_component:expr, $msg:expr) => {
        let stream = $src_component.stream().clone();
        connect_stream!(stream@$message, $dst_component.stream(), $msg);
    };
}

/// Connect events to sending a message.
/// Similar to `connect!` but wants a stream instead of a component.
///
/// ## Rules
/// 1. Send `$msg` to `$other_stream` when the GTK+ `$event` is emitted on `$widget`.
///
/// 2. Send `$msg` to `$widget` when the `$message` is received on `$stream`.
#[macro_export]
macro_rules! connect_stream {
    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    (return $stream:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
        let stream = $stream.clone();
        let _ = $widget.$event(move |$($args),*| {
            let (msg, return_value) = $crate::IntoPair::into_pair($msg);
            let msg: Option<_> = $crate::IntoOption::into_option(msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
            return_value
        });
    }};

    // Connect to a GTK+ widget event, sending a message to another widget.
    ($widget:expr, $event:ident($($args:pat),*), $other_stream:expr, $msg:expr) => {
        let stream = $other_stream.clone();
        let _ = $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    };

    // Connect to a message reception.
    // TODO: create another macro rule accepting multiple patterns.
    ($src_stream:ident @ $message:pat, $dst_stream:expr, $msg:expr) => {
        let stream = $dst_stream.clone();
        $src_stream.observe(move |msg| {
            #[allow(unreachable_patterns)]
            match msg {
                &$message =>  {
                    let msg: Option<_> = $crate::IntoOption::into_option($msg);
                    if let Some(msg) = msg {
                        stream.emit(msg);
                    }
                },
                _ => (),
            }
        });
    };
}

/// Connect an asynchronous method call to send a message.
/// The variants with `$fail_msg` will send this message when there's an error.
/// Those without this argument will ignore the error.
#[macro_export]
macro_rules! connect_async {
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr) => {
        connect_async!($object, $async_method(), $relm, $msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let stream = $relm.stream().clone();
        $object.$async_method($($args,)* None, move |result| {
            if let Ok(result) = result {
                stream.emit($msg(result));
            }
        });
    }};
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async!($object, $async_method(), $relm, $msg, $fail_msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        $object.$async_method($($args,)* None, move |result| {
            match result {
                Ok(value) => event_stream.emit($msg(value)),
                Err(error) => fail_event_stream.emit($fail_msg(error)),
            }
        });
    }};
}

/// Connect an asynchronous function call to send a message.
/// The variants with `$fail_msg` will send this message when there's an error.
/// Those without this argument will ignore the error.
#[macro_export]
macro_rules! connect_async_func {
    ($class:ident :: $async_function:ident, $relm:expr, $msg:expr) => {
        connect_async_func!($class::$async_func(), $relm, $msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let stream = $relm.stream().clone();
        $class::$async_func($($args,)* None, move |result| {
            if let Ok(result) = result {
                stream.emit($msg(result));
            }
        });
    }};
    ($class:ident :: $async_func:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async_func!($class::$async_func(), $relm, $msg, $fail_msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        $class::$async_func($($args,)* None, move |result| {
            match result {
                Ok(value) => event_stream.emit($msg(value)),
                Err(error) => fail_event_stream.emit($fail_msg(error)),
            }
        });

    }};
}

/// Like `connect_async!`, but also return a `Cancellable` to control the asynchronous request.
#[macro_export]
macro_rules! connect_async_full {
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr) => {
        connect_async_full!($object, $async_method(), $relm, $msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let stream = $relm.stream().clone();
        $object.$async_method($($args,)* Some(&cancellable), move |result| {
            if let Ok(result) = result {
                stream.emit($msg(result));
            }
        });
        cancellable
    }};
    ($object:expr, $async_method:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async_full!($object, $async_method(), $relm, $msg, $fail_msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        $object.$async_method($($args,)* Some(&cancellable), move |result| {
            match result {
                Ok(value) => event_stream.emit($msg(value)),
                Err(error) => fail_event_stream.emit($fail_msg(error)),
            }
        });

        cancellable
    }};
}

/// Like `connect_async_func!`, but also return a `Cancellable` to control the asynchronous request.
#[macro_export]
macro_rules! connect_async_func_full {
    ($class:ident :: $async_function:ident, $relm:expr, $msg:expr) => {
        connect_async!($async_func(), $relm, $msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let stream = $relm.stream().clone();
        $class::$async_func($($args,)* Some(&cancellable), move |result| {
            if let Ok(result) = result {
                stream.emit($msg(result));
            }
        });
        cancellable
    }};
    ($class:ident :: $async_func:ident, $relm:expr, $msg:expr, $fail_msg:expr) => {
        connect_async!($async_func(), $relm, $msg, $fail_msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:expr, $fail_msg:expr) => {{
        let cancellable = ::gio::Cancellable::new();
        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        $class::$async_func($($args,)* Some(&cancellable), move |result| {
            match result {
                Ok(value) => event_stream.emit($msg(value)),
                Err(error) => fail_event_stream.emit($fail_msg(error)),
            }
        });

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

include!("../relm-state/src/macros.rs");
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

use super::values::*;
use std::rc::*;

pub use super::treenode_index::*;
pub use super::treenode_builder::*;

///
/// Reference to a tree node
///
pub type TreeRef = Rc<TreeNode>;

///
/// The treenode trait is implemented by types that can act as part of a tree
///
pub trait TreeNode {
    ///
    /// Retrieves a reference to the child of this tree node (or None if this node has no child)
    ///
    fn get_child_ref(&self) -> Option<TreeRef>;

    ///
    /// Retrieves a reference to the sibling of this tree node (or None if this node has no sibling)
    ///
    fn get_sibling_ref(&self) -> Option<TreeRef>;

    ///
    /// Retrieves the tag attached to this tree node
    ///
    fn get_tag(&self) -> &str;

    ///
    /// Retrieves the value attached to this node
    ///
    fn get_value(&self) -> &TreeValue;

    ///
    /// Creates a copy of this node with different references
    ///
    fn with_references(&self, new_child: Option<&TreeRef>, new_sibling: Option<&TreeRef>) -> TreeRef;

    ///
    /// Creates a copy of this node with a specific child node
    ///
    fn with_child_node(&self, new_child: Option<&TreeRef>) -> TreeRef {
        self.with_references(new_child, self.get_sibling_ref().as_ref())
    }

    ///
    /// Creates a copy of this node with a specific sibling node
    ///
    fn with_sibling_node(&self, new_sibling: Option<&TreeRef>) -> TreeRef {
        self.with_references(self.get_child_ref().as_ref(), new_sibling)
    }

    ///
    /// Creates a copy of this node with a specific set of child nodes
    ///
    fn with_children(&self, new_children: &Vec<TreeRef>) -> TreeRef {
        let mut new_child = None;

        for sibling in new_children.into_iter().rev() {
            new_child = Some(sibling.with_sibling_node(new_child.as_ref()));
        }

        self.with_child_node(new_child.as_ref())
    }

    ///
    /// Looks up the child at the specified index
    ///
    fn lookup_child_at_index(&self, index: usize) -> Option<TreeRef> {
        let mut result = self.get_child_ref();

        for _ in 0..index {
            result = result.and_then(|x| { x.get_sibling_ref() });
        }

        result
    }

    ///
    /// Looks up the child at the specified index
    ///
    fn lookup_child_with_tag(&self, tag: &str) -> Option<TreeRef> {
        let mut current = self.get_child_ref();

        loop {
            match current {
                None        => { return None; },
                Some(node) => {
                    if node.get_tag() == tag {
                        return Some(node);
                    } else {
                        current = node.get_sibling_ref();
                    }
                }
            }
        }
    }
}

///
/// This trait is implemented by types that can be converted into a tree node.
///
pub trait ToTreeNode {
    ///
    /// Converts this value into a tree node
    ///
    fn to_tree_node(&self) -> TreeRef;
}

impl<T> ToTreeNode for Rc<T> where T: TreeNode, T: 'static {
    ///
    /// Converts this value into a tree node
    ///
    #[inline]
    fn to_tree_node(&self) -> TreeRef {
        self.clone()
    }
}

impl ToTreeNode for TreeRef {
    ///
    /// Converts this value into a tree node
    ///
    #[inline]
    fn to_tree_node(&self) -> TreeRef {
        self.clone()
    }
}

impl<'a, T> ToTreeNode for &'a Rc<T> where T: TreeNode, T: 'static {
    ///
    /// Converts this value into a tree node
    ///
    #[inline]
    fn to_tree_node(&self) -> TreeRef {
        (*self).clone()
    }
}

impl<'a> ToTreeNode for &'a TreeRef {
    ///
    /// Converts this value into a tree node
    ///
    #[inline]
    fn to_tree_node(&self) -> TreeRef {
        (*self).clone()
    }
}

impl TreeNode for TreeRef {
    ///
    /// Retrieves a reference to the child of this tree node (or None if this node has no child)
    ///
    fn get_child_ref(&self) -> Option<TreeRef> {
        (**self).get_child_ref()
    }

    ///
    /// Retrieves a reference to the sibling of this tree node (or None if this node has no sibling)
    ///
    fn get_sibling_ref(&self) -> Option<TreeRef> {
        (**self).get_sibling_ref()
    }

    ///
    /// Retrieves the tag attached to this tree node
    ///
    fn get_tag(&self) -> &str {
        (**self).get_tag()
    }

    ///
    /// Retrieves the value attached to this node
    ///
    fn get_value(&self) -> &TreeValue {
        (**self).get_value()
    }

    ///
    /// Creates a copy of this node with different references
    ///
    fn with_references(&self, new_child: Option<&TreeRef>, new_sibling: Option<&TreeRef>) -> TreeRef {
        (**self).with_references(new_child, new_sibling)
    }

    ///
    /// Creates a copy of this node with a specific child node
    ///
    fn with_child_node(&self, new_child: Option<&TreeRef>) -> TreeRef {
        (**self).with_child_node(new_child)
    }

    ///
    /// Creates a copy of this node with a specific sibling node
    ///
    fn with_sibling_node(&self, new_sibling: Option<&TreeRef>) -> TreeRef {
        (**self).with_sibling_node(new_sibling)
    }

    ///
    /// Creates a copy of this node with a specific set of child nodes
    ///
    fn with_children(&self, new_children: &Vec<TreeRef>) -> TreeRef {
        (**self).with_children(new_children)
    }

    ///
    /// Looks up the child at the specified index
    ///
    fn lookup_child_at_index(&self, index: usize) -> Option<TreeRef> {
        (**self).lookup_child_at_index(index)
    }

    ///
    /// Looks up the child at the specified index
    ///
    fn lookup_child_with_tag(&self, tag: &str) -> Option<TreeRef> {
        (**self).lookup_child_with_tag(tag)
    }
}
<commit_msg>All these methods should probably be marked as inline<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

use super::values::*;
use std::rc::*;

pub use super::treenode_index::*;
pub use super::treenode_builder::*;

///
/// Reference to a tree node
///
pub type TreeRef = Rc<TreeNode>;

///
/// The treenode trait is implemented by types that can act as part of a tree
///
pub trait TreeNode {
    ///
    /// Retrieves a reference to the child of this tree node (or None if this node has no child)
    ///
    fn get_child_ref(&self) -> Option<TreeRef>;

    ///
    /// Retrieves a reference to the sibling of this tree node (or None if this node has no sibling)
    ///
    fn get_sibling_ref(&self) -> Option<TreeRef>;

    ///
    /// Retrieves the tag attached to this tree node
    ///
    fn get_tag(&self) -> &str;

    ///
    /// Retrieves the value attached to this node
    ///
    fn get_value(&self) -> &TreeValue;

    ///
    /// Creates a copy of this node with different references
    ///
    fn with_references(&self, new_child: Option<&TreeRef>, new_sibling: Option<&TreeRef>) -> TreeRef;

    ///
    /// Creates a copy of this node with a specific child node
    ///
    #[inline]
    fn with_child_node(&self, new_child: Option<&TreeRef>) -> TreeRef {
        self.with_references(new_child, self.get_sibling_ref().as_ref())
    }

    ///
    /// Creates a copy of this node with a specific sibling node
    ///
    #[inline]
    fn with_sibling_node(&self, new_sibling: Option<&TreeRef>) -> TreeRef {
        self.with_references(self.get_child_ref().as_ref(), new_sibling)
    }

    ///
    /// Creates a copy of this node with a specific set of child nodes
    ///
    fn with_children(&self, new_children: &Vec<TreeRef>) -> TreeRef {
        let mut new_child = None;

        for sibling in new_children.into_iter().rev() {
            new_child = Some(sibling.with_sibling_node(new_child.as_ref()));
        }

        self.with_child_node(new_child.as_ref())
    }

    ///
    /// Looks up the child at the specified index
    ///
    fn lookup_child_at_index(&self, index: usize) -> Option<TreeRef> {
        let mut result = self.get_child_ref();

        for _ in 0..index {
            result = result.and_then(|x| { x.get_sibling_ref() });
        }

        result
    }

    ///
    /// Looks up the child at the specified index
    ///
    fn lookup_child_with_tag(&self, tag: &str) -> Option<TreeRef> {
        let mut current = self.get_child_ref();

        loop {
            match current {
                None        => { return None; },
                Some(node) => {
                    if node.get_tag() == tag {
                        return Some(node);
                    } else {
                        current = node.get_sibling_ref();
                    }
                }
            }
        }
    }
}

///
/// This trait is implemented by types that can be converted into a tree node.
///
pub trait ToTreeNode {
    ///
    /// Converts this value into a tree node
    ///
    fn to_tree_node(&self) -> TreeRef;
}

impl<T> ToTreeNode for Rc<T> where T: TreeNode, T: 'static {
    ///
    /// Converts this value into a tree node
    ///
    #[inline]
    fn to_tree_node(&self) -> TreeRef {
        self.clone()
    }
}

impl ToTreeNode for TreeRef {
    ///
    /// Converts this value into a tree node
    ///
    #[inline]
    fn to_tree_node(&self) -> TreeRef {
        self.clone()
    }
}

impl<'a, T> ToTreeNode for &'a Rc<T> where T: TreeNode, T: 'static {
    ///
    /// Converts this value into a tree node
    ///
    #[inline]
    fn to_tree_node(&self) -> TreeRef {
        (*self).clone()
    }
}

impl<'a> ToTreeNode for &'a TreeRef {
    ///
    /// Converts this value into a tree node
    ///
    #[inline]
    fn to_tree_node(&self) -> TreeRef {
        (*self).clone()
    }
}

impl TreeNode for TreeRef {
    ///
    /// Retrieves a reference to the child of this tree node (or None if this node has no child)
    ///
    #[inline]
    fn get_child_ref(&self) -> Option<TreeRef> {
        (**self).get_child_ref()
    }

    ///
    /// Retrieves a reference to the sibling of this tree node (or None if this node has no sibling)
    ///
    #[inline]
    fn get_sibling_ref(&self) -> Option<TreeRef> {
        (**self).get_sibling_ref()
    }

    ///
    /// Retrieves the tag attached to this tree node
    ///
    #[inline]
    fn get_tag(&self) -> &str {
        (**self).get_tag()
    }

    ///
    /// Retrieves the value attached to this node
    ///
    #[inline]
    fn get_value(&self) -> &TreeValue {
        (**self).get_value()
    }

    ///
    /// Creates a copy of this node with different references
    ///
    #[inline]
    fn with_references(&self, new_child: Option<&TreeRef>, new_sibling: Option<&TreeRef>) -> TreeRef {
        (**self).with_references(new_child, new_sibling)
    }

    ///
    /// Creates a copy of this node with a specific child node
    ///
    #[inline]
    fn with_child_node(&self, new_child: Option<&TreeRef>) -> TreeRef {
        (**self).with_child_node(new_child)
    }

    ///
    /// Creates a copy of this node with a specific sibling node
    ///
    #[inline]
    fn with_sibling_node(&self, new_sibling: Option<&TreeRef>) -> TreeRef {
        (**self).with_sibling_node(new_sibling)
    }

    ///
    /// Creates a copy of this node with a specific set of child nodes
    ///
    #[inline]
    fn with_children(&self, new_children: &Vec<TreeRef>) -> TreeRef {
        (**self).with_children(new_children)
    }

    ///
    /// Looks up the child at the specified index
    ///
    #[inline]
    fn lookup_child_at_index(&self, index: usize) -> Option<TreeRef> {
        (**self).lookup_child_at_index(index)
    }

    ///
    /// Looks up the child at the specified index
    ///
    #[inline]
    fn lookup_child_with_tag(&self, tag: &str) -> Option<TreeRef> {
        (**self).lookup_child_with_tag(tag)
    }
}
<|endoftext|>


<commit_before>use std::error::{self, Error};
use std::fmt;

use cairo;
use cssparser::BasicParseError;
use glib;
use markup5ever::QualName;

use crate::allowed_url::Fragment;
use crate::node::RsvgNode;
use crate::parsers::ParseError;

/// A simple error which refers to an attribute's value
#[derive(Debug, Clone, PartialEq)]
pub enum ValueErrorKind {
    /// A property with the specified name was not found
    UnknownProperty,

    /// The value could not be parsed
    Parse(ParseError),

    // The value could be parsed, but is invalid
    Value(String),
}

/// A complete error for an attribute and its erroneous value
#[derive(Debug, Clone, PartialEq)]
pub struct NodeError {
    pub attr: QualName,
    pub err: ValueErrorKind,
}

impl NodeError {
    pub fn parse_error(attr: QualName, error: ParseError) -> NodeError {
        NodeError {
            attr,
            err: ValueErrorKind::Parse(error),
        }
    }

    pub fn value_error(attr: QualName, description: &str) -> NodeError {
        NodeError {
            attr,
            err: ValueErrorKind::Value(description.to_string()),
        }
    }

    pub fn attribute_error(attr: QualName, error: ValueErrorKind) -> NodeError {
        NodeError { attr, err: error }
    }
}

impl error::Error for NodeError {
    fn description(&self) -> &str {
        match self.err {
            ValueErrorKind::UnknownProperty => "unknown property",
            ValueErrorKind::Parse(_) => "parse error",
            ValueErrorKind::Value(_) => "invalid attribute value",
        }
    }
}

impl fmt::Display for NodeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.err {
            ValueErrorKind::UnknownProperty => write!(f, "unknown property name"),

            ValueErrorKind::Parse(ref n) => write!(
                f,
                "error parsing value for attribute \"{}\": {}",
                self.attr.local.to_string(),
                n.display
            ),

            ValueErrorKind::Value(ref s) => write!(
                f,
                "invalid value for attribute \"{}\": {}",
                self.attr.local.to_string(),
                s
            ),
        }
    }
}

impl From<ParseError> for ValueErrorKind {
    fn from(pe: ParseError) -> ValueErrorKind {
        ValueErrorKind::Parse(pe)
    }
}

impl<'a> From<BasicParseError<'a>> for ValueErrorKind {
    fn from(e: BasicParseError<'_>) -> ValueErrorKind {
        ValueErrorKind::from(ParseError::from(e))
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum DefsLookupErrorKind {
    HrefError(HrefError),
    CannotLookupExternalReferences,
    NotFound,
}

#[derive(Debug, Clone, PartialEq)]
pub enum RenderingError {
    Cairo(cairo::Status),
    CircularReference,
    InstancingLimit,
    InvalidId(DefsLookupErrorKind),
    InvalidHref,
    OutOfMemory,
    HandleIsNotLoaded,
}

impl From<cairo::Status> for RenderingError {
    fn from(e: cairo::Status) -> RenderingError {
        assert!(e != cairo::Status::Success);

        RenderingError::Cairo(e)
    }
}

pub enum AcquireError {
    LinkNotFound(Fragment),
    InvalidLinkType(Fragment),
    CircularReference(RsvgNode),
    MaxReferencesExceeded,
}

impl fmt::Display for AcquireError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            AcquireError::LinkNotFound(ref frag) =>
                write!(f, "link not found: {}", frag),

            AcquireError::InvalidLinkType(ref frag) =>
                write!(f, "link {} is to object of invalid type", frag),

            AcquireError::CircularReference(ref node) =>
                write!(f, "circular reference in node {}", node),

            AcquireError::MaxReferencesExceeded =>
                write!(f, "maximum number of references exceeded"),
        }
    }
}

/// Helper for converting `Result<O, E>` into `Result<O, NodeError>`
///
/// A `NodeError` requires a `QualName` that corresponds to the attribute to which the
/// error refers, plus the actual `ValueErrorKind` that describes the error.  However,
/// parsing functions for attribute value types will want to return their own kind of
/// error, instead of `ValueErrorKind`.  If that particular error type has an `impl
/// From<FooError> for ValueErrorKind`, then this trait helps assign attribute values in
/// `set_atts()` methods as follows:
///
/// ```ignore
/// use error::AttributeResultExt;
///
/// // fn parse_foo(...) -> Result<Foo, FooError>
///
/// // It is assumed that there is an impl From<FooError> for ValueErrorKind
///
/// self.foo = parse_foo(value).attribute(local_name!("foo"))?;
/// ```
///
/// The call to `.attribute(attr)` converts the `Result` from `parse_foo()` into a full
/// `NodeError` with the provided `attr`.
pub trait AttributeResultExt<O, E> {
    fn attribute(self, attr: QualName) -> Result<O, NodeError>;
}

impl<O, E: Into<ValueErrorKind>> AttributeResultExt<O, E> for Result<O, E> {
    fn attribute(self, attr: QualName) -> Result<O, NodeError> {
        self.map_err(|e| e.into())
            .map_err(|e| NodeError::attribute_error(attr, e))
    }
}

/// Errors returned when creating an `Href` out of a string
#[derive(Debug, Clone, PartialEq)]
pub enum HrefError {
    /// The href is an invalid URI or has empty components.
    ParseError,

    /// A fragment identifier ("`#foo`") is not allowed here
    ///
    /// For example, the SVG `<image>` element only allows referencing
    /// resources without fragment identifiers like
    /// `xlink:href="foo.png"`.
    FragmentForbidden,

    /// A fragment identifier ("`#foo`") was required but not found.  For example,
    /// the SVG `<use>` element requires one, as in `<use xlink:href="foo.svg#bar">`.
    FragmentRequired,
}

impl From<HrefError> for ValueErrorKind {
    fn from(e: HrefError) -> ValueErrorKind {
        match e {
            HrefError::ParseError => ValueErrorKind::Parse(ParseError::new("url parse error")),
            HrefError::FragmentForbidden => {
                ValueErrorKind::Value("fragment identifier not allowed".to_string())
            }
            HrefError::FragmentRequired => {
                ValueErrorKind::Value("fragment identifier required".to_string())
            }
        }
    }
}

#[derive(Debug, Clone)]
pub enum LoadingError {
    NoDataPassedToParser,
    XmlParseError(String),
    // Could not parse data: URL
    CouldNotCreateXmlParser,
    BadUrl,
    BadDataUrl,
    BadStylesheet,
    BadCss,
    Cairo(cairo::Status),
    EmptyData,
    SvgHasNoElements,
    RootElementIsNotSvg,
    Glib(glib::Error),
    Unknown,
}

impl error::Error for LoadingError {
    fn description(&self) -> &str {
        match *self {
            LoadingError::NoDataPassedToParser => "no data passed to parser",
            LoadingError::CouldNotCreateXmlParser => "could not create XML parser",
            LoadingError::XmlParseError(_) => "XML parse error",
            LoadingError::BadUrl => "invalid URL",
            LoadingError::BadDataUrl => "invalid data: URL",
            LoadingError::BadStylesheet => "invalid stylesheet",
            LoadingError::BadCss => "invalid CSS",
            LoadingError::Cairo(_) => "cairo error",
            LoadingError::EmptyData => "empty data",
            LoadingError::SvgHasNoElements => "SVG has no elements",
            LoadingError::RootElementIsNotSvg => "root element is not <svg>",
            LoadingError::Glib(ref e) => e.description(),
            LoadingError::Unknown => "unknown error",
        }
    }
}

impl fmt::Display for LoadingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            LoadingError::Cairo(status) => write!(f, "cairo error: {:?}", status),
            LoadingError::XmlParseError(ref s) => write!(f, "XML parse error: {}", s),
            LoadingError::NoDataPassedToParser
            | LoadingError::CouldNotCreateXmlParser
            | LoadingError::BadUrl
            | LoadingError::BadDataUrl
            | LoadingError::BadStylesheet
            | LoadingError::BadCss
            | LoadingError::EmptyData
            | LoadingError::SvgHasNoElements
            | LoadingError::RootElementIsNotSvg
            | LoadingError::Glib(_)
            | LoadingError::Unknown => write!(f, "{}", self.description()),
        }
    }
}

impl error::Error for RenderingError {
    fn description(&self) -> &str {
        match *self {
            RenderingError::Cairo(_) => "cairo error",
            RenderingError::CircularReference => "circular reference",
            RenderingError::InstancingLimit => "instancing limit",
            RenderingError::InvalidId(_) => "invalid id",
            RenderingError::InvalidHref => "invalid href",
            RenderingError::OutOfMemory => "out of memory",
            RenderingError::HandleIsNotLoaded => "SVG data is not loaded into handle",
        }
    }
}

impl fmt::Display for RenderingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            RenderingError::Cairo(ref status) => write!(f, "cairo error: {:?}", status),
            RenderingError::InvalidId(ref id) => write!(f, "invalid id: {:?}", id),
            RenderingError::CircularReference
            | RenderingError::InstancingLimit
            | RenderingError::InvalidHref
            | RenderingError::OutOfMemory
            | RenderingError::HandleIsNotLoaded => write!(f, "{}", self.description()),
        }
    }
}

impl From<cairo::Status> for LoadingError {
    fn from(e: cairo::Status) -> LoadingError {
        assert!(e != cairo::Status::Success);

        LoadingError::Cairo(e)
    }
}

impl From<glib::Error> for LoadingError {
    fn from(e: glib::Error) -> LoadingError {
        LoadingError::Glib(e)
    }
}

#[cfg(test)]
pub fn is_parse_error<T>(r: &Result<T, ValueErrorKind>) -> bool {
    match *r {
        Err(ValueErrorKind::Parse(_)) => true,
        _ => false,
    }
}

#[cfg(test)]
pub fn is_value_error<T>(r: &Result<T, ValueErrorKind>) -> bool {
    match *r {
        Err(ValueErrorKind::Value(_)) => true,
        _ => false,
    }
}
<commit_msg>Make fmt::Display for NodeError less verbose<commit_after>use std::error::{self, Error};
use std::fmt;

use cairo;
use cssparser::BasicParseError;
use glib;
use markup5ever::QualName;

use crate::allowed_url::Fragment;
use crate::node::RsvgNode;
use crate::parsers::ParseError;

/// A simple error which refers to an attribute's value
#[derive(Debug, Clone, PartialEq)]
pub enum ValueErrorKind {
    /// A property with the specified name was not found
    UnknownProperty,

    /// The value could not be parsed
    Parse(ParseError),

    // The value could be parsed, but is invalid
    Value(String),
}

/// A complete error for an attribute and its erroneous value
#[derive(Debug, Clone, PartialEq)]
pub struct NodeError {
    pub attr: QualName,
    pub err: ValueErrorKind,
}

impl NodeError {
    pub fn parse_error(attr: QualName, error: ParseError) -> NodeError {
        NodeError {
            attr,
            err: ValueErrorKind::Parse(error),
        }
    }

    pub fn value_error(attr: QualName, description: &str) -> NodeError {
        NodeError {
            attr,
            err: ValueErrorKind::Value(description.to_string()),
        }
    }

    pub fn attribute_error(attr: QualName, error: ValueErrorKind) -> NodeError {
        NodeError { attr, err: error }
    }
}

impl error::Error for NodeError {
    fn description(&self) -> &str {
        match self.err {
            ValueErrorKind::UnknownProperty => "unknown property",
            ValueErrorKind::Parse(_) => "parse error",
            ValueErrorKind::Value(_) => "invalid attribute value",
        }
    }
}

impl fmt::Display for NodeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.err {
            ValueErrorKind::UnknownProperty => write!(f, "unknown property name"),

            ValueErrorKind::Parse(ref n) => write!(
                f,
                "parse error: {}",
                n.display
            ),

            ValueErrorKind::Value(ref s) => write!(
                f,
                "invalid value: {}",
                s
            ),
        }
    }
}

impl From<ParseError> for ValueErrorKind {
    fn from(pe: ParseError) -> ValueErrorKind {
        ValueErrorKind::Parse(pe)
    }
}

impl<'a> From<BasicParseError<'a>> for ValueErrorKind {
    fn from(e: BasicParseError<'_>) -> ValueErrorKind {
        ValueErrorKind::from(ParseError::from(e))
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum DefsLookupErrorKind {
    HrefError(HrefError),
    CannotLookupExternalReferences,
    NotFound,
}

#[derive(Debug, Clone, PartialEq)]
pub enum RenderingError {
    Cairo(cairo::Status),
    CircularReference,
    InstancingLimit,
    InvalidId(DefsLookupErrorKind),
    InvalidHref,
    OutOfMemory,
    HandleIsNotLoaded,
}

impl From<cairo::Status> for RenderingError {
    fn from(e: cairo::Status) -> RenderingError {
        assert!(e != cairo::Status::Success);

        RenderingError::Cairo(e)
    }
}

pub enum AcquireError {
    LinkNotFound(Fragment),
    InvalidLinkType(Fragment),
    CircularReference(RsvgNode),
    MaxReferencesExceeded,
}

impl fmt::Display for AcquireError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            AcquireError::LinkNotFound(ref frag) =>
                write!(f, "link not found: {}", frag),

            AcquireError::InvalidLinkType(ref frag) =>
                write!(f, "link {} is to object of invalid type", frag),

            AcquireError::CircularReference(ref node) =>
                write!(f, "circular reference in node {}", node),

            AcquireError::MaxReferencesExceeded =>
                write!(f, "maximum number of references exceeded"),
        }
    }
}

/// Helper for converting `Result<O, E>` into `Result<O, NodeError>`
///
/// A `NodeError` requires a `QualName` that corresponds to the attribute to which the
/// error refers, plus the actual `ValueErrorKind` that describes the error.  However,
/// parsing functions for attribute value types will want to return their own kind of
/// error, instead of `ValueErrorKind`.  If that particular error type has an `impl
/// From<FooError> for ValueErrorKind`, then this trait helps assign attribute values in
/// `set_atts()` methods as follows:
///
/// ```ignore
/// use error::AttributeResultExt;
///
/// // fn parse_foo(...) -> Result<Foo, FooError>
///
/// // It is assumed that there is an impl From<FooError> for ValueErrorKind
///
/// self.foo = parse_foo(value).attribute(local_name!("foo"))?;
/// ```
///
/// The call to `.attribute(attr)` converts the `Result` from `parse_foo()` into a full
/// `NodeError` with the provided `attr`.
pub trait AttributeResultExt<O, E> {
    fn attribute(self, attr: QualName) -> Result<O, NodeError>;
}

impl<O, E: Into<ValueErrorKind>> AttributeResultExt<O, E> for Result<O, E> {
    fn attribute(self, attr: QualName) -> Result<O, NodeError> {
        self.map_err(|e| e.into())
            .map_err(|e| NodeError::attribute_error(attr, e))
    }
}

/// Errors returned when creating an `Href` out of a string
#[derive(Debug, Clone, PartialEq)]
pub enum HrefError {
    /// The href is an invalid URI or has empty components.
    ParseError,

    /// A fragment identifier ("`#foo`") is not allowed here
    ///
    /// For example, the SVG `<image>` element only allows referencing
    /// resources without fragment identifiers like
    /// `xlink:href="foo.png"`.
    FragmentForbidden,

    /// A fragment identifier ("`#foo`") was required but not found.  For example,
    /// the SVG `<use>` element requires one, as in `<use xlink:href="foo.svg#bar">`.
    FragmentRequired,
}

impl From<HrefError> for ValueErrorKind {
    fn from(e: HrefError) -> ValueErrorKind {
        match e {
            HrefError::ParseError => ValueErrorKind::Parse(ParseError::new("url parse error")),
            HrefError::FragmentForbidden => {
                ValueErrorKind::Value("fragment identifier not allowed".to_string())
            }
            HrefError::FragmentRequired => {
                ValueErrorKind::Value("fragment identifier required".to_string())
            }
        }
    }
}

#[derive(Debug, Clone)]
pub enum LoadingError {
    NoDataPassedToParser,
    XmlParseError(String),
    // Could not parse data: URL
    CouldNotCreateXmlParser,
    BadUrl,
    BadDataUrl,
    BadStylesheet,
    BadCss,
    Cairo(cairo::Status),
    EmptyData,
    SvgHasNoElements,
    RootElementIsNotSvg,
    Glib(glib::Error),
    Unknown,
}

impl error::Error for LoadingError {
    fn description(&self) -> &str {
        match *self {
            LoadingError::NoDataPassedToParser => "no data passed to parser",
            LoadingError::CouldNotCreateXmlParser => "could not create XML parser",
            LoadingError::XmlParseError(_) => "XML parse error",
            LoadingError::BadUrl => "invalid URL",
            LoadingError::BadDataUrl => "invalid data: URL",
            LoadingError::BadStylesheet => "invalid stylesheet",
            LoadingError::BadCss => "invalid CSS",
            LoadingError::Cairo(_) => "cairo error",
            LoadingError::EmptyData => "empty data",
            LoadingError::SvgHasNoElements => "SVG has no elements",
            LoadingError::RootElementIsNotSvg => "root element is not <svg>",
            LoadingError::Glib(ref e) => e.description(),
            LoadingError::Unknown => "unknown error",
        }
    }
}

impl fmt::Display for LoadingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            LoadingError::Cairo(status) => write!(f, "cairo error: {:?}", status),
            LoadingError::XmlParseError(ref s) => write!(f, "XML parse error: {}", s),
            LoadingError::NoDataPassedToParser
            | LoadingError::CouldNotCreateXmlParser
            | LoadingError::BadUrl
            | LoadingError::BadDataUrl
            | LoadingError::BadStylesheet
            | LoadingError::BadCss
            | LoadingError::EmptyData
            | LoadingError::SvgHasNoElements
            | LoadingError::RootElementIsNotSvg
            | LoadingError::Glib(_)
            | LoadingError::Unknown => write!(f, "{}", self.description()),
        }
    }
}

impl error::Error for RenderingError {
    fn description(&self) -> &str {
        match *self {
            RenderingError::Cairo(_) => "cairo error",
            RenderingError::CircularReference => "circular reference",
            RenderingError::InstancingLimit => "instancing limit",
            RenderingError::InvalidId(_) => "invalid id",
            RenderingError::InvalidHref => "invalid href",
            RenderingError::OutOfMemory => "out of memory",
            RenderingError::HandleIsNotLoaded => "SVG data is not loaded into handle",
        }
    }
}

impl fmt::Display for RenderingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            RenderingError::Cairo(ref status) => write!(f, "cairo error: {:?}", status),
            RenderingError::InvalidId(ref id) => write!(f, "invalid id: {:?}", id),
            RenderingError::CircularReference
            | RenderingError::InstancingLimit
            | RenderingError::InvalidHref
            | RenderingError::OutOfMemory
            | RenderingError::HandleIsNotLoaded => write!(f, "{}", self.description()),
        }
    }
}

impl From<cairo::Status> for LoadingError {
    fn from(e: cairo::Status) -> LoadingError {
        assert!(e != cairo::Status::Success);

        LoadingError::Cairo(e)
    }
}

impl From<glib::Error> for LoadingError {
    fn from(e: glib::Error) -> LoadingError {
        LoadingError::Glib(e)
    }
}

#[cfg(test)]
pub fn is_parse_error<T>(r: &Result<T, ValueErrorKind>) -> bool {
    match *r {
        Err(ValueErrorKind::Parse(_)) => true,
        _ => false,
    }
}

#[cfg(test)]
pub fn is_value_error<T>(r: &Result<T, ValueErrorKind>) -> bool {
    match *r {
        Err(ValueErrorKind::Value(_)) => true,
        _ => false,
    }
}
<|endoftext|>


<commit_before>//! Crate **ruma_identifiers** contains types for [Matrix](https://matrix.org/) identifiers
//! for events, rooms, room aliases, room versions, and users.

#![warn(
    rust_2018_idioms,
    missing_copy_implementations,
    missing_debug_implementations,
    missing_docs
)]
// Since we support Rust 1.36.0, we can't apply this suggestion yet
#![allow(clippy::use_self)]
#![cfg_attr(docsrs, feature(doc_cfg))]

use std::{convert::TryFrom, num::NonZeroU8};

#[cfg(feature = "serde")]
use serde::de::{self, Deserialize as _, Deserializer, Unexpected};

#[doc(inline)]
pub use crate::{
    device_id::DeviceId,
    device_key_id::DeviceKeyId,
    error::Error,
    event_id::EventId,
    key_algorithms::{DeviceKeyAlgorithm, ServerKeyAlgorithm},
    room_alias_id::RoomAliasId,
    room_id::RoomId,
    room_id_or_room_alias_id::RoomIdOrAliasId,
    room_version_id::RoomVersionId,
    server_key_id::ServerKeyId,
    server_name::ServerName,
    user_id::UserId,
};

#[macro_use]
mod macros;

pub mod device_id;
pub mod user_id;

mod device_key_id;
mod error;
mod event_id;
mod key_algorithms;
mod room_alias_id;
mod room_id;
mod room_id_or_room_alias_id;
mod room_version_id;
mod server_key_id;
mod server_name;

/// Check whether a given string is a valid server name according to [the specification][].
///
/// [the specification]: https://matrix.org/docs/spec/appendices#server-name
#[deprecated = "Use the [`ServerName`](server_name/struct.ServerName.html) type instead."]
pub fn is_valid_server_name(name: &str) -> bool {
    <&ServerName>::try_from(name).is_ok()
}

/// All identifiers must be 255 bytes or less.
const MAX_BYTES: usize = 255;
/// The minimum number of characters an ID can be.
///
/// This is an optimization and not required by the spec. The shortest possible valid ID is a sigil
/// + a single character local ID + a colon + a single character hostname.
const MIN_CHARS: usize = 4;

/// Generates a random identifier localpart.
#[cfg(feature = "rand")]
fn generate_localpart(length: usize) -> Box<str> {
    use rand::Rng as _;
    rand::thread_rng()
        .sample_iter(&rand::distributions::Alphanumeric)
        .take(length)
        .collect::<String>()
        .into_boxed_str()
}

/// Checks if an identifier is valid.
fn validate_id(id: &str, valid_sigils: &[char]) -> Result<(), Error> {
    if id.len() > MAX_BYTES {
        return Err(Error::MaximumLengthExceeded);
    }

    if id.len() < MIN_CHARS {
        return Err(Error::MinimumLengthNotSatisfied);
    }

    if !valid_sigils.contains(&id.chars().next().unwrap()) {
        return Err(Error::MissingSigil);
    }

    Ok(())
}

/// Checks an identifier that contains a localpart and hostname for validity,
/// and returns the index of the colon that separates the two.
fn parse_id(id: &str, valid_sigils: &[char]) -> Result<NonZeroU8, Error> {
    validate_id(id, valid_sigils)?;

    let colon_idx = id.find(':').ok_or(Error::MissingDelimiter)?;
    if colon_idx < 2 {
        return Err(Error::InvalidLocalPart);
    }

    server_name::validate(&id[colon_idx + 1..])?;

    Ok(NonZeroU8::new(colon_idx as u8).unwrap())
}

/// Deserializes any type of id using the provided TryFrom implementation.
///
/// This is a helper function to reduce the boilerplate of the Deserialize implementations.
#[cfg(feature = "serde")]
fn deserialize_id<'de, D, T>(deserializer: D, expected_str: &str) -> Result<T, D::Error>
where
    D: Deserializer<'de>,
    T: for<'a> std::convert::TryFrom<&'a str>,
{
    std::borrow::Cow::<'_, str>::deserialize(deserializer).and_then(|v| {
        T::try_from(&v).map_err(|_| de::Error::invalid_value(Unexpected::Str(&v), &expected_str))
    })
}
<commit_msg>identifiers: Remove outdated allow attribute<commit_after>//! Crate **ruma_identifiers** contains types for [Matrix](https://matrix.org/) identifiers
//! for events, rooms, room aliases, room versions, and users.

#![warn(
    rust_2018_idioms,
    missing_copy_implementations,
    missing_debug_implementations,
    missing_docs
)]
#![cfg_attr(docsrs, feature(doc_cfg))]

use std::{convert::TryFrom, num::NonZeroU8};

#[cfg(feature = "serde")]
use serde::de::{self, Deserialize as _, Deserializer, Unexpected};

#[doc(inline)]
pub use crate::{
    device_id::DeviceId,
    device_key_id::DeviceKeyId,
    error::Error,
    event_id::EventId,
    key_algorithms::{DeviceKeyAlgorithm, ServerKeyAlgorithm},
    room_alias_id::RoomAliasId,
    room_id::RoomId,
    room_id_or_room_alias_id::RoomIdOrAliasId,
    room_version_id::RoomVersionId,
    server_key_id::ServerKeyId,
    server_name::ServerName,
    user_id::UserId,
};

#[macro_use]
mod macros;

pub mod device_id;
pub mod user_id;

mod device_key_id;
mod error;
mod event_id;
mod key_algorithms;
mod room_alias_id;
mod room_id;
mod room_id_or_room_alias_id;
mod room_version_id;
mod server_key_id;
mod server_name;

/// Check whether a given string is a valid server name according to [the specification][].
///
/// [the specification]: https://matrix.org/docs/spec/appendices#server-name
#[deprecated = "Use the [`ServerName`](server_name/struct.ServerName.html) type instead."]
pub fn is_valid_server_name(name: &str) -> bool {
    <&ServerName>::try_from(name).is_ok()
}

/// All identifiers must be 255 bytes or less.
const MAX_BYTES: usize = 255;
/// The minimum number of characters an ID can be.
///
/// This is an optimization and not required by the spec. The shortest possible valid ID is a sigil
/// + a single character local ID + a colon + a single character hostname.
const MIN_CHARS: usize = 4;

/// Generates a random identifier localpart.
#[cfg(feature = "rand")]
fn generate_localpart(length: usize) -> Box<str> {
    use rand::Rng as _;
    rand::thread_rng()
        .sample_iter(&rand::distributions::Alphanumeric)
        .take(length)
        .collect::<String>()
        .into_boxed_str()
}

/// Checks if an identifier is valid.
fn validate_id(id: &str, valid_sigils: &[char]) -> Result<(), Error> {
    if id.len() > MAX_BYTES {
        return Err(Error::MaximumLengthExceeded);
    }

    if id.len() < MIN_CHARS {
        return Err(Error::MinimumLengthNotSatisfied);
    }

    if !valid_sigils.contains(&id.chars().next().unwrap()) {
        return Err(Error::MissingSigil);
    }

    Ok(())
}

/// Checks an identifier that contains a localpart and hostname for validity,
/// and returns the index of the colon that separates the two.
fn parse_id(id: &str, valid_sigils: &[char]) -> Result<NonZeroU8, Error> {
    validate_id(id, valid_sigils)?;

    let colon_idx = id.find(':').ok_or(Error::MissingDelimiter)?;
    if colon_idx < 2 {
        return Err(Error::InvalidLocalPart);
    }

    server_name::validate(&id[colon_idx + 1..])?;

    Ok(NonZeroU8::new(colon_idx as u8).unwrap())
}

/// Deserializes any type of id using the provided TryFrom implementation.
///
/// This is a helper function to reduce the boilerplate of the Deserialize implementations.
#[cfg(feature = "serde")]
fn deserialize_id<'de, D, T>(deserializer: D, expected_str: &str) -> Result<T, D::Error>
where
    D: Deserializer<'de>,
    T: for<'a> std::convert::TryFrom<&'a str>,
{
    std::borrow::Cow::<'_, str>::deserialize(deserializer).and_then(|v| {
        T::try_from(&v).map_err(|_| de::Error::invalid_value(Unexpected::Str(&v), &expected_str))
    })
}
<|endoftext|>


<commit_before>use num::bigint::{ToBigUint, RandBigInt, BigUint};
use num::{Zero, One};
use num::integer::Integer;
use rand::thread_rng;
use std::sync::{Arc, mpsc};
use std::thread;

/// Cryptographically useful extensions to the provided BigUint functionality.
pub trait BigUintCrypto {
    /// Find the next prime from the current BigUint
    fn next_prime(&self) -> BigUint;

    /// Threaded version of the next_prime() operation, this is not recommended for use because it
    /// is slower than the unthreaded version.
    fn next_prime_threaded(&self) -> BigUint;
    /// use the extended euclidean algorithm to solve for (g,x,y) given (a,b) such that
    /// g = gcd(a,b) = a*x + b*y.
    fn gcdext(&self, other: &BigUint) -> (BigUint, BigUint, BigUint);

    /// Is this number a prime number. Uses a probablistic function to determine primality.
    fn is_prime(n: &BigUint) -> bool;

    /// perform the function (base^exponent) % modulus using exponentiation by sqauring
    fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint;
}

impl BigUintCrypto for BigUint {
    fn next_prime(&self) -> BigUint {
        next_prime_helper(&self.clone(), false)
    }

    fn next_prime_threaded(&self) -> BigUint {
        next_prime_helper(&self.clone(), true)
    }

    fn gcdext(&self, other: &BigUint) -> (BigUint, BigUint, BigUint) {

        (Zero::zero(), Zero::zero(), Zero::zero())
    }

    fn is_prime(n: &BigUint) -> bool {
        is_prime_helper(n, false)
    }

    fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint {
        let zero = Zero::zero();
        let one: BigUint = One::one();
        let two = &one + &one;
        let mut result: BigUint = One::one();
        let mut base_acc = base.clone();
        let mut exp_acc = exponent.clone();
        while exp_acc > zero {
            if (&exp_acc % &two) == one {
                result = (result * &base_acc) % modulus;
            }
            exp_acc = exp_acc >> 1;
            base_acc = (&base_acc * &base_acc) % modulus;
        }
        result
    }
}

fn next_prime_helper(n: &BigUint, thread: bool) -> BigUint {
    let one: BigUint = One::one();
    let two = 2.to_biguint().unwrap();
    let mut next_prime = n.clone();
    if &next_prime % &two == Zero::zero() {
        next_prime = &next_prime + &one;
    } else {
        next_prime = &next_prime + &two;
    }
    while !is_prime_helper(&next_prime, thread) {
        next_prime = &next_prime + &two;
    }
    next_prime
}

fn is_prime_helper(n: &BigUint, thread: bool) -> bool {
    let two = 2.to_biguint().unwrap();
    let three = 3.to_biguint().unwrap();
    if *n == three || *n == two {
        return true;
    }
    if *n < two || n % two == Zero::zero() {
        return false;
    }
    miller_rabin(n, 100, thread)
}
/// n must be greater than 3 and k indicates the number of rounds
fn miller_rabin(n: &BigUint, k: usize, thread: bool) -> bool{
    let one: BigUint = One::one();
    let (tx, rx) = mpsc::channel();

    let mut d: BigUint = n - &One::one();
    let mut s: BigUint = Zero::zero();
    while d.is_even() {
        d = d >> 1;
        s = s + &one;
    }
    if thread {
        let shared_n = Arc::new(n.clone());
        let shared_d = Arc::new(d);
        let shared_s = Arc::new(s);

        // miller rabin lends itself to being concurrent since a is completely random
        // here we spawn multiple threads to help speed up the process
        for _ in 0..8 {
            let tx = tx.clone();
            //let thread_n = n.clone();
            let shared_d = shared_d.clone();
            let shared_s = shared_s.clone();
            let shared_n = shared_n.clone();
            thread::spawn(move || {
                let in_n = shared_n;
                let in_d = shared_d;
                let in_s = shared_s;
                let result = miller_rabin_thread(&in_n, &in_d, &in_s, k/8);
                tx.send(result);
                });
        }

        let mut prime = true;
        for _ in 0..8 {
            if !rx.recv().ok().expect("A thread failed") {
                prime = false;
            }
        }
        prime
    } else {
        return miller_rabin_thread(n, &d, &s, k);
    }
}

fn miller_rabin_thread(n: &BigUint, d: &BigUint, s: &BigUint, k: usize) -> bool {
    let one: BigUint = One::one();
    let two: BigUint = &one + &one;

    for _ in 0..k {
        //println!("loop {} of {}", j, k);
        let a = thread_rng().gen_biguint_range(&two, &(n - &two));
        let mut x = mod_exp(&a, d, n);
        //let mut x = two.clone();
        if (x == one) || (x == (n - &one)) {
            continue;
        }

        // Use a while loop instead of for here because range does not accept BigUint
        let mut i: BigUint = Zero::zero();
        loop  {
            x = mod_exp(&x, &two, n);
            if x == one || i == (s - &one) {
                return false;
            }
            if x == (n - &one) {
                break;
            }
            i = i + &one;
        }
    }
    true
}

fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint {
    let zero = Zero::zero();
    let one: BigUint = One::one();
    let two = &one + &one;
    let mut result: BigUint = One::one();
    let mut base_acc = base.clone();
    let mut exp_acc = exponent.clone();
    while exp_acc > zero {
        if (&exp_acc % &two) == one {
            result = (result * &base_acc) % modulus;
        }
        exp_acc = exp_acc >> 1;
        base_acc = (&base_acc * &base_acc) % modulus;
    }
    result
}

#[cfg(test)]
mod test_BigUint_crypto {
    use super::{BigUintCrypto, mod_exp, miller_rabin};
    use num::bigint::{RandBigInt, BigUint};
    use std::num::FromPrimitive;
    use num::One;
    use rand::thread_rng;
    use test::Bencher;
    use std::sync::{Arc, mpsc};
    use std::thread;

    #[test]
    fn next_prime_test() {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        let expected_next = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(test_num.next_prime() == expected_next);
    }

    #[test]
    fn next_prime_threaded_test() {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        let expected_next = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(test_num.next_prime_threaded() == expected_next);
    }

    #[test]
    fn mod_exp_test() {
        let base = BigUint::from_isize(4).unwrap();
        let exponent = BigUint::from_isize(13).unwrap();
        let modulus = BigUint::from_isize(497).unwrap();
        let expected_result = BigUint::from_isize(445).unwrap();

        assert!(mod_exp(&base, &exponent, &modulus) == expected_result);
    }

    #[test]
    fn is_prime_test() {
        let known_prime = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(BigUint::is_prime(&known_prime));
    }

    #[test]
    #[should_panic(expected = "assertion failed")]
    fn is_prime_test_failuire() {
        let not_prime = BigUint::
        parse_bytes("359709793871987301975987296195681798740165298740176567105918720469720137416098423"
        .as_bytes(), 10).unwrap();

        assert!(BigUint::is_prime(&not_prime));
    }

    #[bench]
    fn bench_spawn_thread_move(bench: &mut Bencher) {

        bench.iter(|| {
            let a = thread_rng().gen_biguint(300);
            let b = thread_rng().gen_biguint(300);
            let c = thread_rng().gen_biguint(300);
            let shared_a = Arc::new(a);
            let shared_b = Arc::new(b);
            let shared_c = Arc::new(c);

            thread::spawn(move || {
                let in_a = shared_a;
                let in_b = shared_b;
                let in_c = shared_c;
                });
            });
    }

    #[bench]
    fn bench_rand_biguint(bench: &mut Bencher) {
        bench.iter(|| {
            thread_rng().gen_biguint(300)
            });
    }

    #[bench]
    fn bench_spawn_thread(bench: &mut Bencher) {
        bench.iter(|| {
            thread::spawn(|| {
                let a = 4;
                });
            });
    }

    #[bench]
    fn bench_mod_exp(bench: &mut Bencher) {
        let a = thread_rng().gen_biguint(300);
        let b = thread_rng().gen_biguint(300);
        let c = thread_rng().gen_biguint(300);
        bench.iter(|| {
            mod_exp(&a, &b, &c);
            });
    }

    #[bench]
    fn bench_miller_rabin(bench: &mut Bencher) {
        let known_prime = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();
        bench.iter(|| {
            miller_rabin(&known_prime, 100, false)
            });
    }

    #[bench]
    fn bench_miller_rabin_thread(bench: &mut Bencher) {
        let known_prime = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();
        bench.iter(|| {
            miller_rabin(&known_prime, 100, true)
            });
    }

    #[bench]
    fn bench_next_prime(bench: &mut Bencher) {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        bench.iter(|| {
            test_num.next_prime()
            });
    }

    #[bench]
    fn bench_next_prime_threaded(bench: &mut Bencher) {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        bench.iter(|| {
            test_num.next_prime_threaded()
            });
    }

}
<commit_msg>Actually update to latest rust.<commit_after>use num::bigint::{ToBigUint, RandBigInt, BigUint};
use num::{Zero, One};
use num::integer::Integer;
use rand::thread_rng;
use std::sync::{Arc, mpsc};
use std::thread;

/// Cryptographically useful extensions to the provided BigUint functionality.
pub trait BigUintCrypto {
    /// Find the next prime from the current BigUint
    fn next_prime(&self) -> BigUint;

    /// Threaded version of the next_prime() operation, this is not recommended for use because it
    /// is slower than the unthreaded version.
    fn next_prime_threaded(&self) -> BigUint;
    /// use the extended euclidean algorithm to solve for (g,x,y) given (a,b) such that
    /// g = gcd(a,b) = a*x + b*y.
    fn gcdext(&self, other: &BigUint) -> (BigUint, BigUint, BigUint);

    /// Is this number a prime number. Uses a probablistic function to determine primality.
    fn is_prime(n: &BigUint) -> bool;

    /// perform the function (base^exponent) % modulus using exponentiation by sqauring
    fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint;
}

impl BigUintCrypto for BigUint {
    fn next_prime(&self) -> BigUint {
        next_prime_helper(&self.clone(), false)
    }

    fn next_prime_threaded(&self) -> BigUint {
        next_prime_helper(&self.clone(), true)
    }

    fn gcdext(&self, other: &BigUint) -> (BigUint, BigUint, BigUint) {

        (Zero::zero(), Zero::zero(), Zero::zero())
    }

    fn is_prime(n: &BigUint) -> bool {
        is_prime_helper(n, false)
    }

    fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint {
        let zero = Zero::zero();
        let one: BigUint = One::one();
        let two = &one + &one;
        let mut result: BigUint = One::one();
        let mut base_acc = base.clone();
        let mut exp_acc = exponent.clone();
        while exp_acc > zero {
            if (&exp_acc % &two) == one {
                result = (result * &base_acc) % modulus;
            }
            exp_acc = exp_acc >> 1;
            base_acc = (&base_acc * &base_acc) % modulus;
        }
        result
    }
}

fn next_prime_helper(n: &BigUint, thread: bool) -> BigUint {
    let one: BigUint = One::one();
    let two = 2.to_biguint().unwrap();
    let mut next_prime = n.clone();
    if &next_prime % &two == Zero::zero() {
        next_prime = &next_prime + &one;
    } else {
        next_prime = &next_prime + &two;
    }
    while !is_prime_helper(&next_prime, thread) {
        next_prime = &next_prime + &two;
    }
    next_prime
}

fn is_prime_helper(n: &BigUint, thread: bool) -> bool {
    let two = 2.to_biguint().unwrap();
    let three = 3.to_biguint().unwrap();
    if *n == three || *n == two {
        return true;
    }
    if *n < two || n % two == Zero::zero() {
        return false;
    }
    miller_rabin(n, 100, thread)
}
/// n must be greater than 3 and k indicates the number of rounds
fn miller_rabin(n: &BigUint, k: usize, thread: bool) -> bool{
    let one: BigUint = One::one();
    let (tx, rx) = mpsc::channel();

    let mut d: BigUint = n - &One::one();
    let mut s: BigUint = Zero::zero();
    while d.is_even() {
        d = d >> 1;
        s = s + &one;
    }
    if thread {
        let shared_n = Arc::new(n.clone());
        let shared_d = Arc::new(d);
        let shared_s = Arc::new(s);

        // miller rabin lends itself to being concurrent since a is completely random
        // here we spawn multiple threads to help speed up the process
        for _ in 0..8 {
            let tx = tx.clone();
            //let thread_n = n.clone();
            let shared_d = shared_d.clone();
            let shared_s = shared_s.clone();
            let shared_n = shared_n.clone();
            thread::spawn(move || {
                let in_n = shared_n;
                let in_d = shared_d;
                let in_s = shared_s;
                let result = miller_rabin_thread(&in_n, &in_d, &in_s, k/8);
                tx.send(result);
                });
        }

        let mut prime = true;
        for _ in 0..8 {
            if !rx.recv().ok().expect("A thread failed") {
                prime = false;
            }
        }
        prime
    } else {
        return miller_rabin_thread(n, &d, &s, k);
    }
}

fn miller_rabin_thread(n: &BigUint, d: &BigUint, s: &BigUint, k: usize) -> bool {
    let one: BigUint = One::one();
    let two: BigUint = &one + &one;

    for _ in 0..k {
        //println!("loop {} of {}", j, k);
        let a = thread_rng().gen_biguint_range(&two, &(n - &two));
        let mut x = mod_exp(&a, d, n);
        //let mut x = two.clone();
        if (x == one) || (x == (n - &one)) {
            continue;
        }

        // Use a while loop instead of for here because range does not accept BigUint
        let mut i: BigUint = Zero::zero();
        loop  {
            x = mod_exp(&x, &two, n);
            if x == one || i == (s - &one) {
                return false;
            }
            if x == (n - &one) {
                break;
            }
            i = i + &one;
        }
    }
    true
}

fn mod_exp(base: &BigUint, exponent: &BigUint, modulus: &BigUint) -> BigUint {
    let zero = Zero::zero();
    let one: BigUint = One::one();
    let two = &one + &one;
    let mut result: BigUint = One::one();
    let mut base_acc = base.clone();
    let mut exp_acc = exponent.clone();
    while exp_acc > zero {
        if (&exp_acc % &two) == one {
            result = (result * &base_acc) % modulus;
        }
        exp_acc = exp_acc >> 1;
        base_acc = (&base_acc * &base_acc) % modulus;
    }
    result
}

#[cfg(test)]
mod test_BigUint_crypto {
    use super::{BigUintCrypto, mod_exp, miller_rabin};
    use num::bigint::{ToBigUint, RandBigInt, BigUint};
    use num::One;
    use rand::thread_rng;
    use test::Bencher;
    use std::sync::{Arc, mpsc};
    use std::thread;

    #[test]
    fn next_prime_test() {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        let expected_next = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(test_num.next_prime() == expected_next);
    }

    #[test]
    fn next_prime_threaded_test() {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        let expected_next = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(test_num.next_prime_threaded() == expected_next);
    }

    #[test]
    fn mod_exp_test() {
        let base = 4.to_biguint().unwrap();
        let exponent = 13.to_biguint().unwrap();
        let modulus = 497.to_biguint().unwrap();
        let expected_result = 445.to_biguint().unwrap();

        assert!(mod_exp(&base, &exponent, &modulus) == expected_result);
    }

    #[test]
    fn is_prime_test() {
        let known_prime = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();

        assert!(BigUint::is_prime(&known_prime));
    }

    #[test]
    #[should_panic(expected = "assertion failed")]
    fn is_prime_test_failuire() {
        let not_prime = BigUint::
        parse_bytes("359709793871987301975987296195681798740165298740176567105918720469720137416098423"
        .as_bytes(), 10).unwrap();

        assert!(BigUint::is_prime(&not_prime));
    }

    #[bench]
    fn bench_spawn_thread_move(bench: &mut Bencher) {

        bench.iter(|| {
            let a = thread_rng().gen_biguint(300);
            let b = thread_rng().gen_biguint(300);
            let c = thread_rng().gen_biguint(300);
            let shared_a = Arc::new(a);
            let shared_b = Arc::new(b);
            let shared_c = Arc::new(c);

            thread::spawn(move || {
                let in_a = shared_a;
                let in_b = shared_b;
                let in_c = shared_c;
                });
            });
    }

    #[bench]
    fn bench_rand_biguint(bench: &mut Bencher) {
        bench.iter(|| {
            thread_rng().gen_biguint(300)
            });
    }

    #[bench]
    fn bench_spawn_thread(bench: &mut Bencher) {
        bench.iter(|| {
            thread::spawn(|| {
                let a = 4;
                });
            });
    }

    #[bench]
    fn bench_mod_exp(bench: &mut Bencher) {
        let a = thread_rng().gen_biguint(300);
        let b = thread_rng().gen_biguint(300);
        let c = thread_rng().gen_biguint(300);
        bench.iter(|| {
            mod_exp(&a, &b, &c);
            });
    }

    #[bench]
    fn bench_miller_rabin(bench: &mut Bencher) {
        let known_prime = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();
        bench.iter(|| {
            miller_rabin(&known_prime, 100, false)
            });
    }

    #[bench]
    fn bench_miller_rabin_thread(bench: &mut Bencher) {
        let known_prime = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875297".as_bytes(), 10).unwrap();
        bench.iter(|| {
            miller_rabin(&known_prime, 100, true)
            });
    }

    #[bench]
    fn bench_next_prime(bench: &mut Bencher) {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        bench.iter(|| {
            test_num.next_prime()
            });
    }

    #[bench]
    fn bench_next_prime_threaded(bench: &mut Bencher) {
        let test_num = BigUint::
        parse_bytes("4829837983753984028472098472089547098728675098723407520875258".as_bytes(), 10).unwrap();

        bench.iter(|| {
            test_num.next_prime_threaded()
            });
    }

}
<|endoftext|>


<commit_before>#![macro_use]

macro_rules! invalid_address {
    ($e:expr) => (panic!("Invalid NES Memory Address: {:X}", $e));
}

use cart::Cart;
use ppu::PPU;
use apu::APU;
use io::IO;
use std::rc::Rc;
use std::cell::RefCell;

pub trait MemSegment {
    fn read(&mut self, idx: u16) -> u8;
    fn read_w(&mut self, idx: u16) -> u16 {
        let low = self.read(idx) as u16;
        let high = self.read(idx + 1) as u16;
        (high << 8) | low
    }

    fn write(&mut self, idx: u16, val: u8);
    fn write_w(&mut self, idx: u16, val: u16) {
        let low = ((val & 0x00FF) >> 0) as u8;
        let high = ((val & 0xFF00) >> 8) as u8;
        self.write(idx, low);
        self.write(idx + 1, high);
    }
}

struct RAM {
    memory: Box<[u8]>,
}

impl RAM {
    fn new() -> RAM {
        RAM { memory: vec!(0u8; 0x0800).into_boxed_slice() }
    }
}

impl MemSegment for RAM {
    fn read(&mut self, idx: u16) -> u8 {
        self.memory[idx as usize % 0x800]
    }

    fn write(&mut self, idx: u16, val: u8) {
        self.memory[idx as usize % 0x800] = val;
    }
}

pub struct CpuMemory {
    ram: RAM,
    pub ppu: Rc<RefCell<PPU>>,
    apu: APU,
    io: IO,
    cart: Rc<RefCell<Cart>>,
}

impl CpuMemory {
    pub fn new(ppu: Rc<RefCell<PPU>>, apu: APU, io: IO, cart: Rc<RefCell<Cart>>) -> CpuMemory {
        CpuMemory {
            ram: RAM::new(),
            ppu: ppu,
            apu: apu,
            io: io,
            cart: cart,
        }
    }

    pub fn read_w_zero_page(&mut self, zp_idx: u8) -> u16 {
        let low = self.read(zp_idx as u16) as u16;
        let high = self.read(zp_idx.wrapping_add(1) as u16) as u16;
        (high << 8) | low
    }
    pub fn read_w_same_page(&mut self, idx: u16) -> u16 {
        let page = idx & 0xFF00;
        let page_idx = idx as u8;
        let low = self.read(page | page_idx as u16) as u16;
        let high = self.read(page | page_idx.wrapping_add(1) as u16) as u16;
        (high << 8) | low
    }
}

impl MemSegment for CpuMemory {
    fn read(&mut self, idx: u16) -> u8 {
        match idx {
            0x0000...0x1FFF => self.ram.read(idx),
            0x2000...0x3FFF => self.ppu.borrow_mut().read(idx),
            0x4000...0x4015 => self.apu.read(idx),
            0x4016...0x4017 => self.io.read(idx),
            0x4018...0x4019 => self.apu.read(idx),
            0x4020...0xFFFF => self.cart.borrow().prg_read(idx),
            x => invalid_address!(x),
        }
    }

    fn write(&mut self, idx: u16, val: u8) {
        match idx {
            0x0000...0x1FFF => self.ram.write(idx, val),
            0x2000...0x3FFF => self.ppu.borrow_mut().write(idx, val),
            0x4000...0x4015 => self.apu.write(idx, val),
            0x4016 => self.io.write(idx, val),
            0x4017...0x4019 => self.apu.write(idx, val),
            0x4020...0xFFFF => self.cart.borrow_mut().prg_write(idx, val),
            x => invalid_address!(x),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::rc::Rc;
    use std::cell::RefCell;
    use mappers::{Mapper, MapperParams};
    use screen::DummyScreen;

    fn create_test_memory() -> CpuMemory {
        let nrom = Mapper::new(0,
                               MapperParams::simple(vec!(0u8; 0x4000), vec!(0u8; 0x4000)));
        let cart = ::cart::Cart::new(nrom);
        let cart = Rc::new(RefCell::new(cart));
        let ppu = ::ppu::PPU::new(cart.clone(), Box::new(DummyScreen::new()));
        let ppu = Rc::new(RefCell::new(ppu));
        CpuMemory::new(ppu, ::apu::APU::new(), ::io::IO::new(), cart)
    }

    #[test]
    fn can_read_write_ram_through_memory() {
        let mut mem = create_test_memory();

        mem.write(0x0000, 0x24);
        assert_eq!(mem.read(0x0000), 0x24);

        mem.write(0x0799, 0x25);
        assert_eq!(mem.read(0x0799), 0x25);
    }

    #[test]
    fn test_ram_mirroring() {
        let mut mem = create_test_memory();

        mem.write(0x0800, 12);
        assert_eq!(mem.read(0x0000), 12);

        mem.write(0x1952, 12);
        assert_eq!(mem.read(0x0152), 12);
    }

    #[test]
    fn can_read_write_prg_ram_through_memory() {
        let mut mem = create_test_memory();

        mem.write(0x6111, 0x24);
        assert_eq!(mem.read(0x6111), 0x24);

        mem.write(0x6799, 0x25);
        assert_eq!(mem.read(0x6799), 0x25);
    }

    #[test]
    fn can_read_write_to_ppu_registers_through_memory() {
        let mut mem = create_test_memory();

        // We're relying on the PPU dynamic latch effect to get the right answers
        mem.write(0x2000, 0x45);
        assert_eq!(mem.ppu.borrow_mut().read(0x2000), 0x45);

        mem.write(0x2000, 0x48);
        assert_eq!(mem.read(0x2000), 0x48);
    }

    #[test]
    fn test_read_w_reads_low_byte_first() {
        let mut mem = create_test_memory();

        mem.write(0x1000, 0xCD);
        mem.write(0x1001, 0xAB);

        assert_eq!(mem.read_w(0x1000), 0xABCD);
    }
}
<commit_msg>Add debugging method to print a section of a memory segment.<commit_after>#![macro_use]

macro_rules! invalid_address {
    ($e:expr) => (panic!("Invalid NES Memory Address: {:X}", $e));
}

use cart::Cart;
use ppu::PPU;
use apu::APU;
use io::IO;
use std::rc::Rc;
use std::cell::RefCell;
use std::ops::Range;

pub trait MemSegment {
    fn read(&mut self, idx: u16) -> u8;
    fn read_w(&mut self, idx: u16) -> u16 {
        let low = self.read(idx) as u16;
        let high = self.read(idx + 1) as u16;
        (high << 8) | low
    }

    fn write(&mut self, idx: u16, val: u8);
    fn write_w(&mut self, idx: u16, val: u16) {
        let low = ((val & 0x00FF) >> 0) as u8;
        let high = ((val & 0xFF00) >> 8) as u8;
        self.write(idx, low);
        self.write(idx + 1, high);
    }

    fn print(&mut self, range: Range<u16>) {
        let lower = range.start / 16;
        let upper = range.end / 16 + 1;

        for y in lower..upper {
            print!("{:04X}: ", y * 16);
            for x in 0..16 {
                let addr = (y * 16) + x;
                print!("{:02X} ", self.read( addr ) );
                if x % 4 == 3 {
                    print!(" ");
                }
            }
            println!("");
        }
    }
}

struct RAM {
    memory: Box<[u8]>,
}

impl RAM {
    fn new() -> RAM {
        RAM { memory: vec!(0u8; 0x0800).into_boxed_slice() }
    }
}

impl MemSegment for RAM {
    fn read(&mut self, idx: u16) -> u8 {
        self.memory[idx as usize % 0x800]
    }

    fn write(&mut self, idx: u16, val: u8) {
        self.memory[idx as usize % 0x800] = val;
    }
}

pub struct CpuMemory {
    ram: RAM,
    pub ppu: Rc<RefCell<PPU>>,
    apu: APU,
    io: IO,
    cart: Rc<RefCell<Cart>>,
}

impl CpuMemory {
    pub fn new(ppu: Rc<RefCell<PPU>>, apu: APU, io: IO, cart: Rc<RefCell<Cart>>) -> CpuMemory {
        CpuMemory {
            ram: RAM::new(),
            ppu: ppu,
            apu: apu,
            io: io,
            cart: cart,
        }
    }

    pub fn read_w_zero_page(&mut self, zp_idx: u8) -> u16 {
        let low = self.read(zp_idx as u16) as u16;
        let high = self.read(zp_idx.wrapping_add(1) as u16) as u16;
        (high << 8) | low
    }
    pub fn read_w_same_page(&mut self, idx: u16) -> u16 {
        let page = idx & 0xFF00;
        let page_idx = idx as u8;
        let low = self.read(page | page_idx as u16) as u16;
        let high = self.read(page | page_idx.wrapping_add(1) as u16) as u16;
        (high << 8) | low
    }
}

impl MemSegment for CpuMemory {
    fn read(&mut self, idx: u16) -> u8 {
        match idx {
            0x0000...0x1FFF => self.ram.read(idx),
            0x2000...0x3FFF => self.ppu.borrow_mut().read(idx),
            0x4000...0x4015 => self.apu.read(idx),
            0x4016...0x4017 => self.io.read(idx),
            0x4018...0x4019 => self.apu.read(idx),
            0x4020...0xFFFF => self.cart.borrow().prg_read(idx),
            x => invalid_address!(x),
        }
    }

    fn write(&mut self, idx: u16, val: u8) {
        match idx {
            0x0000...0x1FFF => self.ram.write(idx, val),
            0x2000...0x3FFF => self.ppu.borrow_mut().write(idx, val),
            0x4000...0x4015 => self.apu.write(idx, val),
            0x4016 => self.io.write(idx, val),
            0x4017...0x4019 => self.apu.write(idx, val),
            0x4020...0xFFFF => self.cart.borrow_mut().prg_write(idx, val),
            x => invalid_address!(x),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::rc::Rc;
    use std::cell::RefCell;
    use mappers::{Mapper, MapperParams};
    use screen::DummyScreen;

    fn create_test_memory() -> CpuMemory {
        let nrom = Mapper::new(0,
                               MapperParams::simple(vec!(0u8; 0x4000), vec!(0u8; 0x4000)));
        let cart = ::cart::Cart::new(nrom);
        let cart = Rc::new(RefCell::new(cart));
        let ppu = ::ppu::PPU::new(cart.clone(), Box::new(DummyScreen::new()));
        let ppu = Rc::new(RefCell::new(ppu));
        CpuMemory::new(ppu, ::apu::APU::new(), ::io::IO::new(), cart)
    }

    #[test]
    fn can_read_write_ram_through_memory() {
        let mut mem = create_test_memory();

        mem.write(0x0000, 0x24);
        assert_eq!(mem.read(0x0000), 0x24);

        mem.write(0x0799, 0x25);
        assert_eq!(mem.read(0x0799), 0x25);
    }

    #[test]
    fn test_ram_mirroring() {
        let mut mem = create_test_memory();

        mem.write(0x0800, 12);
        assert_eq!(mem.read(0x0000), 12);

        mem.write(0x1952, 12);
        assert_eq!(mem.read(0x0152), 12);
    }

    #[test]
    fn can_read_write_prg_ram_through_memory() {
        let mut mem = create_test_memory();

        mem.write(0x6111, 0x24);
        assert_eq!(mem.read(0x6111), 0x24);

        mem.write(0x6799, 0x25);
        assert_eq!(mem.read(0x6799), 0x25);
    }

    #[test]
    fn can_read_write_to_ppu_registers_through_memory() {
        let mut mem = create_test_memory();

        // We're relying on the PPU dynamic latch effect to get the right answers
        mem.write(0x2000, 0x45);
        assert_eq!(mem.ppu.borrow_mut().read(0x2000), 0x45);

        mem.write(0x2000, 0x48);
        assert_eq!(mem.read(0x2000), 0x48);
    }

    #[test]
    fn test_read_w_reads_low_byte_first() {
        let mut mem = create_test_memory();

        mem.write(0x1000, 0xCD);
        mem.write(0x1001, 0xAB);

        assert_eq!(mem.read_w(0x1000), 0xABCD);
    }
}
<|endoftext|>


<commit_before>//! The HTTP request method
use std::fmt;
use std::str::FromStr;

use self::Method::{Options, Get, Post, Put, Delete, Head, Trace, Connect, Patch,
                   Extension};

/// The Request Method (VERB)
///
/// Currently includes 8 variants representing the 8 methods defined in
/// [RFC 7230](https://tools.ietf.org/html/rfc7231#section-4.1), plus PATCH,
/// and an Extension variant for all extensions.
///
/// It may make sense to grow this to include all variants currently
/// registered with IANA, if they are at all common to use.
#[deriving(Clone, PartialEq, Eq, Hash)]
pub enum Method {
    /// OPTIONS
    Options,
    /// GET
    Get,
    /// POST
    Post,
    /// PUT
    Put,
    /// DELETE
    Delete,
    /// HEAD
    Head,
    /// TRACE
    Trace,
    /// CONNECT
    Connect,
    /// PATCH
    Patch,
    /// Method extentions. An example would be `let m = Extension("FOO".to_string())`.
    Extension(String)
}

impl Method {
    /// Whether a method is considered "safe", meaning the request is
    /// essentially read-only.
    ///
    /// See [the spec](https://tools.ietf.org/html/rfc7231#section-4.2.1)
    /// for more words.
    pub fn safe(&self) -> bool {
        match *self {
            Get | Head | Options | Trace => true,
            _ => false
        }
    }

    /// Whether a method is considered "idempotent", meaning the request has
    /// the same result is executed multiple times.
    ///
    /// See [the spec](https://tools.ietf.org/html/rfc7231#section-4.2.2) for
    /// more words.
    pub fn idempotent(&self) -> bool {
        if self.safe() {
            true
        } else {
            match *self {
                Put | Delete => true,
                _ => false
            }
        }
    }
}

impl FromStr for Method {
    fn from_str(s: &str) -> Option<Method> {
        Some(match s {
            "OPTIONS" => Options,
            "GET" => Get,
            "POST" => Post,
            "PUT" => Put,
            "DELETE" => Delete,
            "HEAD" => Head,
            "TRACE" => Trace,
            "CONNECT" => Connect,
            "PATCH" => Patch,
            _ => Extension(s.to_string())
        })
    }
}

impl fmt::Show for Method {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Options => "OPTIONS",
            Get => "GET",
            Post => "POST",
            Put => "PUT",
            Delete => "DELETE",
            Head => "HEAD",
            Trace => "TRACE",
            Connect => "CONNECT",
            Patch => "PATCH",
            Extension(ref s) => s.as_slice()
        }.fmt(fmt)
    }
}
<commit_msg>Add some basic tests for hyper::method::Method<commit_after>//! The HTTP request method
use std::fmt;
use std::str::FromStr;

use self::Method::{Options, Get, Post, Put, Delete, Head, Trace, Connect, Patch,
                   Extension};

/// The Request Method (VERB)
///
/// Currently includes 8 variants representing the 8 methods defined in
/// [RFC 7230](https://tools.ietf.org/html/rfc7231#section-4.1), plus PATCH,
/// and an Extension variant for all extensions.
///
/// It may make sense to grow this to include all variants currently
/// registered with IANA, if they are at all common to use.
#[deriving(Clone, PartialEq, Eq, Hash)]
pub enum Method {
    /// OPTIONS
    Options,
    /// GET
    Get,
    /// POST
    Post,
    /// PUT
    Put,
    /// DELETE
    Delete,
    /// HEAD
    Head,
    /// TRACE
    Trace,
    /// CONNECT
    Connect,
    /// PATCH
    Patch,
    /// Method extentions. An example would be `let m = Extension("FOO".to_string())`.
    Extension(String)
}

impl Method {
    /// Whether a method is considered "safe", meaning the request is
    /// essentially read-only.
    ///
    /// See [the spec](https://tools.ietf.org/html/rfc7231#section-4.2.1)
    /// for more words.
    pub fn safe(&self) -> bool {
        match *self {
            Get | Head | Options | Trace => true,
            _ => false
        }
    }

    /// Whether a method is considered "idempotent", meaning the request has
    /// the same result is executed multiple times.
    ///
    /// See [the spec](https://tools.ietf.org/html/rfc7231#section-4.2.2) for
    /// more words.
    pub fn idempotent(&self) -> bool {
        if self.safe() {
            true
        } else {
            match *self {
                Put | Delete => true,
                _ => false
            }
        }
    }
}

impl FromStr for Method {
    fn from_str(s: &str) -> Option<Method> {
        Some(match s {
            "OPTIONS" => Options,
            "GET" => Get,
            "POST" => Post,
            "PUT" => Put,
            "DELETE" => Delete,
            "HEAD" => Head,
            "TRACE" => Trace,
            "CONNECT" => Connect,
            "PATCH" => Patch,
            _ => Extension(s.to_string())
        })
    }
}

impl fmt::Show for Method {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Options => "OPTIONS",
            Get => "GET",
            Post => "POST",
            Put => "PUT",
            Delete => "DELETE",
            Head => "HEAD",
            Trace => "TRACE",
            Connect => "CONNECT",
            Patch => "PATCH",
            Extension(ref s) => s.as_slice()
        }.fmt(fmt)
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use std::str::FromStr;
    use super::Method;
    use super::Method::{Get, Post, Put, Extension};

    #[test]
    fn test_safe() {
        assert_eq!(true, Get.safe());
        assert_eq!(false, Post.safe());
    }

    #[test]
    fn test_idempotent() {
        assert_eq!(true, Get.idempotent());
        assert_eq!(true, Put.idempotent());
        assert_eq!(false, Post.idempotent());
    }

    #[test]
    fn test_from_str() {
        assert_eq!(Some(Get), FromStr::from_str("GET"));
        assert_eq!(Some(Extension("MOVE".to_string())),
                   FromStr::from_str("MOVE"));
    }

    #[test]
    fn test_fmt() {
        assert_eq!("GET".to_string(), format!("{}", Get));
        assert_eq!("MOVE".to_string(),
                   format!("{}", Extension("MOVE".to_string())));
    }

    #[test]
    fn test_hashable() {
        let mut counter: HashMap<Method,uint> = HashMap::new();
        counter.insert(Get, 1);
        assert_eq!(Some(&1), counter.get(&Get));
    }
}
<|endoftext|>