<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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::rc::Rc;
use std::string::ToString;
use syntax::ast;
use syntax::codemap::MacroBang;
use syntax::codemap::{CodeMap, Span, mk_sp, BytePos, ExpnInfo, NameAndSpan};
use syntax::codemap;
use syntax::diagnostic::Handler;
use syntax::diagnostic::{Emitter, RenderSpan, Level, SpanHandler};
use syntax::ext::base::ExtCtxt;
use syntax::ext::expand::ExpansionConfig;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::parse::ParseSess;
use syntax::print::pprust;

use builder::Builder;
use node;
use parser::Parser;

/// Tests if the source fails to be parsed by PT parser.
pub fn fails_to_parse(src: &str) {
  with_parsed_tts(src, |_, failed, pt| {
    assert!(unsafe{*failed} == true);
    assert!(pt.is_none());
  });
}

/// Tests if the source fails to be built by PT builder.
pub fn fails_to_build(src: &str) {
  with_parsed(src, |cx, failed, pt| {
    assert!(unsafe{*failed} == false);
    Builder::build(cx, pt);
  });
}

/// Yields an ExtCtxt, parser error state and parsed PT.
///
/// TODO(farcaller): get rid of that bool, it's broken.
pub fn with_parsed<F>(src: &str, block: F)
    where F: Fn(&mut ExtCtxt, *mut bool, Rc<node::PlatformTree>) {
  with_parsed_tts(src, |cx, failed, pt| {
    block(cx, failed, pt.unwrap());
  });
}

pub fn with_parsed_node<F>(name: &str, src: &str, block: F)
    where F: Fn(Rc<node::Node>) {
  with_parsed(src, |_, _, pt| {
    block(pt.get_by_path(name).unwrap());
  });
}

pub fn with_parsed_tts<F>(src: &str, block: F)
    where F: Fn(&mut ExtCtxt, *mut bool, Option<Rc<node::PlatformTree>>) {
  let mut failed = false;
  let failptr = &mut failed as *mut bool;
  let ce = Box::new(CustomEmmiter::new(failptr));
  let h = Handler::with_emitter(false, ce);
  let sh = SpanHandler::new(h, CodeMap::new());
  let parse_sess = ParseSess::with_span_handler(sh);
  let cfg = Vec::new();
  let ecfg = ExpansionConfig {
    crate_name: ("test").parse().unwrap(),
    features: None,
    recursion_limit: 10,
    trace_mac: true,
  };
  let mut cx = ExtCtxt::new(&parse_sess, cfg, ecfg);
  cx.bt_push(ExpnInfo {
    call_site: mk_sp(BytePos(0), BytePos(0)),
    callee: NameAndSpan {
      name: "platformtree".to_string(),
      format: MacroBang,
      allow_internal_unstable: true,
      span: None,
    },
  });
  let tts = cx.parse_tts(src.to_string());

  let pt = Parser::new(&mut cx, tts.as_slice()).parse_platformtree();

  block(&mut cx, failptr, pt);
}

struct CustomEmmiter {
  failed: *mut bool
}

impl CustomEmmiter {
  pub fn new(fp: *mut bool) -> CustomEmmiter {
    CustomEmmiter {
      failed: fp,
    }
  }
}

unsafe impl Send for CustomEmmiter {}

impl Emitter for CustomEmmiter {
  fn emit(&mut self, _: Option<(&CodeMap, Span)>, m: &str, _: Option<&str>,
      l: Level) {
    unsafe { *self.failed = true };
    println!("{} {}", l, m);
  }
  fn custom_emit(&mut self, _: &codemap::CodeMap, _: RenderSpan, _: &str,
      _: Level) {
    panic!();
  }
}

pub fn assert_equal_source(stmt: &ast::Stmt, src: &str) {
  let gen_src = pprust::stmt_to_string(stmt);
  println!("generated: {}", gen_src);
  println!("expected:  {}", src);

  let stripped_gen_src = gen_src.replace(" ", "").replace("\n", "");
  let stripped_src = src.replace(" ", "").replace("\n", "");

  assert!(stripped_gen_src == stripped_src);
}

pub fn assert_equal_items(stmt: &ast::Item, src: &str) {
  let gen_src = pprust::item_to_string(stmt);
  println!("generated: {}", gen_src);
  println!("expected:  {}", src);

  let stripped_gen_src = gen_src.replace(" ", "").replace("\n", "");
  let stripped_src = src.replace(" ", "").replace("\n", "");

  assert!(stripped_gen_src == stripped_src);
}
<commit_msg>Fixed a compile error in platformtree test caused by nightly changes<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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::rc::Rc;
use std::string::ToString;
use syntax::ast;
use syntax::codemap::MacroBang;
use syntax::codemap::{CodeMap, Span, mk_sp, BytePos, ExpnInfo, NameAndSpan};
use syntax::codemap;
use syntax::diagnostic::Handler;
use syntax::diagnostic::{Emitter, RenderSpan, Level, SpanHandler};
use syntax::ext::base::ExtCtxt;
use syntax::ext::expand::ExpansionConfig;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::parse::ParseSess;
use syntax::print::pprust;

use builder::Builder;
use node;
use parser::Parser;

/// Tests if the source fails to be parsed by PT parser.
pub fn fails_to_parse(src: &str) {
  with_parsed_tts(src, |_, failed, pt| {
    assert!(unsafe{*failed} == true);
    assert!(pt.is_none());
  });
}

/// Tests if the source fails to be built by PT builder.
pub fn fails_to_build(src: &str) {
  with_parsed(src, |cx, failed, pt| {
    assert!(unsafe{*failed} == false);
    Builder::build(cx, pt);
  });
}

/// Yields an ExtCtxt, parser error state and parsed PT.
///
/// TODO(farcaller): get rid of that bool, it's broken.
pub fn with_parsed<F>(src: &str, block: F)
    where F: Fn(&mut ExtCtxt, *mut bool, Rc<node::PlatformTree>) {
  with_parsed_tts(src, |cx, failed, pt| {
    block(cx, failed, pt.unwrap());
  });
}

pub fn with_parsed_node<F>(name: &str, src: &str, block: F)
    where F: Fn(Rc<node::Node>) {
  with_parsed(src, |_, _, pt| {
    block(pt.get_by_path(name).unwrap());
  });
}

pub fn with_parsed_tts<F>(src: &str, block: F)
    where F: Fn(&mut ExtCtxt, *mut bool, Option<Rc<node::PlatformTree>>) {
  let mut failed = false;
  let failptr = &mut failed as *mut bool;
  let ce = Box::new(CustomEmmiter::new(failptr));
  let h = Handler::with_emitter(false, ce);
  let sh = SpanHandler::new(h, CodeMap::new());
  let parse_sess = ParseSess::with_span_handler(sh);
  let cfg = Vec::new();
  let ecfg = ExpansionConfig {
    crate_name: ("test").parse().unwrap(),
    features: None,
    recursion_limit: 10,
    trace_mac: true,
  };
  let mut gated_cfgs = vec!();
  let mut cx = ExtCtxt::new(&parse_sess, cfg, ecfg, &mut gated_cfgs);
  cx.bt_push(ExpnInfo {
    call_site: mk_sp(BytePos(0), BytePos(0)),
    callee: NameAndSpan {
      name: "platformtree".to_string(),
      format: MacroBang,
      allow_internal_unstable: true,
      span: None,
    },
  });
  let tts = cx.parse_tts(src.to_string());

  let pt = Parser::new(&mut cx, tts.as_slice()).parse_platformtree();

  block(&mut cx, failptr, pt);
}

struct CustomEmmiter {
  failed: *mut bool
}

impl CustomEmmiter {
  pub fn new(fp: *mut bool) -> CustomEmmiter {
    CustomEmmiter {
      failed: fp,
    }
  }
}

unsafe impl Send for CustomEmmiter {}

impl Emitter for CustomEmmiter {
  fn emit(&mut self, _: Option<(&CodeMap, Span)>, m: &str, _: Option<&str>,
      l: Level) {
    unsafe { *self.failed = true };
    println!("{} {}", l, m);
  }
  fn custom_emit(&mut self, _: &codemap::CodeMap, _: RenderSpan, _: &str,
      _: Level) {
    panic!();
  }
}

pub fn assert_equal_source(stmt: &ast::Stmt, src: &str) {
  let gen_src = pprust::stmt_to_string(stmt);
  println!("generated: {}", gen_src);
  println!("expected:  {}", src);

  let stripped_gen_src = gen_src.replace(" ", "").replace("\n", "");
  let stripped_src = src.replace(" ", "").replace("\n", "");

  assert!(stripped_gen_src == stripped_src);
}

pub fn assert_equal_items(stmt: &ast::Item, src: &str) {
  let gen_src = pprust::item_to_string(stmt);
  println!("generated: {}", gen_src);
  println!("expected:  {}", src);

  let stripped_gen_src = gen_src.replace(" ", "").replace("\n", "");
  let stripped_src = src.replace(" ", "").replace("\n", "");

  assert!(stripped_gen_src == stripped_src);
}
<|endoftext|>


<commit_before>// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2019, HST authors.
//
// 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.
// ------------------------------------------------------------------------------------------------

//! Defines primitive CSP events and processes.

use std::fmt::Debug;
use std::fmt::Display;
use std::marker::PhantomData;

use crate::event::EmptyAlphabet;
use crate::process::Cursor;
use crate::process::Process;

//-------------------------------------------------------------------------------------------------
// Built-in CSP events

/// Constructs a new _tau_ event (τ).  This is the hidden event that expresses nondeterminism in a
/// CSP process.  You should rarely have to construct it directly, unless you're digging through
/// the transitions of a process.
pub fn tau<E: From<Tau>>() -> E {
    Tau.into()
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Tau;

impl Display for Tau {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("τ")
    }
}

impl Debug for Tau {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

/// Constructs a new _tick_ event (✔).  This is the hidden event that represents the end of a
/// process that can be sequentially composed with another process.  You should rarely have to
/// construct it directly, unless you're digging through the transitions of a process.
pub fn tick<E: From<Tick>>() -> E {
    Tick.into()
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Tick;

impl Display for Tick {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("✔")
    }
}

impl Debug for Tick {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

//-------------------------------------------------------------------------------------------------
// Stop

/// Constructs a new _Stop_ process.  This is the process that performs no actions (and prevents
/// any other synchronized processes from performing any, either).
pub fn stop<E, P: From<Stop<E>>>() -> P {
    Stop(PhantomData).into()
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Stop<E>(PhantomData<E>);

impl<E> Display for Stop<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("Stop")
    }
}

impl<E> Debug for Stop<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct StopCursor<E>(PhantomData<E>);

impl<E> Debug for StopCursor<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("StopCursor")
    }
}

impl<E> Process<E> for Stop<E>
where
    E: Display + 'static,
{
    type Cursor = StopCursor<E>;

    fn root(&self) -> Self::Cursor {
        StopCursor(PhantomData)
    }
}

impl<E> Cursor<E> for StopCursor<E>
where
    E: Display + 'static,
{
    type Alphabet = EmptyAlphabet;

    fn initials(&self) -> EmptyAlphabet {
        EmptyAlphabet
    }

    fn events(&self) -> Box<dyn Iterator<Item = E>> {
        Box::new(std::iter::empty())
    }

    fn can_perform(&self, _event: &E) -> bool {
        false
    }

    fn perform(&mut self, event: &E) {
        panic!("Stop cannot perform {}", event);
    }
}

#[cfg(test)]
mod stop_tests {
    use super::*;

    use maplit::hashset;

    use crate::process::initials;
    use crate::process::maximal_finite_traces;

    #[test]
    fn check_stop() {
        let process: Stop<Tau> = dbg!(stop());
        assert_eq!(initials(&process.root()), hashset! {});
        assert_eq!(maximal_finite_traces(process.root()), hashset! {vec![]});
    }
}

//-------------------------------------------------------------------------------------------------
// Skip

/// Constructs a new _Skip_ process.  The process that performs Tick and then becomes Stop.  Used
/// to indicate the end of a process that can be sequentially composed with something else.
pub fn skip<E, P: From<Skip<E>>>() -> P {
    Skip(PhantomData).into()
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Skip<E>(PhantomData<E>);

impl<E> Display for Skip<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("Skip")
    }
}

impl<E> Debug for Skip<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct SkipCursor<E> {
    state: SkipState,
    phantom: PhantomData<E>,
}

#[doc(hidden)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum SkipState {
    BeforeTick,
    AfterTick,
}

impl<E> Debug for SkipCursor<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "SkipCursor({:?})", self.state)
    }
}

impl<E> Process<E> for Skip<E>
where
    E: Display + Eq + From<Tick> + 'static,
{
    type Cursor = SkipCursor<E>;

    fn root(&self) -> Self::Cursor {
        SkipCursor {
            state: SkipState::BeforeTick,
            phantom: PhantomData,
        }
    }
}

impl<E> Cursor<E> for SkipCursor<E>
where
    E: Display + Eq + From<Tick> + 'static,
{
    type Alphabet = EmptyAlphabet;

    fn initials(&self) -> EmptyAlphabet {
        EmptyAlphabet
    }

    fn events(&self) -> Box<dyn Iterator<Item = E>> {
        match self.state {
            SkipState::BeforeTick => Box::new(std::iter::once(tick())),
            SkipState::AfterTick => Box::new(std::iter::empty()),
        }
    }

    fn can_perform(&self, event: &E) -> bool {
        match self.state {
            SkipState::BeforeTick => *event == tick(),
            SkipState::AfterTick => false,
        }
    }

    fn perform(&mut self, event: &E) {
        if self.state == SkipState::AfterTick {
            panic!("Skip cannot perform {} after ✔", event);
        }
        if *event != tick() {
            panic!("Skip cannot perform {}", event);
        }
        self.state = SkipState::AfterTick;
    }
}

#[cfg(test)]
mod skip_tests {
    use super::*;

    use maplit::hashset;

    use crate::process::initials;
    use crate::process::maximal_finite_traces;
    use crate::test_support::TestEvent;

    #[test]
    fn check_skip() {
        let process: Skip<TestEvent> = dbg!(skip());
        assert_eq!(initials(&process.root()), hashset! { tick() });
        assert_eq!(
            maximal_finite_traces(process.root()),
            hashset! { vec![tick()] }
        );
    }
}
<commit_msg>Add Alphabet impl for Stop<commit_after>// -*- coding: utf-8 -*-
// ------------------------------------------------------------------------------------------------
// Copyright © 2019, HST authors.
//
// 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.
// ------------------------------------------------------------------------------------------------

//! Defines primitive CSP events and processes.

use std::fmt::Debug;
use std::fmt::Display;
use std::marker::PhantomData;

use crate::event::EmptyAlphabet;
use crate::process::Cursor;
use crate::process::Process;

//-------------------------------------------------------------------------------------------------
// Built-in CSP events

/// Constructs a new _tau_ event (τ).  This is the hidden event that expresses nondeterminism in a
/// CSP process.  You should rarely have to construct it directly, unless you're digging through
/// the transitions of a process.
pub fn tau<E: From<Tau>>() -> E {
    Tau.into()
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Tau;

impl Display for Tau {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("τ")
    }
}

impl Debug for Tau {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

/// Constructs a new _tick_ event (✔).  This is the hidden event that represents the end of a
/// process that can be sequentially composed with another process.  You should rarely have to
/// construct it directly, unless you're digging through the transitions of a process.
pub fn tick<E: From<Tick>>() -> E {
    Tick.into()
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Tick;

impl Display for Tick {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("✔")
    }
}

impl Debug for Tick {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

//-------------------------------------------------------------------------------------------------
// Stop

/// Constructs a new _Stop_ process.  This is the process that performs no actions (and prevents
/// any other synchronized processes from performing any, either).
pub fn stop<E, P: From<Stop<E>>>() -> P {
    Stop(PhantomData).into()
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Stop<E>(PhantomData<E>);

impl<E> Display for Stop<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("Stop")
    }
}

impl<E> Debug for Stop<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct StopCursor<E>(PhantomData<E>);

impl<E> Debug for StopCursor<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("StopCursor")
    }
}

impl<E> Process<E> for Stop<E>
where
    E: Display + 'static,
{
    type Cursor = StopCursor<E>;

    fn root(&self) -> Self::Cursor {
        StopCursor(PhantomData)
    }
}

impl<E> Cursor<E> for StopCursor<E>
where
    E: Display + 'static,
{
    type Alphabet = EmptyAlphabet;

    fn initials(&self) -> EmptyAlphabet {
        EmptyAlphabet
    }

    fn events(&self) -> Box<dyn Iterator<Item = E>> {
        Box::new(std::iter::empty())
    }

    fn can_perform(&self, _event: &E) -> bool {
        false
    }

    fn perform(&mut self, event: &E) {
        panic!("Stop cannot perform {}", event);
    }
}

#[cfg(test)]
mod stop_tests {
    use super::*;

    use maplit::hashset;
    use proptest_attr_macro::proptest;

    use crate::event::Alphabet;
    use crate::process::maximal_finite_traces;
    use crate::test_support::TestEvent;

    #[proptest]
    fn check_stop_initials(event: TestEvent) {
        let process: Stop<Tau> = dbg!(stop());
        let alphabet = process.root().initials();
        assert!(!alphabet.contains(&event));
    }

    #[test]
    fn check_stop_traces() {
        let process: Stop<Tau> = dbg!(stop());
        assert_eq!(maximal_finite_traces(process.root()), hashset! {vec![]});
    }
}

//-------------------------------------------------------------------------------------------------
// Skip

/// Constructs a new _Skip_ process.  The process that performs Tick and then becomes Stop.  Used
/// to indicate the end of a process that can be sequentially composed with something else.
pub fn skip<E, P: From<Skip<E>>>() -> P {
    Skip(PhantomData).into()
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct Skip<E>(PhantomData<E>);

impl<E> Display for Skip<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.write_str("Skip")
    }
}

impl<E> Debug for Skip<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        (self as &dyn Display).fmt(f)
    }
}

#[doc(hidden)]
#[derive(Clone, Eq, Hash, PartialEq)]
pub struct SkipCursor<E> {
    state: SkipState,
    phantom: PhantomData<E>,
}

#[doc(hidden)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub enum SkipState {
    BeforeTick,
    AfterTick,
}

impl<E> Debug for SkipCursor<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "SkipCursor({:?})", self.state)
    }
}

impl<E> Process<E> for Skip<E>
where
    E: Display + Eq + From<Tick> + 'static,
{
    type Cursor = SkipCursor<E>;

    fn root(&self) -> Self::Cursor {
        SkipCursor {
            state: SkipState::BeforeTick,
            phantom: PhantomData,
        }
    }
}

impl<E> Cursor<E> for SkipCursor<E>
where
    E: Display + Eq + From<Tick> + 'static,
{
    type Alphabet = EmptyAlphabet;

    fn initials(&self) -> EmptyAlphabet {
        EmptyAlphabet
    }

    fn events(&self) -> Box<dyn Iterator<Item = E>> {
        match self.state {
            SkipState::BeforeTick => Box::new(std::iter::once(tick())),
            SkipState::AfterTick => Box::new(std::iter::empty()),
        }
    }

    fn can_perform(&self, event: &E) -> bool {
        match self.state {
            SkipState::BeforeTick => *event == tick(),
            SkipState::AfterTick => false,
        }
    }

    fn perform(&mut self, event: &E) {
        if self.state == SkipState::AfterTick {
            panic!("Skip cannot perform {} after ✔", event);
        }
        if *event != tick() {
            panic!("Skip cannot perform {}", event);
        }
        self.state = SkipState::AfterTick;
    }
}

#[cfg(test)]
mod skip_tests {
    use super::*;

    use maplit::hashset;

    use crate::process::initials;
    use crate::process::maximal_finite_traces;
    use crate::test_support::TestEvent;

    #[test]
    fn check_skip() {
        let process: Skip<TestEvent> = dbg!(skip());
        assert_eq!(initials(&process.root()), hashset! { tick() });
        assert_eq!(
            maximal_finite_traces(process.root()),
            hashset! { vec![tick()] }
        );
    }
}
<|endoftext|>


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

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::clone::Clone;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::convert::AsRef;
use core::hash::{Hash, Hasher};
use core::marker::Sized;
use core::ops::Deref;
use core::option::Option;

use fmt;
use alloc::{rc, arc};

use self::Cow::*;

/// A trait for borrowing data.
///
/// In general, there may be several ways to "borrow" a piece of data.  The
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
///
/// When writing generic code, it is often desirable to abstract over all ways
/// of borrowing data from a given type. That is the role of the `Borrow`
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
    /// Immutably borrow from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Borrow;
    ///
    /// fn check<T: Borrow<str>>(s: T) {
    ///     assert_eq!("Hello", s.borrow());
    /// }
    ///
    /// let s = "Hello".to_string();
    ///
    /// check(s);
    ///
    /// let s = "Hello";
    ///
    /// check(s);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// A trait for mutably borrowing data.
///
/// Similar to `Borrow`, but for mutable borrows.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
    /// Mutably borrow from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::BorrowMut;
    ///
    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
    /// }
    ///
    /// let v = vec![1, 2, 3];
    ///
    /// check(v);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

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

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

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

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

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

impl<T> Borrow<T> for rc::Rc<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T> Borrow<T> for arc::Arc<T> {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of Clone to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Create owned data from borrowed data, usually by copying.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
    type Owned = T;
    fn to_owned(&self) -> T { self.clone() }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements both `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable references to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(&'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(<B as ToOwned>::Owned)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            },
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
    /// Acquire a mutable reference to the owned form of the data.
    ///
    /// Copies the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned
        }
    }

    /// Extract the owned data.
    ///
    /// Copies the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow()
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
    B: PartialEq<C> + ToOwned, C: ToOwned,
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned,
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
    B: fmt::Debug + ToOwned,
    <B as ToOwned>::Owned: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
    B: fmt::Display + ToOwned,
    <B as ToOwned>::Owned: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

/// Trait for moving into a `Cow`
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")]
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
    /// Moves `self` into `Cow`
    fn into_cow(self) -> Cow<'a, B>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a,  B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
    fn into_cow(self) -> Cow<'a, B> {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: Clone> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}
<commit_msg>Adjust `AsRef` impl for `Cow`<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A module for working with borrowed data.

#![stable(feature = "rust1", since = "1.0.0")]

use core::clone::Clone;
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
use core::convert::AsRef;
use core::hash::{Hash, Hasher};
use core::marker::Sized;
use core::ops::Deref;
use core::option::Option;

use fmt;
use alloc::{rc, arc};

use self::Cow::*;

/// A trait for borrowing data.
///
/// In general, there may be several ways to "borrow" a piece of data.  The
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
///
/// When writing generic code, it is often desirable to abstract over all ways
/// of borrowing data from a given type. That is the role of the `Borrow`
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
    /// Immutably borrow from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Borrow;
    ///
    /// fn check<T: Borrow<str>>(s: T) {
    ///     assert_eq!("Hello", s.borrow());
    /// }
    ///
    /// let s = "Hello".to_string();
    ///
    /// check(s);
    ///
    /// let s = "Hello";
    ///
    /// check(s);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow(&self) -> &Borrowed;
}

/// A trait for mutably borrowing data.
///
/// Similar to `Borrow`, but for mutable borrows.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
    /// Mutably borrow from an owned value.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::BorrowMut;
    ///
    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
    /// }
    ///
    /// let v = vec![1, 2, 3];
    ///
    /// check(v);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    fn borrow_mut(&mut self) -> &mut Borrowed;
}

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

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

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

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

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

impl<T> Borrow<T> for rc::Rc<T> {
    fn borrow(&self) -> &T { &**self }
}

impl<T> Borrow<T> for arc::Arc<T> {
    fn borrow(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
    fn borrow(&self) -> &B {
        &**self
    }
}

/// A generalization of Clone to borrowed data.
///
/// Some types make it possible to go from borrowed to owned, usually by
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
/// from any borrow of a given type.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait ToOwned {
    #[stable(feature = "rust1", since = "1.0.0")]
    type Owned: Borrow<Self>;

    /// Create owned data from borrowed data, usually by copying.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn to_owned(&self) -> Self::Owned;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ToOwned for T where T: Clone {
    type Owned = T;
    fn to_owned(&self) -> T { self.clone() }
}

/// A clone-on-write smart pointer.
///
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
/// can enclose and provide immutable access to borrowed data, and clone the
/// data lazily when mutation or ownership is required. The type is designed to
/// work with general borrowed data via the `Borrow` trait.
///
/// `Cow` implements both `Deref`, which means that you can call
/// non-mutating methods directly on the data it encloses. If mutation
/// is desired, `to_mut` will obtain a mutable references to an owned
/// value, cloning if necessary.
///
/// # Examples
///
/// ```
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[i32]>) {
///     for i in 0..input.len() {
///         let v = input[i];
///         if v < 0 {
///             // clones into a vector the first time (if not already owned)
///             input.to_mut()[i] = -v;
///         }
///     }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
    /// Borrowed data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Borrowed(&'a B),

    /// Owned data.
    #[stable(feature = "rust1", since = "1.0.0")]
    Owned(<B as ToOwned>::Owned)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
    fn clone(&self) -> Cow<'a, B> {
        match *self {
            Borrowed(b) => Borrowed(b),
            Owned(ref o) => {
                let b: &B = o.borrow();
                Owned(b.to_owned())
            },
        }
    }
}

impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
    /// Acquire a mutable reference to the owned form of the data.
    ///
    /// Copies the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.to_mut();
    ///
    /// assert_eq!(hello, &[1, 2, 3]);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
        match *self {
            Borrowed(borrowed) => {
                *self = Owned(borrowed.to_owned());
                self.to_mut()
            }
            Owned(ref mut owned) => owned
        }
    }

    /// Extract the owned data.
    ///
    /// Copies the data if it is not already owned.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::borrow::Cow;
    ///
    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
    ///
    /// let hello = cow.into_owned();
    ///
    /// assert_eq!(vec![1, 2, 3], hello);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn into_owned(self) -> <B as ToOwned>::Owned {
        match self {
            Borrowed(borrowed) => borrowed.to_owned(),
            Owned(owned) => owned
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
    type Target = B;

    fn deref(&self) -> &B {
        match *self {
            Borrowed(borrowed) => borrowed,
            Owned(ref owned) => owned.borrow()
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
    #[inline]
    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
    B: PartialEq<C> + ToOwned, C: ToOwned,
{
    #[inline]
    fn eq(&self, other: &Cow<'b, C>) -> bool {
        PartialEq::eq(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned,
{
    #[inline]
    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
    B: fmt::Debug + ToOwned,
    <B as ToOwned>::Owned: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Debug::fmt(b, f),
            Owned(ref o) => fmt::Debug::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
    B: fmt::Display + ToOwned,
    <B as ToOwned>::Owned: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Borrowed(ref b) => fmt::Display::fmt(b, f),
            Owned(ref o) => fmt::Display::fmt(o, f),
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
{
    #[inline]
    fn hash<H: Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

/// Trait for moving into a `Cow`
#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")]
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
    /// Moves `self` into `Cow`
    fn into_cow(self) -> Cow<'a, B>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a,  B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
    fn into_cow(self) -> Cow<'a, B> {
        self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized + ToOwned> AsRef<T> for Cow<'a, T> {
    fn as_ref(&self) -> &T {
        self
    }
}
<|endoftext|>


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

use rustc::session::Session;

use rustc::hir::map::Map;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::{self, Destination};
use syntax::ast;
use syntax_pos::Span;

#[derive(Clone, Copy, PartialEq)]
enum LoopKind {
    Loop(hir::LoopSource),
    WhileLoop,
}

impl LoopKind {
    fn name(self) -> &'static str {
        match self {
            LoopKind::Loop(hir::LoopSource::Loop) => "loop",
            LoopKind::Loop(hir::LoopSource::WhileLet) => "while let",
            LoopKind::Loop(hir::LoopSource::ForLoop) => "for",
            LoopKind::WhileLoop => "while",
        }
    }
}

#[derive(Clone, Copy, PartialEq)]
enum Context {
    Normal,
    Loop(LoopKind),
    Closure,
    LabeledBlock,
}

#[derive(Copy, Clone)]
struct CheckLoopVisitor<'a, 'hir: 'a> {
    sess: &'a Session,
    hir_map: &'a Map<'hir>,
    cx: Context,
}

pub fn check_crate(sess: &Session, map: &Map) {
    let krate = map.krate();
    krate.visit_all_item_likes(&mut CheckLoopVisitor {
        sess,
        hir_map: map,
        cx: Normal,
    }.as_deep_visitor());
}

impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
        NestedVisitorMap::OnlyBodies(&self.hir_map)
    }

    fn visit_item(&mut self, i: &'hir hir::Item) {
        self.with_context(Normal, |v| intravisit::walk_item(v, i));
    }

    fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) {
        self.with_context(Normal, |v| intravisit::walk_impl_item(v, i));
    }

    fn visit_expr(&mut self, e: &'hir hir::Expr) {
        match e.node {
            hir::ExprWhile(ref e, ref b, _) => {
                self.with_context(Loop(LoopKind::WhileLoop), |v| {
                    v.visit_expr(&e);
                    v.visit_block(&b);
                });
            }
            hir::ExprLoop(ref b, _, source) => {
                self.with_context(Loop(LoopKind::Loop(source)), |v| v.visit_block(&b));
            }
            hir::ExprClosure(.., b, _, _) => {
                self.with_context(Closure, |v| v.visit_nested_body(b));
            }
            hir::ExprBlock(ref b, Some(_label)) => {
                self.with_context(LabeledBlock, |v| v.visit_block(&b));
            }
            hir::ExprBreak(label, ref opt_expr) => {
                opt_expr.as_ref().map(|e| self.visit_expr(e));

                if self.require_label_in_labeled_block(e.span, &label, "break") {
                    // If we emitted an error about an unlabeled break in a labeled
                    // block, we don't need any further checking for this break any more
                    return;
                }

                let loop_id = match label.target_id.into() {
                    Ok(loop_id) => loop_id,
                    Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
                        self.emit_unlabled_cf_in_while_condition(e.span, "break");
                        ast::DUMMY_NODE_ID
                    },
                    Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
                };

                if loop_id != ast::DUMMY_NODE_ID {
                    match self.hir_map.find(loop_id).unwrap() {
                        hir::map::NodeBlock(_) => return,
                        _=> (),
                    }
                }

                if opt_expr.is_some() {
                    let loop_kind = if loop_id == ast::DUMMY_NODE_ID {
                        None
                    } else {
                        Some(match self.hir_map.expect_expr(loop_id).node {
                            hir::ExprWhile(..) => LoopKind::WhileLoop,
                            hir::ExprLoop(_, _, source) => LoopKind::Loop(source),
                            ref r => span_bug!(e.span,
                                               "break label resolved to a non-loop: {:?}", r),
                        })
                    };
                    match loop_kind {
                        None |
                        Some(LoopKind::Loop(hir::LoopSource::Loop)) => (),
                        Some(kind) => {
                            struct_span_err!(self.sess, e.span, E0571,
                                             "`break` with value from a `{}` loop",
                                             kind.name())
                                .span_label(e.span,
                                            "can only break with a value inside \
                                            `loop` or breakable block")
                                .span_suggestion(e.span,
                                                 &format!("instead, use `break` on its own \
                                                           without a value inside this `{}` loop",
                                                          kind.name()),
                                                 "break".to_string())
                                .emit();
                        }
                    }
                }

                self.require_break_cx("break", e.span);
            }
            hir::ExprAgain(label) => {
                self.require_label_in_labeled_block(e.span, &label, "continue");

                match label.target_id {
                    Ok(loop_id) => {
                        if let hir::map::NodeBlock(block) = self.hir_map.find(loop_id).unwrap() {
                            struct_span_err!(self.sess, e.span, E0696,
                                            "`continue` pointing to a labeled block")
                                .span_label(e.span,
                                            "labeled blocks cannot be `continue`'d")
                                .span_note(block.span,
                                            "labeled block the continue points to")
                                .emit();
                        }
                    }
                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
                        self.emit_unlabled_cf_in_while_condition(e.span, "continue");
                    }
                    _ => {}
                }
                self.require_break_cx("continue", e.span)
            },
            _ => intravisit::walk_expr(self, e),
        }
    }
}

impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
    fn with_context<F>(&mut self, cx: Context, f: F)
        where F: FnOnce(&mut CheckLoopVisitor<'a, 'hir>)
    {
        let old_cx = self.cx;
        self.cx = cx;
        f(self);
        self.cx = old_cx;
    }

    fn require_break_cx(&self, name: &str, span: Span) {
        match self.cx {
            LabeledBlock |
            Loop(_) => {}
            Closure => {
                struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name)
                .span_label(span, "cannot break inside of a closure")
                .emit();
            }
            Normal => {
                struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name)
                .span_label(span, "cannot break outside of a loop")
                .emit();
            }
        }
    }

    fn require_label_in_labeled_block(&mut self, span: Span, label: &Destination, cf_type: &str)
        -> bool
    {
        if self.cx == LabeledBlock {
            if label.label.is_none() {
                struct_span_err!(self.sess, span, E0695,
                                "unlabeled `{}` inside of a labeled block", cf_type)
                    .span_label(span,
                                format!("`{}` statements that would diverge to or through \
                                a labeled block need to bear a label", cf_type))
                    .emit();
                return true;
            }
        }
        return false;
    }
    fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
        struct_span_err!(self.sess, span, E0590,
                         "`break` or `continue` with no label in the condition of a `while` loop")
            .span_label(span,
                        format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
            .emit();
    }
}
<commit_msg>Rollup merge of #50849 - est31:visit_closure_args, r=michaelwoerister<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use self::Context::*;

use rustc::session::Session;

use rustc::hir::map::Map;
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
use rustc::hir::{self, Destination};
use syntax::ast;
use syntax_pos::Span;

#[derive(Clone, Copy, PartialEq)]
enum LoopKind {
    Loop(hir::LoopSource),
    WhileLoop,
}

impl LoopKind {
    fn name(self) -> &'static str {
        match self {
            LoopKind::Loop(hir::LoopSource::Loop) => "loop",
            LoopKind::Loop(hir::LoopSource::WhileLet) => "while let",
            LoopKind::Loop(hir::LoopSource::ForLoop) => "for",
            LoopKind::WhileLoop => "while",
        }
    }
}

#[derive(Clone, Copy, PartialEq)]
enum Context {
    Normal,
    Loop(LoopKind),
    Closure,
    LabeledBlock,
}

#[derive(Copy, Clone)]
struct CheckLoopVisitor<'a, 'hir: 'a> {
    sess: &'a Session,
    hir_map: &'a Map<'hir>,
    cx: Context,
}

pub fn check_crate(sess: &Session, map: &Map) {
    let krate = map.krate();
    krate.visit_all_item_likes(&mut CheckLoopVisitor {
        sess,
        hir_map: map,
        cx: Normal,
    }.as_deep_visitor());
}

impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
        NestedVisitorMap::OnlyBodies(&self.hir_map)
    }

    fn visit_item(&mut self, i: &'hir hir::Item) {
        self.with_context(Normal, |v| intravisit::walk_item(v, i));
    }

    fn visit_impl_item(&mut self, i: &'hir hir::ImplItem) {
        self.with_context(Normal, |v| intravisit::walk_impl_item(v, i));
    }

    fn visit_expr(&mut self, e: &'hir hir::Expr) {
        match e.node {
            hir::ExprWhile(ref e, ref b, _) => {
                self.with_context(Loop(LoopKind::WhileLoop), |v| {
                    v.visit_expr(&e);
                    v.visit_block(&b);
                });
            }
            hir::ExprLoop(ref b, _, source) => {
                self.with_context(Loop(LoopKind::Loop(source)), |v| v.visit_block(&b));
            }
            hir::ExprClosure(_, ref function_decl, b, _, _) => {
                self.visit_fn_decl(&function_decl);
                self.with_context(Closure, |v| v.visit_nested_body(b));
            }
            hir::ExprBlock(ref b, Some(_label)) => {
                self.with_context(LabeledBlock, |v| v.visit_block(&b));
            }
            hir::ExprBreak(label, ref opt_expr) => {
                opt_expr.as_ref().map(|e| self.visit_expr(e));

                if self.require_label_in_labeled_block(e.span, &label, "break") {
                    // If we emitted an error about an unlabeled break in a labeled
                    // block, we don't need any further checking for this break any more
                    return;
                }

                let loop_id = match label.target_id.into() {
                    Ok(loop_id) => loop_id,
                    Err(hir::LoopIdError::OutsideLoopScope) => ast::DUMMY_NODE_ID,
                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
                        self.emit_unlabled_cf_in_while_condition(e.span, "break");
                        ast::DUMMY_NODE_ID
                    },
                    Err(hir::LoopIdError::UnresolvedLabel) => ast::DUMMY_NODE_ID,
                };

                if loop_id != ast::DUMMY_NODE_ID {
                    match self.hir_map.find(loop_id).unwrap() {
                        hir::map::NodeBlock(_) => return,
                        _=> (),
                    }
                }

                if opt_expr.is_some() {
                    let loop_kind = if loop_id == ast::DUMMY_NODE_ID {
                        None
                    } else {
                        Some(match self.hir_map.expect_expr(loop_id).node {
                            hir::ExprWhile(..) => LoopKind::WhileLoop,
                            hir::ExprLoop(_, _, source) => LoopKind::Loop(source),
                            ref r => span_bug!(e.span,
                                               "break label resolved to a non-loop: {:?}", r),
                        })
                    };
                    match loop_kind {
                        None |
                        Some(LoopKind::Loop(hir::LoopSource::Loop)) => (),
                        Some(kind) => {
                            struct_span_err!(self.sess, e.span, E0571,
                                             "`break` with value from a `{}` loop",
                                             kind.name())
                                .span_label(e.span,
                                            "can only break with a value inside \
                                            `loop` or breakable block")
                                .span_suggestion(e.span,
                                                 &format!("instead, use `break` on its own \
                                                           without a value inside this `{}` loop",
                                                          kind.name()),
                                                 "break".to_string())
                                .emit();
                        }
                    }
                }

                self.require_break_cx("break", e.span);
            }
            hir::ExprAgain(label) => {
                self.require_label_in_labeled_block(e.span, &label, "continue");

                match label.target_id {
                    Ok(loop_id) => {
                        if let hir::map::NodeBlock(block) = self.hir_map.find(loop_id).unwrap() {
                            struct_span_err!(self.sess, e.span, E0696,
                                            "`continue` pointing to a labeled block")
                                .span_label(e.span,
                                            "labeled blocks cannot be `continue`'d")
                                .span_note(block.span,
                                            "labeled block the continue points to")
                                .emit();
                        }
                    }
                    Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
                        self.emit_unlabled_cf_in_while_condition(e.span, "continue");
                    }
                    _ => {}
                }
                self.require_break_cx("continue", e.span)
            },
            _ => intravisit::walk_expr(self, e),
        }
    }
}

impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
    fn with_context<F>(&mut self, cx: Context, f: F)
        where F: FnOnce(&mut CheckLoopVisitor<'a, 'hir>)
    {
        let old_cx = self.cx;
        self.cx = cx;
        f(self);
        self.cx = old_cx;
    }

    fn require_break_cx(&self, name: &str, span: Span) {
        match self.cx {
            LabeledBlock |
            Loop(_) => {}
            Closure => {
                struct_span_err!(self.sess, span, E0267, "`{}` inside of a closure", name)
                .span_label(span, "cannot break inside of a closure")
                .emit();
            }
            Normal => {
                struct_span_err!(self.sess, span, E0268, "`{}` outside of loop", name)
                .span_label(span, "cannot break outside of a loop")
                .emit();
            }
        }
    }

    fn require_label_in_labeled_block(&mut self, span: Span, label: &Destination, cf_type: &str)
        -> bool
    {
        if self.cx == LabeledBlock {
            if label.label.is_none() {
                struct_span_err!(self.sess, span, E0695,
                                "unlabeled `{}` inside of a labeled block", cf_type)
                    .span_label(span,
                                format!("`{}` statements that would diverge to or through \
                                a labeled block need to bear a label", cf_type))
                    .emit();
                return true;
            }
        }
        return false;
    }
    fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
        struct_span_err!(self.sess, span, E0590,
                         "`break` or `continue` with no label in the condition of a `while` loop")
            .span_label(span,
                        format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
            .emit();
    }
}
<|endoftext|>


<commit_before>extern crate linked_hash_map;

use self::linked_hash_map::LinkedHashMap;
use std::borrow::Borrow;
use std::collections::hash_state::HashState;
use std::hash::Hash;

impl<K, V, S> super::Collection for LinkedHashMap<K, V, S> where K: Eq + Hash, S: HashState {
    fn clear(&mut self) { self.clear(); }
    fn is_empty(&self) -> bool { self.is_empty() }
    fn len(&self) -> usize { self.len() }
}

impl<K, V, S> super::BaseMap for LinkedHashMap<K, V, S> where K: Eq + Hash, S: HashState {
    type Key = K;
    type Value = V;
}

impl<K, V, S, Q> super::MapLookup<Q> for LinkedHashMap<K, V, S>
where
    K: Eq + Hash + Borrow<Q>,
    S: HashState,
    Q: Eq + Hash,
{
    fn contains_key(&self, key: &Q) -> bool { self.contains_key(key) }
    fn get(&self, key: &Q) -> Option<&V> { self.get(key) }
    fn get_mut(&mut self, key: &Q) -> Option<&mut V> { self.get_mut(key) }
    fn remove(&mut self, key: &Q) -> Option<V> { self.remove(key) }
}

impl<K, V, S> super::Map for LinkedHashMap<K, V, S> where K: Eq + Hash, S: HashState {
    fn insert(&mut self, key: K, value: V) -> Option<V> { self.insert(key, value) }
}
<commit_msg>add missing `?Sized` bound<commit_after>extern crate linked_hash_map;

use self::linked_hash_map::LinkedHashMap;
use std::borrow::Borrow;
use std::collections::hash_state::HashState;
use std::hash::Hash;

impl<K, V, S> super::Collection for LinkedHashMap<K, V, S> where K: Eq + Hash, S: HashState {
    fn clear(&mut self) { self.clear(); }
    fn is_empty(&self) -> bool { self.is_empty() }
    fn len(&self) -> usize { self.len() }
}

impl<K, V, S> super::BaseMap for LinkedHashMap<K, V, S> where K: Eq + Hash, S: HashState {
    type Key = K;
    type Value = V;
}

impl<K, V, S, Q: ?Sized> super::MapLookup<Q> for LinkedHashMap<K, V, S>
where
    K: Eq + Hash + Borrow<Q>,
    S: HashState,
    Q: Eq + Hash,
{
    fn contains_key(&self, key: &Q) -> bool { self.contains_key(key) }
    fn get(&self, key: &Q) -> Option<&V> { self.get(key) }
    fn get_mut(&mut self, key: &Q) -> Option<&mut V> { self.get_mut(key) }
    fn remove(&mut self, key: &Q) -> Option<V> { self.remove(key) }
}

impl<K, V, S> super::Map for LinkedHashMap<K, V, S> where K: Eq + Hash, S: HashState {
    fn insert(&mut self, key: K, value: V) -> Option<V> { self.insert(key, value) }
}
<|endoftext|>


<commit_before>//! A module to parse invidual log lines into Requests and Responses

use chrono::*;
use http_status::HttpStatus;

pub enum LogEvent {
    Request(Request),
    Response(Response),
}

#[derive(Eq, PartialEq, Clone)]
#[derive(Debug)]
pub struct Request {
    pub id: i32,
    pub time: DateTime<FixedOffset>,
    pub url: String,
    pub original_log_line: String,
}

impl Request {
    pub fn new_from_log_line(log_line: &String) -> Result<Request, &'static str> {
        let parts: Vec<&str> = log_line.split(" ").collect();

        let id = match parts.get(2) {
            Some(id) => id,
            None => return Err("Uncomprehensible request logline"),
        };

        // Shortest valid id format is "[1]"
        if id.len() < 3 {
            return Err("Uncomprehensible request logline");
        }

        let id_parsed: i32 = match id[1..id.len() - 1].parse() {
            Ok(id) => id,
            Err(_) => return Err("Uncomprehensible request logline"),
        };

        let url = match parts.get(5) {
            Some(url) => url,
            None => return Err("Uncomprehensible request logline"),
        };

        let date = &format!("{} {}", parts[0], parts[1]);

        let date_parsed = match DateTime::parse_from_str(date, "%d/%b/%Y:%H:%M:%S %z") {
            Ok(date_time) => date_time,
            Err(_) => return Err("Uncomprehensible request logline"),
        };

        Ok(Request {
            id: id_parsed,
            time: date_parsed,
            url: url.to_string(),
            original_log_line: log_line.clone(),
        })
    }
}

#[derive(Eq, PartialEq, Clone)]
#[derive(Debug)]
pub struct Response {
    pub id: i32,
    pub time: DateTime<FixedOffset>,
    pub mime_type: String,
    pub response_time: Duration,
    pub http_status: HttpStatus,
    pub original_log_line: String,
}

impl Response {
    pub fn new_from_log_line(log_line: &String) -> Result<Response, &'static str> {
        let parts: Vec<&str> = log_line.split(" ").collect();

        let id = parts[2];

        // Shortest valid id format is "[1]"
        if id.len() < 3 {
            return Err("Uncomprehensible response logline");
        }

        let id_numeric: i32 = match id[1..id.len() - 1].parse() {
            Ok(number) => number,
            Err(_) => return Err("Uncomprehensible response logline"),
        };

        let time = match DateTime::parse_from_str(&format!("{} {}", parts[0], parts[1]),
                                                  "%d/%b/%Y:%H:%M:%S %z") {
            Ok(time) => time,
            Err(_) => return Err("Uncomprehensible response logline"),
        };

        let response_time = parts[parts.len() - 1];
        if response_time.len() < 3 {
            return Err("Uncomprehensible response logline");
        }

        let response_time_duration = match response_time[0..response_time.len() - 2].parse() {
            Ok(number) => Duration::milliseconds(number),
            Err(_) => return Err("Uncomprehensible response logline"),
        };

        // Handle special case where the mime type sometimes contains
        // a space, so we need to re-assemble it
        let mime_type = match parts.len() {
            8 => format!("{} {}", parts[5], parts[6]),
            _ => parts[5].to_string(),
        };

        let status_code = match parts[4].parse() {
            Ok(number) => HttpStatus::from_code(number),
            Err(_) => return Err("Uncomprehensible response logline"),
        };

        Ok(Response {
            id: id_numeric,
            time: time,
            response_time: response_time_duration,
            mime_type: mime_type,
            http_status: status_code,
            original_log_line: log_line.clone(),
        })
    }
}

#[cfg(test)]
mod tests {
    use::chrono::*;
    use http_status::HttpStatus;

    use super::*;

    #[test]
    fn test_parse_request_line() {
        let line = "08/Apr/2016:09:58:47 +0200 [02] -> GET /content/some/other.html HTTP/1.1"
            .to_string();

        let expected = Request {
            id: 2,
            time: DateTime::parse_from_str("08/Apr/2016:09:58:47 +0200", "%d/%b/%Y:%H:%M:%S %z")
                .unwrap(),
            url: "/content/some/other.html".to_string(),
            original_log_line: line.clone(),
        };

        let result = Request::new_from_log_line(&line);

        assert_eq!(result.unwrap(), expected)
    }

    #[test]
    fn test_parse_request_line_bad_format() {
        let line = "08/A16:09:58:47 justsomegarbage".to_string();

        let expected: Result<Request, &'static str> = Err("Uncomprehensible request logline");
        let result: Result<Request, &'static str> = Request::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_request_line_bad_format_but_enough_parts() {
        let line = "just some garbage with more parts at the end".to_string();

        let expected: Result<Request, &'static str> = Err("Uncomprehensible request logline");
        let result: Result<Request, &'static str> = Request::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_request_line_bad_date_format() {
        let line = "99/XYZ/9999:09:99:99 +9900 [02] -> GET /content/some/other.html HTTP/1.1"
            .to_string();

        let expected: Result<Request, &'static str> = Err("Uncomprehensible request logline");
        let result: Result<Request, &'static str> = Request::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_request_line_bad_id_format() {
        let line = "08/Apr/2016:09:58:47 +0200 2 -> GET /content/some/other.html HTTP/1.1"
            .to_string();

        let expected: Result<Request, &'static str> = Err("Uncomprehensible request logline");
        let result: Result<Request, &'static str> = Request::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line() {
        let line = "08/Apr/2016:09:58:48 +0200 [02] <- 200 text/html 10ms".to_string();

        let expected = Response {
            id: 2,
            time: DateTime::parse_from_str("08/Apr/2016:09:58:48 +0200", "%d/%b/%Y:%H:%M:%S %z")
                .unwrap(),
            mime_type: "text/html".to_string(),
            response_time: Duration::milliseconds(10),
            http_status: HttpStatus::OK,
            original_log_line: line.clone(),
        };

        let result = Response::new_from_log_line(&line);

        assert_eq!(result.unwrap(), expected)
    }

    #[test]
    fn test_parse_response_line_inconsistent_space() {
        let line = "06/Apr/2016:14:54:16 +0200 [200] <- 200 text/html; charset=utf-8 250ms"
            .to_string();

        let expected = Response {
            id: 200,
            time: DateTime::parse_from_str("06/Apr/2016:14:54:16 +0200", "%d/%b/%Y:%H:%M:%S %z")
                .unwrap(),
            mime_type: "text/html; charset=utf-8".to_string(),
            response_time: Duration::milliseconds(250),
            http_status: HttpStatus::OK,
            original_log_line: line.clone(),
        };

        let result = Response::new_from_log_line(&line);

        assert_eq!(result.unwrap(), expected)
    }

    #[test]
    fn test_parse_response_line_bad_id_format() {
        let line = "08/Apr/2016:09:58:48 +0200 2 <- 200 text/html 10ms".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line_bad_id_format_no_number() {
        let line = "08/Apr/2016:09:58:48 +0200 [XXX] <- 200 text/html 10ms".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line_bad_time_format() {
        let line = "08/Apr/2016:5:2X:48 +0200 [83940] <- 200 text/html 14642ms".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line_bad_response_time_too_short() {
        let line = "08/Apr/2016:09:57:47 +0200 [001] <- 200 text/html X".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line_bad_response_time_not_a_number() {
        let line = "08/Apr/2016:09:57:47 +0200 [001] <- 200 text/html XXXms".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line_bad_status_code() {
        let line = "08/Apr/2016:09:57:47 +0200 [001] <- FOO text/html 10ms".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_log_event_type() {
        let request_line =
            "08/Apr/2016:09:58:47 +0200 [02] -> GET /content/some/other.html HTTP/1.1".to_string();
        let response_line = "08/Apr/2016:09:58:48 +0200 [02] <- 200 text/html 10ms".to_string();

        let _ = LogEvent::Request(Request::new_from_log_line(&request_line).unwrap());
        let _ = LogEvent::Response(Response::new_from_log_line(&response_line).unwrap());
    }
}
<commit_msg>Doc comment is outdated<commit_after>use chrono::*;
use http_status::HttpStatus;

pub enum LogEvent {
    Request(Request),
    Response(Response),
}

#[derive(Eq, PartialEq, Clone)]
#[derive(Debug)]
pub struct Request {
    pub id: i32,
    pub time: DateTime<FixedOffset>,
    pub url: String,
    pub original_log_line: String,
}

impl Request {
    pub fn new_from_log_line(log_line: &String) -> Result<Request, &'static str> {
        let parts: Vec<&str> = log_line.split(" ").collect();

        let id = match parts.get(2) {
            Some(id) => id,
            None => return Err("Uncomprehensible request logline"),
        };

        // Shortest valid id format is "[1]"
        if id.len() < 3 {
            return Err("Uncomprehensible request logline");
        }

        let id_parsed: i32 = match id[1..id.len() - 1].parse() {
            Ok(id) => id,
            Err(_) => return Err("Uncomprehensible request logline"),
        };

        let url = match parts.get(5) {
            Some(url) => url,
            None => return Err("Uncomprehensible request logline"),
        };

        let date = &format!("{} {}", parts[0], parts[1]);

        let date_parsed = match DateTime::parse_from_str(date, "%d/%b/%Y:%H:%M:%S %z") {
            Ok(date_time) => date_time,
            Err(_) => return Err("Uncomprehensible request logline"),
        };

        Ok(Request {
            id: id_parsed,
            time: date_parsed,
            url: url.to_string(),
            original_log_line: log_line.clone(),
        })
    }
}

#[derive(Eq, PartialEq, Clone)]
#[derive(Debug)]
pub struct Response {
    pub id: i32,
    pub time: DateTime<FixedOffset>,
    pub mime_type: String,
    pub response_time: Duration,
    pub http_status: HttpStatus,
    pub original_log_line: String,
}

impl Response {
    pub fn new_from_log_line(log_line: &String) -> Result<Response, &'static str> {
        let parts: Vec<&str> = log_line.split(" ").collect();

        let id = parts[2];

        // Shortest valid id format is "[1]"
        if id.len() < 3 {
            return Err("Uncomprehensible response logline");
        }

        let id_numeric: i32 = match id[1..id.len() - 1].parse() {
            Ok(number) => number,
            Err(_) => return Err("Uncomprehensible response logline"),
        };

        let time = match DateTime::parse_from_str(&format!("{} {}", parts[0], parts[1]),
                                                  "%d/%b/%Y:%H:%M:%S %z") {
            Ok(time) => time,
            Err(_) => return Err("Uncomprehensible response logline"),
        };

        let response_time = parts[parts.len() - 1];
        if response_time.len() < 3 {
            return Err("Uncomprehensible response logline");
        }

        let response_time_duration = match response_time[0..response_time.len() - 2].parse() {
            Ok(number) => Duration::milliseconds(number),
            Err(_) => return Err("Uncomprehensible response logline"),
        };

        // Handle special case where the mime type sometimes contains
        // a space, so we need to re-assemble it
        let mime_type = match parts.len() {
            8 => format!("{} {}", parts[5], parts[6]),
            _ => parts[5].to_string(),
        };

        let status_code = match parts[4].parse() {
            Ok(number) => HttpStatus::from_code(number),
            Err(_) => return Err("Uncomprehensible response logline"),
        };

        Ok(Response {
            id: id_numeric,
            time: time,
            response_time: response_time_duration,
            mime_type: mime_type,
            http_status: status_code,
            original_log_line: log_line.clone(),
        })
    }
}

#[cfg(test)]
mod tests {
    use::chrono::*;
    use http_status::HttpStatus;

    use super::*;

    #[test]
    fn test_parse_request_line() {
        let line = "08/Apr/2016:09:58:47 +0200 [02] -> GET /content/some/other.html HTTP/1.1"
            .to_string();

        let expected = Request {
            id: 2,
            time: DateTime::parse_from_str("08/Apr/2016:09:58:47 +0200", "%d/%b/%Y:%H:%M:%S %z")
                .unwrap(),
            url: "/content/some/other.html".to_string(),
            original_log_line: line.clone(),
        };

        let result = Request::new_from_log_line(&line);

        assert_eq!(result.unwrap(), expected)
    }

    #[test]
    fn test_parse_request_line_bad_format() {
        let line = "08/A16:09:58:47 justsomegarbage".to_string();

        let expected: Result<Request, &'static str> = Err("Uncomprehensible request logline");
        let result: Result<Request, &'static str> = Request::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_request_line_bad_format_but_enough_parts() {
        let line = "just some garbage with more parts at the end".to_string();

        let expected: Result<Request, &'static str> = Err("Uncomprehensible request logline");
        let result: Result<Request, &'static str> = Request::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_request_line_bad_date_format() {
        let line = "99/XYZ/9999:09:99:99 +9900 [02] -> GET /content/some/other.html HTTP/1.1"
            .to_string();

        let expected: Result<Request, &'static str> = Err("Uncomprehensible request logline");
        let result: Result<Request, &'static str> = Request::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_request_line_bad_id_format() {
        let line = "08/Apr/2016:09:58:47 +0200 2 -> GET /content/some/other.html HTTP/1.1"
            .to_string();

        let expected: Result<Request, &'static str> = Err("Uncomprehensible request logline");
        let result: Result<Request, &'static str> = Request::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line() {
        let line = "08/Apr/2016:09:58:48 +0200 [02] <- 200 text/html 10ms".to_string();

        let expected = Response {
            id: 2,
            time: DateTime::parse_from_str("08/Apr/2016:09:58:48 +0200", "%d/%b/%Y:%H:%M:%S %z")
                .unwrap(),
            mime_type: "text/html".to_string(),
            response_time: Duration::milliseconds(10),
            http_status: HttpStatus::OK,
            original_log_line: line.clone(),
        };

        let result = Response::new_from_log_line(&line);

        assert_eq!(result.unwrap(), expected)
    }

    #[test]
    fn test_parse_response_line_inconsistent_space() {
        let line = "06/Apr/2016:14:54:16 +0200 [200] <- 200 text/html; charset=utf-8 250ms"
            .to_string();

        let expected = Response {
            id: 200,
            time: DateTime::parse_from_str("06/Apr/2016:14:54:16 +0200", "%d/%b/%Y:%H:%M:%S %z")
                .unwrap(),
            mime_type: "text/html; charset=utf-8".to_string(),
            response_time: Duration::milliseconds(250),
            http_status: HttpStatus::OK,
            original_log_line: line.clone(),
        };

        let result = Response::new_from_log_line(&line);

        assert_eq!(result.unwrap(), expected)
    }

    #[test]
    fn test_parse_response_line_bad_id_format() {
        let line = "08/Apr/2016:09:58:48 +0200 2 <- 200 text/html 10ms".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line_bad_id_format_no_number() {
        let line = "08/Apr/2016:09:58:48 +0200 [XXX] <- 200 text/html 10ms".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line_bad_time_format() {
        let line = "08/Apr/2016:5:2X:48 +0200 [83940] <- 200 text/html 14642ms".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line_bad_response_time_too_short() {
        let line = "08/Apr/2016:09:57:47 +0200 [001] <- 200 text/html X".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line_bad_response_time_not_a_number() {
        let line = "08/Apr/2016:09:57:47 +0200 [001] <- 200 text/html XXXms".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_parse_response_line_bad_status_code() {
        let line = "08/Apr/2016:09:57:47 +0200 [001] <- FOO text/html 10ms".to_string();

        let expected: Result<Response, &'static str> = Err("Uncomprehensible response logline");
        let result: Result<Response, &'static str> = Response::new_from_log_line(&line);

        assert_eq!(result.is_err(), true);
        assert_eq!(result, expected);
    }

    #[test]
    fn test_log_event_type() {
        let request_line =
            "08/Apr/2016:09:58:47 +0200 [02] -> GET /content/some/other.html HTTP/1.1".to_string();
        let response_line = "08/Apr/2016:09:58:48 +0200 [02] <- 200 text/html 10ms".to_string();

        let _ = LogEvent::Request(Request::new_from_log_line(&request_line).unwrap());
        let _ = LogEvent::Response(Response::new_from_log_line(&response_line).unwrap());
    }
}
<|endoftext|>


<commit_before>extern crate pact_matching;
extern crate rustc_serialize;
#[macro_use(expect)] extern crate expectest;

mod spec_testcases;
<commit_msg>added tests for reading pact files<commit_after>#[macro_use] extern crate pact_matching;
extern crate rustc_serialize;
#[macro_use(expect)] extern crate expectest;
#[macro_use] extern crate p_macro;

mod spec_testcases;

use pact_matching::models::Pact;
use std::path::Path;
use expectest::prelude::*;
use rustc_serialize::json::Json;
use std::fs::File;

#[test]
fn test_load_pact() {
    let pact_file = Path::new(file!()).parent().unwrap().join("pact.json");
    let pact_result = Pact::read_pact(&pact_file);

    match pact_result {
        Ok(ref pact) => {
            let mut f = File::open(pact_file).unwrap();
            let pact_json_from_file = Json::from_reader(&mut f).unwrap();
            let pact_json = pact.to_json();
            expect(pact_json.find("consumer")).to(be_equal_to(pact_json_from_file.find("consumer")));
            expect(pact_json.find("provider")).to(be_equal_to(pact_json_from_file.find("provider")));
            expect(pact_json.find("interactions")).to(be_equal_to(pact_json_from_file.find("interactions")));

            expect(pact.metadata.get("pact-specification")).to(be_none());
            let metadata = pact_json.find("metadata").unwrap().as_object().unwrap();
            let expected_keys : Vec<String> = vec![s!("pact-rust"), s!("pact-specification")];
            expect(metadata.keys().cloned().collect::<Vec<String>>()).to(be_equal_to(expected_keys));
            expect(metadata.get("pact-specification").unwrap().to_string()).to(be_equal_to(s!("{\"version\":\"1.0.0\"}")));
        },
        Err(err) => panic!("Failed to load pact from '{:?}' - {}", pact_file, err)
    }
}

#[test]
fn test_load_pact_encoded_query() {
    let pact_file = Path::new(file!()).parent().unwrap().join("test_pact_encoded_query.json");
    let pact_result = Pact::read_pact(&pact_file);

    match pact_result {
        Ok(ref pact) => {
            let mut f = File::open(pact_file).unwrap();
            let pact_json_from_file = Json::from_reader(&mut f).unwrap();
            let pact_json = pact.to_json();
            expect(pact_json.find("consumer")).to(be_equal_to(pact_json_from_file.find("consumer")));
            expect(pact_json.find("provider")).to(be_equal_to(pact_json_from_file.find("provider")));

            let pact_interactions = pact_json.find("interactions").unwrap().as_array().unwrap();
            let pact_interactions_from_file = pact_json_from_file.find("interactions").unwrap().as_array().unwrap();
            expect(pact_interactions.len()).to(be_equal_to(pact_interactions_from_file.len()));

            for (pact_interaction, file_interaction) in pact_interactions.iter().zip(pact_interactions_from_file.iter()) {
                expect(pact_interaction.find("providerState")).to(be_equal_to(file_interaction.find("providerState")));
                expect(pact_interaction.find("description")).to(be_equal_to(file_interaction.find("description")));
                expect(pact_interaction.find("response")).to(be_equal_to(file_interaction.find("response")));

                let pact_request = pact_interaction.find("request").unwrap();
                let file_request = file_interaction.find("request").unwrap();
                expect(pact_request.find("method")).to(be_equal_to(file_request.find("method")));
                expect(pact_request.find("path")).to(be_equal_to(file_request.find("path")));
                expect(pact_request.find("headers")).to(be_equal_to(file_request.find("headers")));
                expect(pact_request.find("body")).to(be_equal_to(file_request.find("body")));
                expect(pact_request.find("query").unwrap().to_string().to_uppercase()).to(
                    be_equal_to(file_request.find("query").unwrap().to_string().to_uppercase()));
            }

            expect(pact.metadata.get("pact-specification").unwrap().get("version")).to(be_some().value("2.0.0"));
            let metadata = pact_json.find("metadata").unwrap().as_object().unwrap();
            let expected_keys : Vec<String> = vec![s!("pact-jvm"), s!("pact-rust"), s!("pact-specification")];
            expect(metadata.keys().cloned().collect::<Vec<String>>()).to(be_equal_to(expected_keys));
            expect(metadata.get("pact-specification").unwrap().to_string()).to(be_equal_to(s!("{\"version\":\"1.0.0\"}")));
        },
        Err(err) => panic!("Failed to load pact from '{:?}' - {}", pact_file, err)
    }
}

// test_pact.json
// test_pact_lowercase_method.json
// test_pact_matchers.json
// test_pact_matchers_old_format.json
// test_pact_no_bodies.json
// test_pact_no_metadata.json
// test_pact_no_spec_version.json
// test_pact_no_version.json
// test_pact_query_old_format.json
// test_pact_v3.json
// test_pact_with_bodies.json
// v1-pact.json
// v2-pact.json
// v2_pact_query.json
// v3-message-pact.json
// v3-pact.json
<|endoftext|>