<commit_before>/// Used for immutable dereferencing operations, like `*v`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
///
/// Implementing `Deref` for smart pointers makes accessing the data behind them
/// convenient, which is why they implement `Deref`. On the other hand, the
/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
/// accommodate smart pointers. Because of this, **`Deref` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
///
/// * In immutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&T` are coerced to values of type `&U`
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`DerefMut`]: trait.DerefMut.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is accessible by dereferencing the
/// struct.
///
/// ```
/// use std::ops::Deref;
///
/// struct DerefExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &Self::Target {
///         &self.value
///     }
/// }
///
/// let x = DerefExample { value: 'a' };
/// assert_eq!('a', *x);
/// ```
#[lang = "deref"]
#[doc(alias = "*")]
#[doc(alias = "&*")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Deref {
    /// The resulting type after dereferencing.
    #[stable(feature = "rust1", since = "1.0.0")]
    type Target: ?Sized;

    /// Dereferences the value.
    #[must_use]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref(&self) -> &Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &mut T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

/// Used for mutable dereferencing operations, like in `*v = 1;`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
///
/// Implementing `DerefMut` for smart pointers makes mutating the data behind
/// them convenient, which is why they implement `DerefMut`. On the other hand,
/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
/// accommodate smart pointers. Because of this, **`DerefMut` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `DerefMut` is invoked
/// implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
/// then:
///
/// * In mutable contexts, `*x` on non-pointer types is equivalent to
///   `*DerefMut::deref_mut(&mut x)`.
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`Deref`]: trait.Deref.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is modifiable by dereferencing the
/// struct.
///
/// ```
/// use std::ops::{Deref, DerefMut};
///
/// struct DerefMutExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefMutExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &Self::Target {
///         &self.value
///     }
/// }
///
/// impl<T> DerefMut for DerefMutExample<T> {
///     fn deref_mut(&mut self) -> &mut Self::Target {
///         &mut self.value
///     }
/// }
///
/// let mut x = DerefMutExample { value: 'a' };
/// *x = 'b';
/// assert_eq!('b', *x);
/// ```
#[lang = "deref_mut"]
#[doc(alias = "*")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DerefMut: Deref {
    /// Mutably dereferences the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref_mut(&mut self) -> &mut Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for &mut T {
    fn deref_mut(&mut self) -> &mut T { *self }
}

/// Indicates that a struct can be used as a method receiver, without the
/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
/// `Rc<T>`, `&T`, and `Pin<P>`.
#[lang = "receiver"]
#[unstable(feature = "receiver_trait", issue = "0")]
#[doc(hidden)]
pub trait Receiver {
    // Empty.
}

#[unstable(feature = "receiver_trait", issue = "0")]
impl<T: ?Sized> Receiver for &T {}

#[unstable(feature = "receiver_trait", issue = "0")]
impl<T: ?Sized> Receiver for &mut T {}
<commit_msg>Fix links in Deref documentation<commit_after>/// Used for immutable dereferencing operations, like `*v`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
///
/// Implementing `Deref` for smart pointers makes accessing the data behind them
/// convenient, which is why they implement `Deref`. On the other hand, the
/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
/// accommodate smart pointers. Because of this, **`Deref` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
///
/// * In immutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&T` are coerced to values of type `&U`
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*][book]
/// as well as the reference sections on [the dereference operator][ref-deref-op],
/// [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`DerefMut`]: trait.DerefMut.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is accessible by dereferencing the
/// struct.
///
/// ```
/// use std::ops::Deref;
///
/// struct DerefExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &Self::Target {
///         &self.value
///     }
/// }
///
/// let x = DerefExample { value: 'a' };
/// assert_eq!('a', *x);
/// ```
#[lang = "deref"]
#[doc(alias = "*")]
#[doc(alias = "&*")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Deref {
    /// The resulting type after dereferencing.
    #[stable(feature = "rust1", since = "1.0.0")]
    type Target: ?Sized;

    /// Dereferences the value.
    #[must_use]
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref(&self) -> &Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for &mut T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

/// Used for mutable dereferencing operations, like in `*v = 1;`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
///
/// Implementing `DerefMut` for smart pointers makes mutating the data behind
/// them convenient, which is why they implement `DerefMut`. On the other hand,
/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
/// accommodate smart pointers. Because of this, **`DerefMut` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `DerefMut` is invoked
/// implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
/// then:
///
/// * In mutable contexts, `*x` on non-pointer types is equivalent to
///   `*DerefMut::deref_mut(&mut x)`.
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*][book]
/// as well as the reference sections on [the dereference operator][ref-deref-op],
/// [method resolution] and [type coercions].
///
/// [book]: ../../book/ch15-02-deref.html
/// [`Deref`]: trait.Deref.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions/operator-expr.html#the-dereference-operator
/// [method resolution]: ../../reference/expressions/method-call-expr.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is modifiable by dereferencing the
/// struct.
///
/// ```
/// use std::ops::{Deref, DerefMut};
///
/// struct DerefMutExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefMutExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &Self::Target {
///         &self.value
///     }
/// }
///
/// impl<T> DerefMut for DerefMutExample<T> {
///     fn deref_mut(&mut self) -> &mut Self::Target {
///         &mut self.value
///     }
/// }
///
/// let mut x = DerefMutExample { value: 'a' };
/// *x = 'b';
/// assert_eq!('b', *x);
/// ```
#[lang = "deref_mut"]
#[doc(alias = "*")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DerefMut: Deref {
    /// Mutably dereferences the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref_mut(&mut self) -> &mut Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for &mut T {
    fn deref_mut(&mut self) -> &mut T { *self }
}

/// Indicates that a struct can be used as a method receiver, without the
/// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box<T>`,
/// `Rc<T>`, `&T`, and `Pin<P>`.
#[lang = "receiver"]
#[unstable(feature = "receiver_trait", issue = "0")]
#[doc(hidden)]
pub trait Receiver {
    // Empty.
}

#[unstable(feature = "receiver_trait", issue = "0")]
impl<T: ?Sized> Receiver for &T {}

#[unstable(feature = "receiver_trait", issue = "0")]
impl<T: ?Sized> Receiver for &mut T {}
<|endoftext|>


<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.

//! An experimental pass that scources for `#[rustc_mir]` attributes,
//! builds the resulting MIR, and dumps it out into a file for inspection.
//!
//! The attribute formats that are currently accepted are:
//!
//! - `#[rustc_mir(graphviz="file.gv")]`
//! - `#[rustc_mir(pretty="file.mir")]`

extern crate syntax;
extern crate rustc;
extern crate rustc_front;

use build;
use dot;
use repr::Mir;
use std::fs::File;
use tcx::{PatNode, Cx};

use self::rustc::middle::infer;
use self::rustc::middle::region::CodeExtentData;
use self::rustc::middle::ty::{self, Ty};
use self::rustc::util::common::ErrorReported;
use self::rustc_front::hir;
use self::rustc_front::visit;
use self::syntax::ast;
use self::syntax::attr::AttrMetaMethods;
use self::syntax::codemap::Span;

pub fn dump_crate(tcx: &ty::ctxt) {
    let mut dump = OuterDump { tcx: tcx };
    visit::walk_crate(&mut dump, tcx.map.krate());
}

///////////////////////////////////////////////////////////////////////////
// OuterDump -- walks a crate, looking for fn items and methods to build MIR from

struct OuterDump<'a,'tcx:'a> {
    tcx: &'a ty::ctxt<'tcx>,
}

impl<'a, 'tcx> OuterDump<'a, 'tcx> {
    fn visit_mir<OP>(&self, attributes: &'tcx [ast::Attribute], mut walk_op: OP)
        where OP: FnMut(&mut InnerDump<'a,'tcx>)
    {
        let mut built_mir = false;

        let mut closure_dump = InnerDump { tcx: self.tcx, attr: None };
        for attr in attributes {
            if attr.check_name("rustc_mir") {
                closure_dump.attr = Some(attr);
            }
        }

        walk_op(&mut closure_dump);
    }
}

impl<'a, 'tcx> visit::Visitor<'tcx> for OuterDump<'a, 'tcx> {
    fn visit_item(&mut self, item: &'tcx hir::Item) {
        self.visit_mir(&item.attrs, |c| visit::walk_item(c, item));
        visit::walk_item(self, item);
    }

    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
        match trait_item.node {
            hir::MethodTraitItem(_, Some(_)) => {
                self.visit_mir(&trait_item.attrs, |c| visit::walk_trait_item(c, trait_item));
            }
            _ => { }
        }
        visit::walk_trait_item(self, trait_item);
    }
}

///////////////////////////////////////////////////////////////////////////
// InnerDump -- dumps MIR for a single fn and its contained closures

struct InnerDump<'a,'tcx:'a> {
    tcx: &'a ty::ctxt<'tcx>,
    attr: Option<&'a ast::Attribute>,
}

impl<'a, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'tcx> {
    fn visit_item(&mut self, _: &'tcx hir::Item) {
        // ignore nested items; they need their own graphviz annotation
    }

    fn visit_fn(&mut self,
                fk: visit::FnKind<'tcx>,
                decl: &'tcx hir::FnDecl,
                body: &'tcx hir::Block,
                span: Span,
                id: ast::NodeId) {
        let (prefix, implicit_arg_tys) = match fk {
            visit::FnKind::Closure =>
                (format!("{}-", id), vec![closure_self_ty(&self.tcx, id, body.id)]),
            _ =>
                (format!(""), vec![]),
        };

        let param_env =
            ty::ParameterEnvironment::for_item(self.tcx, id);

        let infcx =
            infer::new_infer_ctxt(self.tcx,
                                  &self.tcx.tables,
                                  Some(param_env),
                                  true);

        match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) {
            Ok(mir) => {
                let meta_item_list =
                    self.attr.iter()
                             .flat_map(|a| a.meta_item_list())
                             .flat_map(|l| l.iter());
                for item in meta_item_list {
                    if item.check_name("graphviz") {
                        match item.value_str() {
                            Some(s) => {
                                match
                                    File::create(format!("{}{}", prefix, s))
                                    .and_then(|ref mut output| dot::render(&mir, output))
                                {
                                    Ok(()) => { }
                                    Err(e) => {
                                        self.tcx.sess.span_fatal(
                                            item.span,
                                            &format!("Error writing graphviz \
                                                      results to `{}`: {}",
                                                     s, e));
                                    }
                                }
                            }
                            None => {
                                self.tcx.sess.span_err(
                                    item.span,
                                    &format!("graphviz attribute requires a path"));
                            }
                        }
                    }
                }
            }
            Err(ErrorReported) => { }
        }

        visit::walk_fn(self, fk, decl, body, span);
    }
}

fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
                         implicit_arg_tys: Vec<Ty<'tcx>>,
                         fn_id: ast::NodeId,
                         span: Span,
                         decl: &'tcx hir::FnDecl,
                         body: &'tcx hir::Block)
                         -> Result<Mir<'tcx>, ErrorReported> {
    let arguments =
        decl.inputs
            .iter()
            .map(|arg| {
                let ty = cx.tcx().node_id_to_type(arg.id);
                (ty, PatNode::irrefutable(&arg.pat))
            })
            .collect();

    let parameter_scope =
        cx.tcx().region_maps.lookup_code_extent(
            CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id });
    Ok(build::construct(cx,
                        span,
                        implicit_arg_tys,
                        arguments,
                        parameter_scope,
                        body))
}

fn closure_self_ty<'a,'tcx>(tcx: &ty::ctxt<'tcx>,
                            closure_expr_id: ast::NodeId,
                            body_id: ast::NodeId)
                            -> Ty<'tcx>
{
    let closure_ty = tcx.node_id_to_type(closure_expr_id);

    // We're just hard-coding the idea that the signature will be
    // &self or &mut self and hence will have a bound region with
    // number 0, hokey.
    let region =
        ty::Region::ReFree(
            ty::FreeRegion {
                scope: tcx.region_maps.item_extent(body_id),
                bound_region: ty::BoundRegion::BrAnon(0)
            });
    let region =
        tcx.mk_region(region);

    match tcx.closure_kind(tcx.map.local_def_id(closure_expr_id)) {
        ty::ClosureKind::FnClosureKind =>
            tcx.mk_ref(region,
                       ty::TypeAndMut { ty: closure_ty,
                                        mutbl: hir::MutImmutable }),
        ty::ClosureKind::FnMutClosureKind =>
            tcx.mk_ref(region,
                       ty::TypeAndMut { ty: closure_ty,
                                        mutbl: hir::MutMutable }),
        ty::ClosureKind::FnOnceClosureKind =>
            closure_ty
    }
}
<commit_msg>store the mir into a map, restructure to avoid rebuilding so many times<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.

//! An experimental pass that scources for `#[rustc_mir]` attributes,
//! builds the resulting MIR, and dumps it out into a file for inspection.
//!
//! The attribute formats that are currently accepted are:
//!
//! - `#[rustc_mir(graphviz="file.gv")]`
//! - `#[rustc_mir(pretty="file.mir")]`

extern crate syntax;
extern crate rustc;
extern crate rustc_front;

use build;
use dot;
use repr::Mir;
use std::fs::File;
use tcx::{PatNode, Cx};

use self::rustc::middle::infer;
use self::rustc::middle::region::CodeExtentData;
use self::rustc::middle::ty::{self, Ty};
use self::rustc::util::common::ErrorReported;
use self::rustc::util::nodemap::NodeMap;
use self::rustc_front::hir;
use self::rustc_front::visit;
use self::syntax::ast;
use self::syntax::attr::AttrMetaMethods;
use self::syntax::codemap::Span;

pub fn dump_crate(tcx: &ty::ctxt) {
    let mut map = NodeMap();
    let mut dump = OuterDump { tcx: tcx, map: &mut map };
    visit::walk_crate(&mut dump, tcx.map.krate());
}

///////////////////////////////////////////////////////////////////////////
// OuterDump -- walks a crate, looking for fn items and methods to build MIR from

struct OuterDump<'a,'tcx:'a> {
    tcx: &'a ty::ctxt<'tcx>,
    map: &'a mut NodeMap<Mir<'tcx>>,
}

impl<'a, 'tcx> OuterDump<'a, 'tcx> {
    fn visit_mir<OP>(&mut self, attributes: &'a [ast::Attribute], mut walk_op: OP)
        where OP: for<'m> FnMut(&mut InnerDump<'a,'m,'tcx>)
    {
        let mut closure_dump = InnerDump { tcx: self.tcx, attr: None, map: &mut *self.map };
        for attr in attributes {
            if attr.check_name("rustc_mir") {
                closure_dump.attr = Some(attr);
            }
        }
        walk_op(&mut closure_dump);
    }
}

impl<'a, 'tcx> visit::Visitor<'tcx> for OuterDump<'a, 'tcx> {
    fn visit_item(&mut self, item: &'tcx hir::Item) {
        self.visit_mir(&item.attrs, |c| visit::walk_item(c, item));
        visit::walk_item(self, item);
    }

    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
        match trait_item.node {
            hir::MethodTraitItem(_, Some(_)) => {
                self.visit_mir(&trait_item.attrs, |c| visit::walk_trait_item(c, trait_item));
            }
            hir::MethodTraitItem(_, None) |
            hir::ConstTraitItem(..) |
            hir::TypeTraitItem(..) => {
            }
        }
        visit::walk_trait_item(self, trait_item);
    }

    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
        match impl_item.node {
            hir::MethodImplItem(..) => {
                self.visit_mir(&impl_item.attrs, |c| visit::walk_impl_item(c, impl_item));
            }
            hir::ConstImplItem(..) | hir::TypeImplItem(..) => { }
        }
        visit::walk_impl_item(self, impl_item);
    }
}

///////////////////////////////////////////////////////////////////////////
// InnerDump -- dumps MIR for a single fn and its contained closures

struct InnerDump<'a,'m,'tcx:'a+'m> {
    tcx: &'a ty::ctxt<'tcx>,
    map: &'m mut NodeMap<Mir<'tcx>>,
    attr: Option<&'a ast::Attribute>,
}

impl<'a, 'm, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
    fn visit_item(&mut self, _: &'tcx hir::Item) {
        // ignore nested items; they need their own graphviz annotation
    }

    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {
        // ignore nested items; they need their own graphviz annotation
    }

    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {
        // ignore nested items; they need their own graphviz annotation
    }

    fn visit_fn(&mut self,
                fk: visit::FnKind<'tcx>,
                decl: &'tcx hir::FnDecl,
                body: &'tcx hir::Block,
                span: Span,
                id: ast::NodeId) {
        let (prefix, implicit_arg_tys) = match fk {
            visit::FnKind::Closure =>
                (format!("{}-", id), vec![closure_self_ty(&self.tcx, id, body.id)]),
            _ =>
                (format!(""), vec![]),
        };

        let param_env =
            ty::ParameterEnvironment::for_item(self.tcx, id);

        let infcx =
            infer::new_infer_ctxt(self.tcx,
                                  &self.tcx.tables,
                                  Some(param_env),
                                  true);

        match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) {
            Ok(mir) => {
                let meta_item_list =
                    self.attr.iter()
                             .flat_map(|a| a.meta_item_list())
                             .flat_map(|l| l.iter());
                for item in meta_item_list {
                    if item.check_name("graphviz") {
                        match item.value_str() {
                            Some(s) => {
                                match
                                    File::create(format!("{}{}", prefix, s))
                                    .and_then(|ref mut output| dot::render(&mir, output))
                                {
                                    Ok(()) => { }
                                    Err(e) => {
                                        self.tcx.sess.span_fatal(
                                            item.span,
                                            &format!("Error writing graphviz \
                                                      results to `{}`: {}",
                                                     s, e));
                                    }
                                }
                            }
                            None => {
                                self.tcx.sess.span_err(
                                    item.span,
                                    &format!("graphviz attribute requires a path"));
                            }
                        }
                    }
                }

                let previous = self.map.insert(id, mir);
                assert!(previous.is_none());
            }
            Err(ErrorReported) => { }
        }

        visit::walk_fn(self, fk, decl, body, span);
    }
}

fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
                         implicit_arg_tys: Vec<Ty<'tcx>>,
                         fn_id: ast::NodeId,
                         span: Span,
                         decl: &'tcx hir::FnDecl,
                         body: &'tcx hir::Block)
                         -> Result<Mir<'tcx>, ErrorReported> {
    let arguments =
        decl.inputs
            .iter()
            .map(|arg| {
                let ty = cx.tcx().node_id_to_type(arg.id);
                (ty, PatNode::irrefutable(&arg.pat))
            })
            .collect();

    let parameter_scope =
        cx.tcx().region_maps.lookup_code_extent(
            CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id });
    Ok(build::construct(cx,
                        span,
                        implicit_arg_tys,
                        arguments,
                        parameter_scope,
                        body))
}

fn closure_self_ty<'a,'tcx>(tcx: &ty::ctxt<'tcx>,
                            closure_expr_id: ast::NodeId,
                            body_id: ast::NodeId)
                            -> Ty<'tcx>
{
    let closure_ty = tcx.node_id_to_type(closure_expr_id);

    // We're just hard-coding the idea that the signature will be
    // &self or &mut self and hence will have a bound region with
    // number 0, hokey.
    let region =
        ty::Region::ReFree(
            ty::FreeRegion {
                scope: tcx.region_maps.item_extent(body_id),
                bound_region: ty::BoundRegion::BrAnon(0)
            });
    let region =
        tcx.mk_region(region);

    match tcx.closure_kind(tcx.map.local_def_id(closure_expr_id)) {
        ty::ClosureKind::FnClosureKind =>
            tcx.mk_ref(region,
                       ty::TypeAndMut { ty: closure_ty,
                                        mutbl: hir::MutImmutable }),
        ty::ClosureKind::FnMutClosureKind =>
            tcx.mk_ref(region,
                       ty::TypeAndMut { ty: closure_ty,
                                        mutbl: hir::MutMutable }),
        ty::ClosureKind::FnOnceClosureKind =>
            closure_ty
    }
}
<|endoftext|>


<commit_before>#[cfg(test)]
extern crate assert_cli;
extern crate boxcars;
extern crate failure;
extern crate globset;
extern crate rayon;
extern crate serde_json;
#[macro_use]
extern crate structopt;

use failure::{err_msg, Error, ResultExt};
use structopt::StructOpt;
use std::fs::{File, OpenOptions};
use std::io::{self, BufWriter};
use std::io::prelude::*;
use rayon::prelude::*;
use boxcars::{CrcCheck, NetworkParse, ParserBuilder, Replay};
use std::path::Path;
use globset::Glob;

#[derive(StructOpt, Debug, Clone, PartialEq)]
#[structopt(name = "rrrocket",
            about = "Parses Rocket League replay files and outputs JSON with decoded information")]
struct Opt {
    #[structopt(short = "c", long = "crc-check", help = "forces a crc check for corruption even when replay was successfully parsed")]
    crc: bool,

    #[structopt(short = "n", long = "network-parse", help = "parses the network data of a replay instead of skipping it")]
    body: bool,

    #[structopt(short = "m", long = "multiple", help = "parse multiple replays, instead of writing JSON to stdout, write to a sibling JSON file")]
    multiple: bool,

    #[structopt(long = "dry-run", help = "parses but does not write JSON output")]
    dry_run: bool,

    #[structopt(help = "Rocket League replay files")] input: Vec<String>,
}

fn read_file(input: &str) -> Result<Vec<u8>, Error> {
    let mut f = File::open(input)
        .with_context(|_e| format!("Could not open rocket league file: {}", input))?;
    let mut buffer = vec![];
    f.read_to_end(&mut buffer)
        .with_context(|_e| format!("Could not read rocket league file: {}", input))?;
    Ok(buffer)
}

fn parse_replay<'a>(opt: &Opt, data: &'a [u8]) -> Result<Replay<'a>, Error> {
    ParserBuilder::new(&data[..])
        .with_crc_check(if opt.crc {
            CrcCheck::Always
        } else {
            CrcCheck::OnError
        })
        .with_network_parse(if opt.body {
            NetworkParse::Always
        } else {
            NetworkParse::Never
        })
        .parse()
}

/// Each file argument that we get could be a directory so we need to expand that directory and
/// find all the *.replay files. File arguments turn into single element vectors.
fn expand_paths(files: &[String]) -> Result<Vec<Vec<String>>, Error> {
    let glob = Glob::new("*.replay")?.compile_matcher();

    files
        .iter()
        .map(|x| {
            let p = Path::new(x);
            if p.is_dir() {
                // If the commandline argument is a directory we look for all files that match
                // *.replay. A file that does not match the pattern because of an error reading the
                // directory / file will not be filtered and will cause the error to bubble up. In
                // the future, we could get smart and ignore directories / files we don't have
                // permission that wouldn't match the pattern anyways
                let files: Result<Vec<_>, _> = p.read_dir()?
                    .filter_map(|entry| {
                        match entry {
                            Ok(y) => {
                                if glob.is_match(y.path()) {
                                    // Force UTF-8. There is a special place in the fourth circle
                                    // of inferno for people who rename their rocket league replays
                                    // to not contain UTF-8. We won't panic, but will cause an
                                    // error when the file is attempted to be read.
                                    Some(Ok(y.path().to_string_lossy().into_owned()))
                                } else {
                                    None
                                }
                            }
                            Err(e) => Some(Err(e)),
                        }
                    })
                    .collect();
                Ok(files?)
            } else {
                Ok(vec![x.clone()])
            }
        })
        .collect()
}

fn parse_multiple_replays(opt: &Opt) -> Result<(), Error> {
    let res: Result<Vec<()>, Error> = expand_paths(&opt.input)?
        .into_iter()
        .flat_map(|x| x)
        .collect::<Vec<_>>()
        .par_iter()
        .map(|file| {
            let data = read_file(file)?;
            let replay = parse_replay(opt, &data[..])
                .with_context(|_e| format!("Could not parse: {}", file))?;

            if !opt.dry_run {
                let outfile = format!("{}.json", file);
                let fout = OpenOptions::new()
                    .write(true)
                    .create(true)
                    .truncate(true)
                    .open(&outfile)
                    .with_context(|_e| format!("Could not open json output file: {}", outfile))?;

                let mut writer = BufWriter::new(fout);
                serde_json::to_writer(&mut writer, &replay)
                    .with_context(|_e| format!("Could not serialize replay {}", file))?;
            }
            Ok(())
        })
        .collect();
    res?;
    Ok(())
}

fn run() -> Result<(), Error> {
    let opt = Opt::from_args();
    if opt.multiple {
        parse_multiple_replays(&opt)
    } else if opt.input.len() != 1 {
        Err(err_msg(
            "Expected one input file if --multiple is not specified",
        ))
    } else {
        let file = &opt.input[0];
        let data = read_file(file)?;
        let replay = parse_replay(&opt, &data[..]).context("Could not parse replay")?;
        if !opt.dry_run {
            serde_json::to_writer(&mut io::stdout(), &replay)
                .context("Could not serialize replay")?;
        }
        Ok(())
    }
}

fn main() {
    if let Err(ref e) = run() {
        let mut stderr = io::stderr();
        for fail in e.causes() {
            let _ = writeln!(stderr, "{}", fail);
        }

        ::std::process::exit(1);
    }
}

#[cfg(test)]
mod tests {
    use assert_cli::Assert;
    use std::io::Write;

    #[test]
    fn test_error_output() {
        let mut w = Vec::new();
        writeln!(
            &mut w,
            "Could not open rocket league file: assets/fuzz-string-too-long.replay"
        ).unwrap();
        writeln!(&mut w, "No such file or directory (os error 2)").unwrap();

        Assert::cargo_binary("rrrocket")
            .with_args(&[
                "-n",
                "-c",
                "--dry-run",
                "assets/fuzz-string-too-long.replay",
            ])
            .fails_with(1)
            .stderr()
            .contains(String::from_utf8(w).unwrap())
            .unwrap();
    }

    #[test]
    fn test_error_output2() {
        let mut w = Vec::new();
        writeln!(
            &mut w,
            "Could not parse: ../assets/fuzz-string-too-long.replay"
        ).unwrap();
        writeln!(
            &mut w,
            "Crc mismatch. Expected 3765941959 but received 1825689991"
        ).unwrap();

        Assert::cargo_binary("rrrocket")
            .with_args(&[
                "-n",
                "-c",
                "--dry-run",
                "-m",
                "../assets/fuzz-string-too-long.replay",
            ])
            .fails_with(1)
            .stderr()
            .contains(String::from_utf8(w).unwrap())
            .unwrap();
    }
}
<commit_msg>Fix windows tests<commit_after>#[cfg(test)]
extern crate assert_cli;
extern crate boxcars;
extern crate failure;
extern crate globset;
extern crate rayon;
extern crate serde_json;
#[macro_use]
extern crate structopt;

use failure::{err_msg, Error, ResultExt};
use structopt::StructOpt;
use std::fs::{File, OpenOptions};
use std::io::{self, BufWriter};
use std::io::prelude::*;
use rayon::prelude::*;
use boxcars::{CrcCheck, NetworkParse, ParserBuilder, Replay};
use std::path::Path;
use globset::Glob;

#[derive(StructOpt, Debug, Clone, PartialEq)]
#[structopt(name = "rrrocket",
            about = "Parses Rocket League replay files and outputs JSON with decoded information")]
struct Opt {
    #[structopt(short = "c", long = "crc-check", help = "forces a crc check for corruption even when replay was successfully parsed")]
    crc: bool,

    #[structopt(short = "n", long = "network-parse", help = "parses the network data of a replay instead of skipping it")]
    body: bool,

    #[structopt(short = "m", long = "multiple", help = "parse multiple replays, instead of writing JSON to stdout, write to a sibling JSON file")]
    multiple: bool,

    #[structopt(long = "dry-run", help = "parses but does not write JSON output")]
    dry_run: bool,

    #[structopt(help = "Rocket League replay files")] input: Vec<String>,
}

fn read_file(input: &str) -> Result<Vec<u8>, Error> {
    let mut f = File::open(input)
        .with_context(|_e| format!("Could not open rocket league file: {}", input))?;
    let mut buffer = vec![];
    f.read_to_end(&mut buffer)
        .with_context(|_e| format!("Could not read rocket league file: {}", input))?;
    Ok(buffer)
}

fn parse_replay<'a>(opt: &Opt, data: &'a [u8]) -> Result<Replay<'a>, Error> {
    ParserBuilder::new(&data[..])
        .with_crc_check(if opt.crc {
            CrcCheck::Always
        } else {
            CrcCheck::OnError
        })
        .with_network_parse(if opt.body {
            NetworkParse::Always
        } else {
            NetworkParse::Never
        })
        .parse()
}

/// Each file argument that we get could be a directory so we need to expand that directory and
/// find all the *.replay files. File arguments turn into single element vectors.
fn expand_paths(files: &[String]) -> Result<Vec<Vec<String>>, Error> {
    let glob = Glob::new("*.replay")?.compile_matcher();

    files
        .iter()
        .map(|x| {
            let p = Path::new(x);
            if p.is_dir() {
                // If the commandline argument is a directory we look for all files that match
                // *.replay. A file that does not match the pattern because of an error reading the
                // directory / file will not be filtered and will cause the error to bubble up. In
                // the future, we could get smart and ignore directories / files we don't have
                // permission that wouldn't match the pattern anyways
                let files: Result<Vec<_>, _> = p.read_dir()?
                    .filter_map(|entry| {
                        match entry {
                            Ok(y) => {
                                if glob.is_match(y.path()) {
                                    // Force UTF-8. There is a special place in the fourth circle
                                    // of inferno for people who rename their rocket league replays
                                    // to not contain UTF-8. We won't panic, but will cause an
                                    // error when the file is attempted to be read.
                                    Some(Ok(y.path().to_string_lossy().into_owned()))
                                } else {
                                    None
                                }
                            }
                            Err(e) => Some(Err(e)),
                        }
                    })
                    .collect();
                Ok(files?)
            } else {
                Ok(vec![x.clone()])
            }
        })
        .collect()
}

fn parse_multiple_replays(opt: &Opt) -> Result<(), Error> {
    let res: Result<Vec<()>, Error> = expand_paths(&opt.input)?
        .into_iter()
        .flat_map(|x| x)
        .collect::<Vec<_>>()
        .par_iter()
        .map(|file| {
            let data = read_file(file)?;
            let replay = parse_replay(opt, &data[..])
                .with_context(|_e| format!("Could not parse: {}", file))?;

            if !opt.dry_run {
                let outfile = format!("{}.json", file);
                let fout = OpenOptions::new()
                    .write(true)
                    .create(true)
                    .truncate(true)
                    .open(&outfile)
                    .with_context(|_e| format!("Could not open json output file: {}", outfile))?;

                let mut writer = BufWriter::new(fout);
                serde_json::to_writer(&mut writer, &replay)
                    .with_context(|_e| format!("Could not serialize replay {}", file))?;
            }
            Ok(())
        })
        .collect();
    res?;
    Ok(())
}

fn run() -> Result<(), Error> {
    let opt = Opt::from_args();
    if opt.multiple {
        parse_multiple_replays(&opt)
    } else if opt.input.len() != 1 {
        Err(err_msg(
            "Expected one input file if --multiple is not specified",
        ))
    } else {
        let file = &opt.input[0];
        let data = read_file(file)?;
        let replay = parse_replay(&opt, &data[..]).context("Could not parse replay")?;
        if !opt.dry_run {
            serde_json::to_writer(&mut io::stdout(), &replay)
                .context("Could not serialize replay")?;
        }
        Ok(())
    }
}

fn main() {
    if let Err(ref e) = run() {
        let mut stderr = io::stderr();
        for fail in e.causes() {
            let _ = writeln!(stderr, "{}", fail);
        }

        ::std::process::exit(1);
    }
}

#[cfg(test)]
mod tests {
    use assert_cli::Assert;
    use std::io::Write;

    #[test]
    fn test_error_output() {
        let mut w = Vec::new();
        writeln!(
            &mut w,
            "Could not open rocket league file: assets/fuzz-string-too-long.replay"
        ).unwrap();

        Assert::cargo_binary("rrrocket")
            .with_args(&[
                "-n",
                "-c",
                "--dry-run",
                "assets/fuzz-string-too-long.replay",
            ])
            .fails_with(1)
            .stderr()
            .contains(String::from_utf8(w).unwrap())
            .unwrap();
    }

    #[test]
    fn test_error_output2() {
        let mut w = Vec::new();
        writeln!(
            &mut w,
            "Could not parse: ../assets/fuzz-string-too-long.replay"
        ).unwrap();
        writeln!(
            &mut w,
            "Crc mismatch. Expected 3765941959 but received 1825689991"
        ).unwrap();

        Assert::cargo_binary("rrrocket")
            .with_args(&[
                "-n",
                "-c",
                "--dry-run",
                "-m",
                "../assets/fuzz-string-too-long.replay",
            ])
            .fails_with(1)
            .stderr()
            .contains(String::from_utf8(w).unwrap())
            .unwrap();
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate slog;
extern crate slog_term;

extern crate futures;
extern crate hyper;
extern crate tokio_core;
extern crate hyper_tls;
extern crate time;

use std::env;
use std::io::{self, Write};

use futures::{Future, Stream};
use futures::future;
use slog::*;
use hyper::{Client, Uri, Method, Chunk, Error};
use hyper::client::Request;
use hyper::client::FutureResponse;
use tokio_core::reactor::Core;

fn main() {
    let logger = create_loggers();
    info!(logger, "Application started");

    let urlStr = String::from("https://hacker-news.firebaseio.com/v0/item/2921983.json");
    let url = urlStr.parse::<hyper::Uri>().unwrap();
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let client = Client::configure()
        .connector(hyper_tls::HttpsConnector::new(4, &handle))
        .build(&handle);
    let endpoint = hn_news::build_default();

    let work = client.get(url).and_then(|res| {
        println!("Status: {}", res.status());
        println!("Headers:\n{}", res.headers());
        res.body().for_each(|chunk| {
            ::std::io::stdout()
                .write_all(&chunk)
                .map(|_| ())
                .map_err(From::from)
        })
    });
    let url2 = String::from("https://httpbin.org/post").parse::<hyper::Uri>().unwrap();
    let request = Request::new(Method::Post, url2);
    core.run(consume_request(&client, request))
        .and_then(|res| {
            info!(logger,
                  format!("Request finished with status {}", res.status()));
            Ok("ok") // TODO This should handle failures
        });
    let work = endpoint.request_top_story_ids(&client)
        .and_then(|res| {
            info!(logger,
                  format!("Request to {} finished with status {}",
                          endpoint.get_top_stories_path(),
                          res.status()));
            res.body()
                .fold(Vec::new(), |mut v, chunk| {
                    v.extend(&chunk[..]);
                    future::ok::<_, Error>(v)
                })
                .map(|chunks| String::from_utf8(chunks).unwrap())
        });
    let result = core.run(work).unwrap();
    println!("{}", result);
    // core.run(work).unwrap();
}
fn consume_request(client: &Client<hyper_tls::HttpsConnector>, request: Request) -> FutureResponse {
    client.request(request)
}

fn create_loggers() -> Logger {
    let drain = slog_term::streamer().build().fuse();
    let root_logger = Logger::root(drain, o!());
    return root_logger;
}

struct hn_news {
    base_url: String,
    top_news_suffix: String,
    item_suffix: String,
    max_item_suffix: String,
    json_suffix: String,
}

impl hn_news {
    pub fn build_default() -> hn_news {
        let e = hn_news {
            base_url: String::from("https://hacker-news.firebaseio.com/v0/"),
            top_news_suffix: String::from("topstories"),
            item_suffix: String::from("item/"),
            max_item_suffix: String::from("maxitem"),
            json_suffix: String::from(".json"),
        };
        e
    }

    pub fn get_top_stories_path(&self) -> String {
        combine_strings(vec![&self.base_url, &self.top_news_suffix, &self.json_suffix])
    }
    pub fn get_max_item_path(&self) -> String {
        combine_strings(vec![&self.base_url, &self.max_item_suffix, &self.json_suffix])
    }
    pub fn get_item_path(&self, id: &str) -> String {
        combine_strings(vec![&self.base_url, &self.item_suffix, id, &self.json_suffix])
    }

    fn request_top_story_ids(&self, client: &Client<hyper_tls::HttpsConnector>) -> FutureResponse {
        let url = parse_url_from_str(&self.get_top_stories_path());
        let request = Request::new(Method::Get, url);
        client.request(request)
    }
}

fn combine_strings(strings: Vec<&str>) -> String {
    let combine = strings.join("");
    combine
}

fn parse_url_from_str(urlStr: &str) -> Uri {
    let urlStr = String::from(urlStr);
    let url = urlStr.parse::<hyper::Uri>().unwrap();
    url
}

#[test]
fn parse_url_from_str_test() {
    let url = parse_url_from_str("http://www.gooogle.fi");
    assert_eq!("http", url.scheme().unwrap());
    assert_eq!("www.google.fi", url.authority().unwrap());
}

#[test]
fn combine_strings_test() {
    let a = "Abc";
    let b = "Abc";
    let mut vec = Vec::new();
    vec.push(a);
    vec.push(b);
    assert_eq!("AbcAbc", combine_strings(vec));
    assert!(a.len() > 1);
    assert!(b.len() > 1);
}
<commit_msg>added some doc<commit_after>#[macro_use]
extern crate slog;
extern crate slog_term;

extern crate futures;
extern crate hyper;
extern crate tokio_core;
extern crate hyper_tls;
extern crate time;

use std::env;
use std::io::{self, Write};

use futures::{Future, Stream};
use futures::future;
use slog::*;
use hyper::{Client, Uri, Method, Chunk, Error};
use hyper::client::Request;
use hyper::client::FutureResponse;
use tokio_core::reactor::Core;

fn main() {
    let logger = create_loggers();
    info!(logger, "Application started");

    let urlStr = String::from("https://hacker-news.firebaseio.com/v0/item/2921983.json");
    let url = urlStr.parse::<hyper::Uri>().unwrap();
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let client = Client::configure()
        .connector(hyper_tls::HttpsConnector::new(4, &handle))
        .build(&handle);
    let endpoint = hn_news::build_default();

    let work = client.get(url).and_then(|res| {
        println!("Status: {}", res.status());
        println!("Headers:\n{}", res.headers());
        res.body().for_each(|chunk| {
            ::std::io::stdout()
                .write_all(&chunk)
                .map(|_| ())
                .map_err(From::from)
        })
    });
    let url2 = String::from("https://httpbin.org/post").parse::<hyper::Uri>().unwrap();
    let request = Request::new(Method::Post, url2);
    core.run(consume_request(&client, request))
        .and_then(|res| {
            info!(logger,
                  format!("Request finished with status {}", res.status()));
            Ok("ok") // TODO This should handle failures
        });
    let work = endpoint.request_top_story_ids(&client)
        .and_then(|res| {
            info!(logger,
                  format!("Request to {} finished with status {}",
                          endpoint.get_top_stories_path(),
                          res.status()));
            res.body()
                .fold(Vec::new(), |mut v, chunk| {
                    v.extend(&chunk[..]);
                    // _ = It's a placeholder. In this context, it means that there isn't enough information for the compiler to infer a type.
                    // http://stackoverflow.com/questions/37215739/what-does-it-mean-to-instantiate-a-rust-generic-with-an-underscore
                    future::ok::<_, Error>(v)
                })
                .map(|chunks| String::from_utf8(chunks).unwrap())
        });
    let result = core.run(work).unwrap();
    println!("{}", result);
    // core.run(work).unwrap();
}
fn consume_request(client: &Client<hyper_tls::HttpsConnector>, request: Request) -> FutureResponse {
    client.request(request)
}

fn create_loggers() -> Logger {
    let drain = slog_term::streamer().build().fuse();
    let root_logger = Logger::root(drain, o!());
    return root_logger;
}

struct hn_news {
    base_url: String,
    top_news_suffix: String,
    item_suffix: String,
    max_item_suffix: String,
    json_suffix: String,
}

impl hn_news {
    pub fn build_default() -> hn_news {
        let e = hn_news {
            base_url: String::from("https://hacker-news.firebaseio.com/v0/"),
            top_news_suffix: String::from("topstories"),
            item_suffix: String::from("item/"),
            max_item_suffix: String::from("maxitem"),
            json_suffix: String::from(".json"),
        };
        e
    }

    pub fn get_top_stories_path(&self) -> String {
        combine_strings(vec![&self.base_url, &self.top_news_suffix, &self.json_suffix])
    }
    pub fn get_max_item_path(&self) -> String {
        combine_strings(vec![&self.base_url, &self.max_item_suffix, &self.json_suffix])
    }
    pub fn get_item_path(&self, id: &str) -> String {
        combine_strings(vec![&self.base_url, &self.item_suffix, id, &self.json_suffix])
    }

    fn request_top_story_ids(&self, client: &Client<hyper_tls::HttpsConnector>) -> FutureResponse {
        let url = parse_url_from_str(&self.get_top_stories_path());
        let request = Request::new(Method::Get, url);
        client.request(request)
    }
}

fn combine_strings(strings: Vec<&str>) -> String {
    let combine = strings.join("");
    combine
}

fn parse_url_from_str(urlStr: &str) -> Uri {
    let urlStr = String::from(urlStr);
    let url = urlStr.parse::<hyper::Uri>().unwrap();
    url
}

#[test]
fn parse_url_from_str_test() {
    let url = parse_url_from_str("http://www.gooogle.fi");
    assert_eq!("http", url.scheme().unwrap());
    assert_eq!("www.google.fi", url.authority().unwrap());
}

#[test]
fn combine_strings_test() {
    let a = "Abc";
    let b = "Abc";
    let mut vec = Vec::new();
    vec.push(a);
    vec.push(b);
    assert_eq!("AbcAbc", combine_strings(vec));
    assert!(a.len() > 1);
    assert!(b.len() > 1);
}
<|endoftext|>


<commit_before>//! This is a simple example of a fsm for feeding a cat. The states of the fsm are the states of
//! the cat food bowl. Our cat is very whiny and will always be fed when her bowl is empty and she
//! meows. If there is already food in the bowl, she will have to eat it before we give her more.

#[macro_use]
extern crate fsm;

use fsm::{Fsm, StateFn, FsmTypes};
use fsm::constraints::Constraints;
use fsm::constraints;
use fsm::fsm_check::Checker;

const MAX_RESERVES: u8 = 10;
const REFILL_THRESHOLD: u8 = 9;

// Currently the pub members exist because constraint checking happens outside the impl
// TODO: Do we move the constraints in?
#[derive(Debug, Clone)]
pub struct Context {
    pub contents: u8, // % of the bowl that is full
    pub reserves: u8, // The amount of bowls of food left in the bag
}

impl Context {
    pub fn new() -> Context {
        Context {
            contents: 0, // The bowl starts off empty
            reserves: MAX_RESERVES,
        }
    }
}

#[derive(Debug, Clone)]
pub enum CatMsg {
    Meow,
    Eat(u8) // % of food to eat
}

#[derive(Debug, Clone)]
pub enum StoreReq {
    Buy(u8)
}

#[derive(Debug, Clone)]
pub enum StoreRpy {
    Bowls(u8)
}

#[derive(Debug, Clone)]
pub enum BowlMsg {
    CatMsg(CatMsg),
    StoreRpy(StoreRpy)
}

#[derive(Debug)]
pub struct BowlTypes;

impl FsmTypes for BowlTypes {
    type Context = Context;
    type Msg = BowlMsg;
    type Output = StoreReq;
}

pub fn empty(ctx: &mut Context, msg: BowlMsg) -> (StateFn<BowlTypes>, Vec<StoreReq>) {

    if let BowlMsg::CatMsg(CatMsg::Meow) = msg {
        if ctx.reserves > 0 {
            // Fill the bowl
            ctx.contents = 100;
            ctx.reserves -= 1;
            if ctx.reserves <= REFILL_THRESHOLD {
                let output = vec![StoreReq::Buy(10)];
                return next!(full, output);
            }
            return next!(full);
        } else {
            return next!(empty);
        }
    }

    if let BowlMsg::StoreRpy(StoreRpy::Bowls(num)) = msg {
        ctx.reserves += num-1;
        ctx.contents = 100;
        return next!(full);
    }

    next!(empty)
}

pub fn full(ctx: &mut Context, msg: BowlMsg) -> (StateFn<BowlTypes>, Vec<StoreReq>) {
    if let BowlMsg::CatMsg(CatMsg::Eat(pct)) = msg {
        if pct >= ctx.contents {
            ctx.contents = 0;
            return next!(empty)
        } else {
            ctx.contents -= pct;
            return next!(full)
        }
    }

    if let BowlMsg::StoreRpy(StoreRpy::Bowls(num)) = msg {
        ctx.reserves += num;
    }
    next!(full)
}

#[test]
fn test_state_transitions() {
    let mut fsm = Fsm::<BowlTypes>::new(Context::new(), state_fn!(empty));
    let (name, ctx) = fsm.get_state();
    assert_eq!(name, "empty");
    assert_eq!(ctx.contents, 0);
    fsm.send(BowlMsg::CatMsg(CatMsg::Meow));
    let (name, ctx) = fsm.get_state();
    assert_eq!(name, "full");
    assert_eq!(ctx.contents, 100);
    fsm.send(BowlMsg::CatMsg(CatMsg::Eat(30)));
    let (name, ctx) = fsm.get_state();
    assert_eq!(name, "full");
    assert_eq!(ctx.contents, 70);
    fsm.send(BowlMsg::CatMsg(CatMsg::Meow));
    let (name, ctx) = fsm.get_state();
    assert_eq!(name, "full");
    assert_eq!(ctx.contents, 70);
    fsm.send(BowlMsg::CatMsg(CatMsg::Eat(75)));
    let (name, ctx) = fsm.get_state();
    assert_eq!(name, "empty");
    assert_eq!(ctx.contents, 0);
}

#[test]
fn test_check() {
    let msgs = vec![BowlMsg::CatMsg(CatMsg::Meow),
                 BowlMsg::CatMsg(CatMsg::Eat(30)),
                 BowlMsg::CatMsg(CatMsg::Eat(70)),
                 BowlMsg::CatMsg(CatMsg::Meow),
                 BowlMsg::CatMsg(CatMsg::Eat(50)),
                 BowlMsg::CatMsg(CatMsg::Meow)];
    check_constraints(msgs);
}

fn check_constraints(msgs: Vec<BowlMsg>) {
    let mut c = Constraints::new();
    precondition!(c, "empty", |ctx: &Context| ctx.contents == 0);
    precondition!(c, "full", |ctx: &Context| ctx.contents > 0 && ctx.contents <= 100);
    postcondition!(c, "empty", |ctx: &Context| ctx.contents == 0 || ctx.contents == 100);
    invariant!(c, |ctx: &Context| ctx.contents <= 100);
    transition!(c, "empty", "full", |ctx: &Context| ctx.contents == 100);
    transition!(c, "full", "empty", |ctx: &Context| ctx.contents == 0);
    let mut checker = Checker::<BowlTypes>::new(Context::new(), state_fn!(empty), c);
    assert_eq!(Ok(()), checker.check(msgs));
}
<commit_msg>Make tests pass<commit_after>//! This is a simple example of a fsm for feeding a cat. The states of the fsm are the states of
//! the cat food bowl. Our cat is very whiny and will always be fed when her bowl is empty and she
//! meows. If there is already food in the bowl, she will have to eat it before we give her more.

#[macro_use]
extern crate fsm;

use fsm::{Fsm, StateFn, FsmTypes};
use fsm::constraints::Constraints;
use fsm::constraints;
use fsm::fsm_check::Checker;

const MAX_RESERVES: u8 = 10;
const REFILL_THRESHOLD: u8 = 9;

// Currently the pub members exist because constraint checking happens outside the impl
// TODO: Do we move the constraints in?
#[derive(Debug, Clone)]
pub struct Context {
    pub contents: u8, // % of the bowl that is full
    pub reserves: u8, // The amount of bowls of food left in the bag
}

impl Context {
    pub fn new() -> Context {
        Context {
            contents: 0, // The bowl starts off empty
            reserves: MAX_RESERVES,
        }
    }
}

#[derive(Debug, Clone)]
pub enum CatMsg {
    Meow,
    Eat(u8) // % of food to eat
}

#[derive(Debug, Clone)]
pub enum StoreReq {
    Buy(u8)
}

#[derive(Debug, Clone)]
pub enum StoreRpy {
    Bowls(u8)
}

#[derive(Debug, Clone)]
pub enum BowlMsg {
    CatMsg(CatMsg),
    StoreRpy(StoreRpy)
}

#[derive(Debug)]
pub struct BowlTypes;

impl FsmTypes for BowlTypes {
    type Context = Context;
    type Msg = BowlMsg;
    type Output = StoreReq;
}

pub fn empty(ctx: &mut Context, msg: BowlMsg) -> (StateFn<BowlTypes>, Vec<StoreReq>) {

    if let BowlMsg::CatMsg(CatMsg::Meow) = msg {
        if ctx.reserves > 0 {
            // Fill the bowl
            ctx.contents = 100;
            ctx.reserves -= 1;
            if ctx.reserves <= REFILL_THRESHOLD {
                let output = vec![StoreReq::Buy(10)];
                return next!(full, output);
            }
            return next!(full);
        } else {
            return next!(empty);
        }
    }

    if let BowlMsg::StoreRpy(StoreRpy::Bowls(num)) = msg {
        ctx.reserves += num-1;
        ctx.contents = 100;
        return next!(full);
    }

    next!(empty)
}

pub fn full(ctx: &mut Context, msg: BowlMsg) -> (StateFn<BowlTypes>, Vec<StoreReq>) {
    if let BowlMsg::CatMsg(CatMsg::Eat(pct)) = msg {
        if pct >= ctx.contents {
            ctx.contents = 0;
            return next!(empty)
        } else {
            ctx.contents -= pct;
            return next!(full)
        }
    }

    if let BowlMsg::StoreRpy(StoreRpy::Bowls(num)) = msg {
        ctx.reserves += num;
    }
    next!(full)
}

#[test]
/// Note the blocks are to reduce the borrow window for &ctx returned from fsm.get_state().
fn test_state_transitions() {
    let mut fsm = Fsm::<BowlTypes>::new(Context::new(), state_fn!(empty));
    {
        let (name, ctx) = fsm.get_state();
        assert_eq!(name, "empty");
        assert_eq!(ctx.contents, 0);
    }
    fsm.send(BowlMsg::CatMsg(CatMsg::Meow));
    {
        let (name, ctx) = fsm.get_state();
        assert_eq!(name, "full");
        assert_eq!(ctx.contents, 100);
    }
    fsm.send(BowlMsg::CatMsg(CatMsg::Eat(30)));
    {
        let (name, ctx) = fsm.get_state();
        assert_eq!(name, "full");
        assert_eq!(ctx.contents, 70);
    }
    fsm.send(BowlMsg::CatMsg(CatMsg::Meow));
    {
        let (name, ctx) = fsm.get_state();
        assert_eq!(name, "full");
        assert_eq!(ctx.contents, 70);
    }
    fsm.send(BowlMsg::CatMsg(CatMsg::Eat(75)));
    {
        let (name, ctx) = fsm.get_state();
        assert_eq!(name, "empty");
        assert_eq!(ctx.contents, 0);
    }
}

#[test]
fn test_check() {
    let msgs = vec![BowlMsg::CatMsg(CatMsg::Meow),
                 BowlMsg::CatMsg(CatMsg::Eat(30)),
                 BowlMsg::CatMsg(CatMsg::Eat(70)),
                 BowlMsg::CatMsg(CatMsg::Meow),
                 BowlMsg::CatMsg(CatMsg::Eat(50)),
                 BowlMsg::CatMsg(CatMsg::Meow)];
    check_constraints(msgs);
}

fn check_constraints(msgs: Vec<BowlMsg>) {
    let mut c = Constraints::new();
    precondition!(c, "empty", |ctx: &Context| ctx.contents == 0);
    precondition!(c, "full", |ctx: &Context| ctx.contents > 0 && ctx.contents <= 100);
    postcondition!(c, "empty", |ctx: &Context| ctx.contents == 0 || ctx.contents == 100);
    invariant!(c, |ctx: &Context| ctx.contents <= 100);
    transition!(c, "empty", "full", |ctx: &Context| ctx.contents == 100);
    transition!(c, "full", "empty", |ctx: &Context| ctx.contents == 0);
    let mut checker = Checker::<BowlTypes>::new(Context::new(), state_fn!(empty), c);
    assert_eq!(Ok(()), checker.check(msgs));
}
<|endoftext|>


<commit_before>use std::ascii::AsciiExt;
use std::cmp::min as min;

fn main() {
}

fn score(choice: &str, query: &str) -> f64 {
  if query.len() == 0 {
    return 1.0;
  }
  if choice.len() == 0 {
    return 0.0;
  }

  let query = query.to_ascii_lower();
  let choice = choice.to_ascii_lower();

  match compute_match_length(choice.as_slice(), query.as_slice()) {
    None => return 0.0,
    Some(match_length) => {
      let score = query.len() as f64 / match_length as f64;
      return score as f64 / choice.len() as f64;
    }
  }
}

fn compute_match_length(string: &str, chars: &str) -> Option<uint> {
  let first_char = chars.char_at(0);
  let rest = chars.slice(1, chars.len());
  let indices = find_char_in_string(string, first_char);

  let mut current_min: Option<uint> = None;
  for i in indices.iter() {
    let last_index = find_end_of_match(string, rest, *i);
    if last_index.is_some() {
      let idx = last_index.unwrap() - *i + 1;
      if current_min.is_some() {
        let cm = min(current_min.unwrap(), idx);
        current_min = Some(cm);
      } else {
        current_min = Some(idx)
      }
    }
  }
  return current_min;
}

fn find_char_in_string(string: &str, char: char) -> Vec<uint> {
  let mut indices = Vec::new();
  let mut i = 0;
  for c in string.chars() {
    if c == char {
      indices.push(i);
    }
    i = i + 1;
  }
  return indices;
}

fn find_end_of_match(string: &str, rest_of_query: &str, first_index: uint) -> Option<uint> {
  let mut last_index = first_index + 1;
  for c in rest_of_query.chars() {
    let current_substring = string.slice_chars(last_index, string.len());
    match current_substring.find(c) {
      None => return None,
      Some(ref i) => {
        last_index += *i + 1;
      }
    }
  }
  return Some(last_index - 1);
}

#[test]
fn find_end_of_match_test() {
  assert_eq!(find_end_of_match("a", "a", 0), None);
  assert_eq!(find_end_of_match("ba", "a", 1), None);
  assert_eq!(find_end_of_match("aaa", "aa", 0), Some(2));
  assert_eq!(find_end_of_match("aaa", "b", 0), None);
  assert_eq!(find_end_of_match("this is a long match", "this is a match", 0), None);
  assert_eq!(find_end_of_match("this is a long match", "his is a match", 0), Some(19));
}

#[test]
fn basic_scoring() {
  assert_eq!(score("", "a"), 0.0);
  assert_eq!(score("a", ""), 1.0);
  assert_eq!(score("short", "longer"), 0.0);
  assert_eq!(score("a", "b"), 0.0);
  assert_eq!(score("ab", "ac"), 0.0);

  assert!(score("a", "a") > 0.0);
  assert!(score("ab", "a") > 0.0);
  assert!(score("ba", "a") > 0.0);
  assert!(score("bab", "a") > 0.0);
  assert!(score("babababab", "aaaa") > 0.0);

  assert_eq!(score("a", "a"), 1_f64 / "a".len() as f64);
  assert_eq!(score("ab", "ab"), 0.5);
  assert_eq!(score("a long string", "a long string"), 1_f64 / "a long string".len() as f64);
  assert_eq!(score("spec/search_spec.rb", "sear"), 1_f64 / "spec/search_spec.rb".len() as f64);
}

#[test]
fn character_matching() {
  assert!(score("/! symbols $^", "/!$^") > 0.0);

  assert_eq!(score("a", "A"), 1.0);
  assert_eq!(score("A", "a"), 1.0);

  assert_eq!(score("a", "aa"), 0.0);
}

#[test]
fn match_equality() {
  assert!(score("selecta.gemspec", "asp") > score("algorithm4_spec.rb", "asp"));
  assert!(score("README.md", "em") > score("benchmark.rb", "em"));
  assert!(score("search.rb", "sear") > score("spec/search_spec.rb", "sear"));

  assert!(score("fbb", "fbb") > score("foo bar baz", "fbb"));
  assert!(score("foo", "foo") > score("longer foo", "foo"));
  assert!(score("foo", "foo") > score("foo longer", "foo"));
  assert!(score("1/2/3/4", "1/2/3") > score("1/9/2/3/4", "1/2/3"));

  assert!(score("long 12 long", "12") > score("1 long 2", "12"));

  assert_eq!(score("121padding2", "12"), 1.0 / "121padding2".len() as f64);
  assert_eq!(score("1padding212", "12"), 1.0 / "1padding212".len() as f64);
}
<commit_msg>Add arg parsing and a skeletal main() that echoes stdin<commit_after>extern crate getopts;

use std::ascii::AsciiExt;
use std::cmp::min as min;
use std::os;
use std::io;

fn main() {
  let input_args = os::args();

  let args = match parse_args(&input_args) {
    Some(args) => args,
    None => {
      os::set_exit_status(1);
      return;
    },
  };

  if args.help { return; }

  println!("Initial search: \"{}\"", args.initial_search);

  let choices = read_choices();

  println!("");
  println!("Choices:");
  for choice in choices.iter() {
    println!("{}", choice);
  }
}

struct Args {
  initial_search: String,
  help: bool,
}

fn parse_args(args: &Vec<String>) -> Option<Args> {
  let opts = [
    getopts::optflag("h", "help", "Show this message"),
    getopts::optopt("s", "search", "Specify an initial search string", "SEARCH"),
  ];

  let matches = match getopts::getopts(args.tail(), &opts) {
    Ok(m) => m,
    Err(f) => {
      println!("{}", f);
      print_usage(args[0].as_slice(), opts);
      return None;
    }
  };

  let initial_search = match matches.opt_str("search") {
    Some(x) => x.clone(),
    None => String::from_str(""),
  };

  let help = matches.opt_present("help");
  if help {
    print_usage(args[0].as_slice(), opts);
  }

  Some(Args { initial_search: initial_search, help: help })
}

fn print_usage(program: &str, opts: &[getopts::OptGroup]) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", getopts::usage(brief.as_slice(), opts));
}

fn read_choices() -> Vec<String> {
  let mut stdin = io::stdio::stdin();
  let mut lines = Vec::new();

  loop {
    match stdin.read_line() {
      Ok(x) => lines.push(String::from_str(x.as_slice().trim())),
      Err(_) => break,
    }
  }

  lines
}

fn score(choice: &str, query: &str) -> f64 {
  if query.len() == 0 {
    return 1.0;
  }
  if choice.len() == 0 {
    return 0.0;
  }

  let query = query.to_ascii_lower();
  let choice = choice.to_ascii_lower();

  match compute_match_length(choice.as_slice(), query.as_slice()) {
    None => return 0.0,
    Some(match_length) => {
      let score = query.len() as f64 / match_length as f64;
      return score as f64 / choice.len() as f64;
    }
  }
}

fn compute_match_length(string: &str, chars: &str) -> Option<uint> {
  let first_char = chars.char_at(0);
  let rest = chars.slice(1, chars.len());
  let indices = find_char_in_string(string, first_char);

  let mut current_min: Option<uint> = None;
  for i in indices.iter() {
    let last_index = find_end_of_match(string, rest, *i);
    if last_index.is_some() {
      let idx = last_index.unwrap() - *i + 1;
      if current_min.is_some() {
        let cm = min(current_min.unwrap(), idx);
        current_min = Some(cm);
      } else {
        current_min = Some(idx)
      }
    }
  }
  return current_min;
}

fn find_char_in_string(string: &str, char: char) -> Vec<uint> {
  let mut indices = Vec::new();
  let mut i = 0;
  for c in string.chars() {
    if c == char {
      indices.push(i);
    }
    i = i + 1;
  }
  return indices;
}

fn find_end_of_match(string: &str, rest_of_query: &str, first_index: uint) -> Option<uint> {
  let mut last_index = first_index + 1;
  for c in rest_of_query.chars() {
    let current_substring = string.slice_chars(last_index, string.len());
    match current_substring.find(c) {
      None => return None,
      Some(ref i) => {
        last_index += *i + 1;
      }
    }
  }
  return Some(last_index - 1);
}

#[test]
fn find_end_of_match_test() {
  assert_eq!(find_end_of_match("a", "a", 0), None);
  assert_eq!(find_end_of_match("ba", "a", 1), None);
  assert_eq!(find_end_of_match("aaa", "aa", 0), Some(2));
  assert_eq!(find_end_of_match("aaa", "b", 0), None);
  assert_eq!(find_end_of_match("this is a long match", "this is a match", 0), None);
  assert_eq!(find_end_of_match("this is a long match", "his is a match", 0), Some(19));
}

#[test]
fn basic_scoring() {
  assert_eq!(score("", "a"), 0.0);
  assert_eq!(score("a", ""), 1.0);
  assert_eq!(score("short", "longer"), 0.0);
  assert_eq!(score("a", "b"), 0.0);
  assert_eq!(score("ab", "ac"), 0.0);

  assert!(score("a", "a") > 0.0);
  assert!(score("ab", "a") > 0.0);
  assert!(score("ba", "a") > 0.0);
  assert!(score("bab", "a") > 0.0);
  assert!(score("babababab", "aaaa") > 0.0);

  assert_eq!(score("a", "a"), 1_f64 / "a".len() as f64);
  assert_eq!(score("ab", "ab"), 0.5);
  assert_eq!(score("a long string", "a long string"), 1_f64 / "a long string".len() as f64);
  assert_eq!(score("spec/search_spec.rb", "sear"), 1_f64 / "spec/search_spec.rb".len() as f64);
}

#[test]
fn character_matching() {
  assert!(score("/! symbols $^", "/!$^") > 0.0);

  assert_eq!(score("a", "A"), 1.0);
  assert_eq!(score("A", "a"), 1.0);

  assert_eq!(score("a", "aa"), 0.0);
}

#[test]
fn match_equality() {
  assert!(score("selecta.gemspec", "asp") > score("algorithm4_spec.rb", "asp"));
  assert!(score("README.md", "em") > score("benchmark.rb", "em"));
  assert!(score("search.rb", "sear") > score("spec/search_spec.rb", "sear"));

  assert!(score("fbb", "fbb") > score("foo bar baz", "fbb"));
  assert!(score("foo", "foo") > score("longer foo", "foo"));
  assert!(score("foo", "foo") > score("foo longer", "foo"));
  assert!(score("1/2/3/4", "1/2/3") > score("1/9/2/3/4", "1/2/3"));

  assert!(score("long 12 long", "12") > score("1 long 2", "12"));

  assert_eq!(score("121padding2", "12"), 1.0 / "121padding2".len() as f64);
  assert_eq!(score("1padding212", "12"), 1.0 / "1padding212".len() as f64);
}
<|endoftext|>


<commit_before>/* kernel::sgash.rs */

use core::*;
use core::str::*;
use core::option::{Some, Option, None}; // Match statement
use core::iter::Iterator;
use core::vec::Vec;
use core::mem::Allocator;
use kernel::*;
use super::super::platform::*;

pub static mut buffer: cstr = cstr {
				p: 0 as *mut u8,
				p_cstr_i: 0,
				max: 0
			      };
pub fn putchar(key: char) {
    unsafe {
	/*
	 * We need to include a blank asm call to prevent rustc
	 * from optimizing this part out
	 */
	asm!("");
	io::write_char(key, io::UART0);
    }
}

#[lang = "exchange_free"]
fn putstr(msg: &str) {
    for c in slice::iter(as_bytes(msg)) {
	putchar(*c as char);
    }
}

pub unsafe fn putcstr(s: cstr)
{
    let mut p = s.p as uint;
    while *(p as *char) != '\0'
    {
	putchar(*(p as *char));
	p += 1;
    }
}

pub unsafe fn parsekey(x: char) {
    let x = x as u8;
    // Set this to false to learn the keycodes of various keys!
    // Key codes are printed backwards because life is hard
    if (true) {
	match x {
	    13		=>	{ prompt(); }
	    127		=>	{
		if (buffer.delete_char()) {
		    putchar('');
		    putchar(' ');
		    putchar('');
		}
	    }
	    _		=>	{
		if (buffer.add_char(x)) { putchar(x as char); }
	    }
	}
    }
    else {
	keycode(x);
    }
}

fn keycode(x: u8) {
    let mut x = x;
    while ( x != 0 ) {
	putchar((x%10+ ('0' as u8) ) as char);
	x = x/10;
    }
    putchar(' ');
}

pub unsafe fn init() {
    buffer = cstr::new(256);
    prompt();
}

unsafe fn prompt() {
    if (buffer.streq(&"ls")) { putstr( &"\na\tb") };
    match buffer.getarg(' ', 0) {
	Some(y)	=> {
	    if(y.streq(&"cat")) {
		match buffer.getarg(' ', 1) {
		    Some(x)	=> {
			if(x.streq(&"a")) { putstr( &"\nHello"); }
			if(x.streq(&"b")) { putstr( &"\nworld!"); }
		    }
		    None	=> { }
		};
	    }
	}
	None	=> { }
    };

    putstr(&"\nsgash > ");
    buffer.reset();
}

/* BUFFER MODIFICATION FUNCTIONS */

struct cstr {
    p: *mut u8,
    p_cstr_i: uint,
    max: uint
}

impl cstr {
    pub unsafe fn new(size: uint) -> cstr {
	// Sometimes this doesn't allocate enough memory and gets stuck...
	let (x, y) = memory::allocator.alloc(size);
	let this = cstr {
	    p: x,
	    p_cstr_i: 0,
	    max: y
	};
	*(((this.p as uint)+this.p_cstr_i) as *mut char) = '\0';
	this
    }

    unsafe fn from_str(s: &str) -> cstr {
	let mut this = cstr::new(256);
	for c in slice::iter(as_bytes(s)) {
	    this.add_char(*c);
	};
	this
    }

    fn len(&self) -> uint { self.p_cstr_i }

    // HELP THIS DOESN'T WORK THERE IS NO GARBAGE COLLECTION!!!
    unsafe fn destroy(&self) { memory::allocator.free(self.p); }

    unsafe fn add_char(&mut self, x: u8) -> bool{
	if (self.p_cstr_i == self.max) { return false; }
	*(((self.p as uint)+self.p_cstr_i) as *mut u8) = x;
	self.p_cstr_i += 1;
	*(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
	true
    }

    unsafe fn delete_char(&mut self) -> bool {
	if (self.p_cstr_i == 0) { return false; }
	self.p_cstr_i -= 1;
	*(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
	true
    }

    unsafe fn reset(&mut self) {
	self.p_cstr_i = 0;
	*(self.p as *mut char) = '\0';
    }

    unsafe fn eq(&self, other: &cstr) -> bool {
	if (self.len() != other.len()) { return false; }
	else {
	    let mut x = 0;
	    let mut selfp: uint = self.p as uint;
	    let mut otherp: uint = other.p as uint;
	    while (x < self.len()) {
		if (*(selfp as *char) != *(otherp as *char)) { return false; }
		selfp += 1;
		otherp += 1;
		x += 1;
	    }
	    true
	}
    }

    unsafe fn streq(&self, other: &str) -> bool {
	let mut x = 0;
	let mut selfp: uint = self.p as uint;
	for c in slice::iter(as_bytes(other)) {
	    if( *c != *(selfp as *u8) ) { return false; }
	    selfp += 1;
	};
	*(selfp as *char) == '\0'
    }

    unsafe fn getarg(&self, delim: char, mut k: uint) -> Option<cstr> {
	let mut ind: uint = 0;
	let mut found = k == 0;
	let mut selfp: uint = self.p as uint;
	let mut s = cstr::new(256);
	loop {
	    if (*(selfp as *char) == '\0') {
		// End of string
		if (found) { return Some(s); }
		else { return None; }
	    };
	    if (*(selfp as *u8) == delim as u8) {
		if (found) { return Some(s); }
		k -= 1;
	    };
	    if (found) {
		s.add_char(*(selfp as *u8));
	    };
	    found = k == 0;
	    selfp += 1;
	    ind += 1;
	    if (ind == self.max) {
		putstr(&"\nSomething broke!");
		return None;
	    }
	}
    }

    unsafe fn split(&self, delim: char) -> (cstr, cstr) {
	let mut selfp: uint = self.p as uint;
	let mut beg = cstr::new(256);
	let mut end = cstr::new(256);
	let mut found = false;
	loop {
	    if (*(selfp as *char) == '\0') {
		return (beg, end);
	    }
	    else if (*(selfp as *u8) == delim as u8) {
		found = true;
	    }
	    else if (!found) {
		beg.add_char(*(selfp as *u8));
	    }
	    else if (found) {
		end.add_char(*(selfp as *u8));
	    };
	    selfp += 1;
	}
    }

}

<commit_msg>Added super necessary ascii loading logo. Feel free to change<commit_after>/* kernel::sgash.rs */

use core::*;
use core::str::*;
use core::option::{Some, Option, None}; // Match statement
use core::iter::Iterator;
use core::vec::Vec;
use core::mem::Allocator;
use kernel::*;
use super::super::platform::*;

pub static mut buffer: cstr = cstr {
				p: 0 as *mut u8,
				p_cstr_i: 0,
				max: 0
			      };
pub fn putchar(key: char) {
    unsafe {
	/*
	 * We need to include a blank asm call to prevent rustc
	 * from optimizing this part out
	 */
	asm!("");
	io::write_char(key, io::UART0);
    }
}

#[lang = "exchange_free"]
fn putstr(msg: &str) {
    for c in slice::iter(as_bytes(msg)) {
	putchar(*c as char);
    }
}

pub unsafe fn putcstr(s: cstr)
{
    let mut p = s.p as uint;
    while *(p as *char) != '\0'
    {
	putchar(*(p as *char));
	p += 1;
    }
}

pub unsafe fn parsekey(x: char) {
    let x = x as u8;
    // Set this to false to learn the keycodes of various keys!
    // Key codes are printed backwards because life is hard
    if (true) {
	match x {
	    13		=>	{ prompt(); }
	    127		=>	{
		if (buffer.delete_char()) {
		    putchar('');
		    putchar(' ');
		    putchar('');
		}
	    }
	    _		=>	{
		if (buffer.add_char(x)) { putchar(x as char); }
	    }
	}
    }
    else {
	keycode(x);
    }
}

fn keycode(x: u8) {
    let mut x = x;
    while ( x != 0 ) {
	putchar((x%10+ ('0' as u8) ) as char);
	x = x/10;
    }
    putchar(' ');
}
fn screen() {

	putstr(&"\n                                                               ");
	putstr(&"\n                                                               ");
	putstr(&"\n                       7=..~$=..:7                             ");
	putstr(&"\n                  +$: =$$$+$$$?$$$+ ,7?                        ");
	putstr(&"\n                  $$$$$$$$$$$$$$$$$$Z$$                        ");
	putstr(&"\n              7$$$$$$$$$$$$. .Z$$$$$Z$$$$$$                    ");
	putstr(&"\n           ~..7$$Z$$$$$7+7$+.?Z7=7$$Z$$Z$$$..:                 ");
	putstr(&"\n          ~$$$$$$$$7:     :ZZZ,     :7ZZZZ$$$$=                ");
	putstr(&"\n           Z$$$$$?                    .+ZZZZ$$                 ");
	putstr(&"\n       +$ZZ$$$Z7                         7ZZZ$Z$$I.            ");
	putstr(&"\n        $$$$ZZZZZZZZZZZZZZZZZZZZZZZZI,    ,ZZZ$$Z              ");
	putstr(&"\n      :+$$$$ZZZZZZZZZZZZZZZZZZZZZZZZZZZ=    $ZZ$$+~,           ");
	putstr(&" _                     _     _                         _  ");
	putstr(&"\n     ?$Z$$$$ZZZZZZZZZZZZZZZZZZZZZZZZZZZZI   7ZZZ$ZZI           ");
	putstr(&"| |                   (_)   | |                       | | ");
	putstr(&"\n      =Z$$+7Z$$7ZZZZZZZZ$$$$$$$ZZZZZZZZZZ  ~Z$?$ZZ?            ");
	putstr(&"| | ____ ___  ____     _____| |_____  ____ ____  _____| | ");
	putstr(&"\n    :$Z$Z...$Z  $ZZZZZZZ~       ~ZZZZZZZZ,.ZZ...Z$Z$~          ");
	putstr(&"| |/ ___) _ \\|  _ \\   |  _   _) ___ |/ ___)  _ \\| ___ | | ");
	putstr(&"\n    7ZZZZZI$ZZ  $ZZZZZZZ~       =ZZZZZZZ7..ZZ$?$ZZZZ$          ");
	putstr(&"| | |  | |_| | | | |  | |  \\ \\| ____| |   | | | | ____| | ");
	putstr(&"\n      ZZZZ$:    $ZZZZZZZZZZZZZZZZZZZZZZ=     ~$ZZZ$:           ");
	putstr(&"|_|_|  \\____/|_| |_|  |_|   \\_\\_____)_|   |_| |_|_____)__)");
	putstr(&"\n    7Z$ZZ$,     $ZZZZZZZZZZZZZZZZZZZZ7         ZZZ$Z$          ");
	putstr(&"\n   =ZZZZZZ,     $ZZZZZZZZZZZZZZZZZZZZZZ,       ZZZ$ZZ+         ");
	putstr(&"\n     ,ZZZZ,     $ZZZZZZZ:     =ZZZZZZZZZ     ZZZZZ$:           ");
	putstr(&"\n    =$ZZZZ+     ZZZZZZZZ~       ZZZZZZZZ~   =ZZZZZZZI          ");
	putstr(&"\n    $ZZ$ZZZ$$Z$$ZZZZZZZZZ$$$$   IZZZZZZZZZ$ZZZZZZZZZ$          ");
	putstr(&"\n      :ZZZZZZZZZZZZZZZZZZZZZZ   ~ZZZZZZZZZZZZZZZZZ~            ");
	putstr(&"\n     ,Z$$ZZZZZZZZZZZZZZZZZZZZ    ZZZZZZZZZZZZZZZZZZ~           ");
	putstr(&"\n     =$ZZZZZZZZZZZZZZZZZZZZZZ     $ZZZZZZZZZZZZZZZ$+           ");
	putstr(&"\n        IZZZZZ:.                        . ,ZZZZZ$              ");
	putstr(&"\n       ~$ZZZZZZZZZZZ                 ZZZZ$ZZZZZZZ+             ");
	putstr(&"\n           Z$ZZZ. ,Z~               =Z:.,ZZZ$Z                 ");
	putstr(&"\n          ,ZZZZZ..~Z$.             .7Z:..ZZZZZ:                ");
	putstr(&"\n          ~7+:$ZZZZZZZZI=:.   .,=IZZZZZZZ$Z:=7=                ");
	putstr(&"\n              $$ZZZZZZZZZZZZZZZZZZZZZZ$ZZZZ                    ");
	putstr(&"\n              ==..$ZZZ$ZZZZZZZZZZZ$ZZZZ .~+                    ");
	putstr(&"\n                  I$?.?ZZZ$ZZZ$ZZZI =$7                        ");
	putstr(&"\n                       $7..I$7..I$,                            ");
	putstr(&"\n");
	putstr(&"\n");
}

pub unsafe fn init() {
    buffer = cstr::new(256);
    screen();
    prompt();
}

unsafe fn prompt() {
    if (buffer.streq(&"ls")) { putstr( &"\na\tb") };
    match buffer.getarg(' ', 0) {
	Some(y)	=> {
	    if(y.streq(&"cat")) {
		match buffer.getarg(' ', 1) {
		    Some(x)	=> {
			if(x.streq(&"a")) { putstr( &"\nHello"); }
			if(x.streq(&"b")) { putstr( &"\nworld!"); }
		    }
		    None	=> { }
		};
	    }
	}
	None	=> { }
    };

    putstr(&"\nsgash > ");
    buffer.reset();
}

/* BUFFER MODIFICATION FUNCTIONS */

struct cstr {
    p: *mut u8,
    p_cstr_i: uint,
    max: uint
}

impl cstr {
    pub unsafe fn new(size: uint) -> cstr {
	// Sometimes this doesn't allocate enough memory and gets stuck...
	let (x, y) = memory::allocator.alloc(size);
	let this = cstr {
	    p: x,
	    p_cstr_i: 0,
	    max: y
	};
	*(((this.p as uint)+this.p_cstr_i) as *mut char) = '\0';
	this
    }

    unsafe fn from_str(s: &str) -> cstr {
	let mut this = cstr::new(256);
	for c in slice::iter(as_bytes(s)) {
	    this.add_char(*c);
	};
	this
    }

    fn len(&self) -> uint { self.p_cstr_i }

    // HELP THIS DOESN'T WORK THERE IS NO GARBAGE COLLECTION!!!
    unsafe fn destroy(&self) { memory::allocator.free(self.p); }

    unsafe fn add_char(&mut self, x: u8) -> bool{
	if (self.p_cstr_i == self.max) { return false; }
	*(((self.p as uint)+self.p_cstr_i) as *mut u8) = x;
	self.p_cstr_i += 1;
	*(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
	true
    }

    unsafe fn delete_char(&mut self) -> bool {
	if (self.p_cstr_i == 0) { return false; }
	self.p_cstr_i -= 1;
	*(((self.p as uint)+self.p_cstr_i) as *mut char) = '\0';
	true
    }

    unsafe fn reset(&mut self) {
	self.p_cstr_i = 0;
	*(self.p as *mut char) = '\0';
    }

    unsafe fn eq(&self, other: &cstr) -> bool {
	if (self.len() != other.len()) { return false; }
	else {
	    let mut x = 0;
	    let mut selfp: uint = self.p as uint;
	    let mut otherp: uint = other.p as uint;
	    while (x < self.len()) {
		if (*(selfp as *char) != *(otherp as *char)) { return false; }
		selfp += 1;
		otherp += 1;
		x += 1;
	    }
	    true
	}
    }

    unsafe fn streq(&self, other: &str) -> bool {
	let mut x = 0;
	let mut selfp: uint = self.p as uint;
	for c in slice::iter(as_bytes(other)) {
	    if( *c != *(selfp as *u8) ) { return false; }
	    selfp += 1;
	};
	*(selfp as *char) == '\0'
    }

    unsafe fn getarg(&self, delim: char, mut k: uint) -> Option<cstr> {
	let mut ind: uint = 0;
	let mut found = k == 0;
	let mut selfp: uint = self.p as uint;
	let mut s = cstr::new(256);
	loop {
	    if (*(selfp as *char) == '\0') {
		// End of string
		if (found) { return Some(s); }
		else { return None; }
	    };
	    if (*(selfp as *u8) == delim as u8) {
		if (found) { return Some(s); }
		k -= 1;
	    };
	    if (found) {
		s.add_char(*(selfp as *u8));
	    };
	    found = k == 0;
	    selfp += 1;
	    ind += 1;
	    if (ind == self.max) {
		putstr(&"\nSomething broke!");
		return None;
	    }
	}
    }

    unsafe fn split(&self, delim: char) -> (cstr, cstr) {
	let mut selfp: uint = self.p as uint;
	let mut beg = cstr::new(256);
	let mut end = cstr::new(256);
	let mut found = false;
	loop {
	    if (*(selfp as *char) == '\0') {
		return (beg, end);
	    }
	    else if (*(selfp as *u8) == delim as u8) {
		found = true;
	    }
	    else if (!found) {
		beg.add_char(*(selfp as *u8));
	    }
	    else if (found) {
		end.add_char(*(selfp as *u8));
	    };
	    selfp += 1;
	}
    }

}

<|endoftext|>