<commit_before>//! Basic types to build the parsers

use self::Needed::*;
use crate::error::ErrorKind;
use core::num::NonZeroUsize;

/// Holds the result of parsing functions
///
/// It depends on the input type `I`, the output type `O`, and the error type `E`
/// (by default `(I, nom::ErrorKind)`)
///
/// The `Ok` side is a pair containing the remainder of the input (the part of the data that
/// was not parsed) and the produced value. The `Err` side contains an instance of `nom::Err`.
pub type IResult<I, O, E = (I, ErrorKind)> = Result<(I, O), Err<E>>;

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Needed {
  /// Needs more data, but we do not know how much
  Unknown,
  /// Contains the required data size
  Size(NonZeroUsize),
}

impl Needed {
  /// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero
  pub fn new(s: usize) -> Self {
    match NonZeroUsize::new(s) {
      Some(sz) => Needed::Size(sz),
      None => Needed::Unknown,
    }
  }

  /// Indicates if we know how many bytes we need
  pub fn is_known(&self) -> bool {
    *self != Unknown
  }

  /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value.
  #[inline]
  pub fn map<F: Fn(NonZeroUsize) -> usize>(self, f: F) -> Needed {
    match self {
      Unknown => Unknown,
      Size(n) => Needed::new(f(n)),
    }
  }
}

/// The `Err` enum indicates the parser was not successful
///
/// It has three cases:
///
/// * `Incomplete` indicates that more data is needed to decide. The `Needed` enum
/// can contain how many additional bytes are necessary. If you are sure your parser
/// is working on full data, you can wrap your parser with the `complete` combinator
/// to transform that case in `Error`
/// * `Error` means some parser did not succeed, but another one might (as an example,
/// when testing different branches of an `alt` combinator)
/// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix
/// to decide on the next parser to apply, and that parser fails, you know there's no need
/// to try other parsers, you were already in the right branch, so the data is invalid
///
#[derive(Debug, Clone, PartialEq)]
pub enum Err<E> {
  /// There was not enough data
  Incomplete(Needed),
  /// The parser had an error (recoverable)
  Error(E),
  /// The parser had an unrecoverable error: we got to the right
  /// branch and we know other branches won't work, so backtrack
  /// as fast as possible
  Failure(E),
}

impl<E> Err<E> {
  /// Tests if the result is Incomplete
  pub fn is_incomplete(&self) -> bool {
    if let Err::Incomplete(_) = self {
      true
    } else {
      false
    }
  }

  /// Applies the given function to the inner error
  pub fn map<E2, F>(self, f: F) -> Err<E2>
  where
    F: FnOnce(E) -> E2,
  {
    match self {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure(t) => Err::Failure(f(t)),
      Err::Error(t) => Err::Error(f(t)),
    }
  }

  /// Automatically converts between errors if the underlying type supports it
  pub fn convert<F>(e: Err<F>) -> Self
  where
    E: From<F>,
  {
    e.map(Into::into)
  }
}

impl<T> Err<(T, ErrorKind)> {
  /// Maps `Err<(T, ErrorKind)>` to `Err<(U, ErrorKind)>` with the given `F: T -> U`
  pub fn map_input<U, F>(self, f: F) -> Err<(U, ErrorKind)>
  where
    F: FnOnce(T) -> U,
  {
    match self {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure((input, k)) => Err::Failure((f(input), k)),
      Err::Error((input, k)) => Err::Error((f(input), k)),
    }
  }
}

#[cfg(feature = "std")]
impl Err<(&[u8], ErrorKind)> {
  /// Obtaining ownership
  pub fn to_owned(self) -> Err<(Vec<u8>, ErrorKind)> {
    self.map_input(ToOwned::to_owned)
  }
}

#[cfg(feature = "std")]
impl Err<(&str, ErrorKind)> {
  /// Automatically converts between errors if the underlying type supports it
  pub fn to_owned(self) -> Err<(String, ErrorKind)> {
    self.map_input(ToOwned::to_owned)
  }
}

impl<E: Eq> Eq for Err<E> {}

#[cfg(feature = "std")]
use std::fmt;

#[cfg(feature = "std")]
impl<E> fmt::Display for Err<E>
where
  E: fmt::Debug,
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self {
      Err::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u),
      Err::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"),
      Err::Failure(c) => write!(f, "Parsing Failure: {:?}", c),
      Err::Error(c) => write!(f, "Parsing Error: {:?}", c),
    }
  }
}

#[cfg(feature = "std")]
use std::error::Error;

#[cfg(feature = "std")]
impl<E> Error for Err<E>
where
  E: fmt::Debug,
{
  fn source(&self) -> Option<&(dyn Error + 'static)> {
    None // no underlying error
  }
}

/// All nom parsers implement this trait
pub trait Parser<I, O, E> {
  /// A parser takes in input type, and returns a `Result` containing
  /// either the remaining input and the output value, or an error
  fn parse(&mut self, input: I) -> IResult<I, O, E>;

  /// Maps a function over the result of a parser
  fn map<G, O2>(self, g: G) -> Map<Self, G, O>
  where
    G: Fn(O) -> O2,
    Self: core::marker::Sized,
  {
    Map {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Creates a second parser from the output of the first one, then apply over the rest of the input
  fn flat_map<G, H, O2>(self, g: G) -> FlatMap<Self, G, O>
  where
    G: Fn(O) -> H,
    H: Parser<I, O2, E>,
    Self: core::marker::Sized,
  {
    FlatMap {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Applies a second parser over the output of the first one
  fn and_then<G, O2>(self, g: G) -> AndThen<Self, G, O>
  where
    G: Parser<O, O2, E>,
    Self: core::marker::Sized,
  {
    AndThen {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Applies a second parser after the first one, return their results as a tuple
  fn and<G, O2>(self, g: G) -> And<Self, G>
  where
    G: Parser<I, O2, E>,
    Self: core::marker::Sized,
  {
    And { f: self, g }
  }

  /// Applies a second parser over the input if the first one failed
  fn or<G>(self, g: G) -> Or<Self, G>
  where
    G: Parser<I, O, E>,
    Self: core::marker::Sized,
  {
    Or { f: self, g }
  }
}

impl<'a, I, O, E, F> Parser<I, O, E> for F
where
  F: FnMut(I) -> IResult<I, O, E> + 'a,
{
  fn parse(&mut self, i: I) -> IResult<I, O, E> {
    self(i)
  }
}

/// Implementation of `Parser:::map`
pub struct Map<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> O2> Parser<I, O2, E> for Map<F, G, O1> {
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    match self.f.parse(i) {
      Err(e) => Err(e),
      Ok((i, o)) => Ok((i, (self.g)(o))),
    }
  }
}

/// Implementation of `Parser::flat_map`
pub struct FlatMap<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> H, H: Parser<I, O2, E>> Parser<I, O2, E>
  for FlatMap<F, G, O1>
{
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    let (i, o1) = self.f.parse(i)?;
    (self.g)(o1).parse(i)
  }
}

/// Implementation of `Parser::and_then`
pub struct AndThen<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<O1, O2, E>> Parser<I, O2, E>
  for AndThen<F, G, O1>
{
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    let (i, o1) = self.f.parse(i)?;
    let (_, o2) = self.g.parse(o1)?;
    Ok((i, o2))
  }
}

/// Implementation of `Parser::and`
pub struct And<F, G> {
  f: F,
  g: G,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<I, O2, E>> Parser<I, (O1, O2), E>
  for And<F, G>
{
  fn parse(&mut self, i: I) -> IResult<I, (O1, O2), E> {
    let (i, o1) = self.f.parse(i)?;
    let (i, o2) = self.g.parse(i)?;
    Ok((i, (o1, o2)))
  }
}

/// Implementation of `Parser::or`
pub struct Or<F, G> {
  f: F,
  g: G,
}

impl<'a, I: Clone, O, E: crate::error::ParseError<I>, F: Parser<I, O, E>, G: Parser<I, O, E>>
  Parser<I, O, E> for Or<F, G>
{
  fn parse(&mut self, i: I) -> IResult<I, O, E> {
    match self.f.parse(i.clone()) {
      Err(Err::Error(e1)) => match self.g.parse(i) {
        Err(Err::Error(e2)) => Err(Err::Error(e1.or(e2))),
        res => res,
      },
      res => res,
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use crate::error::ErrorKind;

  #[doc(hidden)]
  #[macro_export]
  macro_rules! assert_size (
    ($t:ty, $sz:expr) => (
      assert_eq!(crate::lib::std::mem::size_of::<$t>(), $sz);
    );
  );

  #[test]
  #[cfg(target_pointer_width = "64")]
  fn size_test() {
    assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
    assert_size!(IResult<&str, &str, u32>, 40);
    assert_size!(Needed, 8);
    assert_size!(Err<u32>, 16);
    assert_size!(ErrorKind, 1);
  }

  #[test]
  fn err_map_test() {
    let e = Err::Error(1);
    assert_eq!(e.map(|v| v + 1), Err::Error(2));
  }
}
<commit_msg>add the finish() method to clean up a parser's result<commit_after>//! Basic types to build the parsers

use self::Needed::*;
use crate::error::ErrorKind;
use core::num::NonZeroUsize;

/// Holds the result of parsing functions
///
/// It depends on the input type `I`, the output type `O`, and the error type `E`
/// (by default `(I, nom::ErrorKind)`)
///
/// The `Ok` side is a pair containing the remainder of the input (the part of the data that
/// was not parsed) and the produced value. The `Err` side contains an instance of `nom::Err`.
///
/// Outside of the parsing code, you can use the [Finish::finish] method to convert
/// it to a more common result type
pub type IResult<I, O, E = (I, ErrorKind)> = Result<(I, O), Err<E>>;

/// Helper trait to convert a parser's result to a more manageable type
pub trait Finish<I,O,E> {
    /// converts the parser's result to a type that is more consumable by error
    /// management libraries. It keeps the same `Ok` branch, and merges `Err::Error`
    /// and `Err::Failure` into the `Err` side.
    ///
    /// *warning*: if the result is `Err(Err::Incomplete(_))`, this method will panic.
    /// - "complete" parsers: It will not be an issue, `Incomplete` is never used
    /// - "streaming" parsers: `Incomplete` will be returned if there's not enough data
    /// for the parser to decide, and you should gather more data before parsing again.
    /// Once the parser returns either `Ok(_)`, `Err(Err::Error(_))` or `Err(Err::Failure(_))`,
    /// you can get out of the parsing loop and call `finish()` on the parser's result
    fn finish(self) -> Result<(I, O), E>;
}

impl<I,O,E> Finish<I,O,E> for IResult<I,O,E> {
    fn finish(self) -> Result<(I, O), E> {
        match self {
            Ok(res) => Ok(res),
            Err(Err::Error(e)) | Err(Err::Failure(e)) => Err(e),
            Err(Err::Incomplete(_)) => {
                panic!("Cannot call `finish()` on `Err(Err::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply  the parser instead")
            }
        }
    }
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Needed {
  /// Needs more data, but we do not know how much
  Unknown,
  /// Contains the required data size
  Size(NonZeroUsize),
}

impl Needed {
  /// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero
  pub fn new(s: usize) -> Self {
    match NonZeroUsize::new(s) {
      Some(sz) => Needed::Size(sz),
      None => Needed::Unknown,
    }
  }

  /// Indicates if we know how many bytes we need
  pub fn is_known(&self) -> bool {
    *self != Unknown
  }

  /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value.
  #[inline]
  pub fn map<F: Fn(NonZeroUsize) -> usize>(self, f: F) -> Needed {
    match self {
      Unknown => Unknown,
      Size(n) => Needed::new(f(n)),
    }
  }
}

/// The `Err` enum indicates the parser was not successful
///
/// It has three cases:
///
/// * `Incomplete` indicates that more data is needed to decide. The `Needed` enum
/// can contain how many additional bytes are necessary. If you are sure your parser
/// is working on full data, you can wrap your parser with the `complete` combinator
/// to transform that case in `Error`
/// * `Error` means some parser did not succeed, but another one might (as an example,
/// when testing different branches of an `alt` combinator)
/// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix
/// to decide on the next parser to apply, and that parser fails, you know there's no need
/// to try other parsers, you were already in the right branch, so the data is invalid
///
#[derive(Debug, Clone, PartialEq)]
pub enum Err<E> {
  /// There was not enough data
  Incomplete(Needed),
  /// The parser had an error (recoverable)
  Error(E),
  /// The parser had an unrecoverable error: we got to the right
  /// branch and we know other branches won't work, so backtrack
  /// as fast as possible
  Failure(E),
}

impl<E> Err<E> {
  /// Tests if the result is Incomplete
  pub fn is_incomplete(&self) -> bool {
    if let Err::Incomplete(_) = self {
      true
    } else {
      false
    }
  }

  /// Applies the given function to the inner error
  pub fn map<E2, F>(self, f: F) -> Err<E2>
  where
    F: FnOnce(E) -> E2,
  {
    match self {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure(t) => Err::Failure(f(t)),
      Err::Error(t) => Err::Error(f(t)),
    }
  }

  /// Automatically converts between errors if the underlying type supports it
  pub fn convert<F>(e: Err<F>) -> Self
  where
    E: From<F>,
  {
    e.map(Into::into)
  }
}

impl<T> Err<(T, ErrorKind)> {
  /// Maps `Err<(T, ErrorKind)>` to `Err<(U, ErrorKind)>` with the given `F: T -> U`
  pub fn map_input<U, F>(self, f: F) -> Err<(U, ErrorKind)>
  where
    F: FnOnce(T) -> U,
  {
    match self {
      Err::Incomplete(n) => Err::Incomplete(n),
      Err::Failure((input, k)) => Err::Failure((f(input), k)),
      Err::Error((input, k)) => Err::Error((f(input), k)),
    }
  }
}

#[cfg(feature = "std")]
impl Err<(&[u8], ErrorKind)> {
  /// Obtaining ownership
  pub fn to_owned(self) -> Err<(Vec<u8>, ErrorKind)> {
    self.map_input(ToOwned::to_owned)
  }
}

#[cfg(feature = "std")]
impl Err<(&str, ErrorKind)> {
  /// Automatically converts between errors if the underlying type supports it
  pub fn to_owned(self) -> Err<(String, ErrorKind)> {
    self.map_input(ToOwned::to_owned)
  }
}

impl<E: Eq> Eq for Err<E> {}

#[cfg(feature = "std")]
use std::fmt;

#[cfg(feature = "std")]
impl<E> fmt::Display for Err<E>
where
  E: fmt::Debug,
{
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match self {
      Err::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u),
      Err::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"),
      Err::Failure(c) => write!(f, "Parsing Failure: {:?}", c),
      Err::Error(c) => write!(f, "Parsing Error: {:?}", c),
    }
  }
}

#[cfg(feature = "std")]
use std::error::Error;

#[cfg(feature = "std")]
impl<E> Error for Err<E>
where
  E: fmt::Debug,
{
  fn source(&self) -> Option<&(dyn Error + 'static)> {
    None // no underlying error
  }
}

/// All nom parsers implement this trait
pub trait Parser<I, O, E> {
  /// A parser takes in input type, and returns a `Result` containing
  /// either the remaining input and the output value, or an error
  fn parse(&mut self, input: I) -> IResult<I, O, E>;

  /// Maps a function over the result of a parser
  fn map<G, O2>(self, g: G) -> Map<Self, G, O>
  where
    G: Fn(O) -> O2,
    Self: core::marker::Sized,
  {
    Map {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Creates a second parser from the output of the first one, then apply over the rest of the input
  fn flat_map<G, H, O2>(self, g: G) -> FlatMap<Self, G, O>
  where
    G: Fn(O) -> H,
    H: Parser<I, O2, E>,
    Self: core::marker::Sized,
  {
    FlatMap {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Applies a second parser over the output of the first one
  fn and_then<G, O2>(self, g: G) -> AndThen<Self, G, O>
  where
    G: Parser<O, O2, E>,
    Self: core::marker::Sized,
  {
    AndThen {
      f: self,
      g,
      phantom: core::marker::PhantomData,
    }
  }

  /// Applies a second parser after the first one, return their results as a tuple
  fn and<G, O2>(self, g: G) -> And<Self, G>
  where
    G: Parser<I, O2, E>,
    Self: core::marker::Sized,
  {
    And { f: self, g }
  }

  /// Applies a second parser over the input if the first one failed
  fn or<G>(self, g: G) -> Or<Self, G>
  where
    G: Parser<I, O, E>,
    Self: core::marker::Sized,
  {
    Or { f: self, g }
  }
}

impl<'a, I, O, E, F> Parser<I, O, E> for F
where
  F: FnMut(I) -> IResult<I, O, E> + 'a,
{
  fn parse(&mut self, i: I) -> IResult<I, O, E> {
    self(i)
  }
}

/// Implementation of `Parser:::map`
pub struct Map<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> O2> Parser<I, O2, E> for Map<F, G, O1> {
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    match self.f.parse(i) {
      Err(e) => Err(e),
      Ok((i, o)) => Ok((i, (self.g)(o))),
    }
  }
}

/// Implementation of `Parser::flat_map`
pub struct FlatMap<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> H, H: Parser<I, O2, E>> Parser<I, O2, E>
  for FlatMap<F, G, O1>
{
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    let (i, o1) = self.f.parse(i)?;
    (self.g)(o1).parse(i)
  }
}

/// Implementation of `Parser::and_then`
pub struct AndThen<F, G, O1> {
  f: F,
  g: G,
  phantom: core::marker::PhantomData<O1>,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<O1, O2, E>> Parser<I, O2, E>
  for AndThen<F, G, O1>
{
  fn parse(&mut self, i: I) -> IResult<I, O2, E> {
    let (i, o1) = self.f.parse(i)?;
    let (_, o2) = self.g.parse(o1)?;
    Ok((i, o2))
  }
}

/// Implementation of `Parser::and`
pub struct And<F, G> {
  f: F,
  g: G,
}

impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<I, O2, E>> Parser<I, (O1, O2), E>
  for And<F, G>
{
  fn parse(&mut self, i: I) -> IResult<I, (O1, O2), E> {
    let (i, o1) = self.f.parse(i)?;
    let (i, o2) = self.g.parse(i)?;
    Ok((i, (o1, o2)))
  }
}

/// Implementation of `Parser::or`
pub struct Or<F, G> {
  f: F,
  g: G,
}

impl<'a, I: Clone, O, E: crate::error::ParseError<I>, F: Parser<I, O, E>, G: Parser<I, O, E>>
  Parser<I, O, E> for Or<F, G>
{
  fn parse(&mut self, i: I) -> IResult<I, O, E> {
    match self.f.parse(i.clone()) {
      Err(Err::Error(e1)) => match self.g.parse(i) {
        Err(Err::Error(e2)) => Err(Err::Error(e1.or(e2))),
        res => res,
      },
      res => res,
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use crate::error::ErrorKind;

  #[doc(hidden)]
  #[macro_export]
  macro_rules! assert_size (
    ($t:ty, $sz:expr) => (
      assert_eq!(crate::lib::std::mem::size_of::<$t>(), $sz);
    );
  );

  #[test]
  #[cfg(target_pointer_width = "64")]
  fn size_test() {
    assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
    assert_size!(IResult<&str, &str, u32>, 40);
    assert_size!(Needed, 8);
    assert_size!(Err<u32>, 16);
    assert_size!(ErrorKind, 1);
  }

  #[test]
  fn err_map_test() {
    let e = Err::Error(1);
    assert_eq!(e.map(|v| v + 1), Err::Error(2));
  }
}
<|endoftext|>


<commit_before>//! Lazily initialized data.
//! Used in generated code.

use std::cell::UnsafeCell;
use std::sync;

/// Lasily initialized data.
pub struct Lazy<T> {
    lock: sync::Once,
    ptr: UnsafeCell<*const T>,
}

unsafe impl<T> Sync for Lazy<T> {}

impl<T> Lazy<T> {
    /// Uninitialized `Lazy` object.
    pub const INIT: Lazy<T> = Lazy {
        lock: sync::Once::new(),
        ptr: UnsafeCell::new(0 as *const T),
    };

    /// Get lazy field value, initialize it with given function if not yet.
    pub fn get<F>(&'static self, init: F) -> &'static T
    where
        F: FnOnce() -> T,
    {
        self.lock.call_once(|| unsafe {
            *self.ptr.get() = Box::into_raw(Box::new(init()));
        });
        unsafe { &**self.ptr.get() }
    }
}

#[cfg(test)]
mod test {
    use super::Lazy;
    use std::sync::atomic::{AtomicIsize, Ordering};
    use std::sync::{Arc, Barrier};
    use std::thread;

    #[test]
    fn many_threads_calling_get() {
        const N_THREADS: usize = 32;
        const N_ITERS_IN_THREAD: usize = 32;
        const N_ITERS: usize = 16;

        static mut LAZY: Lazy<String> = Lazy::INIT;
        static CALL_COUNT: AtomicIsize = AtomicIsize::new(0);

        let value = "Hello, world!".to_owned();

        for _ in 0..N_ITERS {
            // Reset mutable state.
            unsafe {
                LAZY = Lazy::INIT;
            }
            CALL_COUNT.store(0, Ordering::SeqCst);

            // Create a bunch of threads, all calling .get() at the same time.
            let mut threads = vec![];
            let barrier = Arc::new(Barrier::new(N_THREADS));

            for _ in 0..N_THREADS {
                let cloned_value_thread = value.clone();
                let cloned_barrier = barrier.clone();
                threads.push(thread::spawn(move || {
                    // Ensure all threads start at once to maximise contention.
                    cloned_barrier.wait();
                    for _ in 0..N_ITERS_IN_THREAD {
                        assert_eq!(&cloned_value_thread, unsafe {
                            LAZY.get(|| {
                                CALL_COUNT.fetch_add(1, Ordering::SeqCst);
                                cloned_value_thread.clone()
                            })
                        });
                    }
                }));
            }

            for thread in threads {
                thread.join().unwrap();
            }

            assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1);
        }
    }
}
<commit_msg>Minor formatting<commit_after>//! Lazily initialized data.
//! Used in generated code.

use std::cell::UnsafeCell;
use std::sync;

/// Lasily initialized data.
pub struct Lazy<T> {
    lock: sync::Once,
    ptr: UnsafeCell<*const T>,
}

unsafe impl<T> Sync for Lazy<T> {}

impl<T> Lazy<T> {
    /// Uninitialized `Lazy` object.
    pub const INIT: Lazy<T> = Lazy {
        lock: sync::Once::new(),
        ptr: UnsafeCell::new(0 as *const T),
    };

    /// Get lazy field value, initialize it with given function if not yet.
    pub fn get<F>(&'static self, init: F) -> &'static T
    where
        F: FnOnce() -> T,
    {
        self.lock.call_once(|| unsafe {
            *self.ptr.get() = Box::into_raw(Box::new(init()));
        });
        unsafe { &**self.ptr.get() }
    }
}

#[cfg(test)]
mod test {
    use super::Lazy;
    use std::sync::atomic::AtomicIsize;
    use std::sync::atomic::Ordering;
    use std::sync::Arc;
    use std::sync::Barrier;
    use std::thread;

    #[test]
    fn many_threads_calling_get() {
        const N_THREADS: usize = 32;
        const N_ITERS_IN_THREAD: usize = 32;
        const N_ITERS: usize = 16;

        static mut LAZY: Lazy<String> = Lazy::INIT;
        static CALL_COUNT: AtomicIsize = AtomicIsize::new(0);

        let value = "Hello, world!".to_owned();

        for _ in 0..N_ITERS {
            // Reset mutable state.
            unsafe {
                LAZY = Lazy::INIT;
            }
            CALL_COUNT.store(0, Ordering::SeqCst);

            // Create a bunch of threads, all calling .get() at the same time.
            let mut threads = vec![];
            let barrier = Arc::new(Barrier::new(N_THREADS));

            for _ in 0..N_THREADS {
                let cloned_value_thread = value.clone();
                let cloned_barrier = barrier.clone();
                threads.push(thread::spawn(move || {
                    // Ensure all threads start at once to maximise contention.
                    cloned_barrier.wait();
                    for _ in 0..N_ITERS_IN_THREAD {
                        assert_eq!(&cloned_value_thread, unsafe {
                            LAZY.get(|| {
                                CALL_COUNT.fetch_add(1, Ordering::SeqCst);
                                cloned_value_thread.clone()
                            })
                        });
                    }
                }));
            }

            for thread in threads {
                thread.join().unwrap();
            }

            assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1);
        }
    }
}
<|endoftext|>


<commit_before>#![cfg(feature = "secretsmanager")]

extern crate env_logger;
extern crate rusoto_core;
extern crate rusoto_secretsmanager;

use rusoto_secretsmanager::{ListSecretsRequest, SecretsManager, SecretsManagerClient};
use rusoto_core::Region;

#[test]
fn should_list_invitations() {
  let _ = env_logger::try_init();
  let client = SecretsManagerClient::simple(Region::UsWest2);
  let request = ListSecretsRequest {
    ..Default::default()
  };

  let result = client.list_secrets(&request).sync();
  println!("{:#?}", result);
  assert!(result.is_ok());
}
<commit_msg>not the kind of thing you want to print out in a test<commit_after>#![cfg(feature = "secretsmanager")]

extern crate env_logger;
extern crate rusoto_core;
extern crate rusoto_secretsmanager;

use rusoto_secretsmanager::{ListSecretsRequest, SecretsManager, SecretsManagerClient};
use rusoto_core::Region;

#[test]
fn should_list_invitations() {
  let _ = env_logger::try_init();
  let client = SecretsManagerClient::simple(Region::UsWest2);
  let request = ListSecretsRequest {
    ..Default::default()
  };

  let result = client.list_secrets(&request).sync();
  assert!(result.is_ok());
}
<|endoftext|>


<commit_before>// rustfmt-version: One

fn main() {
    thread::spawn(|| {
        while true {
            println!("iteration");
        }
    });

    thread::spawn(|| loop {
        println!("iteration");
    });
}
<commit_msg>remove tests/source/issue-3227/one.rs<commit_after><|endoftext|>


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

use target::{Target, TargetOptions};

pub fn target() -> Target {
    Target {
        llvm_target: "mipsel-unknown-linux-musl".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
        arch: "mips".to_string(),
        target_os: "linux".to_string(),
        target_env: "musl".to_string(),
        target_vendor: "unknown".to_string(),
        options: TargetOptions {
            cpu: "mips32".to_string(),
            features: "+mips32".to_string(),
            max_atomic_width: 32,
            ..super::linux_base::opts()
        }
    }
}
<commit_msg>switch mipsel-musl to soft float<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use target::{Target, TargetOptions};

pub fn target() -> Target {
    Target {
        llvm_target: "mipsel-unknown-linux-musl".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
        arch: "mips".to_string(),
        target_os: "linux".to_string(),
        target_env: "musl".to_string(),
        target_vendor: "unknown".to_string(),
        options: TargetOptions {
            cpu: "mips32".to_string(),
            features: "+mips32,+soft-float".to_string(),
            max_atomic_width: 32,
            ..super::linux_base::opts()
        }
    }
}
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// 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/.

use std::ascii::AsciiExt;
use std::ffi::OsString;
use std::ops::Range;
use std::str;

use super::Input;

/// A `struct` useful for matching heap-allocated `String`s.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct StringInput {
    string: String,
}

/// A `struct` useful for matching borrowed `str`s.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct StrInput<'a> {
    str_ref: &'a str,
}

impl StringInput {
    /// Creates a new `StringInput` from a `String`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use pest::inputs::{Input, StringInput};
    /// let input = StringInput::new("asd".to_owned());
    ///
    /// assert_eq!(input.len(), 3);
    /// ```
    pub fn new(string: String) -> StringInput {
        StringInput { string }
    }
}

impl<'a> StrInput<'a> {
    /// Creates a new `StrInput` from a `&str`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use pest::inputs::{Input, StrInput};
    /// let input = StrInput::new("asd");
    ///
    /// assert_eq!(input.len(), 3);
    /// ```
    pub fn new(source: &'a str) -> StrInput<'a> {
        StrInput { str_ref: source }
    }
}

#[inline]
unsafe fn line_col(source: &str, pos: usize) -> (usize, usize) {
    if pos > source.len() {
        panic!("position out of bounds");
    }

    let mut pos = pos;
    let slice = &source[..pos];
    let mut chars = slice.chars().peekable();

    let mut line_col = (1, 1);

    while pos != 0 {
        match chars.next() {
            Some('\r') => {
                if let Some(&'\n') = chars.peek() {
                    chars.next();

                    if pos == 1 {
                        pos -= 1;
                    } else {
                        pos -= 2;
                    }

                    line_col = (line_col.0 + 1, 1);
                } else {
                    pos -= 1;
                    line_col = (line_col.0, line_col.1 + 1);
                }
            }
            Some('\n') => {
                pos -= 1;
                line_col = (line_col.0 + 1, 1);
            }
            Some(c) => {
                pos -= c.len_utf8();
                line_col = (line_col.0, line_col.1 + 1);
            }
            None => unreachable!(),
        }
    }

    line_col
}

#[inline]
unsafe fn line_of(source: &str, mut pos: usize) -> &str {
    if pos > source.len() {
        panic!("position out of bounds");
    }

    let start = if pos == 0 {
        0
    } else {
        if source.slice_unchecked(pos, pos + 1) == "\n" {
            pos -= 1;
        }

        let start = source
            .char_indices()
            .rev()
            .skip_while(|&(i, _)| i > pos)
            .find(|&(_, c)| c == '\n');
        match start {
            Some((i, _)) => i + 1,
            None => 0,
        }
    };

    let end = if source.len() == 0 {
        0
    } else if pos == source.len() - 1 {
        let mut end = source.len();

        if end > 0 && source.slice_unchecked(end - 1, end) == "\n" {
            end -= 1;
        }
        if end > 0 && source.slice_unchecked(end - 1, end) == "\r" {
            end -= 1;
        }

        end
    } else {
        let end = source.char_indices().skip_while(|&(i, _)| i < pos).find(
            |&(_,
               c)| {
                c == '\n'
            },
        );
        let mut end = match end {
            Some((i, _)) => i,
            None => source.len(),
        };

        if end > 0 && source.slice_unchecked(end - 1, end) == "\r" {
            end -= 1;
        }

        end
    };

    source.slice_unchecked(start, end)
}

#[inline]
unsafe fn skip(source: &str, n: usize, pos: usize) -> Option<usize> {
    let mut len = 0;
    let mut chars = source.slice_unchecked(pos, source.len()).chars();

    for _ in 0..n {
        if let Some(c) = chars.next() {
            len += c.len_utf8();
        } else {
            return None;
        }
    }

    Some(len)
}

#[inline]
unsafe fn match_string(source: &str, string: &str, pos: usize) -> bool {
    let to = pos + string.len();

    if to <= source.len() {
        let slice = source.slice_unchecked(pos, to);
        slice == string
    } else {
        false
    }
}

#[inline]
unsafe fn match_insensitive(source: &str, string: &str, pos: usize) -> bool {
    let slice = source.slice_unchecked(pos, source.len());

    if slice.is_char_boundary(string.len()) {
        let slice = slice.slice_unchecked(0, string.len());
        slice.eq_ignore_ascii_case(string)
    } else {
        false
    }
}

#[inline]
unsafe fn match_range(source: &str, range: Range<char>, pos: usize) -> Option<usize> {
    let slice = source.slice_unchecked(pos, source.len());

    if let Some(char) = slice.chars().next() {
        if range.start <= char && char <= range.end {
            Some(char.len_utf8())
        } else {
            None
        }
    } else {
        None
    }
}

impl Input for StringInput {
    #[inline]
    fn len(&self) -> usize {
        self.string.len()
    }

    #[inline]
    fn is_empty(&self) -> bool {
        self.string.is_empty()
    }

    #[inline]
    fn file_name(&self) -> Option<OsString> {
        None
    }

    #[inline]
    unsafe fn slice(&self, start: usize, end: usize) -> &str {
        self.string.slice_unchecked(start, end)
    }

    unsafe fn line_col(&self, pos: usize) -> (usize, usize) {
        line_col(&self.string, pos)
    }

    unsafe fn line_of(&self, pos: usize) -> &str {
        line_of(&self.string, pos)
    }

    #[inline]
    unsafe fn skip(&self, n: usize, pos: usize) -> Option<usize> {
        skip(&self.string, n, pos)
    }

    #[inline]
    unsafe fn match_string(&self, string: &str, pos: usize) -> bool {
        match_string(&self.string, string, pos)
    }

    #[inline]
    unsafe fn match_insensitive(&self, string: &str, pos: usize) -> bool {
        match_insensitive(&self.string, string, pos)
    }

    #[inline]
    unsafe fn match_range(&self, range: Range<char>, pos: usize) -> Option<usize> {
        match_range(&self.string, range, pos)
    }
}

impl<'a> Input for StrInput<'a> {
    #[inline]
    fn len(&self) -> usize {
        self.str_ref.len()
    }

    #[inline]
    fn is_empty(&self) -> bool {
        self.str_ref.is_empty()
    }

    #[inline]
    fn file_name(&self) -> Option<OsString> {
        None
    }

    #[inline]
    unsafe fn slice(&self, start: usize, end: usize) -> &str {
        self.str_ref.slice_unchecked(start, end)
    }

    unsafe fn line_col(&self, pos: usize) -> (usize, usize) {
        line_col(self.str_ref, pos)
    }

    unsafe fn line_of(&self, pos: usize) -> &str {
        line_of(self.str_ref, pos)
    }

    #[inline]
    unsafe fn skip(&self, n: usize, pos: usize) -> Option<usize> {
        skip(self.str_ref, n, pos)
    }

    #[inline]
    unsafe fn match_string(&self, string: &str, pos: usize) -> bool {
        match_string(self.str_ref, string, pos)
    }

    #[inline]
    unsafe fn match_insensitive(&self, string: &str, pos: usize) -> bool {
        match_insensitive(self.str_ref, string, pos)
    }

    #[inline]
    unsafe fn match_range(&self, range: Range<char>, pos: usize) -> Option<usize> {
        match_range(self.str_ref, range, pos)
    }
}

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

    #[test]
    fn empty() {
        let input = StringInput::new("".to_owned());

        unsafe {
            assert!(input.is_empty());
            assert!(input.match_string("", 0));
            assert!(!input.match_string("a", 0));
        }
    }

    #[test]
    fn parts() {
        let input = StringInput::new("asdasdf".to_owned());

        unsafe {
            assert!(!input.is_empty());
            assert!(input.match_string("asd", 0));
            assert!(input.match_string("asdf", 3));
        }
    }

    #[test]
    fn len() {
        assert_eq!(StringInput::new("asdasdf".to_owned()).len(), 7);
    }

    #[test]
    fn slice() {
        let input = StringInput::new("asdasdf".to_owned());

        unsafe {
            assert_eq!(input.slice(1, 3), "sd");
        }
    }

    #[test]
    fn line_col() {
        let input = StringInput::new("a\rb\nc\r\nd嗨".to_owned());

        unsafe {
            assert_eq!(input.line_col(0), (1, 1));
            assert_eq!(input.line_col(1), (1, 2));
            assert_eq!(input.line_col(2), (1, 3));
            assert_eq!(input.line_col(3), (1, 4));
            assert_eq!(input.line_col(4), (2, 1));
            assert_eq!(input.line_col(5), (2, 2));
            assert_eq!(input.line_col(6), (2, 3));
            assert_eq!(input.line_col(7), (3, 1));
            assert_eq!(input.line_col(8), (3, 2));
            assert_eq!(input.line_col(11), (3, 3));
        }
    }

    #[test]
    fn line_of() {
        let input = StringInput::new("a\rb\nc\r\nd嗨".to_owned());

        unsafe {
            assert_eq!(input.line_of(0), "a\rb");
            assert_eq!(input.line_of(1), "a\rb");
            assert_eq!(input.line_of(2), "a\rb");
            assert_eq!(input.line_of(3), "a\rb");
            assert_eq!(input.line_of(4), "c");
            assert_eq!(input.line_of(5), "c");
            assert_eq!(input.line_of(6), "c");
            assert_eq!(input.line_of(7), "d嗨");
            assert_eq!(input.line_of(8), "d嗨");
            assert_eq!(input.line_of(11), "d嗨");
        }
    }

    #[test]
    fn line_of_empty() {
        let input = StringInput::new("".to_owned());

        unsafe {
            assert_eq!(input.line_of(0), "");
        }
    }

    #[test]
    fn line_of_new_line() {
        let input = StringInput::new("\n".to_owned());

        unsafe {
            assert_eq!(input.line_of(0), "");
        }
    }

    #[test]
    fn skip_empty() {
        let input = StringInput::new("".to_owned());

        unsafe {
            assert_eq!(input.skip(0, 0), Some(0));
            assert_eq!(input.skip(1, 0), None);
        }
    }

    #[test]
    fn skip() {
        let input = StringInput::new("d嗨".to_owned());

        unsafe {
            assert_eq!(input.skip(0, 0), Some(0));
            assert_eq!(input.skip(1, 0), Some(1));
            assert_eq!(input.skip(1, 1), Some(3));
        }
    }

    #[test]
    fn match_range() {
        let input = StringInput::new("b".to_owned());

        unsafe {
            assert!(input.match_range('a'..'c', 0).is_some());
            assert!(input.match_range('b'..'b', 0).is_some());
            assert!(input.match_range('a'..'a', 0).is_none());
            assert!(input.match_range('c'..'c', 0).is_none());
            assert!(input.match_range('a'..'嗨', 0).is_some());
        }
    }

    #[test]
    fn match_insensitive() {
        let input = StringInput::new("AsdASdF".to_owned());

        unsafe {
            assert!(input.match_insensitive("asd", 0));
            assert!(input.match_insensitive("asdf", 3));
        }
    }
}
<commit_msg>(test) added tests for StrInput<commit_after>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// 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/.

use std::ascii::AsciiExt;
use std::ffi::OsString;
use std::ops::Range;
use std::str;

use super::Input;

/// A `struct` useful for matching heap-allocated `String`s.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct StringInput {
    string: String,
}

/// A `struct` useful for matching borrowed `str`s.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct StrInput<'a> {
    str_ref: &'a str,
}

impl StringInput {
    /// Creates a new `StringInput` from a `String`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use pest::inputs::{Input, StringInput};
    /// let input = StringInput::new("asd".to_owned());
    ///
    /// assert_eq!(input.len(), 3);
    /// ```
    pub fn new(string: String) -> StringInput {
        StringInput { string }
    }
}

impl<'a> StrInput<'a> {
    /// Creates a new `StrInput` from a `&str`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use pest::inputs::{Input, StrInput};
    /// let input = StrInput::new("asd");
    ///
    /// assert_eq!(input.len(), 3);
    /// ```
    pub fn new(source: &'a str) -> StrInput<'a> {
        StrInput { str_ref: source }
    }
}

#[inline]
unsafe fn line_col(source: &str, pos: usize) -> (usize, usize) {
    if pos > source.len() {
        panic!("position out of bounds");
    }

    let mut pos = pos;
    let slice = &source[..pos];
    let mut chars = slice.chars().peekable();

    let mut line_col = (1, 1);

    while pos != 0 {
        match chars.next() {
            Some('\r') => {
                if let Some(&'\n') = chars.peek() {
                    chars.next();

                    if pos == 1 {
                        pos -= 1;
                    } else {
                        pos -= 2;
                    }

                    line_col = (line_col.0 + 1, 1);
                } else {
                    pos -= 1;
                    line_col = (line_col.0, line_col.1 + 1);
                }
            }
            Some('\n') => {
                pos -= 1;
                line_col = (line_col.0 + 1, 1);
            }
            Some(c) => {
                pos -= c.len_utf8();
                line_col = (line_col.0, line_col.1 + 1);
            }
            None => unreachable!(),
        }
    }

    line_col
}

#[inline]
unsafe fn line_of(source: &str, mut pos: usize) -> &str {
    if pos > source.len() {
        panic!("position out of bounds");
    }

    let start = if pos == 0 {
        0
    } else {
        if source.slice_unchecked(pos, pos + 1) == "\n" {
            pos -= 1;
        }

        let start = source
            .char_indices()
            .rev()
            .skip_while(|&(i, _)| i > pos)
            .find(|&(_, c)| c == '\n');
        match start {
            Some((i, _)) => i + 1,
            None => 0,
        }
    };

    let end = if source.len() == 0 {
        0
    } else if pos == source.len() - 1 {
        let mut end = source.len();

        if end > 0 && source.slice_unchecked(end - 1, end) == "\n" {
            end -= 1;
        }
        if end > 0 && source.slice_unchecked(end - 1, end) == "\r" {
            end -= 1;
        }

        end
    } else {
        let end = source.char_indices().skip_while(|&(i, _)| i < pos).find(
            |&(_,
               c)| {
                c == '\n'
            },
        );
        let mut end = match end {
            Some((i, _)) => i,
            None => source.len(),
        };

        if end > 0 && source.slice_unchecked(end - 1, end) == "\r" {
            end -= 1;
        }

        end
    };

    source.slice_unchecked(start, end)
}

#[inline]
unsafe fn skip(source: &str, n: usize, pos: usize) -> Option<usize> {
    let mut len = 0;
    let mut chars = source.slice_unchecked(pos, source.len()).chars();

    for _ in 0..n {
        if let Some(c) = chars.next() {
            len += c.len_utf8();
        } else {
            return None;
        }
    }

    Some(len)
}

#[inline]
unsafe fn match_string(source: &str, string: &str, pos: usize) -> bool {
    let to = pos + string.len();

    if to <= source.len() {
        let slice = source.slice_unchecked(pos, to);
        slice == string
    } else {
        false
    }
}

#[inline]
unsafe fn match_insensitive(source: &str, string: &str, pos: usize) -> bool {
    let slice = source.slice_unchecked(pos, source.len());

    if slice.is_char_boundary(string.len()) {
        let slice = slice.slice_unchecked(0, string.len());
        slice.eq_ignore_ascii_case(string)
    } else {
        false
    }
}

#[inline]
unsafe fn match_range(source: &str, range: Range<char>, pos: usize) -> Option<usize> {
    let slice = source.slice_unchecked(pos, source.len());

    if let Some(char) = slice.chars().next() {
        if range.start <= char && char <= range.end {
            Some(char.len_utf8())
        } else {
            None
        }
    } else {
        None
    }
}

impl Input for StringInput {
    #[inline]
    fn len(&self) -> usize {
        self.string.len()
    }

    #[inline]
    fn is_empty(&self) -> bool {
        self.string.is_empty()
    }

    #[inline]
    fn file_name(&self) -> Option<OsString> {
        None
    }

    #[inline]
    unsafe fn slice(&self, start: usize, end: usize) -> &str {
        self.string.slice_unchecked(start, end)
    }

    unsafe fn line_col(&self, pos: usize) -> (usize, usize) {
        line_col(&self.string, pos)
    }

    unsafe fn line_of(&self, pos: usize) -> &str {
        line_of(&self.string, pos)
    }

    #[inline]
    unsafe fn skip(&self, n: usize, pos: usize) -> Option<usize> {
        skip(&self.string, n, pos)
    }

    #[inline]
    unsafe fn match_string(&self, string: &str, pos: usize) -> bool {
        match_string(&self.string, string, pos)
    }

    #[inline]
    unsafe fn match_insensitive(&self, string: &str, pos: usize) -> bool {
        match_insensitive(&self.string, string, pos)
    }

    #[inline]
    unsafe fn match_range(&self, range: Range<char>, pos: usize) -> Option<usize> {
        match_range(&self.string, range, pos)
    }
}

impl<'a> Input for StrInput<'a> {
    #[inline]
    fn len(&self) -> usize {
        self.str_ref.len()
    }

    #[inline]
    fn is_empty(&self) -> bool {
        self.str_ref.is_empty()
    }

    #[inline]
    fn file_name(&self) -> Option<OsString> {
        None
    }

    #[inline]
    unsafe fn slice(&self, start: usize, end: usize) -> &str {
        self.str_ref.slice_unchecked(start, end)
    }

    unsafe fn line_col(&self, pos: usize) -> (usize, usize) {
        line_col(self.str_ref, pos)
    }

    unsafe fn line_of(&self, pos: usize) -> &str {
        line_of(self.str_ref, pos)
    }

    #[inline]
    unsafe fn skip(&self, n: usize, pos: usize) -> Option<usize> {
        skip(self.str_ref, n, pos)
    }

    #[inline]
    unsafe fn match_string(&self, string: &str, pos: usize) -> bool {
        match_string(self.str_ref, string, pos)
    }

    #[inline]
    unsafe fn match_insensitive(&self, string: &str, pos: usize) -> bool {
        match_insensitive(self.str_ref, string, pos)
    }

    #[inline]
    unsafe fn match_range(&self, range: Range<char>, pos: usize) -> Option<usize> {
        match_range(self.str_ref, range, pos)
    }
}

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

    #[test]
    fn empty() {
        let input = StringInput::new("".to_owned());

        unsafe {
            assert!(input.is_empty());
            assert!(input.match_string("", 0));
            assert!(!input.match_string("a", 0));
        }

        let input2 = StrInput::new("");

        unsafe {
            assert!(input2.is_empty());
            assert!(input2.match_string("", 0));
            assert!(!input2.match_string("a", 0));
        }
    }

    #[test]
    fn parts() {
        let input = StringInput::new("asdasdf".to_owned());

        unsafe {
            assert!(!input.is_empty());
            assert!(input.match_string("asd", 0));
            assert!(input.match_string("asdf", 3));
        }

        let input2 = StrInput::new("asdasdf");

        unsafe {
            assert!(!input2.is_empty());
            assert!(input2.match_string("asd", 0));
            assert!(input2.match_string("asdf", 3));
        }
    }

    #[test]
    fn len() {
        assert_eq!(StringInput::new("asdasdf".to_owned()).len(), 7);
        assert_eq!(StrInput::new("asdasdf").len(), 7);
    }

    #[test]
    fn slice() {
        let input = StringInput::new("asdasdf".to_owned());

        unsafe {
            assert_eq!(input.slice(1, 3), "sd");
        }

        let input2 = StrInput::new("asdasdf");

        unsafe {
            assert_eq!(input2.slice(1, 3), "sd");
        }
    }

    #[test]
    fn line_col() {
        let input = StringInput::new("a\rb\nc\r\nd嗨".to_owned());

        unsafe {
            assert_eq!(input.line_col(0), (1, 1));
            assert_eq!(input.line_col(1), (1, 2));
            assert_eq!(input.line_col(2), (1, 3));
            assert_eq!(input.line_col(3), (1, 4));
            assert_eq!(input.line_col(4), (2, 1));
            assert_eq!(input.line_col(5), (2, 2));
            assert_eq!(input.line_col(6), (2, 3));
            assert_eq!(input.line_col(7), (3, 1));
            assert_eq!(input.line_col(8), (3, 2));
            assert_eq!(input.line_col(11), (3, 3));
        }

        let input2 = StrInput::new("a\rb\nc\r\nd嗨");

        unsafe {
            assert_eq!(input2.line_col(0), (1, 1));
            assert_eq!(input2.line_col(1), (1, 2));
            assert_eq!(input2.line_col(2), (1, 3));
            assert_eq!(input2.line_col(3), (1, 4));
            assert_eq!(input2.line_col(4), (2, 1));
            assert_eq!(input2.line_col(5), (2, 2));
            assert_eq!(input2.line_col(6), (2, 3));
            assert_eq!(input2.line_col(7), (3, 1));
            assert_eq!(input2.line_col(8), (3, 2));
            assert_eq!(input2.line_col(11), (3, 3));
        }
    }

    #[test]
    fn line_of() {
        let input = StringInput::new("a\rb\nc\r\nd嗨".to_owned());

        unsafe {
            assert_eq!(input.line_of(0), "a\rb");
            assert_eq!(input.line_of(1), "a\rb");
            assert_eq!(input.line_of(2), "a\rb");
            assert_eq!(input.line_of(3), "a\rb");
            assert_eq!(input.line_of(4), "c");
            assert_eq!(input.line_of(5), "c");
            assert_eq!(input.line_of(6), "c");
            assert_eq!(input.line_of(7), "d嗨");
            assert_eq!(input.line_of(8), "d嗨");
            assert_eq!(input.line_of(11), "d嗨");
        }

        let input2 = StrInput::new("a\rb\nc\r\nd嗨");

        unsafe {
            assert_eq!(input2.line_of(0), "a\rb");
            assert_eq!(input2.line_of(1), "a\rb");
            assert_eq!(input2.line_of(2), "a\rb");
            assert_eq!(input2.line_of(3), "a\rb");
            assert_eq!(input2.line_of(4), "c");
            assert_eq!(input2.line_of(5), "c");
            assert_eq!(input2.line_of(6), "c");
            assert_eq!(input2.line_of(7), "d嗨");
            assert_eq!(input2.line_of(8), "d嗨");
            assert_eq!(input2.line_of(11), "d嗨");
        }
    }

    #[test]
    fn line_of_empty() {
        let input = StringInput::new("".to_owned());

        unsafe {
            assert_eq!(input.line_of(0), "");
        }

        let input2 = StrInput::new("");

        unsafe {
            assert_eq!(input2.line_of(0), "");
        }
    }

    #[test]
    fn line_of_new_line() {
        let input = StringInput::new("\n".to_owned());

        unsafe {
            assert_eq!(input.line_of(0), "");
        }

        let input2 = StrInput::new("\n");

        unsafe {
            assert_eq!(input2.line_of(0), "");
        }
    }

    #[test]
    fn skip_empty() {
        let input = StringInput::new("".to_owned());

        unsafe {
            assert_eq!(input.skip(0, 0), Some(0));
            assert_eq!(input.skip(1, 0), None);
        }

        let input2 = StrInput::new("");

        unsafe {
            assert_eq!(input2.skip(0, 0), Some(0));
            assert_eq!(input2.skip(1, 0), None);
        }
    }

    #[test]
    fn skip() {
        let input = StringInput::new("d嗨".to_owned());

        unsafe {
            assert_eq!(input.skip(0, 0), Some(0));
            assert_eq!(input.skip(1, 0), Some(1));
            assert_eq!(input.skip(1, 1), Some(3));
        }

        let input2 = StrInput::new("d嗨");

        unsafe {
            assert_eq!(input2.skip(0, 0), Some(0));
            assert_eq!(input2.skip(1, 0), Some(1));
            assert_eq!(input2.skip(1, 1), Some(3));
        }
    }

    #[test]
    fn match_range() {
        let input = StringInput::new("b".to_owned());

        unsafe {
            assert!(input.match_range('a'..'c', 0).is_some());
            assert!(input.match_range('b'..'b', 0).is_some());
            assert!(input.match_range('a'..'a', 0).is_none());
            assert!(input.match_range('c'..'c', 0).is_none());
            assert!(input.match_range('a'..'嗨', 0).is_some());
        }

        let input2 = StrInput::new("b");

        unsafe {
            assert!(input2.match_range('a'..'c', 0).is_some());
            assert!(input2.match_range('b'..'b', 0).is_some());
            assert!(input2.match_range('a'..'a', 0).is_none());
            assert!(input2.match_range('c'..'c', 0).is_none());
            assert!(input2.match_range('a'..'嗨', 0).is_some());
        }
    }

    #[test]
    fn match_insensitive() {
        let input = StringInput::new("AsdASdF".to_owned());

        unsafe {
            assert!(input.match_insensitive("asd", 0));
            assert!(input.match_insensitive("asdf", 3));
        }

        let input2 = StrInput::new("AsdASdF");

        unsafe {
            assert!(input2.match_insensitive("asd", 0));
            assert!(input2.match_insensitive("asdf", 3));
        }
    }
}
<|endoftext|>


<commit_before>use resources::*;
use resources::common::*;
use caches::common::*;

use rustc_serialize::base64::{self, ToBase64};

use std::io::Read;

use ::hyper::Client;
use ::hyper::net::HttpsConnector;
use ::hyper_native_tls::NativeTlsClient;
use ::hyper::header::{Headers, UserAgent};

use std::thread;
use std::sync::mpsc::channel;
use cancellation::{CancellationToken, CancellationTokenSource, OperationCanceled};

use std::sync::mpsc::{Receiver, Sender};

use std::sync::{Arc};
use std::sync::atomic::{AtomicBool, Ordering};

use caches::file_cache::*;

use crossbeam::*;

pub struct ImageResource<'a, T: 'a + Cache + Send> {
    cache: &'a mut Box<T>,
    client: Client
}

impl<'a, T: 'a + Cache + Send> ImageResource<'a, T> {
    pub fn new(cache: &'a mut Box<T>) -> Self {
        let ssl = NativeTlsClient::new().unwrap();
        let connector = HttpsConnector::new(ssl);
        ImageResource {
            cache: cache,
            client: Client::with_connector(connector)
        }
    }
}

impl<'a, T: 'a + Cache + Send> Resource for ImageResource<'a, T> {
    fn fetch(&mut self, item: &ChannelItem) -> ChannelItem {
        match item.extra.clone() {
            Some(o) => {
                match o {
                    ChannelItemType::Image(extra) => {
                        let url = extra.url;
                        let url2 = url.clone();
                        let img_path = "data/cache/img/";
                        let img_file_name = url.into_bytes().as_slice().to_base64(base64::URL_SAFE);

                        info!("image resource - before find in cache. url: {}", url2.clone());
                        let (from_cache, result, reason) = match self.cache.read(&img_path, &img_file_name) {
                            Ok(result) => {
                                info!("image resource - find in cache success. url:  {}", url2.clone());
                                (true, result, "".to_string())
                            }
                            Err(_) => {
                                info!("image resource - find in cache fail. url:  {}", url2.clone());

                                let ct = CancellationTokenSource::new();
                                ct.cancel_after(::std::time::Duration::new(2, 0));

                                let (tx_req, rx_req) = channel::<Option<(bool, Vec<u8>, String)>>();

                                let url3 = url2.clone();
                                let ssl = NativeTlsClient::new().unwrap();
                                let connector = HttpsConnector::new(ssl);
                                let mut headers = Headers::new();
                                headers.set(UserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36".to_owned()));

                                ::crossbeam::scope(|scope| {
                                    scope.spawn(move ||{
                                        let th = thread::current();
                                        ct.run(|| { th.unpark(); }, || {

                                            let client = Client::with_connector(connector);
                                            match client.get(&url3).headers(headers).send() {
                                                Ok(mut resp) => {
                                                        info!("image resource - http request success url:  {}", url3.clone());
                                                        let mut buffer = Vec::new();
                                                        resp.read_to_end(&mut buffer).expect("fail to read buffer from the http response");
                                                        self.cache.write(&img_path, &img_file_name, buffer.clone()).expect("fail to write cache");
                                                        tx_req.send(Some( (false, buffer, "".to_string()) ) );
                                                    }
                                                Err(e) => {
                                                    info!("image resource - http request fail url:  {}", url3.clone());
                                                    tx_req.send( Some( (false, Vec::new(), e.to_string()) ) );
                                                }
                                            }
                                        });

                                        if ct.is_canceled() {
                                            warn!("image request {} is canceled!", url3.clone());
                                            thread::park_timeout(::std::time::Duration::from_secs(0));
                                            tx_req.send(None);
                                            Err(OperationCanceled)
                                        } else {
                                            Ok(())
                                        }
                                    });
                                });

                                match rx_req.recv() {
                                    Ok(o) => {
                                        match o {
                                            Some((from_cache, result, reason)) => (from_cache, result, reason),
                                            None => (false, Vec::new(), "".to_string())
                                        }
                                    }
                                    Err(e) => { (false, Vec::new(), e.to_string()) }
                                }
                            }
                        };

                        let url4 = url2.clone();
                        info!("image url: {} reason: {}", url4, reason);
                        let result_item = ChannelItem {
                            extra: Some(ChannelItemType::Image(ChannelImageItem { url: url2, bytes: result })),
                            result: reason,
                        };
                        result_item
                    },
                    _ => {
                        ChannelItem {
                            extra: Some(ChannelItemType::Image(Default::default())),
                            result: Default::default(),
                        }
                    }
                }
            }
            None => {
                ChannelItem {
                    extra: Some(ChannelItemType::Image(Default::default())),
                    result: Default::default(),
                }
            }
        }
    }
}
<commit_msg>timeout without cancelation token source<commit_after>use resources::*;
use resources::common::*;
use caches::common::*;

use rustc_serialize::base64::{self, ToBase64};

use std::io::Read;

use ::hyper::Client;
use ::hyper::net::HttpsConnector;
use ::hyper_native_tls::NativeTlsClient;
use ::hyper::header::{Headers, UserAgent};

use std::thread;
use std::sync::mpsc::channel;
use cancellation::{CancellationToken, CancellationTokenSource, OperationCanceled};

use std::sync::mpsc::{Receiver, Sender};

use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicBool, Ordering};

use caches::file_cache::*;

use crossbeam::*;

use std::thread::park_timeout;
use std::time::{Instant, Duration};

pub struct ImageResource<'a, T: 'a + Cache + Send> {
    cache: &'a mut Box<T>,
    client: Client
}

impl<'a, T: 'a + Cache + Send> ImageResource<'a, T> {
    pub fn new(cache: &'a mut Box<T>) -> Self {
        let ssl = NativeTlsClient::new().unwrap();
        let connector = HttpsConnector::new(ssl);
        ImageResource {
            cache: cache,
            client: Client::with_connector(connector)
        }
    }
}

impl<'a, T: 'a + Cache + Send> Resource for ImageResource<'a, T> {
    fn fetch(&mut self, item: &ChannelItem) -> ChannelItem {
        match item.extra.clone() {
            Some(o) => {
                match o {
                    ChannelItemType::Image(extra) => {
                        let url = extra.url;
                        let url2 = url.clone();
                        let img_path = "data/cache/img/";
                        let img_file_name = url.into_bytes().as_slice().to_base64(base64::URL_SAFE);

                        info!("image resource - before find in cache. url: {}", url2.clone());
                        let (from_cache, result, reason) = match self.cache.read(&img_path, &img_file_name) {
                            Ok(result) => {
                                info!("image resource - find in cache success. url:  {}", url2.clone());
                                (true, result, "".to_string())
                            }
                            Err(_) => {
                                info!("image resource - find in cache fail. url:  {}", url2.clone());

                                let (tx_req, rx_req) = channel::<Option<(bool, Vec<u8>, String)>>();
                                let tx_req2 = tx_req.clone();

                                let url3 = url2.clone();
                                let url4 = url2.clone();
                                let ssl = NativeTlsClient::new().unwrap();
                                let connector = HttpsConnector::new(ssl);
                                let mut headers = Headers::new();
                                headers.set(UserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36".to_owned()));

                                let beginning_park = Instant::now();
                                let timeout = Duration::from_secs(2);

                                let mut is_done = Arc::new(AtomicBool::new(false));
                                let mut is_done2 = is_done.clone();
                                ::crossbeam::scope(|scope| {
                                    scope.spawn(move ||{
                                        let th = thread::current();

                                        let client = Client::with_connector(connector);
                                        match client.get(&url3).headers(headers).send() {
                                            Ok(mut resp) => {
                                                    is_done.store(true, Ordering::Relaxed);
                                                    info!("image resource - http request success url:  {}", url3.clone());
                                                    let mut buffer = Vec::new();
                                                    resp.read_to_end(&mut buffer).expect("fail to read buffer from the http response");
                                                    self.cache.write(&img_path, &img_file_name, buffer.clone()).expect("fail to write cache");
                                                    tx_req.send(Some( (false, buffer, "".to_string()) ) );
                                                }
                                            Err(e) => {
                                                is_done.store(true, Ordering::Relaxed);
                                                info!("image resource - http request fail url:  {}", url3.clone());
                                                tx_req.send( Some( (false, Vec::new(), e.to_string()) ) );
                                            }
                                        }
                                    });
                                    scope.spawn(move || {
                                        while beginning_park.elapsed() < timeout {
                                            let timeout = timeout - beginning_park.elapsed();
                                            park_timeout(timeout);
                                        }
                                        match Arc::try_unwrap(is_done2) {
                                            Ok(o) => {
                                                let is_done_flag = o.load(Ordering::Relaxed);
                                                warn!("is done flag: {} url: {}", is_done_flag, url4.clone());
                                                if !is_done_flag {
                                                    warn!("image request {} is canceled!", url4.clone());
                                                    thread::park_timeout(::std::time::Duration::from_secs(0));
                                                    tx_req2.send(None);
                                                }
                                            }
                                            Err(e) => {
                                                error!("fail to read is done flag, url: {}, reason: {:?}", url4.clone(), e);
                                                tx_req2.send(None);
                                            }
                                        }

                                    })
                                });

                                match rx_req.recv() {
                                    Ok(o) => {
                                        match o {
                                            Some((from_cache, result, reason)) => (from_cache, result, reason),
                                            None => (false, Vec::new(), "".to_string())
                                        }
                                    }
                                    Err(e) => { (false, Vec::new(), e.to_string()) }
                                }
                            }
                        };

                        let url5 = url2.clone();
                        info!("image url: {} reason: {}", url5, reason);
                        let result_item = ChannelItem {
                            extra: Some(ChannelItemType::Image(ChannelImageItem { url: url2, bytes: result })),
                            result: reason,
                        };
                        result_item
                    },
                    _ => {
                        ChannelItem {
                            extra: Some(ChannelItemType::Image(Default::default())),
                            result: Default::default(),
                        }
                    }
                }
            }
            None => {
                ChannelItem {
                    extra: Some(ChannelItemType::Image(Default::default())),
                    result: Default::default(),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use super::artifact_content::ArtifactContent;
use super::Artifact;
use crate::{
    config::{Config, PersistConfig},
    errors::BuildProjectError,
};
use lazy_static::lazy_static;
use log::info;
use md5::{Digest, Md5};
use persist_query::persist;
use regex::Regex;
use std::{
    fs,
    path::PathBuf,
    sync::{Arc, Mutex},
};

lazy_static! {
    static ref RELAY_HASH_REGEX: Regex = Regex::new(r#"@relayHash (\w{32})\n"#).unwrap();
    static ref REQUEST_ID_REGEX: Regex = Regex::new(r#"@relayRequestID (\w+)\n"#).unwrap();
}

pub async fn persist_operations(
    config: &Config,
    artifacts: &mut [Artifact],
    persist_config: &PersistConfig,
) -> Result<(), BuildProjectError> {
    let mut handles = Vec::new();
    let persist_errors: Arc<Mutex<Vec<_>>> = Default::default();
    for artifact in artifacts {
        if let ArtifactContent::Operation {
            text,
            id_and_text_hash,
            ..
        } = &mut artifact.content
        {
            let text_hash = md5(text);
            let extracted_id =
                extract_persist_id(&config.root_dir.join(&artifact.path), &text_hash);
            if let Some(id) = extracted_id {
                *id_and_text_hash = Some((id, text_hash));
            } else {
                let text = text.clone();
                let url = persist_config.url.clone();
                let params = persist_config.params.clone();
                // let errors = Arc::clone(&persist_errors);
                handles.push(async move {
                    let request = persist(&text, &url, &params);
                    match request.await {
                        Ok(id) => {
                            *id_and_text_hash = Some((id, text_hash));
                        }
                        Err(_err) => {
                            // TODO(T66947325) re-enable errors instead of setting
                            // "ERROR" as id.
                            *id_and_text_hash = Some(("ERROR".into(), text_hash));
                            // errors.lock().unwrap().push(err);
                        }
                    };
                });
            }
        }
    }
    info!("persisting {} documents", handles.len());
    futures::future::join_all(handles).await;
    info!("done persisting");
    let errors = Arc::try_unwrap(persist_errors)
        .unwrap()
        .into_inner()
        .unwrap();
    if errors.is_empty() {
        Ok(())
    } else {
        Err(BuildProjectError::PersistErrors { errors })
    }
}

fn extract_persist_id(path: &PathBuf, text_hash: &str) -> Option<String> {
    let content = fs::read_to_string(path).ok()?;

    // Looks like a merge conflict, let's not trust this file.
    if content.contains("<<<<") || content.contains(">>>>") {
        return None;
    }

    // If the existing hash doesn't match the hash of the new query test, abort.
    if let Some(existing_hash) = extract_relay_hash(&content) {
        if existing_hash != text_hash {
            return None;
        }
    }

    extract_request_id(&content)
}

fn extract_relay_hash(content: &str) -> Option<&str> {
    RELAY_HASH_REGEX
        .captures(content)
        .and_then(|captures| captures.get(1).map(|m| m.as_str()))
}

fn extract_request_id(content: &str) -> Option<String> {
    REQUEST_ID_REGEX
        .captures(content)
        .map(|captures| captures[1].to_owned())
}

fn md5(data: &str) -> String {
    let mut md5 = Md5::new();
    md5.input(data);
    hex::encode(md5.result())
}
<commit_msg>fail on failed query persisting<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use super::artifact_content::ArtifactContent;
use super::Artifact;
use crate::{
    config::{Config, PersistConfig},
    errors::BuildProjectError,
};
use lazy_static::lazy_static;
use log::info;
use md5::{Digest, Md5};
use persist_query::persist;
use regex::Regex;
use std::{
    fs,
    path::PathBuf,
    sync::{Arc, Mutex},
};

lazy_static! {
    static ref RELAY_HASH_REGEX: Regex = Regex::new(r#"@relayHash (\w{32})\n"#).unwrap();
    static ref REQUEST_ID_REGEX: Regex = Regex::new(r#"@relayRequestID (\w+)\n"#).unwrap();
}

pub async fn persist_operations(
    config: &Config,
    artifacts: &mut [Artifact],
    persist_config: &PersistConfig,
) -> Result<(), BuildProjectError> {
    let mut handles = Vec::new();
    let persist_errors: Arc<Mutex<Vec<_>>> = Default::default();
    for artifact in artifacts {
        if let ArtifactContent::Operation {
            text,
            id_and_text_hash,
            ..
        } = &mut artifact.content
        {
            let text_hash = md5(text);
            let extracted_id =
                extract_persist_id(&config.root_dir.join(&artifact.path), &text_hash);
            if let Some(id) = extracted_id {
                *id_and_text_hash = Some((id, text_hash));
            } else {
                let text = text.clone();
                let url = persist_config.url.clone();
                let params = persist_config.params.clone();
                let errors = Arc::clone(&persist_errors);
                handles.push(async move {
                    let request = persist(&text, &url, &params);
                    match request.await {
                        Ok(id) => {
                            *id_and_text_hash = Some((id, text_hash));
                        }
                        Err(err) => {
                            errors.lock().unwrap().push(err);
                        }
                    };
                });
            }
        }
    }
    info!("persisting {} documents", handles.len());
    futures::future::join_all(handles).await;
    info!("done persisting");
    let errors = Arc::try_unwrap(persist_errors)
        .unwrap()
        .into_inner()
        .unwrap();
    if errors.is_empty() {
        Ok(())
    } else {
        Err(BuildProjectError::PersistErrors { errors })
    }
}

fn extract_persist_id(path: &PathBuf, text_hash: &str) -> Option<String> {
    let content = fs::read_to_string(path).ok()?;

    // Looks like a merge conflict, let's not trust this file.
    if content.contains("<<<<") || content.contains(">>>>") {
        return None;
    }

    // If the existing hash doesn't match the hash of the new query test, abort.
    if let Some(existing_hash) = extract_relay_hash(&content) {
        if existing_hash != text_hash {
            return None;
        }
    }

    extract_request_id(&content)
}

fn extract_relay_hash(content: &str) -> Option<&str> {
    RELAY_HASH_REGEX
        .captures(content)
        .and_then(|captures| captures.get(1).map(|m| m.as_str()))
}

fn extract_request_id(content: &str) -> Option<String> {
    REQUEST_ID_REGEX
        .captures(content)
        .map(|captures| captures[1].to_owned())
}

fn md5(data: &str) -> String {
    let mut md5 = Md5::new();
    md5.input(data);
    hex::encode(md5.result())
}
<|endoftext|>


<commit_before>//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[cfg_attr(stage0, doc(include = "os/raw/char.md"))]
#[cfg_attr(not(stage0), doc(include = "char.md"))]
#[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                       target_arch = "arm",
                                       target_arch = "powerpc",
                                       target_arch = "powerpc64",
                                       target_arch = "s390x")),
          all(target_os = "android", any(target_arch = "aarch64",
                                         target_arch = "arm")),
          all(target_os = "l4re", target_arch = "x86_64"),
          all(target_os = "freebsd", any(target_arch = "aarch64",
                                         target_arch = "arm",
                                         target_arch = "powerpc",
                                         target_arch = "powerpc64")),
          all(target_os = "netbsd", any(target_arch = "aarch64",
                                        target_arch = "arm",
                                        target_arch = "powerpc")),
          all(target_os = "openbsd", target_arch = "aarch64"),
          all(target_os = "vxworks", any(target_arch = "aarch64",
                                         target_arch = "arm",
                                         target_arch = "powerpc64",
                                         target_arch = "powerpc")),
          all(target_os = "fuchsia", target_arch = "aarch64")))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
#[cfg_attr(stage0, doc(include = "os/raw/char.md"))]
#[cfg_attr(not(stage0), doc(include = "char.md"))]
#[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
                                           target_arch = "arm",
                                           target_arch = "powerpc",
                                           target_arch = "powerpc64",
                                           target_arch = "s390x")),
              all(target_os = "android", any(target_arch = "aarch64",
                                             target_arch = "arm")),
              all(target_os = "l4re", target_arch = "x86_64"),
              all(target_os = "freebsd", any(target_arch = "aarch64",
                                             target_arch = "arm",
                                             target_arch = "powerpc",
                                             target_arch = "powerpc64")),
              all(target_os = "netbsd", any(target_arch = "aarch64",
                                            target_arch = "arm",
                                            target_arch = "powerpc")),
              all(target_os = "openbsd", target_arch = "aarch64"),
              all(target_os = "vxworks", any(target_arch = "aarch64",
                                             target_arch = "arm",
                                             target_arch = "powerpc64",
                                             target_arch = "powerpc")),
              all(target_os = "fuchsia", target_arch = "aarch64"))))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
#[cfg_attr(stage0, doc(include = "os/raw/schar.md"))]
#[cfg_attr(not(stage0), doc(include = "schar.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
#[cfg_attr(stage0, doc(include = "os/raw/uchar.md"))]
#[cfg_attr(not(stage0), doc(include = "uchar.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
#[cfg_attr(stage0, doc(include = "os/raw/short.md"))]
#[cfg_attr(not(stage0), doc(include = "short.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16;
#[cfg_attr(stage0, doc(include = "os/raw/ushort.md"))]
#[cfg_attr(not(stage0), doc(include = "ushort.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16;
#[cfg_attr(stage0, doc(include = "os/raw/int.md"))]
#[cfg_attr(not(stage0), doc(include = "int.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32;
#[cfg_attr(stage0, doc(include = "os/raw/uint.md"))]
#[cfg_attr(not(stage0), doc(include = "uint.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32;
#[cfg_attr(stage0, doc(include = "os/raw/long.md"))]
#[cfg_attr(not(stage0), doc(include = "long.md"))]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
#[cfg_attr(stage0, doc(include = "os/raw/ulong.md"))]
#[cfg_attr(not(stage0), doc(include = "ulong.md"))]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32;
#[cfg_attr(stage0, doc(include = "os/raw/long.md"))]
#[cfg_attr(not(stage0), doc(include = "long.md"))]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
#[cfg_attr(stage0, doc(include = "os/raw/ulong.md"))]
#[cfg_attr(not(stage0), doc(include = "ulong.md"))]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64;
#[cfg_attr(stage0, doc(include = "os/raw/longlong.md"))]
#[cfg_attr(not(stage0), doc(include = "longlong.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64;
#[cfg_attr(stage0, doc(include = "os/raw/ulonglong.md"))]
#[cfg_attr(not(stage0), doc(include = "ulonglong.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64;
#[cfg_attr(stage0, doc(include = "os/raw/float.md"))]
#[cfg_attr(not(stage0), doc(include = "float.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32;
#[cfg_attr(stage0, doc(include = "os/raw/double.md"))]
#[cfg_attr(not(stage0), doc(include = "double.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;

#[cfg(test)]
#[allow(unused_imports)]
mod tests {
    use crate::any::TypeId;
    use crate::mem;

    macro_rules! ok {
        ($($t:ident)*) => {$(
            assert!(TypeId::of::<libc::$t>() == TypeId::of::<raw::$t>(),
                    "{} is wrong", stringify!($t));
        )*}
    }

    #[test]
    fn same() {
        use crate::os::raw;
        ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong
            c_longlong c_ulonglong c_float c_double);
    }
}
<commit_msg>stage0 -> bootstrap<commit_after>//! Platform-specific types, as defined by C.
//!
//! Code that interacts via FFI will almost certainly be using the
//! base types provided by C, which aren't nearly as nicely defined
//! as Rust's primitive types. This module provides types which will
//! match those defined by C, so that code that interacts with C will
//! refer to the correct types.

#![stable(feature = "raw_os", since = "1.1.0")]

#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
#[cfg(any(all(target_os = "linux", any(target_arch = "aarch64",
                                       target_arch = "arm",
                                       target_arch = "powerpc",
                                       target_arch = "powerpc64",
                                       target_arch = "s390x")),
          all(target_os = "android", any(target_arch = "aarch64",
                                         target_arch = "arm")),
          all(target_os = "l4re", target_arch = "x86_64"),
          all(target_os = "freebsd", any(target_arch = "aarch64",
                                         target_arch = "arm",
                                         target_arch = "powerpc",
                                         target_arch = "powerpc64")),
          all(target_os = "netbsd", any(target_arch = "aarch64",
                                        target_arch = "arm",
                                        target_arch = "powerpc")),
          all(target_os = "openbsd", target_arch = "aarch64"),
          all(target_os = "vxworks", any(target_arch = "aarch64",
                                         target_arch = "arm",
                                         target_arch = "powerpc64",
                                         target_arch = "powerpc")),
          all(target_os = "fuchsia", target_arch = "aarch64")))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
#[cfg_attr(bootstrap, doc(include = "os/raw/char.md"))]
#[cfg_attr(not(bootstrap), doc(include = "char.md"))]
#[cfg(not(any(all(target_os = "linux", any(target_arch = "aarch64",
                                           target_arch = "arm",
                                           target_arch = "powerpc",
                                           target_arch = "powerpc64",
                                           target_arch = "s390x")),
              all(target_os = "android", any(target_arch = "aarch64",
                                             target_arch = "arm")),
              all(target_os = "l4re", target_arch = "x86_64"),
              all(target_os = "freebsd", any(target_arch = "aarch64",
                                             target_arch = "arm",
                                             target_arch = "powerpc",
                                             target_arch = "powerpc64")),
              all(target_os = "netbsd", any(target_arch = "aarch64",
                                            target_arch = "arm",
                                            target_arch = "powerpc")),
              all(target_os = "openbsd", target_arch = "aarch64"),
              all(target_os = "vxworks", any(target_arch = "aarch64",
                                             target_arch = "arm",
                                             target_arch = "powerpc64",
                                             target_arch = "powerpc")),
              all(target_os = "fuchsia", target_arch = "aarch64"))))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
#[cfg_attr(bootstrap, doc(include = "os/raw/schar.md"))]
#[cfg_attr(not(bootstrap), doc(include = "schar.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
#[cfg_attr(bootstrap, doc(include = "os/raw/uchar.md"))]
#[cfg_attr(not(bootstrap), doc(include = "uchar.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
#[cfg_attr(bootstrap, doc(include = "os/raw/short.md"))]
#[cfg_attr(not(bootstrap), doc(include = "short.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_short = i16;
#[cfg_attr(bootstrap, doc(include = "os/raw/ushort.md"))]
#[cfg_attr(not(bootstrap), doc(include = "ushort.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ushort = u16;
#[cfg_attr(bootstrap, doc(include = "os/raw/int.md"))]
#[cfg_attr(not(bootstrap), doc(include = "int.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_int = i32;
#[cfg_attr(bootstrap, doc(include = "os/raw/uint.md"))]
#[cfg_attr(not(bootstrap), doc(include = "uint.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_uint = u32;
#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i32;
#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
#[cfg(any(target_pointer_width = "32", windows))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u32;
#[cfg_attr(bootstrap, doc(include = "os/raw/long.md"))]
#[cfg_attr(not(bootstrap), doc(include = "long.md"))]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_long = i64;
#[cfg_attr(bootstrap, doc(include = "os/raw/ulong.md"))]
#[cfg_attr(not(bootstrap), doc(include = "ulong.md"))]
#[cfg(all(target_pointer_width = "64", not(windows)))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulong = u64;
#[cfg_attr(bootstrap, doc(include = "os/raw/longlong.md"))]
#[cfg_attr(not(bootstrap), doc(include = "longlong.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_longlong = i64;
#[cfg_attr(bootstrap, doc(include = "os/raw/ulonglong.md"))]
#[cfg_attr(not(bootstrap), doc(include = "ulonglong.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_ulonglong = u64;
#[cfg_attr(bootstrap, doc(include = "os/raw/float.md"))]
#[cfg_attr(not(bootstrap), doc(include = "float.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_float = f32;
#[cfg_attr(bootstrap, doc(include = "os/raw/double.md"))]
#[cfg_attr(not(bootstrap), doc(include = "double.md"))]
#[stable(feature = "raw_os", since = "1.1.0")] pub type c_double = f64;

#[stable(feature = "raw_os", since = "1.1.0")]
#[doc(no_inline)]
pub use core::ffi::c_void;

#[cfg(test)]
#[allow(unused_imports)]
mod tests {
    use crate::any::TypeId;
    use crate::mem;

    macro_rules! ok {
        ($($t:ident)*) => {$(
            assert!(TypeId::of::<libc::$t>() == TypeId::of::<raw::$t>(),
                    "{} is wrong", stringify!($t));
        )*}
    }

    #[test]
    fn same() {
        use crate::os::raw;
        ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong
            c_longlong c_ulonglong c_float c_double);
    }
}
<|endoftext|>