<commit_before>//! Support for whitespace delimited formats
//!

#[macro_export]
macro_rules! wrap_sep (
  ($i:expr, $separator:expr, $submac:ident!( $($args:tt)* )) => (
    match ($separator)($i) {
      $crate::IResult::Error(e)      => $crate::IResult::Error(e),
      $crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
      $crate::IResult::Done(i1,_)    => {
        match $submac!(i1, $($args)*) {
          $crate::IResult::Error(e)      => $crate::IResult::Error(e),
          $crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
          $crate::IResult::Done(i2,o)    => {
            match ($separator)(i2) {
              $crate::IResult::Error(e)      => $crate::IResult::Error(e),
              $crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
              $crate::IResult::Done(i3,_)    => $crate::IResult::Done(i3, o)
            }
          }
        }
      }
    }
  )
);

#[macro_export]
macro_rules! pair_sep (
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
    tuple!(
      $i,
      sep!($separator, $submac!($($args)*)),
      sep!($separator, $submac2!($($args2)*))
    )
  );
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $g:expr) => (
    pair_sep!($i, $separator, $submac!($($args)*), call!($g));
  );
  ($i:expr, $separator:ident, $f:expr, $submac:ident!( $($args:tt)* )) => (
    pair_sep!($i, $separator, call!($f), $submac!($($args)*));
  );
  ($i:expr, $separator:ident, $f:expr, $g:expr) => (
    pair_sep!($i, $separator, call!($f), call!($g));
  );
);

#[macro_export]
macro_rules! preceded_sep (
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
    match pair_sep!($i, $separator, $submac!($($args)*), $submac2!($($args2)*)) {
      $crate::IResult::Error(a)               => $crate::IResult::Error(a),
      $crate::IResult::Incomplete(i)          => $crate::IResult::Incomplete(i),
      $crate::IResult::Done(remaining, (_,o)) => {
        $crate::IResult::Done(remaining, o)
      }
    }
  );
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $g:expr) => (
    preceded_sep!($i, $separator, $submac!($($args)*), call!($g));
  );
  ($i:expr, $separator:ident, $f:expr, $submac:ident!( $($args:tt)* )) => (
    preceded_sep!($i, $separator, call!($f), $submac!($($args)*));
  );
  ($i:expr, $separator:ident, $f:expr, $g:expr) => (
    preceded_sep!($i, $separator, call!($f), call!($g));
  );
);

#[macro_export]
macro_rules! terminated_sep (
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
    match pair_sep!($i, $separator, $submac!($($args)*), $submac2!($($args2)*)) {
      $crate::IResult::Error(a)               => $crate::IResult::Error(a),
      $crate::IResult::Incomplete(i)          => $crate::IResult::Incomplete(i),
      $crate::IResult::Done(remaining, (o,_)) => {
        $crate::IResult::Done(remaining, o)
      }
    }
  );
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $g:expr) => (
    terminated_wrap!($i, $separator, $submac!($($args)*), call!($g));
  );
  ($i:expr, $separator:ident, $f:expr, $submac:ident!( $($args:tt)* )) => (
    terminated_sep!($i, $separator, call!($f), $submac!($($args)*));
  );
  ($i:expr, $separator:ident, $f:expr, $g:expr) => (
    terminated_sep!($i, $separator, call!($f), call!($g));
  );
);

/// Internal parser, do not use directly
#[doc(hidden)]
#[macro_export]
macro_rules! tuple_sep (
  ($i:expr, $separator:ident, $consumed:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => (
    tuple_sep!($i, $separator, $consumed, ($($parsed),*), call!($e), $($rest)*);
  );
  ($i:expr, $separator:ident, $consumed:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
    {
      match sep!($i, $separator, $submac!($($args)*)) {
        $crate::IResult::Error(e)                            => $crate::IResult::Error(e),
        $crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
        $crate::IResult::Incomplete($crate::Needed::Size(i)) => $crate::IResult::Incomplete($crate::Needed::Size($consumed + i)),
        $crate::IResult::Done(i,o)     => {
          tuple_sep!(i, $separator, $consumed + ($crate::InputLength::input_len(&($i)) - $crate::InputLength::input_len(&i)), (o), $($rest)*)
        }
      }
    }
  );
  ($i:expr, $separator:ident, $consumed:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
    {
      match sep!($i, $separator, $submac!($($args)*)) {
        $crate::IResult::Error(e)                            => $crate::IResult::Error(e),
        $crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
        $crate::IResult::Incomplete($crate::Needed::Size(i)) => $crate::IResult::Incomplete($crate::Needed::Size($consumed + i)),
        $crate::IResult::Done(i,o)     => {
          tuple_sep!(i, $separator, $consumed + ($crate::InputLength::input_len(&($i)) - $crate::InputLength::input_len(&i)), ($($parsed)* , o), $($rest)*)
        }
      }
    }
  );
  ($i:expr, $separator:ident, $consumed:expr, ($($parsed:tt),*), $e:ident) => (
    tuple_sep!($i, $separator,  $consumed, ($($parsed),*), call!($e));
  );
  ($i:expr, $separator:ident, $consumed:expr, (), $submac:ident!( $($args:tt)* )) => (
    {
      match sep!($i, $separator, $submac!($($args)*)) {
        $crate::IResult::Error(e)                            => $crate::IResult::Error(e),
        $crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
        $crate::IResult::Incomplete($crate::Needed::Size(i)) => $crate::IResult::Incomplete($crate::Needed::Size($consumed + i)),
        $crate::IResult::Done(i,o)     => {
          $crate::IResult::Done(i, (o))
        }
      }
    }
  );
  ($i:expr, $separator:ident, $consumed:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => (
    {
      match sep!($i, $separator, $submac!($($args)*)) {
        $crate::IResult::Error(e)                            => $crate::IResult::Error(e),
        $crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
        $crate::IResult::Incomplete($crate::Needed::Size(i)) => $crate::IResult::Incomplete($crate::Needed::Size($consumed + i)),
        $crate::IResult::Done(i,o)     => {
          $crate::IResult::Done(i, ($($parsed),* , o))
        }
      }
    }
  );
  ($i:expr, $separator:ident, $consumed:expr, ($($parsed:expr),*)) => (
    {
      $crate::IResult::Done($i, ($($parsed),*))
    }
  );
);

#[macro_export]
macro_rules! eat_separator (
  ($i:expr, $arr:expr) => (
    {
      use $crate::util::{InputLength,IterIndices};
      use std::str;
      println!("got input: \"{}\"", str::from_utf8($i).unwrap());
      if ($i).input_len() == 0 {
        println!("empty input");
        $crate::IResult::Done($i, &($i)[0..0])
      } else {
        match ($i).iter_indices().position(|(_, item)| {
          for (_,c) in ($arr).iter_indices() {
            if c == item { return false; }
          }
          true
        }) {
          Some(index) => {
            println!("got index: {}", index);
            $crate::IResult::Done(&($i)[index..], &($i)[..index])
          },
          None        => {
            println!("got no index");
            $crate::IResult::Done(&($i)[($i).input_len()..], $i)
          }
        }
      }
    }
  );
);

#[macro_export]
macro_rules! sep (
  ($i:expr,  $separator:ident, tuple ! ($($rest:tt)*) ) => {
    tuple_sep!($i, $separator, 0usize, (), $($rest)*)
  };
  ($i:expr,  $separator:ident, pair ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      pair_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:ident, preceded ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      preceded_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:ident, terminated ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      terminated_sep!($separator, $($rest)*)
    )
  };
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* )) => {
    wrap_sep!($i, $separator, $submac!($($args)*))
  };
  ($i:expr, $separator:ident, $f:expr) => {
    wrap_sep!($i, $separator, $f)
  };
);

named!(pub sp, eat_separator!(b" \t\r\n"));

#[macro_export]
macro_rules! ws (
  ($i:expr, $($args:tt)*) => (
    {
      use $crate::sp;
      sep!($i, sp, $($args)*)
    }
  )
);

#[cfg(test)]
mod tests {
  use internal::IResult::*;
  use super::sp;

  #[test]
  fn spaaaaace() {
    assert_eq!(sp(&b" \t abc "[..]),  Done(&b"abc "[..], &b" \t "[..]));
  }

  #[test]
  fn tag() {
    named!(abc, ws!(tag!("abc")));

    assert_eq!(abc(&b" \t abc def"[..]),  Done(&b"def"[..], &b"abc"[..]));
  }

  #[test]
  fn pair() {
    named!(pair_2<&[u8], (&[u8], &[u8]) >,
      ws!(pair!( take!(3), tag!("de") ))
    );

    assert_eq!(pair_2(&b" \t abc de fg"[..]),  Done(&b"fg"[..], (&b"abc"[..], &b"de"[..])));
  }

  #[test]
  fn preceded() {
    named!(prec<&[u8], &[u8] >,
      ws!(preceded!( take!(3), tag!("de") ))
    );

    assert_eq!(prec(&b" \t abc de fg"[..]),  Done(&b"fg"[..], &b"de"[..]));
  }

  #[test]
  fn terminated() {
    named!(term<&[u8], &[u8] >,
      ws!(terminated!( take!(3), tag!("de") ))
    );

    assert_eq!(term(&b" \t abc de fg"[..]),  Done(&b"fg"[..], &b"abc"[..]));
  }

  #[test]
  fn tuple() {
    //trace_macros!(true);
    named!(tuple_2<&[u8], (&[u8], &[u8]) >,
      ws!(tuple!( take!(3), tag!("de") ))
    );
    //trace_macros!(false);

    assert_eq!(tuple_2(&b" \t abc de fg"[..]),  Done(&b"fg"[..], (&b"abc"[..], &b"de"[..])));
  }

  #[test]
  fn levels() {
    //trace_macros!(true);
    named!(level_2<&[u8], (&[u8], (&[u8], &[u8])) >,
      ws!(pair!(take!(3), tuple!( tag!("de"), tag!("fg ") )))
    );
    //trace_macros!(false);

    assert_eq!(level_2(&b" \t abc de fg \t hi "[..]),  Done(&b"hi "[..], (&b"abc"[..], (&b"de"[..], &b"fg "[..]))));
  }
}
<commit_msg>missing usage of wrap_sep<commit_after>//! Support for whitespace delimited formats
//!

#[macro_export]
macro_rules! wrap_sep (
  ($i:expr, $separator:expr, $submac:ident!( $($args:tt)* )) => (
    match ($separator)($i) {
      $crate::IResult::Error(e)      => $crate::IResult::Error(e),
      $crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
      $crate::IResult::Done(i1,_)    => {
        match $submac!(i1, $($args)*) {
          $crate::IResult::Error(e)      => $crate::IResult::Error(e),
          $crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
          $crate::IResult::Done(i2,o)    => {
            match ($separator)(i2) {
              $crate::IResult::Error(e)      => $crate::IResult::Error(e),
              $crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
              $crate::IResult::Done(i3,_)    => $crate::IResult::Done(i3, o)
            }
          }
        }
      }
    }
  );
  ($i:expr, $separator:expr, $f:expr) => (
    wrap_sep!($i, $separator, call!($f))
  );
);

#[macro_export]
macro_rules! pair_sep (
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
    tuple!(
      $i,
      sep!($separator, $submac!($($args)*)),
      sep!($separator, $submac2!($($args2)*))
    )
  );
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $g:expr) => (
    pair_sep!($i, $separator, $submac!($($args)*), call!($g));
  );
  ($i:expr, $separator:ident, $f:expr, $submac:ident!( $($args:tt)* )) => (
    pair_sep!($i, $separator, call!($f), $submac!($($args)*));
  );
  ($i:expr, $separator:ident, $f:expr, $g:expr) => (
    pair_sep!($i, $separator, call!($f), call!($g));
  );
);

#[macro_export]
macro_rules! preceded_sep (
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
    match pair_sep!($i, $separator, $submac!($($args)*), $submac2!($($args2)*)) {
      $crate::IResult::Error(a)               => $crate::IResult::Error(a),
      $crate::IResult::Incomplete(i)          => $crate::IResult::Incomplete(i),
      $crate::IResult::Done(remaining, (_,o)) => {
        $crate::IResult::Done(remaining, o)
      }
    }
  );
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $g:expr) => (
    preceded_sep!($i, $separator, $submac!($($args)*), call!($g));
  );
  ($i:expr, $separator:ident, $f:expr, $submac:ident!( $($args:tt)* )) => (
    preceded_sep!($i, $separator, call!($f), $submac!($($args)*));
  );
  ($i:expr, $separator:ident, $f:expr, $g:expr) => (
    preceded_sep!($i, $separator, call!($f), call!($g));
  );
);

#[macro_export]
macro_rules! terminated_sep (
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $submac2:ident!( $($args2:tt)* )) => (
    match pair_sep!($i, $separator, $submac!($($args)*), $submac2!($($args2)*)) {
      $crate::IResult::Error(a)               => $crate::IResult::Error(a),
      $crate::IResult::Incomplete(i)          => $crate::IResult::Incomplete(i),
      $crate::IResult::Done(remaining, (o,_)) => {
        $crate::IResult::Done(remaining, o)
      }
    }
  );
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* ), $g:expr) => (
    terminated_wrap!($i, $separator, $submac!($($args)*), call!($g));
  );
  ($i:expr, $separator:ident, $f:expr, $submac:ident!( $($args:tt)* )) => (
    terminated_sep!($i, $separator, call!($f), $submac!($($args)*));
  );
  ($i:expr, $separator:ident, $f:expr, $g:expr) => (
    terminated_sep!($i, $separator, call!($f), call!($g));
  );
);

/// Internal parser, do not use directly
#[doc(hidden)]
#[macro_export]
macro_rules! tuple_sep (
  ($i:expr, $separator:ident, $consumed:expr, ($($parsed:tt),*), $e:ident, $($rest:tt)*) => (
    tuple_sep!($i, $separator, $consumed, ($($parsed),*), call!($e), $($rest)*);
  );
  ($i:expr, $separator:ident, $consumed:expr, (), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
    {
      match sep!($i, $separator, $submac!($($args)*)) {
        $crate::IResult::Error(e)                            => $crate::IResult::Error(e),
        $crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
        $crate::IResult::Incomplete($crate::Needed::Size(i)) => $crate::IResult::Incomplete($crate::Needed::Size($consumed + i)),
        $crate::IResult::Done(i,o)     => {
          tuple_sep!(i, $separator, $consumed + ($crate::InputLength::input_len(&($i)) - $crate::InputLength::input_len(&i)), (o), $($rest)*)
        }
      }
    }
  );
  ($i:expr, $separator:ident, $consumed:expr, ($($parsed:tt)*), $submac:ident!( $($args:tt)* ), $($rest:tt)*) => (
    {
      match sep!($i, $separator, $submac!($($args)*)) {
        $crate::IResult::Error(e)                            => $crate::IResult::Error(e),
        $crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
        $crate::IResult::Incomplete($crate::Needed::Size(i)) => $crate::IResult::Incomplete($crate::Needed::Size($consumed + i)),
        $crate::IResult::Done(i,o)     => {
          tuple_sep!(i, $separator, $consumed + ($crate::InputLength::input_len(&($i)) - $crate::InputLength::input_len(&i)), ($($parsed)* , o), $($rest)*)
        }
      }
    }
  );
  ($i:expr, $separator:ident, $consumed:expr, ($($parsed:tt),*), $e:ident) => (
    tuple_sep!($i, $separator,  $consumed, ($($parsed),*), call!($e));
  );
  ($i:expr, $separator:ident, $consumed:expr, (), $submac:ident!( $($args:tt)* )) => (
    {
      match sep!($i, $separator, $submac!($($args)*)) {
        $crate::IResult::Error(e)                            => $crate::IResult::Error(e),
        $crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
        $crate::IResult::Incomplete($crate::Needed::Size(i)) => $crate::IResult::Incomplete($crate::Needed::Size($consumed + i)),
        $crate::IResult::Done(i,o)     => {
          $crate::IResult::Done(i, (o))
        }
      }
    }
  );
  ($i:expr, $separator:ident, $consumed:expr, ($($parsed:expr),*), $submac:ident!( $($args:tt)* )) => (
    {
      match sep!($i, $separator, $submac!($($args)*)) {
        $crate::IResult::Error(e)                            => $crate::IResult::Error(e),
        $crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
        $crate::IResult::Incomplete($crate::Needed::Size(i)) => $crate::IResult::Incomplete($crate::Needed::Size($consumed + i)),
        $crate::IResult::Done(i,o)     => {
          $crate::IResult::Done(i, ($($parsed),* , o))
        }
      }
    }
  );
  ($i:expr, $separator:ident, $consumed:expr, ($($parsed:expr),*)) => (
    {
      $crate::IResult::Done($i, ($($parsed),*))
    }
  );
);

#[macro_export]
macro_rules! eat_separator (
  ($i:expr, $arr:expr) => (
    {
      use $crate::util::{InputLength,IterIndices};
      use std::str;
      println!("got input: \"{}\"", str::from_utf8($i).unwrap());
      if ($i).input_len() == 0 {
        println!("empty input");
        $crate::IResult::Done($i, &($i)[0..0])
      } else {
        match ($i).iter_indices().position(|(_, item)| {
          for (_,c) in ($arr).iter_indices() {
            if c == item { return false; }
          }
          true
        }) {
          Some(index) => {
            println!("got index: {}", index);
            $crate::IResult::Done(&($i)[index..], &($i)[..index])
          },
          None        => {
            println!("got no index");
            $crate::IResult::Done(&($i)[($i).input_len()..], $i)
          }
        }
      }
    }
  );
);

#[macro_export]
macro_rules! sep (
  ($i:expr,  $separator:ident, tuple ! ($($rest:tt)*) ) => {
    tuple_sep!($i, $separator, 0usize, (), $($rest)*)
  };
  ($i:expr,  $separator:ident, pair ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      pair_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:ident, preceded ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      preceded_sep!($separator, $($rest)*)
    )
  };
  ($i:expr,  $separator:ident, terminated ! ($($rest:tt)*) ) => {
    wrap_sep!($i,
      $separator,
      terminated_sep!($separator, $($rest)*)
    )
  };
  ($i:expr, $separator:ident, $submac:ident!( $($args:tt)* )) => {
    wrap_sep!($i, $separator, $submac!($($args)*))
  };
  ($i:expr, $separator:ident, $f:expr) => {
    wrap_sep!($i, $separator, call!($f))
  };
);

named!(pub sp, eat_separator!(b" \t\r\n"));

#[macro_export]
macro_rules! ws (
  ($i:expr, $($args:tt)*) => (
    {
      use $crate::sp;
      sep!($i, sp, $($args)*)
    }
  )
);

#[cfg(test)]
mod tests {
  use internal::IResult::*;
  use super::sp;

  #[test]
  fn spaaaaace() {
    assert_eq!(sp(&b" \t abc "[..]),  Done(&b"abc "[..], &b" \t "[..]));
  }

  #[test]
  fn tag() {
    named!(abc, ws!(tag!("abc")));

    assert_eq!(abc(&b" \t abc def"[..]),  Done(&b"def"[..], &b"abc"[..]));
  }

  #[test]
  fn pair() {
    named!(pair_2<&[u8], (&[u8], &[u8]) >,
      ws!(pair!( take!(3), tag!("de") ))
    );

    assert_eq!(pair_2(&b" \t abc de fg"[..]),  Done(&b"fg"[..], (&b"abc"[..], &b"de"[..])));
  }

  #[test]
  fn preceded() {
    named!(prec<&[u8], &[u8] >,
      ws!(preceded!( take!(3), tag!("de") ))
    );

    assert_eq!(prec(&b" \t abc de fg"[..]),  Done(&b"fg"[..], &b"de"[..]));
  }

  #[test]
  fn terminated() {
    named!(term<&[u8], &[u8] >,
      ws!(terminated!( take!(3), tag!("de") ))
    );

    assert_eq!(term(&b" \t abc de fg"[..]),  Done(&b"fg"[..], &b"abc"[..]));
  }

  #[test]
  fn tuple() {
    //trace_macros!(true);
    named!(tuple_2<&[u8], (&[u8], &[u8]) >,
      ws!(tuple!( take!(3), tag!("de") ))
    );
    //trace_macros!(false);

    assert_eq!(tuple_2(&b" \t abc de fg"[..]),  Done(&b"fg"[..], (&b"abc"[..], &b"de"[..])));
  }

  #[test]
  fn levels() {
    //trace_macros!(true);
    named!(level_2<&[u8], (&[u8], (&[u8], &[u8])) >,
      ws!(pair!(take!(3), tuple!( tag!("de"), tag!("fg ") )))
    );
    //trace_macros!(false);

    assert_eq!(level_2(&b" \t abc de fg \t hi "[..]),  Done(&b"hi "[..], (&b"abc"[..], (&b"de"[..], &b"fg "[..]))));
  }
}
<|endoftext|>


<commit_before>use std::rand;
use std::rand::Rng;
use cgmath::{Vector2};
use calx::color::RGB;
use calx::color::consts::*;
use world::system::{World, Entity, EngineLogic};
use world::spatial::{Location, Position, DIRECTIONS6};
use world::mapgen::{AreaSpec};
use world::mapgen;
use world::area::Area;

#[deriving(Clone, Show)]
pub struct MobComp {
    pub t: MobType,
    pub max_hp: int,
    pub hp: int,
    pub power: int,
    pub armor: int,
    pub status: int,
}

impl MobComp {
    pub fn new(t: MobType) -> MobComp {
        let data = MOB_KINDS[t as uint];
        let status = if t != Player { status::Asleep as int } else { 0 };
        MobComp {
            t: t,
            max_hp: data.power / 2,
            hp: data.power / 2,
            power: data.power,
            armor: 0,
            status: status,
        }
    }
}

pub mod intrinsic {
#[deriving(Eq, PartialEq, Clone)]
pub enum Intrinsic {
    /// Moves 1/3 slower than usual.
    Slow        = 0b1,
    /// Moves 1/3 faster than usual, stacks with Quick status.
    Fast        = 0b10,
    /// Can manipulate objects and doors.
    Hands       = 0b100,

    // XXX: The bugmove thing is possibly stupid.

    /// Only moves along the (1, 1) and (1, -1) diagonal axes.
    BugMove     = 0b1000,
}
}

pub mod status {
#[deriving(Eq, PartialEq, Clone)]
pub enum Status {
    /// Moves 1/3 slower than usual.
    Slow        = 0b1,
    /// Moves 1/3 faster than usual, stacks with Fast intrinsic.
    Quick       = 0b10,
    /// Mob is inactive until disturbed.
    Asleep      = 0b100,
    /// Mob moves erratically.
    Confused    = 0b1000,
}
}

pub struct MobKind {
    pub typ: MobType,
    pub name: &'static str,
    pub power: int,
    pub area_spec: AreaSpec,
    pub sprite: uint,
    pub color: RGB,
    pub intrinsics: int,
}

// Intrinsic flag union.
macro_rules! f {
    { $($flag:ident),* } => { 0 $( | intrinsic::$flag as int )* }
}

macro_rules! mob_data {
    {
        count: $count:expr;
        $($symbol:ident: $power:expr, $depth:expr, $biome:ident, $sprite:expr, $color:expr, $flags:expr;)*

    } => {
#[deriving(Eq, PartialEq, Clone, Show)]
pub enum MobType {
    $($symbol,)*
}

pub static MOB_KINDS: [MobKind, ..$count] = [
    $(MobKind {
        typ: $symbol,
        name: stringify!($symbol),
        power: $power,
        area_spec: AreaSpec {
            depth: $depth,
            biome: mapgen::$biome,
        },
        sprite: $sprite,
        color: $color,
        intrinsics: $flags,
    },)*
];

// End macro
    }
}

mob_data! {
    count: 11;
//  Symbol   power, depth, biome, sprite, color,        intrinsics
    Player:     5,  -1, Anywhere, 51, AZURE,            f!();
    Dreg:       2,   1, Anywhere, 72, OLIVE,            f!(Hands);
    Snake:      2,   1, Overland, 71, GREEN,            f!();
    GridBug:    2,   2, Dungeon,  76, MAGENTA,          f!(Fast,BugMove);
    Ooze:       4,   3, Dungeon,  77, LIGHTSEAGREEN,    f!();
    Flayer:     8,   4, Anywhere, 75, INDIANRED,        f!();
    Ogre:       9,   5, Anywhere, 73, DARKSLATEGRAY,    f!(Hands);
    Wraith:     10,  6, Dungeon,  74, HOTPINK,          f!(Hands);
    Octopus:    12,  7, Anywhere, 63, DARKTURQUOISE,    f!();
    Efreet:     15,  8, Anywhere, 78, ORANGE,           f!();
    Serpent:    20,  9, Dungeon,  94, CORAL,            f!();
}

/// Trait for entities that are mobile things.
pub trait Mob {
    fn is_active(&self) -> bool;
    fn acts_this_frame(&self) -> bool;
    fn has_intrinsic(&self, f: intrinsic::Intrinsic) -> bool;
    fn has_status(&self, f: status::Status) -> bool;
    fn mob_type(&self) -> MobType;
    fn power(&self) -> int;
    fn update_ai(&mut self);

    /// Try to move the mob in a direction, then try to roll around obstacles
    /// if the direction is blocked.
    fn smart_move(&mut self, dir8: uint) -> Option<Vector2<int>>;

    fn enemy_at(&self, loc: Location) -> Option<Entity>;
    fn attack(&mut self, loc: Location);
}

impl Mob for Entity {
    fn is_active(&self) -> bool {
        if !self.has::<MobComp>() { return false; }
        if self.has_status(status::Asleep) { return false; }
        return true;
    }

    fn acts_this_frame(&self) -> bool {
        if !self.has::<MobComp>() { return false; }
        if !self.is_active() { return false; }

        // Go through a cycle of 5 phases to get 4 possible speeds.
        // System idea from Jeff Lait.
        let phase = self.world().get_tick() % 5;
        match phase {
            0 => return true,
            1 => return self.has_intrinsic(intrinsic::Fast),
            2 => return true,
            3 => return self.has_status(status::Quick),
            4 => return !self.has_intrinsic(intrinsic::Slow),
            _ => fail!("Invalid action phase"),
        }
    }

    fn has_intrinsic(&self, f: intrinsic::Intrinsic) -> bool {
        self.into::<MobComp>().map_or(false,
            |m| MOB_KINDS[m.t as uint].intrinsics as int & f as int != 0)
    }

    fn has_status(&self, s: status::Status) -> bool {
        self.into::<MobComp>().map_or(false,
            |m| m.status as int & s as int != 0)
    }

    fn mob_type(&self) -> MobType { self.into::<MobComp>().unwrap().t }

    fn power(&self) -> int { self.into::<MobComp>().unwrap().power }

    fn update_ai(&mut self) {
        if self.mob_type() == GridBug {
            // Grid bugs move only non-diagonally. Even though horizontal
            // non-diagonal movement actually involves teleporting through
            // walls...
            let delta = *rand::task_rng()
                .choose(&[
                        Vector2::new(-1, -1),
                        Vector2::new( 1, -1),
                        Vector2::new( 1,  1),
                        Vector2::new(-1,  1),
                        ])
                .unwrap();
            self.move(&delta);
            return;
        }

        self.move(rand::task_rng().choose(DIRECTIONS6.as_slice()).unwrap());
    }

    fn smart_move(&mut self, dir8: uint) -> Option<Vector2<int>> {
        static SMART_MOVE: &'static [&'static [Vector2<int>]] = &[
            &[DIRECTIONS6[0], DIRECTIONS6[5], DIRECTIONS6[1]],
            &[DIRECTIONS6[1], DIRECTIONS6[0], DIRECTIONS6[2]],
            &[DIRECTIONS6[2], DIRECTIONS6[1], DIRECTIONS6[3]],
            &[DIRECTIONS6[3], DIRECTIONS6[2], DIRECTIONS6[4]],
            &[DIRECTIONS6[4], DIRECTIONS6[3], DIRECTIONS6[5]],
            &[DIRECTIONS6[5], DIRECTIONS6[4], DIRECTIONS6[0]],

            // Right sideways move zigzag.
            &[DIRECTIONS6[1], DIRECTIONS6[2]],
            &[DIRECTIONS6[2], DIRECTIONS6[1]],

            // Left sideways move zigzag.
            &[DIRECTIONS6[5], DIRECTIONS6[4]],
            &[DIRECTIONS6[4], DIRECTIONS6[5]],
            ];
        // "horizontal" movement is a zig-zag since there's no natural hex axis
        // in that direction. Find out the grid column the mob is on and
        // determine whether to zig or zag based on that.
        let loc = self.location();
        let zag = ((loc.x - loc.y) % 2) as uint;

        let deltas = SMART_MOVE[match dir8 {
                0 => 0,
                1 => 1,
                2 => 6 + zag,
                3 => 2,
                4 => 3,
                5 => 4,
                6 => 8 + zag,
                7 => 5,
                _ => fail!("Invalid dir8"),
            }];

        for delta in deltas.iter() {
            let new_loc = loc + *delta;
            match self.enemy_at(new_loc) {
                Some(_) => {
                    self.attack(new_loc);
                    return None;
                }
                _ => ()
            }
            if self.move(delta) { return Some(*delta); }
        }

        None
    }

    fn enemy_at(&self, loc: Location) -> Option<Entity> {
        let targs = self.world().mobs_at(loc);
        // Nothing to fight.
        if targs.len() == 0 { return None; }
        // TODO: Alignment check
        Some(targs[0].clone())
    }

    fn attack(&mut self, loc: Location) {
        let p = self.power();
        // No power, can't fight.
        if p == 0 { return; }

        let target = match self.enemy_at(loc) {
            None => return,
            Some(t) => t,
        };

        // Every five points of power is one certain hit.
        let full = p / 5;
        let partial = (p % 5) as f64 / 5.0;

        // TODO: Make some rng utility functions.
        let r = rand::random::<f64>() % 1.0;

        let damage = full + if r < partial { 1 } else { 0 };

        // TODO: A deal_damage method.
        let mut tm = target.into::<MobComp>().unwrap();
        tm.hp -= damage;

        if tm.hp <= 0 {
            if target.mob_type() == Player {
                println!("TODO handle player death");
                tm.hp = tm.max_hp;
            }
            // TODO: Whatever extra stuff we want to do when killing a mob.
            // It's probably a special occasion if it's the player avatar.
            self.world().delete_entity(&target);
        }
    }
}

/// Game world trait for global creature operations.
pub trait Mobs {
    fn mobs_at(&self, loc: Location) -> Vec<Entity>;
    fn mobs(&self) -> Vec<Entity>;
    fn player(&self) -> Option<Entity>;
    fn player_has_turn(&self) -> bool;
    fn clear_npcs(&mut self);
    fn update_mobs(&mut self);
}

impl Mobs for World {
    fn mobs_at(&self, loc: Location) -> Vec<Entity> {
        self.entities_at(loc).iter().filter(|e| e.has::<MobComp>())
            .map(|e| e.clone()).collect()
    }

    fn mobs(&self) -> Vec<Entity> {
        self.entities().filter(|e| e.has::<MobComp>())
            .map(|e| e.clone()).collect()
    }

    fn player(&self) -> Option<Entity> {
        for e in self.mobs().iter() {
            if e.mob_type() == Player {
                return Some(e.clone());
            }
        }
        None
    }

    fn player_has_turn(&self) -> bool {
        match self.player() {
            Some(p) => p.acts_this_frame(),
            _ => false
        }
    }

    fn clear_npcs(&mut self) {
        for e in self.mobs().mut_iter() {
            if e.mob_type() != Player {
                e.delete();
            }
        }
    }

    fn update_mobs(&mut self) {
        for mob in self.mobs().mut_iter() {
            if !mob.acts_this_frame() { continue; }
            if mob.mob_type() == Player { continue; }
            mob.update_ai();
        }

        self.advance_frame();
    }
}
<commit_msg>Status flag set API<commit_after>use std::rand;
use std::rand::Rng;
use cgmath::{Vector2};
use calx::color::RGB;
use calx::color::consts::*;
use world::system::{World, Entity, EngineLogic};
use world::spatial::{Location, Position, DIRECTIONS6};
use world::mapgen::{AreaSpec};
use world::mapgen;
use world::area::Area;

#[deriving(Clone, Show)]
pub struct MobComp {
    pub t: MobType,
    pub max_hp: int,
    pub hp: int,
    pub power: int,
    pub armor: int,
    pub status: int,
}

impl MobComp {
    pub fn new(t: MobType) -> MobComp {
        let data = MOB_KINDS[t as uint];
        let status = if t != Player { status::Asleep as int } else { 0 };
        MobComp {
            t: t,
            max_hp: data.power / 2,
            hp: data.power / 2,
            power: data.power,
            armor: 0,
            status: status,
        }
    }
}

pub mod intrinsic {
#[deriving(Eq, PartialEq, Clone)]
pub enum Intrinsic {
    /// Moves 1/3 slower than usual.
    Slow        = 0b1,
    /// Moves 1/3 faster than usual, stacks with Quick status.
    Fast        = 0b10,
    /// Can manipulate objects and doors.
    Hands       = 0b100,

    // XXX: The bugmove thing is possibly stupid.

    /// Only moves along the (1, 1) and (1, -1) diagonal axes.
    BugMove     = 0b1000,
}
}

pub mod status {
#[deriving(Eq, PartialEq, Clone)]
pub enum Status {
    /// Moves 1/3 slower than usual.
    Slow        = 0b1,
    /// Moves 1/3 faster than usual, stacks with Fast intrinsic.
    Quick       = 0b10,
    /// Mob is inactive until disturbed.
    Asleep      = 0b100,
    /// Mob moves erratically.
    Confused    = 0b1000,
}
}

pub struct MobKind {
    pub typ: MobType,
    pub name: &'static str,
    pub power: int,
    pub area_spec: AreaSpec,
    pub sprite: uint,
    pub color: RGB,
    pub intrinsics: int,
}

// Intrinsic flag union.
macro_rules! f {
    { $($flag:ident),* } => { 0 $( | intrinsic::$flag as int )* }
}

macro_rules! mob_data {
    {
        count: $count:expr;
        $($symbol:ident: $power:expr, $depth:expr, $biome:ident, $sprite:expr, $color:expr, $flags:expr;)*

    } => {
#[deriving(Eq, PartialEq, Clone, Show)]
pub enum MobType {
    $($symbol,)*
}

pub static MOB_KINDS: [MobKind, ..$count] = [
    $(MobKind {
        typ: $symbol,
        name: stringify!($symbol),
        power: $power,
        area_spec: AreaSpec {
            depth: $depth,
            biome: mapgen::$biome,
        },
        sprite: $sprite,
        color: $color,
        intrinsics: $flags,
    },)*
];

// End macro
    }
}

mob_data! {
    count: 11;
//  Symbol   power, depth, biome, sprite, color,        intrinsics
    Player:     5,  -1, Anywhere, 51, AZURE,            f!();
    Dreg:       2,   1, Anywhere, 72, OLIVE,            f!(Hands);
    Snake:      2,   1, Overland, 71, GREEN,            f!();
    GridBug:    2,   2, Dungeon,  76, MAGENTA,          f!(Fast,BugMove);
    Ooze:       4,   3, Dungeon,  77, LIGHTSEAGREEN,    f!();
    Flayer:     8,   4, Anywhere, 75, INDIANRED,        f!();
    Ogre:       9,   5, Anywhere, 73, DARKSLATEGRAY,    f!(Hands);
    Wraith:     10,  6, Dungeon,  74, HOTPINK,          f!(Hands);
    Octopus:    12,  7, Anywhere, 63, DARKTURQUOISE,    f!();
    Efreet:     15,  8, Anywhere, 78, ORANGE,           f!();
    Serpent:    20,  9, Dungeon,  94, CORAL,            f!();
}

/// Trait for entities that are mobile things.
pub trait Mob {
    fn is_active(&self) -> bool;
    fn acts_this_frame(&self) -> bool;
    fn has_intrinsic(&self, f: intrinsic::Intrinsic) -> bool;
    fn has_status(&self, s: status::Status) -> bool;
    fn add_status(&mut self, s: status::Status);
    fn remove_status(&mut self, s: status::Status);
    fn mob_type(&self) -> MobType;
    fn power(&self) -> int;
    fn update_ai(&mut self);

    /// Try to move the mob in a direction, then try to roll around obstacles
    /// if the direction is blocked.
    fn smart_move(&mut self, dir8: uint) -> Option<Vector2<int>>;

    fn enemy_at(&self, loc: Location) -> Option<Entity>;
    fn attack(&mut self, loc: Location);
}

impl Mob for Entity {
    fn is_active(&self) -> bool {
        if !self.has::<MobComp>() { return false; }
        if self.has_status(status::Asleep) { return false; }
        return true;
    }

    fn acts_this_frame(&self) -> bool {
        if !self.has::<MobComp>() { return false; }
        if !self.is_active() { return false; }

        // Go through a cycle of 5 phases to get 4 possible speeds.
        // System idea from Jeff Lait.
        let phase = self.world().get_tick() % 5;
        match phase {
            0 => return true,
            1 => return self.has_intrinsic(intrinsic::Fast),
            2 => return true,
            3 => return self.has_status(status::Quick),
            4 => return !self.has_intrinsic(intrinsic::Slow),
            _ => fail!("Invalid action phase"),
        }
    }

    fn has_intrinsic(&self, f: intrinsic::Intrinsic) -> bool {
        self.into::<MobComp>().map_or(false,
            |m| MOB_KINDS[m.t as uint].intrinsics as int & f as int != 0)
    }

    fn has_status(&self, s: status::Status) -> bool {
        self.into::<MobComp>().map_or(false,
            |m| m.status as int & s as int != 0)
    }

    fn add_status(&mut self, s: status::Status) {
        self.into::<MobComp>().as_mut().map(
            |m| m.status |= s as int);
    }

    fn remove_status(&mut self, s: status::Status) {
        self.into::<MobComp>().as_mut().map(
            |m| m.status &= !(s as int));
    }

    fn mob_type(&self) -> MobType { self.into::<MobComp>().unwrap().t }

    fn power(&self) -> int { self.into::<MobComp>().unwrap().power }

    fn update_ai(&mut self) {
        if self.mob_type() == GridBug {
            // Grid bugs move only non-diagonally. Even though horizontal
            // non-diagonal movement actually involves teleporting through
            // walls...
            let delta = *rand::task_rng()
                .choose(&[
                        Vector2::new(-1, -1),
                        Vector2::new( 1, -1),
                        Vector2::new( 1,  1),
                        Vector2::new(-1,  1),
                        ])
                .unwrap();
            self.move(&delta);
            return;
        }

        self.move(rand::task_rng().choose(DIRECTIONS6.as_slice()).unwrap());
    }

    fn smart_move(&mut self, dir8: uint) -> Option<Vector2<int>> {
        static SMART_MOVE: &'static [&'static [Vector2<int>]] = &[
            &[DIRECTIONS6[0], DIRECTIONS6[5], DIRECTIONS6[1]],
            &[DIRECTIONS6[1], DIRECTIONS6[0], DIRECTIONS6[2]],
            &[DIRECTIONS6[2], DIRECTIONS6[1], DIRECTIONS6[3]],
            &[DIRECTIONS6[3], DIRECTIONS6[2], DIRECTIONS6[4]],
            &[DIRECTIONS6[4], DIRECTIONS6[3], DIRECTIONS6[5]],
            &[DIRECTIONS6[5], DIRECTIONS6[4], DIRECTIONS6[0]],

            // Right sideways move zigzag.
            &[DIRECTIONS6[1], DIRECTIONS6[2]],
            &[DIRECTIONS6[2], DIRECTIONS6[1]],

            // Left sideways move zigzag.
            &[DIRECTIONS6[5], DIRECTIONS6[4]],
            &[DIRECTIONS6[4], DIRECTIONS6[5]],
            ];
        // "horizontal" movement is a zig-zag since there's no natural hex axis
        // in that direction. Find out the grid column the mob is on and
        // determine whether to zig or zag based on that.
        let loc = self.location();
        let zag = ((loc.x - loc.y) % 2) as uint;

        let deltas = SMART_MOVE[match dir8 {
                0 => 0,
                1 => 1,
                2 => 6 + zag,
                3 => 2,
                4 => 3,
                5 => 4,
                6 => 8 + zag,
                7 => 5,
                _ => fail!("Invalid dir8"),
            }];

        for delta in deltas.iter() {
            let new_loc = loc + *delta;
            match self.enemy_at(new_loc) {
                Some(_) => {
                    self.attack(new_loc);
                    return None;
                }
                _ => ()
            }
            if self.move(delta) { return Some(*delta); }
        }

        None
    }

    fn enemy_at(&self, loc: Location) -> Option<Entity> {
        let targs = self.world().mobs_at(loc);
        // Nothing to fight.
        if targs.len() == 0 { return None; }
        // TODO: Alignment check
        Some(targs[0].clone())
    }

    fn attack(&mut self, loc: Location) {
        let p = self.power();
        // No power, can't fight.
        if p == 0 { return; }

        let target = match self.enemy_at(loc) {
            None => return,
            Some(t) => t,
        };

        // Every five points of power is one certain hit.
        let full = p / 5;
        let partial = (p % 5) as f64 / 5.0;

        // TODO: Make some rng utility functions.
        let r = rand::random::<f64>() % 1.0;

        let damage = full + if r < partial { 1 } else { 0 };

        // TODO: A deal_damage method.
        let mut tm = target.into::<MobComp>().unwrap();
        tm.hp -= damage;

        if tm.hp <= 0 {
            if target.mob_type() == Player {
                println!("TODO handle player death");
                tm.hp = tm.max_hp;
            }
            // TODO: Whatever extra stuff we want to do when killing a mob.
            // It's probably a special occasion if it's the player avatar.
            self.world().delete_entity(&target);
        }
    }
}

/// Game world trait for global creature operations.
pub trait Mobs {
    fn mobs_at(&self, loc: Location) -> Vec<Entity>;
    fn mobs(&self) -> Vec<Entity>;
    fn player(&self) -> Option<Entity>;
    fn player_has_turn(&self) -> bool;
    fn clear_npcs(&mut self);
    fn update_mobs(&mut self);
}

impl Mobs for World {
    fn mobs_at(&self, loc: Location) -> Vec<Entity> {
        self.entities_at(loc).iter().filter(|e| e.has::<MobComp>())
            .map(|e| e.clone()).collect()
    }

    fn mobs(&self) -> Vec<Entity> {
        self.entities().filter(|e| e.has::<MobComp>())
            .map(|e| e.clone()).collect()
    }

    fn player(&self) -> Option<Entity> {
        for e in self.mobs().iter() {
            if e.mob_type() == Player {
                return Some(e.clone());
            }
        }
        None
    }

    fn player_has_turn(&self) -> bool {
        match self.player() {
            Some(p) => p.acts_this_frame(),
            _ => false
        }
    }

    fn clear_npcs(&mut self) {
        for e in self.mobs().mut_iter() {
            if e.mob_type() != Player {
                e.delete();
            }
        }
    }

    fn update_mobs(&mut self) {
        for mob in self.mobs().mut_iter() {
            if !mob.acts_this_frame() { continue; }
            if mob.mob_type() == Player { continue; }
            mob.update_ai();
        }

        self.advance_frame();
    }
}
<|endoftext|>


<commit_before>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//114
pub type OLECHAR = ::WCHAR;
pub type LPOLESTR = *mut OLECHAR;
pub type LPCOLESTR = *const OLECHAR;
//281
pub type SCODE = ::LONG;
pub type PSCODE = *mut SCODE;
<commit_msg>Add the type DOUBLE to wtypesbase.rs<commit_after>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//114
pub type OLECHAR = ::WCHAR;
pub type LPOLESTR = *mut OLECHAR;
pub type LPCOLESTR = *const OLECHAR;
//147
pub type DOUBLE = ::c_double;
//281
pub type SCODE = ::LONG;
pub type PSCODE = *mut SCODE;
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(ascii)]
#![feature(as_unsafe_cell)]
#![feature(borrow_state)]
#![feature(box_syntax)]
#![feature(cell_extras)]
#![feature(const_fn)]
#![feature(core)]
#![feature(core_intrinsics)]
#![feature(custom_attribute)]
#![feature(custom_derive)]
#![feature(drain)]
#![feature(fnbox)]
#![feature(hashmap_hasher)]
#![feature(iter_arith)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(on_unimplemented)]
#![feature(peekable_is_empty)]
#![feature(plugin)]
#![feature(slice_patterns)]
#![feature(str_utf16)]
#![feature(unicode)]
#![feature(vec_push_all)]

#![deny(unsafe_code)]
#![allow(non_snake_case)]

#![doc = "The script crate contains all matters DOM."]

#![plugin(plugins)]

extern crate angle;
extern crate app_units;
#[macro_use]
extern crate bitflags;
extern crate canvas;
extern crate canvas_traits;
extern crate caseless;
extern crate core;
extern crate cssparser;
extern crate devtools_traits;
extern crate encoding;
extern crate euclid;
extern crate fnv;
extern crate html5ever;
extern crate hyper;
extern crate image;
extern crate ipc_channel;
extern crate js;
extern crate libc;
#[macro_use]
extern crate log;
extern crate msg;
extern crate net_traits;
extern crate num;
extern crate offscreen_gl_context;
#[macro_use]
extern crate profile_traits;
extern crate rand;
extern crate ref_slice;
extern crate rustc_serialize;
extern crate rustc_unicode;
extern crate script_traits;
#[macro_use(state_pseudo_classes)] extern crate selectors;
extern crate serde;
extern crate smallvec;
#[macro_use(atom, ns)] extern crate string_cache;
#[macro_use]
extern crate style;
extern crate style_traits;
extern crate tendril;
extern crate time;
extern crate unicase;
extern crate url;
#[macro_use]
extern crate util;
extern crate uuid;
extern crate websocket;
extern crate xml5ever;

pub mod clipboard_provider;
pub mod cors;
mod devtools;
pub mod document_loader;
#[macro_use]
pub mod dom;
pub mod layout_interface;
mod mem;
mod network_listener;
pub mod page;
pub mod parse;
pub mod reporter;
#[allow(unsafe_code)]
pub mod script_task;
pub mod textinput;
mod timers;
mod unpremultiplytable;
mod webdriver_handlers;

use dom::bindings::codegen::RegisterBindings;
use js::jsapi::SetDOMProxyInformation;
use std::ptr;

#[cfg(target_os = "linux")]
#[allow(unsafe_code)]
fn perform_platform_specific_initialization() {
    use std::mem;
    // 4096 is default max on many linux systems
    const MAX_FILE_LIMIT: libc::rlim_t = 4096;

    // Bump up our number of file descriptors to save us from impending doom caused by an onslaught
    // of iframes.
    unsafe {
        let mut rlim: libc::rlimit = mem::uninitialized();
        match libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
            0 => {
                if rlim.rlim_cur >= MAX_FILE_LIMIT {
                    // we have more than enough
                    return;
                }

                rlim.rlim_cur = match rlim.rlim_max {
                    libc::RLIM_INFINITY => MAX_FILE_LIMIT,
                    _ => {
                        if rlim.rlim_max < MAX_FILE_LIMIT {
                            rlim.rlim_max
                        } else {
                            MAX_FILE_LIMIT
                        }
                    }
                };
                match libc::setrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
                    0 => (),
                    _ => warn!("Failed to set file count limit"),
                };
            },
            _ => warn!("Failed to get file count limit"),
        };
    }
}

#[cfg(not(target_os = "linux"))]
fn perform_platform_specific_initialization() {}

#[allow(unsafe_code)]
pub fn init() {
    unsafe {
        assert_eq!(js::jsapi::JS_Init(), true);
        SetDOMProxyInformation(ptr::null(), 0, Some(script_task::shadow_check_callback));
    }

    // Create the global vtables used by the (generated) DOM
    // bindings to implement JS proxies.
    RegisterBindings::RegisterProxyHandlers();

    perform_platform_specific_initialization();
}
<commit_msg>Auto merge of #8911 - alex:patch-1, r=frewsxcv<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(ascii)]
#![feature(as_unsafe_cell)]
#![feature(borrow_state)]
#![feature(box_syntax)]
#![feature(cell_extras)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(custom_attribute)]
#![feature(custom_derive)]
#![feature(fnbox)]
#![feature(hashmap_hasher)]
#![feature(iter_arith)]
#![feature(mpsc_select)]
#![feature(nonzero)]
#![feature(on_unimplemented)]
#![feature(peekable_is_empty)]
#![feature(plugin)]
#![feature(slice_patterns)]
#![feature(str_utf16)]
#![feature(unicode)]
#![feature(vec_push_all)]

#![deny(unsafe_code)]
#![allow(non_snake_case)]

#![doc = "The script crate contains all matters DOM."]

#![plugin(plugins)]

extern crate angle;
extern crate app_units;
#[macro_use]
extern crate bitflags;
extern crate canvas;
extern crate canvas_traits;
extern crate caseless;
extern crate core;
extern crate cssparser;
extern crate devtools_traits;
extern crate encoding;
extern crate euclid;
extern crate fnv;
extern crate html5ever;
extern crate hyper;
extern crate image;
extern crate ipc_channel;
extern crate js;
extern crate libc;
#[macro_use]
extern crate log;
extern crate msg;
extern crate net_traits;
extern crate num;
extern crate offscreen_gl_context;
#[macro_use]
extern crate profile_traits;
extern crate rand;
extern crate ref_slice;
extern crate rustc_serialize;
extern crate rustc_unicode;
extern crate script_traits;
#[macro_use(state_pseudo_classes)] extern crate selectors;
extern crate serde;
extern crate smallvec;
#[macro_use(atom, ns)] extern crate string_cache;
#[macro_use]
extern crate style;
extern crate style_traits;
extern crate tendril;
extern crate time;
extern crate unicase;
extern crate url;
#[macro_use]
extern crate util;
extern crate uuid;
extern crate websocket;
extern crate xml5ever;

pub mod clipboard_provider;
pub mod cors;
mod devtools;
pub mod document_loader;
#[macro_use]
pub mod dom;
pub mod layout_interface;
mod mem;
mod network_listener;
pub mod page;
pub mod parse;
pub mod reporter;
#[allow(unsafe_code)]
pub mod script_task;
pub mod textinput;
mod timers;
mod unpremultiplytable;
mod webdriver_handlers;

use dom::bindings::codegen::RegisterBindings;
use js::jsapi::SetDOMProxyInformation;
use std::ptr;

#[cfg(target_os = "linux")]
#[allow(unsafe_code)]
fn perform_platform_specific_initialization() {
    use std::mem;
    // 4096 is default max on many linux systems
    const MAX_FILE_LIMIT: libc::rlim_t = 4096;

    // Bump up our number of file descriptors to save us from impending doom caused by an onslaught
    // of iframes.
    unsafe {
        let mut rlim: libc::rlimit = mem::uninitialized();
        match libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
            0 => {
                if rlim.rlim_cur >= MAX_FILE_LIMIT {
                    // we have more than enough
                    return;
                }

                rlim.rlim_cur = match rlim.rlim_max {
                    libc::RLIM_INFINITY => MAX_FILE_LIMIT,
                    _ => {
                        if rlim.rlim_max < MAX_FILE_LIMIT {
                            rlim.rlim_max
                        } else {
                            MAX_FILE_LIMIT
                        }
                    }
                };
                match libc::setrlimit(libc::RLIMIT_NOFILE, &mut rlim) {
                    0 => (),
                    _ => warn!("Failed to set file count limit"),
                };
            },
            _ => warn!("Failed to get file count limit"),
        };
    }
}

#[cfg(not(target_os = "linux"))]
fn perform_platform_specific_initialization() {}

#[allow(unsafe_code)]
pub fn init() {
    unsafe {
        assert_eq!(js::jsapi::JS_Init(), true);
        SetDOMProxyInformation(ptr::null(), 0, Some(script_task::shadow_check_callback));
    }

    // Create the global vtables used by the (generated) DOM
    // bindings to implement JS proxies.
    RegisterBindings::RegisterProxyHandlers();

    perform_platform_specific_initialization();
}
<|endoftext|>


<commit_before>use num::bigint::{ BigInt, RandBigInt, Sign };
use num::traits::{ Zero, One, FromPrimitive };
use num::integer::Integer;
use rand::{ OsRng, StdRng };

mod key_pair;
pub use self::key_pair::KeyPair;

use public_key::PublicKey;
use private_key::PrivateKey;

use bigint_extensions::{ Two, Three, ModPow, ModInverse };

pub struct KeyPairBuilder {
    bits: usize,
    certainty: u32
}

impl KeyPairBuilder {
    pub fn new() -> KeyPairBuilder {
        KeyPairBuilder { bits: 512, certainty: 4 }
    }

    pub fn bits(&mut self, bits: usize) -> &mut KeyPairBuilder {
        self.bits = bits;
        self
    }

    pub fn certainty(&mut self, certainty: u32) -> &mut KeyPairBuilder {
        self.certainty = certainty;
        self
    }

    pub fn finalize(&self) -> KeyPair {

        let mut sec_rng = match OsRng::new() {
            Ok(g) => g,
            Err(e) => panic!("Failed to obtain OS RNG: {}", e)
        };

        let p = &generate_possible_prime(&mut sec_rng, self.bits, self.certainty);
        let q = &generate_possible_prime(&mut sec_rng, self.bits, self.certainty);

        let n = p * q;
        let n_squared = &n * &n;

        let p_minus_one = p - BigInt::one();
        let q_minus_one = q - BigInt::one();

        let lambda = Integer::lcm(&p_minus_one, &q_minus_one);

        let mut g;
        let mut helper;

        loop {
        // while {
            g = BigInt::from_biguint(Sign::Plus, sec_rng.gen_biguint(self.bits));
            helper = calculate_l(&g.mod_pow(&lambda, &n_squared), &n);

            let a = helper.gcd(&n);
            if a == BigInt::one() {
                break;
            }
        }

        let public_key =
            PublicKey {
                bits: self.bits,
                n: n.clone(),
                n_squared: n_squared,
                g: g.clone()
            };

        let private_key = PrivateKey {
                lambda: lambda,
                denominator: helper.mod_inverse(&n).unwrap()
            };

        KeyPair { public_key: public_key, private_key: private_key }
    }

}

fn calculate_l(u: &BigInt, n: &BigInt) -> BigInt{
    let r = u - BigInt::one();
    r / n
}

fn generate_possible_prime(sec_rng: &mut OsRng, bits: usize, certainty: u32) -> BigInt {
    let mut pp;

    'outer:
    loop {
        pp = BigInt::from_biguint(Sign::Plus, sec_rng.gen_biguint(bits));
        if pp.is_even() {
            continue;
        }

        let primes = [ 2, 3, 5, 7, 11, 13, 17, 19, 23 ];
        for prime in primes.iter() {
            let big_prime = BigInt::from_u64(*prime).unwrap();
            if &pp % big_prime == BigInt::zero() {
                continue 'outer;
            }
        }

        if miller_rabin(&pp, certainty) {
            break;
        }
    }
    return pp;
}

fn miller_rabin(n: &BigInt, k: u32) -> bool{
    if n <= &BigInt::three() {
        return true;
    }

    let n_minus_one = n - BigInt::one();

    let mut s = 0;
    let mut r = n_minus_one.clone();

    while &r % &BigInt::two() == BigInt::zero() {
       s += 1;
       r = r / BigInt::two();
    }

    let mut rng = match StdRng::new() {
        Ok(g) => g,
        Err(e) => panic!("Failed to obtain OS RNG: {}", e)
    };

   let mut a = BigInt::two();
   for _ in 0..k {
       let mut x = a.mod_pow(&r, &n);

       if x == BigInt::one() || x == n_minus_one {
            continue;
        }

       for _ in 1..(s - 1) {
           x = &x * &x % n;
           if x == BigInt::one(){
               return false;
           }
        }
        if x != n_minus_one{
            return false;
        }

        a = rng.gen_bigint_range(&BigInt::two(), &n_minus_one);
    }

    true
}

#[cfg(test)]
mod tests {
    use super::generate_possible_prime;
    use rand::OsRng;

    use test::Bencher;

    #[bench]
    fn bench_generate_possible_prime(b: &mut Bencher) {
        let mut rng = match OsRng::new() {
            Ok(g) => g,
            Err(e) => panic!("Failed to obtain OS RNG: {}", e)
        };

        b.iter(|| {
            generate_possible_prime(&mut rng, 64, 10);
        });
    }

}
<commit_msg>Replace 'do-while' construct with 'loop'<commit_after>use num::bigint::{ BigInt, RandBigInt, Sign };
use num::traits::{ Zero, One, FromPrimitive };
use num::integer::Integer;
use rand::{ OsRng, StdRng };

mod key_pair;
pub use self::key_pair::KeyPair;

use public_key::PublicKey;
use private_key::PrivateKey;

use bigint_extensions::{ Two, Three, ModPow, ModInverse };

pub struct KeyPairBuilder {
    bits: usize,
    certainty: u32
}

impl KeyPairBuilder {
    pub fn new() -> KeyPairBuilder {
        KeyPairBuilder { bits: 512, certainty: 4 }
    }

    pub fn bits(&mut self, bits: usize) -> &mut KeyPairBuilder {
        self.bits = bits;
        self
    }

    pub fn certainty(&mut self, certainty: u32) -> &mut KeyPairBuilder {
        self.certainty = certainty;
        self
    }

    pub fn finalize(&self) -> KeyPair {

        let mut sec_rng = match OsRng::new() {
            Ok(g) => g,
            Err(e) => panic!("Failed to obtain OS RNG: {}", e)
        };

        let p = &generate_possible_prime(&mut sec_rng, self.bits, self.certainty);
        let q = &generate_possible_prime(&mut sec_rng, self.bits, self.certainty);

        let n = p * q;
        let n_squared = &n * &n;

        let p_minus_one = p - BigInt::one();
        let q_minus_one = q - BigInt::one();

        let lambda = Integer::lcm(&p_minus_one, &q_minus_one);

        let mut g;
        let mut helper;

        loop {
            g = BigInt::from_biguint(Sign::Plus, sec_rng.gen_biguint(self.bits));
            helper = calculate_l(&g.mod_pow(&lambda, &n_squared), &n);

            let a = helper.gcd(&n);
            if a == BigInt::one() {
                break;
            }
        }

        let public_key =
            PublicKey {
                bits: self.bits,
                n: n.clone(),
                n_squared: n_squared,
                g: g.clone()
            };

        let private_key = PrivateKey {
                lambda: lambda,
                denominator: helper.mod_inverse(&n).unwrap()
            };

        KeyPair { public_key: public_key, private_key: private_key }
    }

}

fn calculate_l(u: &BigInt, n: &BigInt) -> BigInt{
    let r = u - BigInt::one();
    r / n
}

fn generate_possible_prime(sec_rng: &mut OsRng, bits: usize, certainty: u32) -> BigInt {
    let mut pp;

    'outer:
    loop {
        pp = BigInt::from_biguint(Sign::Plus, sec_rng.gen_biguint(bits));
        if pp.is_even() {
            continue;
        }

        let primes = [ 2, 3, 5, 7, 11, 13, 17, 19, 23 ];
        for prime in primes.iter() {
            let big_prime = BigInt::from_u64(*prime).unwrap();
            if &pp % big_prime == BigInt::zero() {
                continue 'outer;
            }
        }

        if miller_rabin(&pp, certainty) {
            break;
        }
    }
    return pp;
}

fn miller_rabin(n: &BigInt, k: u32) -> bool{
    if n <= &BigInt::three() {
        return true;
    }

    let n_minus_one = n - BigInt::one();

    let mut s = 0;
    let mut r = n_minus_one.clone();

    while &r % &BigInt::two() == BigInt::zero() {
       s += 1;
       r = r / BigInt::two();
    }

    let mut rng = match StdRng::new() {
        Ok(g) => g,
        Err(e) => panic!("Failed to obtain OS RNG: {}", e)
    };

   let mut a = BigInt::two();
   for _ in 0..k {
       let mut x = a.mod_pow(&r, &n);

       if x == BigInt::one() || x == n_minus_one {
            continue;
        }

       for _ in 1..(s - 1) {
           x = &x * &x % n;
           if x == BigInt::one(){
               return false;
           }
        }
        if x != n_minus_one{
            return false;
        }

        a = rng.gen_bigint_range(&BigInt::two(), &n_minus_one);
    }

    true
}

#[cfg(test)]
mod tests {
    use super::generate_possible_prime;
    use rand::OsRng;

    use test::Bencher;

    #[bench]
    fn bench_generate_possible_prime(b: &mut Bencher) {
        let mut rng = match OsRng::new() {
            Ok(g) => g,
            Err(e) => panic!("Failed to obtain OS RNG: {}", e)
        };

        b.iter(|| {
            generate_possible_prime(&mut rng, 64, 10);
        });
    }

}
<|endoftext|>


<commit_before>//! The Host request header, defined in RFC 2616, Section 14.23.

use std::u16;
use std::rt::io::Reader;

/// A simple little thing for the host of a request
#[deriving(Clone, Eq)]
pub struct Host {

    /// The name of the host that was requested
    name: ~str,

    /// If unspecified, assume the default port was used (80 for HTTP, 443 for HTTPS).
    /// In that case, you shouldn't need to worry about it in URLs that you build, provided you
    /// include the scheme.
    port: Option<u16>,
}
impl ToStr for Host {
    fn to_str(&self) -> ~str {
        match self.port {
            Some(port) => fmt!("%s:%s", self.name, port.to_str()),
            None => self.name.clone(),
        }
    }
}

impl super::HeaderConvertible for Host {
    fn from_stream<T: Reader>(reader: &mut super::HeaderValueByteIterator<T>) -> Option<Host> {
        let s = reader.collect_to_str();
        // TODO: this doesn't support IPv6 address access (e.g. "[::1]")
        // Do this properly with correct authority parsing.
        let mut hi = s.splitn_iter(':', 1);
        Some(Host {
            name: hi.next().unwrap().to_owned(),
            port: match hi.next() {
                Some(name) => u16::from_str(name),
                None => None,
            },
        })
    }

    fn http_value(&self) -> ~str {
        self.to_str()
    }
}
<commit_msg>updated from_str syntax<commit_after>//! The Host request header, defined in RFC 2616, Section 14.23.

use std::u16;
use std::rt::io::Reader;

/// A simple little thing for the host of a request
#[deriving(Clone, Eq)]
pub struct Host {

    /// The name of the host that was requested
    name: ~str,

    /// If unspecified, assume the default port was used (80 for HTTP, 443 for HTTPS).
    /// In that case, you shouldn't need to worry about it in URLs that you build, provided you
    /// include the scheme.
    port: Option<u16>,
}
impl ToStr for Host {
    fn to_str(&self) -> ~str {
        match self.port {
            Some(port) => fmt!("%s:%s", self.name, port.to_str()),
            None => self.name.clone(),
        }
    }
}

impl super::HeaderConvertible for Host {
    fn from_stream<T: Reader>(reader: &mut super::HeaderValueByteIterator<T>) -> Option<Host> {
        let s = reader.collect_to_str();
        // TODO: this doesn't support IPv6 address access (e.g. "[::1]")
        // Do this properly with correct authority parsing.
        let mut hi = s.splitn_iter(':', 1);
        Some(Host {
            name: hi.next().unwrap().to_owned(),
            port: match hi.next() {
                Some(name) => from_str::<u16>(name),
                None => None,
            },
        })
    }

    fn http_value(&self) -> ~str {
        self.to_str()
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 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 core::prelude::*;

use ast::{crate, expr_, expr_mac, mac_invoc_tt};
use ast::{tt_delim, tt_tok, item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi};
use ast;
use codemap::{span, ExpandedFrom};
use ext::base::*;
use fold::*;
use parse::{parser, parse_expr_from_source_str, new_parser_from_tts};

use core::option;
use core::vec;
use std::map::HashMap;

fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
               e: expr_, s: span, fld: ast_fold,
               orig: fn@(expr_, span, ast_fold) -> (expr_, span))
    -> (expr_, span)
{
    return match e {
      // expr_mac should really be expr_ext or something; it's the
      // entry-point for all syntax extensions.
          expr_mac(ref mac) => {

            match (*mac).node {

              // Token-tree macros, these will be the only case when we're
              // finished transitioning.
              mac_invoc_tt(pth, ref tts) => {
                assert (vec::len(pth.idents) == 1u);
                /* using idents and token::special_idents would make the
                the macro names be hygienic */
                let extname = cx.parse_sess().interner.get(pth.idents[0]);
                match exts.find(*extname) {
                  None => {
                    cx.span_fatal(pth.span,
                                  fmt!("macro undefined: '%s'", *extname))
                  }
                  Some(normal_tt({expander: exp, span: exp_sp})) => {
                    cx.bt_push(ExpandedFrom({call_site: s,
                                callie: {name: *extname, span: exp_sp}}));

                    let expanded = match exp(cx, (*mac).span, (*tts)) {
                      mr_expr(e) => e,
                      mr_any(expr_maker,_,_) => expr_maker(),
                      _ => cx.span_fatal(
                          pth.span, fmt!("non-expr macro in expr pos: %s",
                                         *extname))
                    };

                    //keep going, outside-in
                    let fully_expanded = fld.fold_expr(expanded).node;
                    cx.bt_pop();

                    (fully_expanded, s)
                  }
                  _ => {
                    cx.span_fatal(pth.span,
                                  fmt!("'%s' is not a tt-style macro",
                                       *extname))
                  }

                }
              }
            }
          }
          _ => orig(e, s, fld)
        };
}

// This is a secondary mechanism for invoking syntax extensions on items:
// "decorator" attributes, such as #[auto_encode]. These are invoked by an
// attribute prefixing an item, and are interpreted by feeding the item
// through the named attribute _as a syntax extension_ and splicing in the
// resulting item vec into place in favour of the decorator. Note that
// these do _not_ work for macro extensions, just item_decorator ones.
//
// NB: there is some redundancy between this and expand_item, below, and
// they might benefit from some amount of semantic and language-UI merger.
fn expand_mod_items(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
                    module_: ast::_mod, fld: ast_fold,
                    orig: fn@(ast::_mod, ast_fold) -> ast::_mod)
    -> ast::_mod
{
    // Fold the contents first:
    let module_ = orig(module_, fld);

    // For each item, look through the attributes.  If any of them are
    // decorated with "item decorators", then use that function to transform
    // the item into a new set of items.
    let new_items = do vec::flat_map(module_.items) |item| {
        do vec::foldr(item.attrs, ~[*item]) |attr, items| {
            let mname = match attr.node.value.node {
              ast::meta_word(ref n) => (*n),
              ast::meta_name_value(ref n, _) => (*n),
              ast::meta_list(ref n, _) => (*n)
            };
            match exts.find(mname) {
              None | Some(normal_tt(_)) | Some(item_tt(*)) => items,
              Some(item_decorator(dec_fn)) => {
                  cx.bt_push(ExpandedFrom({call_site: attr.span,
                                           callie: {name: copy mname,
                                                    span: None}}));
                  let r = dec_fn(cx, attr.span, attr.node.value, items);
                  cx.bt_pop();
                  r
              }
            }
        }
    };

    return {items: new_items, ..module_};
}

// When we enter a module, record it, for the sake of `module!`
fn expand_item(exts: HashMap<~str, syntax_extension>,
               cx: ext_ctxt, &&it: @ast::item, fld: ast_fold,
               orig: fn@(&&v: @ast::item, ast_fold) -> Option<@ast::item>)
    -> Option<@ast::item>
{
    let is_mod = match it.node {
      ast::item_mod(_) | ast::item_foreign_mod(_) => true,
      _ => false
    };
    let maybe_it = match it.node {
      ast::item_mac(*) => expand_item_mac(exts, cx, it, fld),
      _ => Some(it)
    };

    match maybe_it {
      Some(it) => {
        if is_mod { cx.mod_push(it.ident); }
        let ret_val = orig(it, fld);
        if is_mod { cx.mod_pop(); }
        return ret_val;
      }
      None => return None
    }
}

// Support for item-position macro invocations, exactly the same
// logic as for expression-position macro invocations.
fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
                   cx: ext_ctxt, &&it: @ast::item,
                   fld: ast_fold) -> Option<@ast::item> {

    let (pth, tts) = match it.node {
        item_mac(ast::spanned { node: mac_invoc_tt(pth, ref tts), _}) => {
            (pth, (*tts))
        }
        _ => cx.span_bug(it.span, ~"invalid item macro invocation")
    };

    let extname = cx.parse_sess().interner.get(pth.idents[0]);
    let expanded = match exts.find(*extname) {
        None => cx.span_fatal(pth.span,
                              fmt!("macro undefined: '%s!'", *extname)),

        Some(normal_tt(ref expand)) => {
            if it.ident != parse::token::special_idents::invalid {
                cx.span_fatal(pth.span,
                              fmt!("macro %s! expects no ident argument, \
                                    given '%s'", *extname,
                                   *cx.parse_sess().interner.get(it.ident)));
            }
            cx.bt_push(ExpandedFrom({call_site: it.span,
                                     callie: {name: *extname,
                                              span: (*expand).span}}));
            ((*expand).expander)(cx, it.span, tts)
        }
        Some(item_tt(ref expand)) => {
            if it.ident == parse::token::special_idents::invalid {
                cx.span_fatal(pth.span,
                              fmt!("macro %s! expects an ident argument",
                                   *extname));
            }
            cx.bt_push(ExpandedFrom({call_site: it.span,
                                     callie: {name: *extname,
                                              span: (*expand).span}}));
            ((*expand).expander)(cx, it.span, it.ident, tts)
        }
        _ => cx.span_fatal(
            it.span, fmt!("%s! is not legal in item position", *extname))
    };

    let maybe_it = match expanded {
        mr_item(it) => fld.fold_item(it),
        mr_expr(_) => cx.span_fatal(pth.span,
                                    ~"expr macro in item position: "
                                    + *extname),
        mr_any(_, item_maker, _) =>
            option::chain(item_maker(), |i| {fld.fold_item(i)}),
        mr_def(ref mdef) => {
            exts.insert((*mdef).name, (*mdef).ext);
            None
        }
    };
    cx.bt_pop();
    return maybe_it;
}

fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
               && s: stmt_, sp: span, fld: ast_fold,
               orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span))
    -> (stmt_, span)
{

    let (mac, pth, tts, semi) = match s {
        stmt_mac(ref mac, semi) => {
            match (*mac).node {
                mac_invoc_tt(pth, ref tts) => ((*mac), pth, (*tts), semi)
            }
        }
        _ => return orig(s, sp, fld)
    };

    assert(vec::len(pth.idents) == 1u);
    let extname = cx.parse_sess().interner.get(pth.idents[0]);
    let (fully_expanded, sp) = match exts.find(*extname) {
        None =>
            cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)),

        Some(normal_tt({expander: exp, span: exp_sp})) => {
            cx.bt_push(ExpandedFrom(
                {call_site: sp, callie: {name: *extname, span: exp_sp}}));
            let expanded = match exp(cx, mac.span, tts) {
                mr_expr(e) =>
                    @ast::spanned { node: stmt_expr(e, cx.next_id()),
                                    span: e.span},
                mr_any(_,_,stmt_mkr) => stmt_mkr(),
                _ => cx.span_fatal(
                    pth.span,
                    fmt!("non-stmt macro in stmt pos: %s", *extname))
            };

            //keep going, outside-in
            let fully_expanded = fld.fold_stmt(expanded).node;
            cx.bt_pop();

            (fully_expanded, sp)
        }

        _ => {
            cx.span_fatal(pth.span,
                          fmt!("'%s' is not a tt-style macro", *extname))
        }
    };

    return (match fully_expanded {
        stmt_expr(e, stmt_id) if semi => stmt_semi(e, stmt_id),
        _ => { fully_expanded } /* might already have a semi */
    }, sp)

}

fn new_span(cx: ext_ctxt, sp: span) -> span {
    /* this discards information in the case of macro-defining macros */
    return span {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()};
}

// FIXME (#2247): this is a terrible kludge to inject some macros into
// the default compilation environment. When the macro-definition system
// is substantially more mature, these should move from here, into a
// compiled part of libcore at very least.

fn core_macros() -> ~str {
    return
~"{
    macro_rules! ignore (($($x:tt)*) => (()))

    macro_rules! error ( ($( $arg:expr ),+) => (
        log(::core::error, fmt!( $($arg),+ )) ))
    macro_rules! warn ( ($( $arg:expr ),+) => (
        log(::core::warn, fmt!( $($arg),+ )) ))
    macro_rules! info ( ($( $arg:expr ),+) => (
        log(::core::info, fmt!( $($arg),+ )) ))
    macro_rules! debug ( ($( $arg:expr ),+) => (
        log(::core::debug, fmt!( $($arg),+ )) ))

    macro_rules! die(
        ($msg: expr) => (
            ::core::sys::begin_unwind($msg, file!().to_owned(), line!())
        );
        () => (
            die!(~\"explicit failure\")
        )
    )

    macro_rules! condition (

        { $c:ident: $in:ty -> $out:ty; } => {

            mod $c {
                fn key(_x: @::core::condition::Handler<$in,$out>) { }

                pub const cond : ::core::condition::Condition<$in,$out> =
                    ::core::condition::Condition {
                    name: stringify!(c),
                    key: key
                };
            }
        }
    )

}";
}

fn expand_crate(parse_sess: parse::parse_sess,
                cfg: ast::crate_cfg, c: @crate) -> @crate {
    let exts = syntax_expander_table();
    let afp = default_ast_fold();
    let cx: ext_ctxt = mk_ctxt(parse_sess, cfg);
    let f_pre = @AstFoldFns {
        fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr),
        fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod),
        fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item),
        fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt),
        new_span: |a| new_span(cx, a),
        .. *afp};
    let f = make_fold(f_pre);
    let cm = parse_expr_from_source_str(~"<core-macros>",
                                        @core_macros(),
                                        cfg,
                                        parse_sess);

    // This is run for its side-effects on the expander env,
    // as it registers all the core macros as expanders.
    f.fold_expr(cm);

    let res = @f.fold_crate(*c);
    return res;
}
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>libsyntax: Fix name generation in condition! macro<commit_after>// Copyright 2012 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 core::prelude::*;

use ast::{crate, expr_, expr_mac, mac_invoc_tt};
use ast::{tt_delim, tt_tok, item_mac, stmt_, stmt_mac, stmt_expr, stmt_semi};
use ast;
use codemap::{span, ExpandedFrom};
use ext::base::*;
use fold::*;
use parse::{parser, parse_expr_from_source_str, new_parser_from_tts};

use core::option;
use core::vec;
use std::map::HashMap;

fn expand_expr(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
               e: expr_, s: span, fld: ast_fold,
               orig: fn@(expr_, span, ast_fold) -> (expr_, span))
    -> (expr_, span)
{
    return match e {
      // expr_mac should really be expr_ext or something; it's the
      // entry-point for all syntax extensions.
          expr_mac(ref mac) => {

            match (*mac).node {

              // Token-tree macros, these will be the only case when we're
              // finished transitioning.
              mac_invoc_tt(pth, ref tts) => {
                assert (vec::len(pth.idents) == 1u);
                /* using idents and token::special_idents would make the
                the macro names be hygienic */
                let extname = cx.parse_sess().interner.get(pth.idents[0]);
                match exts.find(*extname) {
                  None => {
                    cx.span_fatal(pth.span,
                                  fmt!("macro undefined: '%s'", *extname))
                  }
                  Some(normal_tt({expander: exp, span: exp_sp})) => {
                    cx.bt_push(ExpandedFrom({call_site: s,
                                callie: {name: *extname, span: exp_sp}}));

                    let expanded = match exp(cx, (*mac).span, (*tts)) {
                      mr_expr(e) => e,
                      mr_any(expr_maker,_,_) => expr_maker(),
                      _ => cx.span_fatal(
                          pth.span, fmt!("non-expr macro in expr pos: %s",
                                         *extname))
                    };

                    //keep going, outside-in
                    let fully_expanded = fld.fold_expr(expanded).node;
                    cx.bt_pop();

                    (fully_expanded, s)
                  }
                  _ => {
                    cx.span_fatal(pth.span,
                                  fmt!("'%s' is not a tt-style macro",
                                       *extname))
                  }

                }
              }
            }
          }
          _ => orig(e, s, fld)
        };
}

// This is a secondary mechanism for invoking syntax extensions on items:
// "decorator" attributes, such as #[auto_encode]. These are invoked by an
// attribute prefixing an item, and are interpreted by feeding the item
// through the named attribute _as a syntax extension_ and splicing in the
// resulting item vec into place in favour of the decorator. Note that
// these do _not_ work for macro extensions, just item_decorator ones.
//
// NB: there is some redundancy between this and expand_item, below, and
// they might benefit from some amount of semantic and language-UI merger.
fn expand_mod_items(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
                    module_: ast::_mod, fld: ast_fold,
                    orig: fn@(ast::_mod, ast_fold) -> ast::_mod)
    -> ast::_mod
{
    // Fold the contents first:
    let module_ = orig(module_, fld);

    // For each item, look through the attributes.  If any of them are
    // decorated with "item decorators", then use that function to transform
    // the item into a new set of items.
    let new_items = do vec::flat_map(module_.items) |item| {
        do vec::foldr(item.attrs, ~[*item]) |attr, items| {
            let mname = match attr.node.value.node {
              ast::meta_word(ref n) => (*n),
              ast::meta_name_value(ref n, _) => (*n),
              ast::meta_list(ref n, _) => (*n)
            };
            match exts.find(mname) {
              None | Some(normal_tt(_)) | Some(item_tt(*)) => items,
              Some(item_decorator(dec_fn)) => {
                  cx.bt_push(ExpandedFrom({call_site: attr.span,
                                           callie: {name: copy mname,
                                                    span: None}}));
                  let r = dec_fn(cx, attr.span, attr.node.value, items);
                  cx.bt_pop();
                  r
              }
            }
        }
    };

    return {items: new_items, ..module_};
}

// When we enter a module, record it, for the sake of `module!`
fn expand_item(exts: HashMap<~str, syntax_extension>,
               cx: ext_ctxt, &&it: @ast::item, fld: ast_fold,
               orig: fn@(&&v: @ast::item, ast_fold) -> Option<@ast::item>)
    -> Option<@ast::item>
{
    let is_mod = match it.node {
      ast::item_mod(_) | ast::item_foreign_mod(_) => true,
      _ => false
    };
    let maybe_it = match it.node {
      ast::item_mac(*) => expand_item_mac(exts, cx, it, fld),
      _ => Some(it)
    };

    match maybe_it {
      Some(it) => {
        if is_mod { cx.mod_push(it.ident); }
        let ret_val = orig(it, fld);
        if is_mod { cx.mod_pop(); }
        return ret_val;
      }
      None => return None
    }
}

// Support for item-position macro invocations, exactly the same
// logic as for expression-position macro invocations.
fn expand_item_mac(exts: HashMap<~str, syntax_extension>,
                   cx: ext_ctxt, &&it: @ast::item,
                   fld: ast_fold) -> Option<@ast::item> {

    let (pth, tts) = match it.node {
        item_mac(ast::spanned { node: mac_invoc_tt(pth, ref tts), _}) => {
            (pth, (*tts))
        }
        _ => cx.span_bug(it.span, ~"invalid item macro invocation")
    };

    let extname = cx.parse_sess().interner.get(pth.idents[0]);
    let expanded = match exts.find(*extname) {
        None => cx.span_fatal(pth.span,
                              fmt!("macro undefined: '%s!'", *extname)),

        Some(normal_tt(ref expand)) => {
            if it.ident != parse::token::special_idents::invalid {
                cx.span_fatal(pth.span,
                              fmt!("macro %s! expects no ident argument, \
                                    given '%s'", *extname,
                                   *cx.parse_sess().interner.get(it.ident)));
            }
            cx.bt_push(ExpandedFrom({call_site: it.span,
                                     callie: {name: *extname,
                                              span: (*expand).span}}));
            ((*expand).expander)(cx, it.span, tts)
        }
        Some(item_tt(ref expand)) => {
            if it.ident == parse::token::special_idents::invalid {
                cx.span_fatal(pth.span,
                              fmt!("macro %s! expects an ident argument",
                                   *extname));
            }
            cx.bt_push(ExpandedFrom({call_site: it.span,
                                     callie: {name: *extname,
                                              span: (*expand).span}}));
            ((*expand).expander)(cx, it.span, it.ident, tts)
        }
        _ => cx.span_fatal(
            it.span, fmt!("%s! is not legal in item position", *extname))
    };

    let maybe_it = match expanded {
        mr_item(it) => fld.fold_item(it),
        mr_expr(_) => cx.span_fatal(pth.span,
                                    ~"expr macro in item position: "
                                    + *extname),
        mr_any(_, item_maker, _) =>
            option::chain(item_maker(), |i| {fld.fold_item(i)}),
        mr_def(ref mdef) => {
            exts.insert((*mdef).name, (*mdef).ext);
            None
        }
    };
    cx.bt_pop();
    return maybe_it;
}

fn expand_stmt(exts: HashMap<~str, syntax_extension>, cx: ext_ctxt,
               && s: stmt_, sp: span, fld: ast_fold,
               orig: fn@(&&s: stmt_, span, ast_fold) -> (stmt_, span))
    -> (stmt_, span)
{

    let (mac, pth, tts, semi) = match s {
        stmt_mac(ref mac, semi) => {
            match (*mac).node {
                mac_invoc_tt(pth, ref tts) => ((*mac), pth, (*tts), semi)
            }
        }
        _ => return orig(s, sp, fld)
    };

    assert(vec::len(pth.idents) == 1u);
    let extname = cx.parse_sess().interner.get(pth.idents[0]);
    let (fully_expanded, sp) = match exts.find(*extname) {
        None =>
            cx.span_fatal(pth.span, fmt!("macro undefined: '%s'", *extname)),

        Some(normal_tt({expander: exp, span: exp_sp})) => {
            cx.bt_push(ExpandedFrom(
                {call_site: sp, callie: {name: *extname, span: exp_sp}}));
            let expanded = match exp(cx, mac.span, tts) {
                mr_expr(e) =>
                    @ast::spanned { node: stmt_expr(e, cx.next_id()),
                                    span: e.span},
                mr_any(_,_,stmt_mkr) => stmt_mkr(),
                _ => cx.span_fatal(
                    pth.span,
                    fmt!("non-stmt macro in stmt pos: %s", *extname))
            };

            //keep going, outside-in
            let fully_expanded = fld.fold_stmt(expanded).node;
            cx.bt_pop();

            (fully_expanded, sp)
        }

        _ => {
            cx.span_fatal(pth.span,
                          fmt!("'%s' is not a tt-style macro", *extname))
        }
    };

    return (match fully_expanded {
        stmt_expr(e, stmt_id) if semi => stmt_semi(e, stmt_id),
        _ => { fully_expanded } /* might already have a semi */
    }, sp)

}

fn new_span(cx: ext_ctxt, sp: span) -> span {
    /* this discards information in the case of macro-defining macros */
    return span {lo: sp.lo, hi: sp.hi, expn_info: cx.backtrace()};
}

// FIXME (#2247): this is a terrible kludge to inject some macros into
// the default compilation environment. When the macro-definition system
// is substantially more mature, these should move from here, into a
// compiled part of libcore at very least.

fn core_macros() -> ~str {
    return
~"{
    macro_rules! ignore (($($x:tt)*) => (()))

    macro_rules! error ( ($( $arg:expr ),+) => (
        log(::core::error, fmt!( $($arg),+ )) ))
    macro_rules! warn ( ($( $arg:expr ),+) => (
        log(::core::warn, fmt!( $($arg),+ )) ))
    macro_rules! info ( ($( $arg:expr ),+) => (
        log(::core::info, fmt!( $($arg),+ )) ))
    macro_rules! debug ( ($( $arg:expr ),+) => (
        log(::core::debug, fmt!( $($arg),+ )) ))

    macro_rules! die(
        ($msg: expr) => (
            ::core::sys::begin_unwind($msg, file!().to_owned(), line!())
        );
        () => (
            die!(~\"explicit failure\")
        )
    )

    macro_rules! condition (

        { $c:ident: $in:ty -> $out:ty; } => {

            mod $c {
                fn key(_x: @::core::condition::Handler<$in,$out>) { }

                pub const cond : ::core::condition::Condition<$in,$out> =
                    ::core::condition::Condition {
                    name: stringify!($c),
                    key: key
                };
            }
        }
    )

}";
}

fn expand_crate(parse_sess: parse::parse_sess,
                cfg: ast::crate_cfg, c: @crate) -> @crate {
    let exts = syntax_expander_table();
    let afp = default_ast_fold();
    let cx: ext_ctxt = mk_ctxt(parse_sess, cfg);
    let f_pre = @AstFoldFns {
        fold_expr: |a,b,c| expand_expr(exts, cx, a, b, c, afp.fold_expr),
        fold_mod: |a,b| expand_mod_items(exts, cx, a, b, afp.fold_mod),
        fold_item: |a,b| expand_item(exts, cx, a, b, afp.fold_item),
        fold_stmt: |a,b,c| expand_stmt(exts, cx, a, b, c, afp.fold_stmt),
        new_span: |a| new_span(cx, a),
        .. *afp};
    let f = make_fold(f_pre);
    let cm = parse_expr_from_source_str(~"<core-macros>",
                                        @core_macros(),
                                        cfg,
                                        parse_sess);

    // This is run for its side-effects on the expander env,
    // as it registers all the core macros as expanders.
    f.fold_expr(cm);

    let res = @f.fold_crate(*c);
    return res;
}
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>// 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 crate::address::Address;
use crate::instruction::Instruction;

/// Information about the target of a `CallSite`.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum CallSiteTarget {
    /// The call site directly invokes the function at the `Address`.
    Direct(Address),
    /// The call site is indirect, and we haven't yet done further
    /// analysis.
    Indirect,
}

/// Information about a call site.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct CallSite {
    /// The address of the call site.
    pub call_site_address: Address,
    /// Information about the target of the call site.
    pub target: CallSiteTarget,
}

/// Assist in performing call graph analysis.
pub trait CallGraphAnalysis<I: Instruction> {
    /// Get information about the function calls made.
    fn identify_call_sites(&self) -> Vec<CallSite>;

    /// Get information about the function calls made within a set of instructions.
    ///
    /// This is meant to be called by implementations of this trait.
    fn identify_call_sites_in_instructions(&self, instructions: &[I]) -> Vec<CallSite> {
        instructions
            .iter()
            .filter(|i| i.is_call())
            .map(|i| CallSite {
                call_site_address: i.address(),
                target: match i.target_address() {
                    Some(a) => CallSiteTarget::Direct(a),
                    None => CallSiteTarget::Indirect,
                },
            }).collect()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::address::Address;
    use crate::function::Function;
    use crate::symbol::Symbol;
    use crate::tests::*;

    #[test]
    fn calls_none() {
        let insts = vec![
            TestInstruction::new(0, Opcode::Add),
            TestInstruction::new(1, Opcode::Add),
            TestInstruction::new(2, Opcode::Ret),
        ];
        let f = Function::new(Symbol::new(Address::new(100), None), insts);
        let calls = f.identify_call_sites();
        assert!(calls.is_empty());
    }

    #[test]
    fn calls_some() {
        let insts = vec![
            TestInstruction::new(0, Opcode::Add),
            TestInstruction::new(1, Opcode::Call(Address::new(500))),
            TestInstruction::new(2, Opcode::Add),
            TestInstruction::new(3, Opcode::Call(Address::new(400))),
            TestInstruction::new(4, Opcode::Call(Address::new(500))),
            TestInstruction::new(5, Opcode::Ret),
        ];
        let f = Function::new(Symbol::new(Address::new(100), None), insts);
        let calls = f.identify_call_sites();
        assert_eq!(
            calls,
            vec![
                CallSite {
                    call_site_address: Address::new(1),
                    target: CallSiteTarget::Direct(Address::new(500)),
                },
                CallSite {
                    call_site_address: Address::new(3),
                    target: CallSiteTarget::Direct(Address::new(400)),
                },
                CallSite {
                    call_site_address: Address::new(4),
                    target: CallSiteTarget::Direct(Address::new(500)),
                },
            ]
        );
    }
}
<commit_msg>clippy: CallSite/CallSiteTarget: Derive Eq as well.<commit_after>// 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 crate::address::Address;
use crate::instruction::Instruction;

/// Information about the target of a `CallSite`.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CallSiteTarget {
    /// The call site directly invokes the function at the `Address`.
    Direct(Address),
    /// The call site is indirect, and we haven't yet done further
    /// analysis.
    Indirect,
}

/// Information about a call site.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct CallSite {
    /// The address of the call site.
    pub call_site_address: Address,
    /// Information about the target of the call site.
    pub target: CallSiteTarget,
}

/// Assist in performing call graph analysis.
pub trait CallGraphAnalysis<I: Instruction> {
    /// Get information about the function calls made.
    fn identify_call_sites(&self) -> Vec<CallSite>;

    /// Get information about the function calls made within a set of instructions.
    ///
    /// This is meant to be called by implementations of this trait.
    fn identify_call_sites_in_instructions(&self, instructions: &[I]) -> Vec<CallSite> {
        instructions
            .iter()
            .filter(|i| i.is_call())
            .map(|i| CallSite {
                call_site_address: i.address(),
                target: match i.target_address() {
                    Some(a) => CallSiteTarget::Direct(a),
                    None => CallSiteTarget::Indirect,
                },
            }).collect()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::address::Address;
    use crate::function::Function;
    use crate::symbol::Symbol;
    use crate::tests::*;

    #[test]
    fn calls_none() {
        let insts = vec![
            TestInstruction::new(0, Opcode::Add),
            TestInstruction::new(1, Opcode::Add),
            TestInstruction::new(2, Opcode::Ret),
        ];
        let f = Function::new(Symbol::new(Address::new(100), None), insts);
        let calls = f.identify_call_sites();
        assert!(calls.is_empty());
    }

    #[test]
    fn calls_some() {
        let insts = vec![
            TestInstruction::new(0, Opcode::Add),
            TestInstruction::new(1, Opcode::Call(Address::new(500))),
            TestInstruction::new(2, Opcode::Add),
            TestInstruction::new(3, Opcode::Call(Address::new(400))),
            TestInstruction::new(4, Opcode::Call(Address::new(500))),
            TestInstruction::new(5, Opcode::Ret),
        ];
        let f = Function::new(Symbol::new(Address::new(100), None), insts);
        let calls = f.identify_call_sites();
        assert_eq!(
            calls,
            vec![
                CallSite {
                    call_site_address: Address::new(1),
                    target: CallSiteTarget::Direct(Address::new(500)),
                },
                CallSite {
                    call_site_address: Address::new(3),
                    target: CallSiteTarget::Direct(Address::new(400)),
                },
                CallSite {
                    call_site_address: Address::new(4),
                    target: CallSiteTarget::Direct(Address::new(500)),
                },
            ]
        );
    }
}
<|endoftext|>


<commit_before>extern crate glutin;
extern crate libc;
use std::ptr;

mod gl {
    pub use self::Gles2 as Gl;
    include!(concat!(env!("OUT_DIR"), "/test_gl_bindings.rs"));
}
use gl::types::*;

#[cfg(target_os = "macos")]
#[test]
fn test_headless() {
    let width: i32 = 256;
    let height: i32 = 256;
    let window = glutin::HeadlessRendererBuilder::new(width as u32, height as u32).build().unwrap();

    unsafe { window.make_current().expect("Couldn't make window current") };

    let gl = gl::Gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    unsafe {
        let mut framebuffer = 0;
        let mut texture = 0;
        gl.GenFramebuffers(1, &mut framebuffer);
        gl.BindFramebuffer(gl::FRAMEBUFFER, framebuffer);
        gl.GenTextures(1, &mut texture);
        gl.BindTexture(gl::TEXTURE_2D, texture);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
        gl.TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32, width, height,
                     0, gl::RGBA, gl::UNSIGNED_BYTE, ptr::null());
        gl.FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, texture, 0);
        let status = gl.CheckFramebufferStatus(gl::FRAMEBUFFER);
        if status != gl::FRAMEBUFFER_COMPLETE {
          panic!("Error while creating the framebuffer");
        }

        gl.ClearColor(0.0, 1.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);
        gl.Enable(gl::SCISSOR_TEST);
        gl.Scissor(1, 0, 1, 1);
        gl.ClearColor(1.0, 0.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);

        let mut values: Vec<u8> = vec![0;(width*height*4) as usize];
        gl.ReadPixels(0, 0, width, height, gl::RGBA, gl::UNSIGNED_BYTE, values.as_mut_ptr() as *mut GLvoid);

        assert_eq!(values[0], 0);
        assert_eq!(values[1], 255);
        assert_eq!(values[2], 0);
        assert_eq!(values[3], 255);

        assert_eq!(values[4], 255);
        assert_eq!(values[5], 0);
        assert_eq!(values[6], 0);
        assert_eq!(values[7], 255);
    }
}
<commit_msg>Update headless test for re-addition of GlContext trait<commit_after>extern crate glutin;
extern crate libc;
use std::ptr;

mod gl {
    pub use self::Gles2 as Gl;
    include!(concat!(env!("OUT_DIR"), "/test_gl_bindings.rs"));
}
use gl::types::*;
use glutin::GlContext;

#[cfg(target_os = "macos")]
#[test]
fn test_headless() {
    let width: i32 = 256;
    let height: i32 = 256;
    let window = glutin::HeadlessRendererBuilder::new(width as u32, height as u32).build().unwrap();

    unsafe { window.make_current().expect("Couldn't make window current") };

    let gl = gl::Gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    unsafe {
        let mut framebuffer = 0;
        let mut texture = 0;
        gl.GenFramebuffers(1, &mut framebuffer);
        gl.BindFramebuffer(gl::FRAMEBUFFER, framebuffer);
        gl.GenTextures(1, &mut texture);
        gl.BindTexture(gl::TEXTURE_2D, texture);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
        gl.TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
        gl.TexImage2D(gl::TEXTURE_2D, 0, gl::RGBA as i32, width, height,
                     0, gl::RGBA, gl::UNSIGNED_BYTE, ptr::null());
        gl.FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, texture, 0);
        let status = gl.CheckFramebufferStatus(gl::FRAMEBUFFER);
        if status != gl::FRAMEBUFFER_COMPLETE {
          panic!("Error while creating the framebuffer");
        }

        gl.ClearColor(0.0, 1.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);
        gl.Enable(gl::SCISSOR_TEST);
        gl.Scissor(1, 0, 1, 1);
        gl.ClearColor(1.0, 0.0, 0.0, 1.0);
        gl.Clear(gl::COLOR_BUFFER_BIT);

        let mut values: Vec<u8> = vec![0;(width*height*4) as usize];
        gl.ReadPixels(0, 0, width, height, gl::RGBA, gl::UNSIGNED_BYTE, values.as_mut_ptr() as *mut GLvoid);

        assert_eq!(values[0], 0);
        assert_eq!(values[1], 255);
        assert_eq!(values[2], 0);
        assert_eq!(values[3], 255);

        assert_eq!(values[4], 255);
        assert_eq!(values[5], 0);
        assert_eq!(values[6], 0);
        assert_eq!(values[7], 255);
    }
}
<|endoftext|>