<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// 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 std::fmt;
use std::str::FromStr;
use syntax::{ast, ext};
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic;
use syntax::{attr, codemap};
use syntax::parse::token;
use syntax::ptr::P;

/// A component modifier.
#[deriving(PartialEq)]
enum Modifier {
    /// Corresponds to the `#[normalized]` attribute.
    ///
    /// Normalizes the component at runtime. Unsigned integers are normalized to
    /// `[0, 1]`. Signed integers are normalized to `[-1, 1]`.
    Normalized,
    /// Corresponds to the `#[as_float]` attribute.
    ///
    /// Casts the component to a float precision floating-point number at runtime.
    AsFloat,
    /// Corresponds to the `#[as_double]` attribute.
    ///
    /// Specifies a high-precision float.
    AsDouble,
}

impl fmt::Show for Modifier {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Modifier::Normalized => write!(f, "normalized"),
            Modifier::AsFloat => write!(f, "as_float"),
            Modifier::AsDouble => write!(f, "as_double"),
        }
    }
}

impl FromStr for Modifier {
    fn from_str(src: &str) -> Option<Modifier> {
        match src {
            "normalized" => Some(Modifier::Normalized),
            "as_float" => Some(Modifier::AsFloat),
            "as_double" => Some(Modifier::AsDouble),
            _ => None,
        }
    }
}

/// Scan through the field's attributes and extract a relevant modifier. If
/// multiple modifier attributes are found, use the first modifier and emit a
/// warning.
fn find_modifier(cx: &mut ext::base::ExtCtxt, span: codemap::Span,
                 attributes: &[ast::Attribute]) -> Option<Modifier> {
    attributes.iter().fold(None, |modifier, attribute| {
        match attribute.node.value.node {
            ast::MetaWord(ref word) => {
                from_str(word.get()).and_then(|new_modifier| {
                    attr::mark_used(attribute);
                    modifier.map_or(Some(new_modifier), |modifier| {
                        cx.span_warn(span, format!(
                            "Extra attribute modifier detected: `#[{}]` - \
                            ignoring in favour of `#[{}]`.", new_modifier, modifier
                        ).as_slice());
                        None
                    })
                }).or(modifier)
            },
            _ => modifier,
        }
    })
}

/// Find a `gfx::attrib::Type` that describes the given type identifier.
fn decode_type(cx: &mut ext::base::ExtCtxt, span: codemap::Span,
               ty_ident: &ast::Ident, modifier: Option<Modifier>,
               path_root: ast::Ident) -> P<ast::Expr> {
    let ty_str = ty_ident.name.as_str();
    match ty_str {
        "f32" | "f64" => {
            let kind = cx.ident_of(match modifier {
                None | Some(Modifier::AsFloat) => "Default",
                Some(Modifier::AsDouble) => "Precision",
                Some(Modifier::Normalized) => {
                    cx.span_warn(span, format!(
                        "Incompatible float modifier attribute: `#[{}]`", modifier
                    ).as_slice());
                    ""
                }
            });
            let sub_type = cx.ident_of(format!("F{}", ty_str.slice_from(1)).as_slice());
            quote_expr!(cx, $path_root::gfx::attrib::Type::Float($path_root::gfx::attrib::FloatSubType::$kind,
                                                                 $path_root::gfx::attrib::$sub_type))
        },
        "u8" | "u16" | "u32" | "u64" |
        "i8" | "i16" | "i32" | "i64" => {
            let sign = cx.ident_of({
                if ty_str.starts_with("i") { "Signed" } else { "Unsigned" }
            });
            let kind = cx.ident_of(match modifier {
                None => "IntSubType::Raw",
                Some(Modifier::Normalized) => "Normalized",
                Some(Modifier::AsFloat) => "AsFloat",
                Some(Modifier::AsDouble) => {
                    cx.span_warn(span, format!(
                        "Incompatible int modifier attribute: `#[{}]`", modifier
                    ).as_slice());
                    ""
                }
            });
            let sub_type = cx.ident_of(format!("U{}", ty_str.slice_from(1)).as_slice());
            quote_expr!(cx, $path_root::gfx::attrib::Int($path_root::gfx::attrib::IntSubType::$kind,
                                                         $path_root::gfx::attrib::$sub_type,
                                                         $path_root::gfx::attrib::SignFlag::$sign))
        },
        "uint" | "int" => {
            cx.span_err(span, format!("Pointer-sized integer components are \
                                      not supported, but found: `{}`. Use an \
                                      integer component with an explicit size \
                                      instead.", ty_str).as_slice());
            cx.expr_tuple(span, vec![])
        },
        ty_str => {
            cx.span_err(span, format!("Unrecognized component type: `{}`",
                                      ty_str).as_slice());
            cx.expr_tuple(span, vec![])
        },
    }
}

fn decode_count_and_type(cx: &mut ext::base::ExtCtxt, span: codemap::Span,
                         field: &ast::StructField,
                         path_root: ast::Ident) -> (P<ast::Expr>, P<ast::Expr>) {
    let modifier = find_modifier(cx, span, field.node.attrs.as_slice());
    match field.node.ty.node {
        ast::TyPath(ref p, _, _) => (
            cx.expr_lit(span, ast::LitInt(1, ast::UnsuffixedIntLit(ast::Plus))),
            decode_type(cx, span, &p.segments[0].identifier, modifier, path_root),
        ),
        ast::TyFixedLengthVec(ref pty, ref expr) => (expr.clone(), match pty.node {
            ast::TyPath(ref p, _, _) => {
                decode_type(cx, span, &p.segments[0].identifier, modifier, path_root)
            },
            _ => {
                cx.span_err(span, format!("Unsupported fixed vector sub-type: \
                                          `{}`",pty.node).as_slice());
                cx.expr_tuple(span, vec![])
            },
        }),
        _ => {
            cx.span_err(span, format!("Unsupported attribute type: `{}`",
                                      field.node.ty.node).as_slice());
            (cx.expr_tuple(span, vec![]), cx.expr_tuple(span, vec![]))
        },
    }
}

/// Generates the the method body for `gfx::VertexFormat::generate`.
fn method_body(cx: &mut ext::base::ExtCtxt, span: codemap::Span,
                   substr: &generic::Substructure,
                   path_root: ast::Ident) -> P<ast::Expr> {
    match *substr.fields {
        generic::StaticStruct(ref definition, generic::Named(ref fields)) => {
            let attribute_pushes = definition.fields.iter().zip(fields.iter())
                .map(|(def, &(ident, _))| {
                    let struct_ident = substr.type_ident;
                    let buffer_expr = &substr.nonself_args[1];
                    let (count_expr, type_expr) = decode_count_and_type(cx, span, def, path_root);
                    let ident_str = match super::find_name(cx, span, def.node.attrs.as_slice()) {
                        Some(name) => name,
                        None => token::get_ident(ident),
                    };
                    let ident_str = ident_str.get();
                    let instance_expr = cx.expr_u8(span, 0); // not supposed to be set by the macro
                    quote_expr!(cx, {
                        attributes.push($path_root::gfx::Attribute {
                            name: $ident_str.to_string(),
                            buffer: $buffer_expr,
                            format: $path_root::gfx::attrib::Format {
                                elem_count: $count_expr,
                                elem_type: $type_expr,
                                offset: unsafe {
                                    let x: $struct_ident = ::std::mem::uninitialized();
                                    let offset = (&x.$ident as *const _ as uint) -
                                        (&x as *const _ as uint);
                                    ::std::mem::forget(x);
                                    offset as $path_root::gfx::attrib::Offset
                                },
                                stride: { use std::mem;
                                    mem::size_of::<$struct_ident>() as
                                        $path_root::gfx::attrib::Stride
                                },
                                instance_rate: $instance_expr,
                            }
                        });
                    })
                }).collect::<Vec<P<ast::Expr>>>();
            let capacity = fields.len();
            quote_expr!(cx, {
                let mut attributes = Vec::with_capacity($capacity);
                $attribute_pushes;
                attributes
            })
        },
        _ => {
            cx.span_err(span, "Unable to implement `gfx::VertexFormat::generate` \
                              on a non-structure");
            cx.expr_tuple(span, vec![])
        }
    }
}

/// Derive a `gfx::VertexFormat` implementation for the `struct`
pub fn expand(context: &mut ext::base::ExtCtxt, span: codemap::Span,
              meta_item: &ast::MetaItem, item: &ast::Item,
              push: |P<ast::Item>|) {
    // Insert the `gfx` reexport module
    let path_root = super::extern_crate_hack(context, span, |i| push(i));
    let fixup = |item| {
        push(super::fixup_extern_crate_paths(item, path_root))
    };

    // `impl gfx::VertexFormat for $item`
    generic::TraitDef {
        span: span,
        attributes: Vec::new(),
        path: generic::ty::Path {
            path: vec![super::EXTERN_CRATE_HACK, "gfx", "VertexFormat"],
            lifetime: None,
            params: Vec::new(),
            global: true,
        },
        additional_bounds: Vec::new(),
        generics: generic::ty::LifetimeBounds::empty(),
        methods: vec![
            // `fn generate(Option<Self>, gfx::RawBufferHandle) -> Vec<gfx::Attribute>`
            generic::MethodDef {
                name: "generate",
                generics: generic::ty::LifetimeBounds::empty(),
                explicit_self: None,
                args: vec![
                    generic::ty::Literal(generic::ty::Path {
                        path: vec!["Option"],
                        lifetime: None,
                        params: vec![box generic::ty::Self],
                        global: false,
                    }),
                    generic::ty::Literal(generic::ty::Path::new(
                        vec![super::EXTERN_CRATE_HACK, "gfx", "RawBufferHandle"]
                    )),
                ],
                ret_ty: generic::ty::Literal(
                    generic::ty::Path {
                        path: vec!["Vec"],
                        lifetime: None,
                        params: vec![
                            box generic::ty::Literal(generic::ty::Path::new(
                                vec![super::EXTERN_CRATE_HACK, "gfx", "Attribute"])),
                        ],
                        global: false,
                    },
                ),
                attributes: Vec::new(),
                // generate the method body
                combine_substructure: generic::combine_substructure(
                    |c, s, ss| method_body(c, s, ss, path_root)),
            },
        ],
    }.expand(context, meta_item, item, fixup);
}
<commit_msg>Fix IntSubType::Raw in vertex_format macro<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// 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 std::fmt;
use std::str::FromStr;
use syntax::{ast, ext};
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic;
use syntax::{attr, codemap};
use syntax::parse::token;
use syntax::ptr::P;

/// A component modifier.
#[deriving(PartialEq)]
enum Modifier {
    /// Corresponds to the `#[normalized]` attribute.
    ///
    /// Normalizes the component at runtime. Unsigned integers are normalized to
    /// `[0, 1]`. Signed integers are normalized to `[-1, 1]`.
    Normalized,
    /// Corresponds to the `#[as_float]` attribute.
    ///
    /// Casts the component to a float precision floating-point number at runtime.
    AsFloat,
    /// Corresponds to the `#[as_double]` attribute.
    ///
    /// Specifies a high-precision float.
    AsDouble,
}

impl fmt::Show for Modifier {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Modifier::Normalized => write!(f, "normalized"),
            Modifier::AsFloat => write!(f, "as_float"),
            Modifier::AsDouble => write!(f, "as_double"),
        }
    }
}

impl FromStr for Modifier {
    fn from_str(src: &str) -> Option<Modifier> {
        match src {
            "normalized" => Some(Modifier::Normalized),
            "as_float" => Some(Modifier::AsFloat),
            "as_double" => Some(Modifier::AsDouble),
            _ => None,
        }
    }
}

/// Scan through the field's attributes and extract a relevant modifier. If
/// multiple modifier attributes are found, use the first modifier and emit a
/// warning.
fn find_modifier(cx: &mut ext::base::ExtCtxt, span: codemap::Span,
                 attributes: &[ast::Attribute]) -> Option<Modifier> {
    attributes.iter().fold(None, |modifier, attribute| {
        match attribute.node.value.node {
            ast::MetaWord(ref word) => {
                from_str(word.get()).and_then(|new_modifier| {
                    attr::mark_used(attribute);
                    modifier.map_or(Some(new_modifier), |modifier| {
                        cx.span_warn(span, format!(
                            "Extra attribute modifier detected: `#[{}]` - \
                            ignoring in favour of `#[{}]`.", new_modifier, modifier
                        ).as_slice());
                        None
                    })
                }).or(modifier)
            },
            _ => modifier,
        }
    })
}

/// Find a `gfx::attrib::Type` that describes the given type identifier.
fn decode_type(cx: &mut ext::base::ExtCtxt, span: codemap::Span,
               ty_ident: &ast::Ident, modifier: Option<Modifier>,
               path_root: ast::Ident) -> P<ast::Expr> {
    let ty_str = ty_ident.name.as_str();
    match ty_str {
        "f32" | "f64" => {
            let kind = cx.ident_of(match modifier {
                None | Some(Modifier::AsFloat) => "Default",
                Some(Modifier::AsDouble) => "Precision",
                Some(Modifier::Normalized) => {
                    cx.span_warn(span, format!(
                        "Incompatible float modifier attribute: `#[{}]`", modifier
                    ).as_slice());
                    ""
                }
            });
            let sub_type = cx.ident_of(format!("F{}", ty_str.slice_from(1)).as_slice());
            quote_expr!(cx, $path_root::gfx::attrib::Type::Float($path_root::gfx::attrib::FloatSubType::$kind,
                                                                 $path_root::gfx::attrib::$sub_type))
        },
        "u8" | "u16" | "u32" | "u64" |
        "i8" | "i16" | "i32" | "i64" => {
            let sign = cx.ident_of({
                if ty_str.starts_with("i") { "Signed" } else { "Unsigned" }
            });
            let kind = cx.ident_of(match modifier {
                None => "Raw",
                Some(Modifier::Normalized) => "Normalized",
                Some(Modifier::AsFloat) => "AsFloat",
                Some(Modifier::AsDouble) => {
                    cx.span_warn(span, format!(
                        "Incompatible int modifier attribute: `#[{}]`", modifier
                    ).as_slice());
                    ""
                }
            });
            let sub_type = cx.ident_of(format!("U{}", ty_str.slice_from(1)).as_slice());
            quote_expr!(cx, $path_root::gfx::attrib::Int($path_root::gfx::attrib::IntSubType::$kind,
                                                         $path_root::gfx::attrib::$sub_type,
                                                         $path_root::gfx::attrib::SignFlag::$sign))
        },
        "uint" | "int" => {
            cx.span_err(span, format!("Pointer-sized integer components are \
                                      not supported, but found: `{}`. Use an \
                                      integer component with an explicit size \
                                      instead.", ty_str).as_slice());
            cx.expr_tuple(span, vec![])
        },
        ty_str => {
            cx.span_err(span, format!("Unrecognized component type: `{}`",
                                      ty_str).as_slice());
            cx.expr_tuple(span, vec![])
        },
    }
}

fn decode_count_and_type(cx: &mut ext::base::ExtCtxt, span: codemap::Span,
                         field: &ast::StructField,
                         path_root: ast::Ident) -> (P<ast::Expr>, P<ast::Expr>) {
    let modifier = find_modifier(cx, span, field.node.attrs.as_slice());
    match field.node.ty.node {
        ast::TyPath(ref p, _, _) => (
            cx.expr_lit(span, ast::LitInt(1, ast::UnsuffixedIntLit(ast::Plus))),
            decode_type(cx, span, &p.segments[0].identifier, modifier, path_root),
        ),
        ast::TyFixedLengthVec(ref pty, ref expr) => (expr.clone(), match pty.node {
            ast::TyPath(ref p, _, _) => {
                decode_type(cx, span, &p.segments[0].identifier, modifier, path_root)
            },
            _ => {
                cx.span_err(span, format!("Unsupported fixed vector sub-type: \
                                          `{}`",pty.node).as_slice());
                cx.expr_tuple(span, vec![])
            },
        }),
        _ => {
            cx.span_err(span, format!("Unsupported attribute type: `{}`",
                                      field.node.ty.node).as_slice());
            (cx.expr_tuple(span, vec![]), cx.expr_tuple(span, vec![]))
        },
    }
}

/// Generates the the method body for `gfx::VertexFormat::generate`.
fn method_body(cx: &mut ext::base::ExtCtxt, span: codemap::Span,
                   substr: &generic::Substructure,
                   path_root: ast::Ident) -> P<ast::Expr> {
    match *substr.fields {
        generic::StaticStruct(ref definition, generic::Named(ref fields)) => {
            let attribute_pushes = definition.fields.iter().zip(fields.iter())
                .map(|(def, &(ident, _))| {
                    let struct_ident = substr.type_ident;
                    let buffer_expr = &substr.nonself_args[1];
                    let (count_expr, type_expr) = decode_count_and_type(cx, span, def, path_root);
                    let ident_str = match super::find_name(cx, span, def.node.attrs.as_slice()) {
                        Some(name) => name,
                        None => token::get_ident(ident),
                    };
                    let ident_str = ident_str.get();
                    let instance_expr = cx.expr_u8(span, 0); // not supposed to be set by the macro
                    quote_expr!(cx, {
                        attributes.push($path_root::gfx::Attribute {
                            name: $ident_str.to_string(),
                            buffer: $buffer_expr,
                            format: $path_root::gfx::attrib::Format {
                                elem_count: $count_expr,
                                elem_type: $type_expr,
                                offset: unsafe {
                                    let x: $struct_ident = ::std::mem::uninitialized();
                                    let offset = (&x.$ident as *const _ as uint) -
                                        (&x as *const _ as uint);
                                    ::std::mem::forget(x);
                                    offset as $path_root::gfx::attrib::Offset
                                },
                                stride: { use std::mem;
                                    mem::size_of::<$struct_ident>() as
                                        $path_root::gfx::attrib::Stride
                                },
                                instance_rate: $instance_expr,
                            }
                        });
                    })
                }).collect::<Vec<P<ast::Expr>>>();
            let capacity = fields.len();
            quote_expr!(cx, {
                let mut attributes = Vec::with_capacity($capacity);
                $attribute_pushes;
                attributes
            })
        },
        _ => {
            cx.span_err(span, "Unable to implement `gfx::VertexFormat::generate` \
                              on a non-structure");
            cx.expr_tuple(span, vec![])
        }
    }
}

/// Derive a `gfx::VertexFormat` implementation for the `struct`
pub fn expand(context: &mut ext::base::ExtCtxt, span: codemap::Span,
              meta_item: &ast::MetaItem, item: &ast::Item,
              push: |P<ast::Item>|) {
    // Insert the `gfx` reexport module
    let path_root = super::extern_crate_hack(context, span, |i| push(i));
    let fixup = |item| {
        push(super::fixup_extern_crate_paths(item, path_root))
    };

    // `impl gfx::VertexFormat for $item`
    generic::TraitDef {
        span: span,
        attributes: Vec::new(),
        path: generic::ty::Path {
            path: vec![super::EXTERN_CRATE_HACK, "gfx", "VertexFormat"],
            lifetime: None,
            params: Vec::new(),
            global: true,
        },
        additional_bounds: Vec::new(),
        generics: generic::ty::LifetimeBounds::empty(),
        methods: vec![
            // `fn generate(Option<Self>, gfx::RawBufferHandle) -> Vec<gfx::Attribute>`
            generic::MethodDef {
                name: "generate",
                generics: generic::ty::LifetimeBounds::empty(),
                explicit_self: None,
                args: vec![
                    generic::ty::Literal(generic::ty::Path {
                        path: vec!["Option"],
                        lifetime: None,
                        params: vec![box generic::ty::Self],
                        global: false,
                    }),
                    generic::ty::Literal(generic::ty::Path::new(
                        vec![super::EXTERN_CRATE_HACK, "gfx", "RawBufferHandle"]
                    )),
                ],
                ret_ty: generic::ty::Literal(
                    generic::ty::Path {
                        path: vec!["Vec"],
                        lifetime: None,
                        params: vec![
                            box generic::ty::Literal(generic::ty::Path::new(
                                vec![super::EXTERN_CRATE_HACK, "gfx", "Attribute"])),
                        ],
                        global: false,
                    },
                ),
                attributes: Vec::new(),
                // generate the method body
                combine_substructure: generic::combine_substructure(
                    |c, s, ss| method_body(c, s, ss, path_root)),
            },
        ],
    }.expand(context, meta_item, item, fixup);
}
<|endoftext|>


<commit_before>use super::*;
use std::str::FromStr;

#[test]
fn after_reading_valid_xml_expect_map_to_have_version() {
    let map = get_simple_valid_map();
    assert_eq!("1.0", map.version());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_orientation() {
    let map = get_simple_valid_map();
    assert_eq!(Orientation::Orthogonal, map.orientation());
}

#[test]
fn after_reading_valid_xml_without_render_order_expect_map_to_have_default_render_order() {
    let map = get_simple_valid_map();
    assert_eq!(RenderOrder::RightDown, map.render_order());
}

#[test]
fn after_reading_valid_xml_with_render_order_expect_map_to_have_that_render_order() {
    let map = Map::from_str("<map renderorder=\"left-up\"></map>").unwrap();
    assert_eq!(RenderOrder::LeftUp, map.render_order());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_width() {
    let map = get_simple_valid_map();
    assert_eq!(200, map.width());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_height() {
    let map = get_simple_valid_map();
    assert_eq!(100, map.height());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_tile_width() {
    let map = get_simple_valid_map();
    assert_eq!(16, map.tile_width());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_tile_height() {
    let map = get_simple_valid_map();
    assert_eq!(32, map.tile_height());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_next_object_id() {
    let map = get_simple_valid_map();
    assert_eq!(1, map.next_object_id());
}

#[test]
fn when_reading_map_xml_with_invalid_attribute_expect_attribute_error() {
    let result = Map::from_str(r#"<map bad=""></map>"#);
    assert_matches!(result, Err(Error::UnknownAttribute(..)));
}

#[test]
fn when_reading_map_xml_with_invalid_orientation_expect_orientation_error() {
    let result = Map::from_str(r#"<map orientation="bad"></map>"#);
    assert_matches!(result, Err(Error::BadOrientation(..)));
}

#[test]
fn when_reading_map_xml_with_invalid_render_order_expect_render_order_error() {
    let result = Map::from_str(r#"<map renderorder="bad"></map>"#);
    assert_matches!(result, Err(Error::BadRenderOrder(..)));
}

#[test]
fn when_reading_invalid_xml_element_expect_error() {
    let result = Map::from_str("<nomap/>");
    assert_matches!(result, Err(Error::BadXml));
}

#[test]
fn after_reading_xml_with_tilesets_expect_map_to_be_iterable_over_tilesets() {
    let map = get_map_with_tilesets();
    assert_eq!(2, map.tilesets().count());
}

#[test]
fn after_reading_xml_with_layers_expect_map_to_be_iterable_over_layers() {
    let map = get_map_with_layers();
    assert_eq!(5, map.layers().count());

    let mut layers = map.layers();
    let layer1 = layers.next().unwrap();
    assert_eq!("layer1_name", layer1.name());
    assert_eq!(1.0, layer1.opacity());
    assert!(layer1.is_visible());
    assert_eq!(0, layer1.offset_x());
    assert_eq!(0, layer1.offset_y());

    let layer2 = layers.next().unwrap();
    assert_eq!(0.0, layer2.opacity());

    let layer3 = layers.next().unwrap();
    assert!(!layer3.is_visible());

    let layer4 = layers.next().unwrap();
    assert_eq!(1, layer4.offset_x());
    assert_eq!(2, layer4.offset_y());

    let layer5 = layers.next().unwrap();
    assert_eq!(1, layer5.properties().count());
}

#[test]
fn after_reading_xml_with_image_layers_expect_map_to_be_iterable_over_image_layers() {
    let map = get_map_with_image_layers();
    assert_eq!(6, map.image_layers().count());

    let mut layers = map.image_layers();
    let layer1 = layers.next().unwrap();
    assert_eq!("layer1_name", layer1.name());
    assert_eq!(1.0, layer1.opacity());
    assert!(layer1.is_visible());
    assert_eq!(0, layer1.offset_x());
    assert_eq!(0, layer1.offset_y());

    let layer2 = layers.next().unwrap();
    assert_eq!(0.0, layer2.opacity());

    let layer3 = layers.next().unwrap();
    assert!(!layer3.is_visible());

    let layer4 = layers.next().unwrap();
    assert_eq!(1, layer4.offset_x());
    assert_eq!(2, layer4.offset_y());

    let layer5 = layers.next().unwrap();
    assert_eq!(1, layer5.properties().count());

    let layer6 = layers.next().unwrap();
    assert!(layer6.image().is_some());
}

#[test]
fn after_reading_xml_with_object_groups_expect_map_to_be_iterable_over_object_groups() {
    let map = get_map_with_objectgroups();
    assert_eq!(2, map.object_groups().count());

    let mut object_groups = map.object_groups();
    let group1 = object_groups.next().unwrap();
    assert_eq!("some_name", group1.name());
    assert_eq!(1.0, group1.opacity());
    assert!(group1.is_visible());
    assert_eq!(0, group1.offset_x());
    assert_eq!(0, group1.offset_y());
    assert_eq!(DrawOrder::TopDown, group1.draw_order());
    assert_eq!(1, group1.properties().count());

    let group2 = object_groups.next().unwrap();
    assert_eq!(0.0, group2.opacity());
    assert!(!group2.is_visible());
    assert_eq!(1, group2.offset_x());
    assert_eq!(2, group2.offset_y());
    assert_eq!(DrawOrder::Index, group2.draw_order());
}

#[test]
fn after_reading_valid_xml_expect_tileset_to_have_first_gid() {
    let tileset = get_simple_valid_tileset();
    assert_eq!(1, tileset.first_gid());
}

#[test]
fn after_reading_valid_xml_expect_tileset_to_have_name() {
    let tileset = get_simple_valid_tileset();
    assert_eq!("simple", tileset.name());
}

#[test]
fn after_reading_valid_xml_expect_tileset_to_have_tile_width() {
    let tileset = get_simple_valid_tileset();
    assert_eq!(32, tileset.tile_width());
}

#[test]
fn after_reading_valid_xml_expect_tileset_to_have_tile_height() {
    let tileset = get_simple_valid_tileset();
    assert_eq!(16, tileset.tile_height());
}

#[test]
fn after_reading_valid_xml_expect_tileset_to_have_tile_count() {
    let tileset = get_simple_valid_tileset();
    assert_eq!(100, tileset.tile_count());
}

#[test]
fn after_reading_valid_xml_with_image_element_expect_tileset_to_have_image() {
    let tileset = Tileset::from_str(
        r#"<tileset>
        <image source="some_file.png"
                width="1024"
                height="768"/>
    <tileset>"#).unwrap();
    let image = tileset.image().unwrap();
    assert_eq!("some_file.png", image.source());
    assert_eq!(1024, image.width());
    assert_eq!(768, image.height());
}

#[test]
fn after_reading_valid_xml_with_properties_expect_tileset_to_have_properties() {
    let tileset = Tileset::from_str(
        r#"<tileset>
        <properties>
            <property name="prop1_name" value="prop1_value"/>
            <property name="prop2_name" value="0" type="int"/>
            <property name="prop3_name" value="0.0" type="float"/>
            <property name="prop4_name" value="true" type="bool"/>
        </properties>
    <tileset>"#).unwrap();
    assert_eq!(4, tileset.properties().count());
    let mut props = tileset.properties();

    let prop1 = props.next().unwrap();
    assert_eq!("prop1_name", prop1.name());
    assert_eq!("prop1_value", prop1.value());
    assert_eq!(PropertyType::String, prop1.property_type());

    let prop2 = props.next().unwrap();
    assert_eq!(PropertyType::Int, prop2.property_type());

    let prop3 = props.next().unwrap();
    assert_eq!(PropertyType::Float, prop3.property_type());

    let prop4 = props.next().unwrap();
    assert_eq!(PropertyType::Bool, prop4.property_type());
}

#[test]
fn after_reading_valid_xml_with_tile_offset_expect_tileset_to_have_tile_offset() {
    let tileset = Tileset::from_str(
        r#"<tileset>
        <tileoffset x="0" y="1"/>
    <tileset>"#).unwrap();
    let offset = tileset.tile_offset().unwrap();
    assert_eq!(0, offset.x());
    assert_eq!(1, offset.y());
}

#[test]
fn after_reading_valid_xml_with_terrains_expect_tileset_to_have_terrains() {
    let tileset = Tileset::from_str(r#"
    <tileset>
        <terraintypes>
            <terrain name="terrain1"/>
            <terrain tile="tile-id">
                <properties>
                    <property/>
                </properties>
            </terrain>
        </terraintypes>
    <tileset>"#).unwrap();
    assert_eq!(2, tileset.terrain_types().count());
    let mut terrain_types = tileset.terrain_types();

    let terrain1 = terrain_types.next().unwrap();
    assert_eq!("terrain1", terrain1.name());

    let terrain2 = terrain_types.next().unwrap();
    assert_eq!("tile-id", terrain2.tile());
    assert_eq!(1, terrain2.properties().count());
}

fn get_simple_valid_map() -> Map {
    Map::from_str(r#"<map version="1.0"
        orientation="orthogonal"
        width="200"
        height="100"
        tilewidth="16"
        tileheight="32"
        nextobjectid="1">
    </map>"#).unwrap()
}

fn get_map_with_tilesets() -> Map {
    Map::from_str("<map>
        <tileset></tileset>
        <tileset></tileset>
    </map>").unwrap()
}

fn get_map_with_layers() -> Map {
    Map::from_str(r#"<map>
        <layer name="layer1_name"/>
        <layer name="layer2_name" opacity="0"/>
        <layer name="layer3_name" visibility="0"/>
        <layer name="layer4_name" offsetx="1" offsety="2"/>
        <layer>
            <properties>
                <property name="some_name" value="some_value"/>
            </properties>
        </layer>
    </map>"#).unwrap()
}

fn get_map_with_image_layers() -> Map {
    Map::from_str(r#"<map>
        <imagelayer name="layer1_name"/>
        <imagelayer name="layer2_name" opacity="0"/>
        <imagelayer name="layer3_name" visibility="0"/>
        <imagelayer name="layer4_name" offsetx="1" offsety="2"/>
        <imagelayer>
            <properties>
                <property name="some_name" value="some_value"/>
            </properties>
        </imagelayer>
        <imagelayer>
            <image source="some_file.png"
                    width="1024"
                    height="768"/>
        </imagelayer>
    </map>"#).unwrap()
}

fn get_simple_valid_tileset() -> Tileset {
    Tileset::from_str(r#"<tileset firstgid="1"
                name="simple"
                tilewidth="32"
                tileheight="16"
                tilecount="100">
    </tileset>"#).unwrap()
}

fn get_map_with_objectgroups() -> Map {
    Map::from_str(r#"<map>
        <objectgroup name="some_name">
            <properties>
                <property/>
            </properties>
        </objectgroup>
        <objectgroup opacity="0" visibility="0" offsetx="1" offsety="2" draworder="index">
        </objectgroup>
    </map>"#).unwrap()
}

<commit_msg>Added missing use directive<commit_after>use super::*;
use std::str::FromStr;

use ::error::Error;

#[test]
fn after_reading_valid_xml_expect_map_to_have_version() {
    let map = get_simple_valid_map();
    assert_eq!("1.0", map.version());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_orientation() {
    let map = get_simple_valid_map();
    assert_eq!(Orientation::Orthogonal, map.orientation());
}

#[test]
fn after_reading_valid_xml_without_render_order_expect_map_to_have_default_render_order() {
    let map = get_simple_valid_map();
    assert_eq!(RenderOrder::RightDown, map.render_order());
}

#[test]
fn after_reading_valid_xml_with_render_order_expect_map_to_have_that_render_order() {
    let map = Map::from_str("<map renderorder=\"left-up\"></map>").unwrap();
    assert_eq!(RenderOrder::LeftUp, map.render_order());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_width() {
    let map = get_simple_valid_map();
    assert_eq!(200, map.width());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_height() {
    let map = get_simple_valid_map();
    assert_eq!(100, map.height());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_tile_width() {
    let map = get_simple_valid_map();
    assert_eq!(16, map.tile_width());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_tile_height() {
    let map = get_simple_valid_map();
    assert_eq!(32, map.tile_height());
}

#[test]
fn after_reading_valid_xml_expect_map_to_have_next_object_id() {
    let map = get_simple_valid_map();
    assert_eq!(1, map.next_object_id());
}

#[test]
fn when_reading_map_xml_with_invalid_attribute_expect_attribute_error() {
    let result = Map::from_str(r#"<map bad=""></map>"#);
    assert_matches!(result, Err(Error::UnknownAttribute(..)));
}

#[test]
fn when_reading_map_xml_with_invalid_orientation_expect_orientation_error() {
    let result = Map::from_str(r#"<map orientation="bad"></map>"#);
    assert_matches!(result, Err(Error::BadOrientation(..)));
}

#[test]
fn when_reading_map_xml_with_invalid_render_order_expect_render_order_error() {
    let result = Map::from_str(r#"<map renderorder="bad"></map>"#);
    assert_matches!(result, Err(Error::BadRenderOrder(..)));
}

#[test]
fn when_reading_invalid_xml_element_expect_error() {
    let result = Map::from_str("<nomap/>");
    assert_matches!(result, Err(Error::BadXml));
}

#[test]
fn after_reading_xml_with_tilesets_expect_map_to_be_iterable_over_tilesets() {
    let map = get_map_with_tilesets();
    assert_eq!(2, map.tilesets().count());
}

#[test]
fn after_reading_xml_with_layers_expect_map_to_be_iterable_over_layers() {
    let map = get_map_with_layers();
    assert_eq!(5, map.layers().count());

    let mut layers = map.layers();
    let layer1 = layers.next().unwrap();
    assert_eq!("layer1_name", layer1.name());
    assert_eq!(1.0, layer1.opacity());
    assert!(layer1.is_visible());
    assert_eq!(0, layer1.offset_x());
    assert_eq!(0, layer1.offset_y());

    let layer2 = layers.next().unwrap();
    assert_eq!(0.0, layer2.opacity());

    let layer3 = layers.next().unwrap();
    assert!(!layer3.is_visible());

    let layer4 = layers.next().unwrap();
    assert_eq!(1, layer4.offset_x());
    assert_eq!(2, layer4.offset_y());

    let layer5 = layers.next().unwrap();
    assert_eq!(1, layer5.properties().count());
}

#[test]
fn after_reading_xml_with_image_layers_expect_map_to_be_iterable_over_image_layers() {
    let map = get_map_with_image_layers();
    assert_eq!(6, map.image_layers().count());

    let mut layers = map.image_layers();
    let layer1 = layers.next().unwrap();
    assert_eq!("layer1_name", layer1.name());
    assert_eq!(1.0, layer1.opacity());
    assert!(layer1.is_visible());
    assert_eq!(0, layer1.offset_x());
    assert_eq!(0, layer1.offset_y());

    let layer2 = layers.next().unwrap();
    assert_eq!(0.0, layer2.opacity());

    let layer3 = layers.next().unwrap();
    assert!(!layer3.is_visible());

    let layer4 = layers.next().unwrap();
    assert_eq!(1, layer4.offset_x());
    assert_eq!(2, layer4.offset_y());

    let layer5 = layers.next().unwrap();
    assert_eq!(1, layer5.properties().count());

    let layer6 = layers.next().unwrap();
    assert!(layer6.image().is_some());
}

#[test]
fn after_reading_xml_with_object_groups_expect_map_to_be_iterable_over_object_groups() {
    let map = get_map_with_objectgroups();
    assert_eq!(2, map.object_groups().count());

    let mut object_groups = map.object_groups();
    let group1 = object_groups.next().unwrap();
    assert_eq!("some_name", group1.name());
    assert_eq!(1.0, group1.opacity());
    assert!(group1.is_visible());
    assert_eq!(0, group1.offset_x());
    assert_eq!(0, group1.offset_y());
    assert_eq!(DrawOrder::TopDown, group1.draw_order());
    assert_eq!(1, group1.properties().count());

    let group2 = object_groups.next().unwrap();
    assert_eq!(0.0, group2.opacity());
    assert!(!group2.is_visible());
    assert_eq!(1, group2.offset_x());
    assert_eq!(2, group2.offset_y());
    assert_eq!(DrawOrder::Index, group2.draw_order());
}

#[test]
fn after_reading_valid_xml_expect_tileset_to_have_first_gid() {
    let tileset = get_simple_valid_tileset();
    assert_eq!(1, tileset.first_gid());
}

#[test]
fn after_reading_valid_xml_expect_tileset_to_have_name() {
    let tileset = get_simple_valid_tileset();
    assert_eq!("simple", tileset.name());
}

#[test]
fn after_reading_valid_xml_expect_tileset_to_have_tile_width() {
    let tileset = get_simple_valid_tileset();
    assert_eq!(32, tileset.tile_width());
}

#[test]
fn after_reading_valid_xml_expect_tileset_to_have_tile_height() {
    let tileset = get_simple_valid_tileset();
    assert_eq!(16, tileset.tile_height());
}

#[test]
fn after_reading_valid_xml_expect_tileset_to_have_tile_count() {
    let tileset = get_simple_valid_tileset();
    assert_eq!(100, tileset.tile_count());
}

#[test]
fn after_reading_valid_xml_with_image_element_expect_tileset_to_have_image() {
    let tileset = Tileset::from_str(
        r#"<tileset>
        <image source="some_file.png"
                width="1024"
                height="768"/>
    <tileset>"#).unwrap();
    let image = tileset.image().unwrap();
    assert_eq!("some_file.png", image.source());
    assert_eq!(1024, image.width());
    assert_eq!(768, image.height());
}

#[test]
fn after_reading_valid_xml_with_properties_expect_tileset_to_have_properties() {
    let tileset = Tileset::from_str(
        r#"<tileset>
        <properties>
            <property name="prop1_name" value="prop1_value"/>
            <property name="prop2_name" value="0" type="int"/>
            <property name="prop3_name" value="0.0" type="float"/>
            <property name="prop4_name" value="true" type="bool"/>
        </properties>
    <tileset>"#).unwrap();
    assert_eq!(4, tileset.properties().count());
    let mut props = tileset.properties();

    let prop1 = props.next().unwrap();
    assert_eq!("prop1_name", prop1.name());
    assert_eq!("prop1_value", prop1.value());
    assert_eq!(PropertyType::String, prop1.property_type());

    let prop2 = props.next().unwrap();
    assert_eq!(PropertyType::Int, prop2.property_type());

    let prop3 = props.next().unwrap();
    assert_eq!(PropertyType::Float, prop3.property_type());

    let prop4 = props.next().unwrap();
    assert_eq!(PropertyType::Bool, prop4.property_type());
}

#[test]
fn after_reading_valid_xml_with_tile_offset_expect_tileset_to_have_tile_offset() {
    let tileset = Tileset::from_str(
        r#"<tileset>
        <tileoffset x="0" y="1"/>
    <tileset>"#).unwrap();
    let offset = tileset.tile_offset().unwrap();
    assert_eq!(0, offset.x());
    assert_eq!(1, offset.y());
}

#[test]
fn after_reading_valid_xml_with_terrains_expect_tileset_to_have_terrains() {
    let tileset = Tileset::from_str(r#"
    <tileset>
        <terraintypes>
            <terrain name="terrain1"/>
            <terrain tile="tile-id">
                <properties>
                    <property/>
                </properties>
            </terrain>
        </terraintypes>
    <tileset>"#).unwrap();
    assert_eq!(2, tileset.terrain_types().count());
    let mut terrain_types = tileset.terrain_types();

    let terrain1 = terrain_types.next().unwrap();
    assert_eq!("terrain1", terrain1.name());

    let terrain2 = terrain_types.next().unwrap();
    assert_eq!("tile-id", terrain2.tile());
    assert_eq!(1, terrain2.properties().count());
}

fn get_simple_valid_map() -> Map {
    Map::from_str(r#"<map version="1.0"
        orientation="orthogonal"
        width="200"
        height="100"
        tilewidth="16"
        tileheight="32"
        nextobjectid="1">
    </map>"#).unwrap()
}

fn get_map_with_tilesets() -> Map {
    Map::from_str("<map>
        <tileset></tileset>
        <tileset></tileset>
    </map>").unwrap()
}

fn get_map_with_layers() -> Map {
    Map::from_str(r#"<map>
        <layer name="layer1_name"/>
        <layer name="layer2_name" opacity="0"/>
        <layer name="layer3_name" visibility="0"/>
        <layer name="layer4_name" offsetx="1" offsety="2"/>
        <layer>
            <properties>
                <property name="some_name" value="some_value"/>
            </properties>
        </layer>
    </map>"#).unwrap()
}

fn get_map_with_image_layers() -> Map {
    Map::from_str(r#"<map>
        <imagelayer name="layer1_name"/>
        <imagelayer name="layer2_name" opacity="0"/>
        <imagelayer name="layer3_name" visibility="0"/>
        <imagelayer name="layer4_name" offsetx="1" offsety="2"/>
        <imagelayer>
            <properties>
                <property name="some_name" value="some_value"/>
            </properties>
        </imagelayer>
        <imagelayer>
            <image source="some_file.png"
                    width="1024"
                    height="768"/>
        </imagelayer>
    </map>"#).unwrap()
}

fn get_simple_valid_tileset() -> Tileset {
    Tileset::from_str(r#"<tileset firstgid="1"
                name="simple"
                tilewidth="32"
                tileheight="16"
                tilecount="100">
    </tileset>"#).unwrap()
}

fn get_map_with_objectgroups() -> Map {
    Map::from_str(r#"<map>
        <objectgroup name="some_name">
            <properties>
                <property/>
            </properties>
        </objectgroup>
        <objectgroup opacity="0" visibility="0" offsetx="1" offsety="2" draworder="index">
        </objectgroup>
    </map>"#).unwrap()
}

<|endoftext|>


<commit_before>use {osc_types, errors};

use std::{io, string, mem, error};
use std::io::BufRead;

use byteorder;
use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8], size: usize) -> osc_types::OscResult<osc_types::OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg, size)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(errors::OscError::BadOscPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8], size: usize) -> osc_types::OscResult<osc_types::OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);
    let mut pos: u64 = 0;

    match read_osc_string(&mut cursor) {
        Ok(s) => {
            let addr: String = s;
            println!("{}, {}", addr, pos);

            pad_cursor(&mut cursor);
        }
        Err(e) => {
            println!("{}", e)
        }
    }

    Ok(osc_types::OscPacket::Message(osc_types::OscMessage))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> osc_types::OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => String::from_utf8(str_buf).map_err(|e| errors::OscError::StringError(e)),
        Err(e) => Err(errors::OscError::ReadError(e)),
    }
}

fn decode_bundle(msg: &[u8]) -> osc_types::OscResult<osc_types::OscPacket> {
    Err(errors::OscError::BadOscBundle)
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    match pos % 4 {
        0 => (),
        d => cursor.set_position(pos + (4 - d)),
    }
}<commit_msg>Pad cursor after successfully reading an OscString<commit_after>use {osc_types, errors};

use std::{io, string, mem, error};
use std::io::BufRead;

use byteorder;
use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8], size: usize) -> osc_types::OscResult<osc_types::OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg, size)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(errors::OscError::BadOscPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8], size: usize) -> osc_types::OscResult<osc_types::OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);
    let mut pos: u64 = 0;

    match read_osc_string(&mut cursor) {
        Ok(s) => {
            let addr: String = s;
            println!("{}, {}", addr, pos);
        }
        Err(e) => {
            println!("{}", e)
        }
    }

    Ok(osc_types::OscPacket::Message(osc_types::OscMessage))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> osc_types::OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => {
            pad_cursor(cursor);
            String::from_utf8(str_buf).map_err(|e| errors::OscError::StringError(e))
        },
        Err(e) => Err(errors::OscError::ReadError(e)),
    }
}

fn decode_bundle(msg: &[u8]) -> osc_types::OscResult<osc_types::OscPacket> {
    Err(errors::OscError::BadOscBundle)
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    match pos % 4 {
        0 => (),
        d => cursor.set_position(pos + (4 - d)),
    }
}<|endoftext|>


<commit_before>extern crate tina;

use tina::*;

#[test]
fn it_should_find_pushed_element()
{
	let mut q = IndexedLimitedQueue::new(3);

	q.upsert("a".to_owned(), 1);
	q.upsert("b".to_owned(), 2);
	q.upsert("c".to_owned(), 3);

	assert_eq!(q.get("a"), Some(&1));
	assert_eq!(q.get("b"), Some(&2));
	assert_eq!(q.get("c"), Some(&3));
}

#[test]
fn it_should_update_element()
{
	let mut q = IndexedLimitedQueue::new(3);

	q.upsert("a".to_owned(), 1);
	q.upsert("b".to_owned(), 2);
	q.upsert("c".to_owned(), 3);
	q.upsert("b".to_owned(), 4);

	assert_eq!(q.get("a"), Some(&1));
	assert_eq!(q.get("b"), Some(&4));
	assert_eq!(q.get("c"), Some(&3));
}

#[test]
fn it_should_forget_element()
{
	let mut q = IndexedLimitedQueue::new(3);

	q.upsert("a".to_owned(), 1);
	q.upsert("b".to_owned(), 2);
	q.upsert("c".to_owned(), 3);
	q.upsert("d".to_owned(), 4);

	assert_eq!(q.get("a"), None);
	assert_eq!(q.get("b"), Some(&2));
}

#[test]
fn it_should_create_default_element()
{
	let mut q = IndexedLimitedQueue::new(3);

	q.upsert("a".to_owned(), 1);
	q.upsert("b".to_owned(), 2);
	q.upsert("c".to_owned(), 3);

	assert_eq!(q.get_mut_default("a".to_owned()), &1);
	assert_eq!(q.get_mut_default("d".to_owned()), &0);
	assert_eq!(q.get("a".to_owned()), None);
}

#[test]
fn it_should_return_old_element_when_upserting()
{
	let mut q = IndexedLimitedQueue::new(2);

	assert_eq!(q.upsert("a".to_owned(), 100), None);
	assert_eq!(q.upsert("a".to_owned(), 200), Some(100));
	assert_eq!(q.upsert("a".to_owned(), 300), Some(200));

	q.upsert("b".to_owned(), 100);
	q.upsert("c".to_owned(), 100);

	assert_eq!(q.upsert("a".to_owned(), 100), None);
}
<commit_msg>Remove unnecessary to_owned<commit_after>extern crate tina;

use tina::*;

#[test]
fn it_should_find_pushed_element()
{
	let mut q = IndexedLimitedQueue::new(3);

	q.upsert("a", 1);
	q.upsert("b", 2);
	q.upsert("c", 3);

	assert_eq!(q.get("a"), Some(&1));
	assert_eq!(q.get("b"), Some(&2));
	assert_eq!(q.get("c"), Some(&3));
}

#[test]
fn it_should_update_element()
{
	let mut q = IndexedLimitedQueue::new(3);

	q.upsert("a", 1);
	q.upsert("b", 2);
	q.upsert("c", 3);
	q.upsert("b", 4);

	assert_eq!(q.get("a"), Some(&1));
	assert_eq!(q.get("b"), Some(&4));
	assert_eq!(q.get("c"), Some(&3));
}

#[test]
fn it_should_forget_element()
{
	let mut q = IndexedLimitedQueue::new(3);

	q.upsert("a", 1);
	q.upsert("b", 2);
	q.upsert("c", 3);
	q.upsert("d", 4);

	assert_eq!(q.get("a"), None);
	assert_eq!(q.get("b"), Some(&2));
}

#[test]
fn it_should_create_default_element()
{
	let mut q = IndexedLimitedQueue::new(3);

	q.upsert("a", 1);
	q.upsert("b", 2);
	q.upsert("c", 3);

	assert_eq!(q.get_mut_default("a"), &1);
	assert_eq!(q.get_mut_default("d"), &0);
	assert_eq!(q.get("a"), None);
}

#[test]
fn it_should_return_old_element_when_upserting()
{
	let mut q = IndexedLimitedQueue::new(2);

	assert_eq!(q.upsert("a", 100), None);
	assert_eq!(q.upsert("a", 200), Some(100));
	assert_eq!(q.upsert("a", 300), Some(200));

	q.upsert("b", 100);
	q.upsert("c", 100);

	assert_eq!(q.upsert("a", 100), None);
}
<|endoftext|>


<commit_before>//! The core reactor driving all I/O.
//!
//! This module contains the [`Core`] reactor type which is the event loop for
//! all I/O happening in `tokio`. This core reactor (or event loop) is used to
//! drive I/O resources.
//!
//! The [`Handle`] and [`Remote`] structs are refences to the event loop,
//! created by the [`handle`][handle_method] and [`remote`][remote_method]
//! respectively, and are used to construct I/O objects. `Remote` is sendable,
//! while `Handle` is not.
//!
//! Lastly [`PollEvented`] can be used to construct I/O objects that interact
//! with the event loop, e.g. [`TcpStream`] in the net module.
//!
//! [`Core`]: struct.Core.html
//! [`Handle`]: struct.Handle.html
//! [`Remote`]: struct.Remote.html
//! [handle_method]: struct.Core.html#method.handle
//! [remote_method]: struct.Core.html#method.remote
//! [`PollEvented`]: struct.PollEvented.html
//! [`TcpStream`]: ../net/struct.TcpStream.html

use std::fmt;
use std::io::{self, ErrorKind};
use std::sync::{Arc, Weak, RwLock};
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
use std::time::{Duration};

use futures::{Future, Async};
use futures::executor::{self, Notify};
use futures::task::{AtomicTask};
use mio;
use mio::event::Evented;
use slab::Slab;

mod io_token;

mod poll_evented;
pub use self::poll_evented::PollEvented;

/// Global counter used to assign unique IDs to reactor instances.
static NEXT_LOOP_ID: AtomicUsize = ATOMIC_USIZE_INIT;

/// The core reactor, or event loop.
///
/// The event loop is the main source of blocking in an application which drives
/// all other I/O events and notifications happening. Each event loop can have
/// multiple handles pointing to it, each of which can then be used to create
/// various I/O objects to interact with the event loop in interesting ways.
pub struct Core {
    /// Reuse the `mio::Events` value across calls to poll.
    events: mio::Events,

    /// State shared between the reactor and the handles.
    inner: Arc<Inner>,

    /// Used for determining when the future passed to `run` is ready. Once the
    /// registration is passed to `io` above we never touch it again, just keep
    /// it alive.
    _future_registration: mio::Registration,
    future_readiness: Arc<MySetReadiness>,
}

struct Inner {
    /// Unique identifier referencing this reactor.
    id: usize,

    /// The underlying system event queue.
    io: mio::Poll,

    /// Dispatch slabs for I/O and futures events
    io_dispatch: RwLock<Slab<ScheduledIo>>,
}

/// A handle to an event loop.
///
/// A `Handle` is used for associating I/O objects with an event loop
/// explicitly. Typically though you won't end up using a `Handle` that often
/// and will instead use and implicitly configured handle for your thread.
#[derive(Clone)]
pub struct Handle {
    id: usize,
    inner: Weak<Inner>,
}

struct ScheduledIo {
    readiness: AtomicUsize,
    reader: AtomicTask,
    writer: AtomicTask,
}

enum Direction {
    Read,
    Write,
}

const TOKEN_FUTURE: mio::Token = mio::Token(1);
const TOKEN_START: usize = 2;

fn _assert_kinds() {
    fn _assert<T: Send + Sync>() {}

    _assert::<Handle>();
}

impl Core {
    /// Creates a new event loop, returning any error that happened during the
    /// creation.
    pub fn new() -> io::Result<Core> {
        // Create the I/O poller
        let io = try!(mio::Poll::new());

        // Create a registration for unblocking the reactor when the "run"
        // future becomes ready.
        let future_pair = mio::Registration::new2();
        try!(io.register(&future_pair.0,
                         TOKEN_FUTURE,
                         mio::Ready::readable(),
                         mio::PollOpt::level()));

        Ok(Core {
            events: mio::Events::with_capacity(1024),
            _future_registration: future_pair.0,
            future_readiness: Arc::new(MySetReadiness(future_pair.1)),
            inner: Arc::new(Inner {
                id: NEXT_LOOP_ID.fetch_add(1, Ordering::Relaxed),
                io: io,
                io_dispatch: RwLock::new(Slab::with_capacity(1)),
            }),
        })
    }

    /// Returns a handle to this event loop which cannot be sent across threads
    /// but can be used as a proxy to the event loop itself.
    ///
    /// Handles are cloneable and clones always refer to the same event loop.
    /// This handle is typically passed into functions that create I/O objects
    /// to bind them to this event loop.
    pub fn handle(&self) -> Handle {
        Handle {
            id: self.inner.id,
            inner: Arc::downgrade(&self.inner),
        }
    }

    /// Runs a future until completion, driving the event loop while we're
    /// otherwise waiting for the future to complete.
    ///
    /// This function will begin executing the event loop and will finish once
    /// the provided future is resolved. Note that the future argument here
    /// crucially does not require the `'static` nor `Send` bounds. As a result
    /// the future will be "pinned" to not only this thread but also this stack
    /// frame.
    ///
    /// This function will return the value that the future resolves to once
    /// the future has finished. If the future never resolves then this function
    /// will never return.
    ///
    /// # Panics
    ///
    /// This method will **not** catch panics from polling the future `f`. If
    /// the future panics then it's the responsibility of the caller to catch
    /// that panic and handle it as appropriate.
    pub fn run<F>(&mut self, f: F) -> Result<F::Item, F::Error>
        where F: Future,
    {
        let mut task = executor::spawn(f);
        let mut future_fired = true;

        loop {
            if future_fired {
                let res = task.poll_future_notify(&self.future_readiness, 0)?;
                if let Async::Ready(e) = res {
                    return Ok(e)
                }
            }
            future_fired = self.poll(None);
        }
    }

    /// Performs one iteration of the event loop, blocking on waiting for events
    /// for at most `max_wait` (forever if `None`).
    ///
    /// It only makes sense to call this method if you've previously spawned
    /// a future onto this event loop.
    ///
    /// `loop { lp.turn(None) }` is equivalent to calling `run` with an
    /// empty future (one that never finishes).
    pub fn turn(&mut self, max_wait: Option<Duration>) {
        self.poll(max_wait);
    }

    fn poll(&mut self, max_wait: Option<Duration>) -> bool {
        // Block waiting for an event to happen, peeling out how many events
        // happened.
        match self.inner.io.poll(&mut self.events, max_wait) {
            Ok(_) => {}
            Err(ref e) if e.kind() == ErrorKind::Interrupted => return false,
            // TODO: This should return an io::Result instead of panic.
            Err(e) => panic!("error in poll: {}", e),
        }

        // Process all the events that came in, dispatching appropriately
        let mut fired = false;
        for i in 0..self.events.len() {
            let event = self.events.get(i).unwrap();
            let token = event.token();
            trace!("event {:?} {:?}", event.readiness(), event.token());

            if token == TOKEN_FUTURE {
                self.future_readiness.0.set_readiness(mio::Ready::empty()).unwrap();
                fired = true;
            } else {
                self.dispatch(token, event.readiness());
            }
        }

        return fired
    }

    fn dispatch(&mut self, token: mio::Token, ready: mio::Ready) {
        let token = usize::from(token) - TOKEN_START;
        let io_dispatch = self.inner.io_dispatch.read().unwrap();

        if let Some(io) = io_dispatch.get(token) {
            io.readiness.fetch_or(ready2usize(ready), Ordering::Relaxed);
            if ready.is_writable() {
                io.writer.notify();
            }
            if !(ready & (!mio::Ready::writable())).is_empty() {
                io.reader.notify();
            }
        }
    }
}

impl fmt::Debug for Core {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Core")
    }
}

impl Inner {
    /// Register an I/O resource with the reactor.
    ///
    /// The registration token is returned.
    fn add_source(&self, source: &Evented)
        -> io::Result<usize>
    {
        // Acquire a write lock
        let key = self.io_dispatch.write().unwrap()
            .insert(ScheduledIo {
                readiness: AtomicUsize::new(0),
                reader: AtomicTask::new(),
                writer: AtomicTask::new(),
            });

        try!(self.io.register(source,
                              mio::Token(TOKEN_START + key),
                              mio::Ready::readable() |
                                mio::Ready::writable() |
                                platform::all(),
                              mio::PollOpt::edge()));

        Ok(key)
    }

    fn deregister_source(&self, source: &Evented) -> io::Result<()> {
        self.io.deregister(source)
    }

    fn drop_source(&self, token: usize) {
        debug!("dropping I/O source: {}", token);
        self.io_dispatch.write().unwrap().remove(token);
    }

    /// Registers interest in the I/O resource associated with `token`.
    fn schedule(&self, token: usize, dir: Direction) {
        debug!("scheduling direction for: {}", token);
        let io_dispatch = self.io_dispatch.read().unwrap();
        let sched = io_dispatch.get(token).unwrap();

        let (task, ready) = match dir {
            Direction::Read => (&sched.reader, !mio::Ready::writable()),
            Direction::Write => (&sched.writer, mio::Ready::writable()),
        };

        task.register();

        if sched.readiness.load(Ordering::SeqCst) & ready2usize(ready) != 0 {
            task.notify();
        }
    }
}

impl fmt::Debug for Handle {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Handle")
    }
}

struct MySetReadiness(mio::SetReadiness);

impl Notify for MySetReadiness {
    fn notify(&self, _id: usize) {
        self.0.set_readiness(mio::Ready::readable())
              .expect("failed to set readiness");
    }
}

fn read_ready() -> mio::Ready {
    mio::Ready::readable() | platform::hup()
}

const READ: usize = 1 << 0;
const WRITE: usize = 1 << 1;

fn ready2usize(ready: mio::Ready) -> usize {
    let mut bits = 0;
    if ready.is_readable() {
        bits |= READ;
    }
    if ready.is_writable() {
        bits |= WRITE;
    }
    bits | platform::ready2usize(ready)
}

fn usize2ready(bits: usize) -> mio::Ready {
    let mut ready = mio::Ready::empty();
    if bits & READ != 0 {
        ready.insert(mio::Ready::readable());
    }
    if bits & WRITE != 0 {
        ready.insert(mio::Ready::writable());
    }
    ready | platform::usize2ready(bits)
}

#[cfg(all(unix, not(target_os = "fuchsia")))]
mod platform {
    use mio::Ready;
    use mio::unix::UnixReady;

    pub fn aio() -> Ready {
        UnixReady::aio().into()
    }

    pub fn all() -> Ready {
        hup() | aio()
    }

    pub fn hup() -> Ready {
        UnixReady::hup().into()
    }

    const HUP: usize = 1 << 2;
    const ERROR: usize = 1 << 3;
    const AIO: usize = 1 << 4;

    pub fn ready2usize(ready: Ready) -> usize {
        let ready = UnixReady::from(ready);
        let mut bits = 0;
        if ready.is_aio() {
            bits |= AIO;
        }
        if ready.is_error() {
            bits |= ERROR;
        }
        if ready.is_hup() {
            bits |= HUP;
        }
        bits
    }

    pub fn usize2ready(bits: usize) -> Ready {
        let mut ready = UnixReady::from(Ready::empty());
        if bits & AIO != 0 {
            ready.insert(UnixReady::aio());
        }
        if bits & HUP != 0 {
            ready.insert(UnixReady::hup());
        }
        if bits & ERROR != 0 {
            ready.insert(UnixReady::error());
        }
        ready.into()
    }
}

#[cfg(any(windows, target_os = "fuchsia"))]
mod platform {
    use mio::Ready;

    pub fn all() -> Ready {
        // No platform-specific Readinesses for Windows
        Ready::empty()
    }

    pub fn hup() -> Ready {
        Ready::empty()
    }

    pub fn ready2usize(_r: Ready) -> usize {
        0
    }

    pub fn usize2ready(_r: usize) -> Ready {
        Ready::empty()
    }
}
<commit_msg>Remove `NEXT_LOOP_ID`<commit_after>//! The core reactor driving all I/O.
//!
//! This module contains the [`Core`] reactor type which is the event loop for
//! all I/O happening in `tokio`. This core reactor (or event loop) is used to
//! drive I/O resources.
//!
//! The [`Handle`] and [`Remote`] structs are refences to the event loop,
//! created by the [`handle`][handle_method] and [`remote`][remote_method]
//! respectively, and are used to construct I/O objects. `Remote` is sendable,
//! while `Handle` is not.
//!
//! Lastly [`PollEvented`] can be used to construct I/O objects that interact
//! with the event loop, e.g. [`TcpStream`] in the net module.
//!
//! [`Core`]: struct.Core.html
//! [`Handle`]: struct.Handle.html
//! [`Remote`]: struct.Remote.html
//! [handle_method]: struct.Core.html#method.handle
//! [remote_method]: struct.Core.html#method.remote
//! [`PollEvented`]: struct.PollEvented.html
//! [`TcpStream`]: ../net/struct.TcpStream.html

use std::fmt;
use std::io::{self, ErrorKind};
use std::sync::{Arc, Weak, RwLock};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::{Duration};

use futures::{Future, Async};
use futures::executor::{self, Notify};
use futures::task::{AtomicTask};
use mio;
use mio::event::Evented;
use slab::Slab;

mod io_token;

mod poll_evented;
pub use self::poll_evented::PollEvented;

/// The core reactor, or event loop.
///
/// The event loop is the main source of blocking in an application which drives
/// all other I/O events and notifications happening. Each event loop can have
/// multiple handles pointing to it, each of which can then be used to create
/// various I/O objects to interact with the event loop in interesting ways.
pub struct Core {
    /// Reuse the `mio::Events` value across calls to poll.
    events: mio::Events,

    /// State shared between the reactor and the handles.
    inner: Arc<Inner>,

    /// Used for determining when the future passed to `run` is ready. Once the
    /// registration is passed to `io` above we never touch it again, just keep
    /// it alive.
    _future_registration: mio::Registration,
    future_readiness: Arc<MySetReadiness>,
}

struct Inner {
    /// The underlying system event queue.
    io: mio::Poll,

    /// Dispatch slabs for I/O and futures events
    io_dispatch: RwLock<Slab<ScheduledIo>>,
}

/// A handle to an event loop.
///
/// A `Handle` is used for associating I/O objects with an event loop
/// explicitly. Typically though you won't end up using a `Handle` that often
/// and will instead use and implicitly configured handle for your thread.
#[derive(Clone)]
pub struct Handle {
    inner: Weak<Inner>,
}

struct ScheduledIo {
    readiness: AtomicUsize,
    reader: AtomicTask,
    writer: AtomicTask,
}

enum Direction {
    Read,
    Write,
}

const TOKEN_FUTURE: mio::Token = mio::Token(1);
const TOKEN_START: usize = 2;

fn _assert_kinds() {
    fn _assert<T: Send + Sync>() {}

    _assert::<Handle>();
}

impl Core {
    /// Creates a new event loop, returning any error that happened during the
    /// creation.
    pub fn new() -> io::Result<Core> {
        // Create the I/O poller
        let io = try!(mio::Poll::new());

        // Create a registration for unblocking the reactor when the "run"
        // future becomes ready.
        let future_pair = mio::Registration::new2();
        try!(io.register(&future_pair.0,
                         TOKEN_FUTURE,
                         mio::Ready::readable(),
                         mio::PollOpt::level()));

        Ok(Core {
            events: mio::Events::with_capacity(1024),
            _future_registration: future_pair.0,
            future_readiness: Arc::new(MySetReadiness(future_pair.1)),
            inner: Arc::new(Inner {
                io: io,
                io_dispatch: RwLock::new(Slab::with_capacity(1)),
            }),
        })
    }

    /// Returns a handle to this event loop which cannot be sent across threads
    /// but can be used as a proxy to the event loop itself.
    ///
    /// Handles are cloneable and clones always refer to the same event loop.
    /// This handle is typically passed into functions that create I/O objects
    /// to bind them to this event loop.
    pub fn handle(&self) -> Handle {
        Handle {
            inner: Arc::downgrade(&self.inner),
        }
    }

    /// Runs a future until completion, driving the event loop while we're
    /// otherwise waiting for the future to complete.
    ///
    /// This function will begin executing the event loop and will finish once
    /// the provided future is resolved. Note that the future argument here
    /// crucially does not require the `'static` nor `Send` bounds. As a result
    /// the future will be "pinned" to not only this thread but also this stack
    /// frame.
    ///
    /// This function will return the value that the future resolves to once
    /// the future has finished. If the future never resolves then this function
    /// will never return.
    ///
    /// # Panics
    ///
    /// This method will **not** catch panics from polling the future `f`. If
    /// the future panics then it's the responsibility of the caller to catch
    /// that panic and handle it as appropriate.
    pub fn run<F>(&mut self, f: F) -> Result<F::Item, F::Error>
        where F: Future,
    {
        let mut task = executor::spawn(f);
        let mut future_fired = true;

        loop {
            if future_fired {
                let res = task.poll_future_notify(&self.future_readiness, 0)?;
                if let Async::Ready(e) = res {
                    return Ok(e)
                }
            }
            future_fired = self.poll(None);
        }
    }

    /// Performs one iteration of the event loop, blocking on waiting for events
    /// for at most `max_wait` (forever if `None`).
    ///
    /// It only makes sense to call this method if you've previously spawned
    /// a future onto this event loop.
    ///
    /// `loop { lp.turn(None) }` is equivalent to calling `run` with an
    /// empty future (one that never finishes).
    pub fn turn(&mut self, max_wait: Option<Duration>) {
        self.poll(max_wait);
    }

    fn poll(&mut self, max_wait: Option<Duration>) -> bool {
        // Block waiting for an event to happen, peeling out how many events
        // happened.
        match self.inner.io.poll(&mut self.events, max_wait) {
            Ok(_) => {}
            Err(ref e) if e.kind() == ErrorKind::Interrupted => return false,
            // TODO: This should return an io::Result instead of panic.
            Err(e) => panic!("error in poll: {}", e),
        }

        // Process all the events that came in, dispatching appropriately
        let mut fired = false;
        for i in 0..self.events.len() {
            let event = self.events.get(i).unwrap();
            let token = event.token();
            trace!("event {:?} {:?}", event.readiness(), event.token());

            if token == TOKEN_FUTURE {
                self.future_readiness.0.set_readiness(mio::Ready::empty()).unwrap();
                fired = true;
            } else {
                self.dispatch(token, event.readiness());
            }
        }

        return fired
    }

    fn dispatch(&mut self, token: mio::Token, ready: mio::Ready) {
        let token = usize::from(token) - TOKEN_START;
        let io_dispatch = self.inner.io_dispatch.read().unwrap();

        if let Some(io) = io_dispatch.get(token) {
            io.readiness.fetch_or(ready2usize(ready), Ordering::Relaxed);
            if ready.is_writable() {
                io.writer.notify();
            }
            if !(ready & (!mio::Ready::writable())).is_empty() {
                io.reader.notify();
            }
        }
    }
}

impl fmt::Debug for Core {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Core")
    }
}

impl Inner {
    /// Register an I/O resource with the reactor.
    ///
    /// The registration token is returned.
    fn add_source(&self, source: &Evented)
        -> io::Result<usize>
    {
        // Acquire a write lock
        let key = self.io_dispatch.write().unwrap()
            .insert(ScheduledIo {
                readiness: AtomicUsize::new(0),
                reader: AtomicTask::new(),
                writer: AtomicTask::new(),
            });

        try!(self.io.register(source,
                              mio::Token(TOKEN_START + key),
                              mio::Ready::readable() |
                                mio::Ready::writable() |
                                platform::all(),
                              mio::PollOpt::edge()));

        Ok(key)
    }

    fn deregister_source(&self, source: &Evented) -> io::Result<()> {
        self.io.deregister(source)
    }

    fn drop_source(&self, token: usize) {
        debug!("dropping I/O source: {}", token);
        self.io_dispatch.write().unwrap().remove(token);
    }

    /// Registers interest in the I/O resource associated with `token`.
    fn schedule(&self, token: usize, dir: Direction) {
        debug!("scheduling direction for: {}", token);
        let io_dispatch = self.io_dispatch.read().unwrap();
        let sched = io_dispatch.get(token).unwrap();

        let (task, ready) = match dir {
            Direction::Read => (&sched.reader, !mio::Ready::writable()),
            Direction::Write => (&sched.writer, mio::Ready::writable()),
        };

        task.register();

        if sched.readiness.load(Ordering::SeqCst) & ready2usize(ready) != 0 {
            task.notify();
        }
    }
}

impl fmt::Debug for Handle {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Handle")
    }
}

struct MySetReadiness(mio::SetReadiness);

impl Notify for MySetReadiness {
    fn notify(&self, _id: usize) {
        self.0.set_readiness(mio::Ready::readable())
              .expect("failed to set readiness");
    }
}

fn read_ready() -> mio::Ready {
    mio::Ready::readable() | platform::hup()
}

const READ: usize = 1 << 0;
const WRITE: usize = 1 << 1;

fn ready2usize(ready: mio::Ready) -> usize {
    let mut bits = 0;
    if ready.is_readable() {
        bits |= READ;
    }
    if ready.is_writable() {
        bits |= WRITE;
    }
    bits | platform::ready2usize(ready)
}

fn usize2ready(bits: usize) -> mio::Ready {
    let mut ready = mio::Ready::empty();
    if bits & READ != 0 {
        ready.insert(mio::Ready::readable());
    }
    if bits & WRITE != 0 {
        ready.insert(mio::Ready::writable());
    }
    ready | platform::usize2ready(bits)
}

#[cfg(all(unix, not(target_os = "fuchsia")))]
mod platform {
    use mio::Ready;
    use mio::unix::UnixReady;

    pub fn aio() -> Ready {
        UnixReady::aio().into()
    }

    pub fn all() -> Ready {
        hup() | aio()
    }

    pub fn hup() -> Ready {
        UnixReady::hup().into()
    }

    const HUP: usize = 1 << 2;
    const ERROR: usize = 1 << 3;
    const AIO: usize = 1 << 4;

    pub fn ready2usize(ready: Ready) -> usize {
        let ready = UnixReady::from(ready);
        let mut bits = 0;
        if ready.is_aio() {
            bits |= AIO;
        }
        if ready.is_error() {
            bits |= ERROR;
        }
        if ready.is_hup() {
            bits |= HUP;
        }
        bits
    }

    pub fn usize2ready(bits: usize) -> Ready {
        let mut ready = UnixReady::from(Ready::empty());
        if bits & AIO != 0 {
            ready.insert(UnixReady::aio());
        }
        if bits & HUP != 0 {
            ready.insert(UnixReady::hup());
        }
        if bits & ERROR != 0 {
            ready.insert(UnixReady::error());
        }
        ready.into()
    }
}

#[cfg(any(windows, target_os = "fuchsia"))]
mod platform {
    use mio::Ready;

    pub fn all() -> Ready {
        // No platform-specific Readinesses for Windows
        Ready::empty()
    }

    pub fn hup() -> Ready {
        Ready::empty()
    }

    pub fn ready2usize(_r: Ready) -> usize {
        0
    }

    pub fn usize2ready(_r: usize) -> Ready {
        Ready::empty()
    }
}
<|endoftext|>