<commit_before>#[lib]

extern crate libc;

/*
SchedulerDriverStatus scheduler_launchTasks() [int]
	SchedulerDriverPtr driver [void *]
	ProtobufObj * offerId [ProtobufObj *]
	ProtobufObj * tasks [ProtobufObj *]
	ProtobufObj * filters [ProtobufObj *]
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_launchTasks(driver: *mut libc::c_void, offerId: *mut ProtobufObj, tasks: *mut ProtobufObj, filters: *mut ProtobufObj) -> libc::c_int;
}

/*
SchedulerDriverStatus scheduler_start() [int]
	SchedulerDriverPtr driver [void *]
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_start(driver: *mut libc::c_void) -> libc::c_int;
}

/*
SchedulerDriverStatus scheduler_stop() [int]
	SchedulerDriverPtr driver [void *]
	int failover
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_stop(driver: *mut libc::c_void, failover: libc::c_int) -> libc::c_int;
}

/*
SchedulerDriverStatus scheduler_abort() [int]
	SchedulerDriverPtr driver [void *]
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_abort(driver: *mut libc::c_void) -> libc::c_int;
}

/*
SchedulerDriverStatus scheduler_join() [int]
	SchedulerDriverPtr driver [void *]
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_join(driver: *mut libc::c_void) -> libc::c_int;
}

/*
SchedulerDriverStatus scheduler_run() [int]
	SchedulerDriverPtr driver [void *]
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_run(driver: *mut libc::c_void) -> libc::c_int;
}

/*
SchedulerDriverStatus scheduler_requestResources() [int]
	SchedulerDriverPtr driver [void *]
	ProtobufObj * requestsData [ProtobufObj *]
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_requestResources(driver: *mut libc::c_void, requestsData: *mut ProtobufObj) -> libc::c_int;
}

/*
SchedulerDriverStatus scheduler_declineOffer() [int]
	SchedulerDriverPtr driver [void *]
	ProtobufObj * offerId [ProtobufObj *]
	ProtobufObj * filters [ProtobufObj *]
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_declineOffer(driver: *mut libc::c_void, offerId: *mut ProtobufObj, filters: *mut ProtobufObj) -> libc::c_int;
}

/*
SchedulerDriverStatus scheduler_killTask() [int]
	SchedulerDriverPtr driver [void *]
	ProtobufObj * taskId [ProtobufObj *]
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_killTask(driver: *mut libc::c_void, taskId: *mut ProtobufObj) -> libc::c_int;
}

/*
SchedulerDriverStatus scheduler_reviveOffers() [int]
	SchedulerDriverPtr driver [void *]
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_reviveOffers(driver: *mut libc::c_void) -> libc::c_int;
}

/*
SchedulerDriverStatus scheduler_sendFrameworkMessage() [int]
	SchedulerDriverPtr driver [void *]
	ProtobufObj * executor [ProtobufObj *]
	ProtobufObj * slaveId [ProtobufObj *]
	const char * data
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_sendFrameworkMessage(driver: *mut libc::c_void, executor: *mut ProtobufObj, slaveId: *mut ProtobufObj, data: *const libc::c_char) -> libc::c_int;
}

/*
SchedulerPtrPair scheduler_init() [SchedulerPtrPair]
	SchedulerCallbacks * callbacks [SchedulerCallbacks *]
	void * payload
	ProtobufObj * framework [ProtobufObj *]
	const char * master
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_init(callbacks: *mut SchedulerCallbacks, payload: *mut libc::c_void, framework: *mut ProtobufObj, master: *const libc::c_char) -> SchedulerPtrPair;
}

/*
void scheduler_destroy()
	void * driver
	void * scheduler
*/
#[link(name="libmesos")]
extern "C" {
	fn scheduler_destroy(driver: *mut libc::c_void, scheduler: *mut libc::c_void);
}

/*
ExecutorDriverStatus executor_start() [int]
	ExecutorDriverPtr driver [void *]
*/
#[link(name="libmesos")]
extern "C" {
	fn executor_start(driver: *mut libc::c_void) -> libc::c_int;
}

/*
ExecutorDriverStatus executor_stop() [int]
	ExecutorDriverPtr driver [void *]
*/
#[link(name="libmesos")]
extern "C" {
	fn executor_stop(driver: *mut libc::c_void) -> libc::c_int;
}

/*
ExecutorDriverStatus executor_abort() [int]
	ExecutorDriverPtr driver [void *]
*/
#[link(name="libmesos")]
extern "C" {
	fn executor_abort(driver: *mut libc::c_void) -> libc::c_int;
}

/*
ExecutorDriverStatus executor_join() [int]
	ExecutorDriverPtr driver [void *]
*/
#[link(name="libmesos")]
extern "C" {
	fn executor_join(driver: *mut libc::c_void) -> libc::c_int;
}

/*
ExecutorDriverStatus executor_run() [int]
	ExecutorDriverPtr driver [void *]
*/
#[link(name="libmesos")]
extern "C" {
	fn executor_run(driver: *mut libc::c_void) -> libc::c_int;
}

/*
ExecutorDriverStatus executor_sendStatusUpdate() [int]
	ExecutorDriverPtr driver [void *]
	ProtobufObj * status [ProtobufObj *]
*/
#[link(name="libmesos")]
extern "C" {
	fn executor_sendStatusUpdate(driver: *mut libc::c_void, status: *mut ProtobufObj) -> libc::c_int;
}

/*
ExecutorDriverStatus executor_sendFrameworkMessage() [int]
	ExecutorDriverPtr driver [void *]
	const char * data
*/
#[link(name="libmesos")]
extern "C" {
	fn executor_sendFrameworkMessage(driver: *mut libc::c_void, data: *const libc::c_char) -> libc::c_int;
}

/*
ExecutorPtrPair executor_init() [ExecutorPtrPair]
	ExecutorCallbacks * callbacks [ExecutorCallbacks *]
	void * payload
*/
#[link(name="libmesos")]
extern "C" {
	fn executor_init(callbacks: *mut ExecutorCallbacks, payload: *mut libc::c_void) -> ExecutorPtrPair;
}

/*
void executor_destroy()
	void * driver
	void * executor
*/
#[link(name="libmesos")]
extern "C" {
	fn executor_destroy(driver: *mut libc::c_void, executor: *mut libc::c_void);
}

/*
struct
		void * data
		int size
*/
#[repr(C)]
struct ProtobufObj {
	data: *mut libc::c_void,
	size: libc::c_int,
}

/*
struct
		scheduler_registeredCallBack_t registeredCallBack [void (*)(void *, ProtobufObj *, ProtobufObj *)]
		scheduler_reregisteredCallBack_t reregisteredCallBack [void (*)(void *, ProtobufObj *)]
		scheduler_resourceOffersCallBack_t resourceOffersCallBack [void (*)(void *, ProtobufObj *, int)]
		scheduler_statusUpdateCallBack_t statusUpdateCallBack [void (*)(void *, ProtobufObj *)]
		scheduler_disconnectedCallBack_t disconnectedCallBack [void (*)(void *)]
		scheduler_offerRescindedCallBack_t offerRescindedCallBack [void (*)(void *, ProtobufObj *)]
		scheduler_frameworkMessageCallBack_t frameworkMessageCallBack [void (*)(void *, ProtobufObj *, ProtobufObj *, ProtobufObj *)]
		scheduler_slaveLostCallBack_t slaveLostCallBack [void (*)(void *, ProtobufObj *)]
		scheduler_executorLostCallBack_t executorLostCallBack [void (*)(void *, ProtobufObj *, ProtobufObj *, int)]
		scheduler_errorCallBack_t errorCallBack [void (*)(void *, ProtobufObj *)]
*/
#[repr(C)]
struct SchedulerCallbacks {
	registeredCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj, *mut ProtobufObj),
	reregisteredCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
	resourceOffersCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj, libc::c_int),
	statusUpdateCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
	disconnectedCallBack: extern fn(*mut libc::c_void),
	offerRescindedCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
	frameworkMessageCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj, *mut ProtobufObj, *mut ProtobufObj),
	slaveLostCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
	executorLostCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj, *mut ProtobufObj, libc::c_int),
	errorCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
}

/*
struct
		void * scheduler
		void * driver
*/
#[repr(C)]
struct SchedulerPtrPair {
	scheduler: *mut libc::c_void,
	driver: *mut libc::c_void,
}

/*
struct
		executor_registeredCallBack_t registeredCallBack [void (*)(void *, ProtobufObj *, ProtobufObj *, ProtobufObj *)]
		executor_reregisteredCallBack_t reregisteredCallBack [void (*)(void *, ProtobufObj *)]
		executor_disconnectedCallBack_t disconnectedCallBack [void (*)(void *)]
		executor_launchTaskCallBack_t launchTaskCallBack [void (*)(void *, ProtobufObj *)]
		executor_killTaskCallBack_t killTaskCallBack [void (*)(void *, ProtobufObj *)]
		executor_frameworkMessageCallBack_t frameworkMessageCallBack [void (*)(void *, ProtobufObj *)]
		executor_shutdownCallBack_t shutdownCallBack [void (*)(void *)]
		executor_errorCallBack_t errorCallBack [void (*)(void *, ProtobufObj *)]
*/
#[repr(C)]
struct ExecutorCallbacks {
	registeredCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj, *mut ProtobufObj, *mut ProtobufObj),
	reregisteredCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
	disconnectedCallBack: extern fn(*mut libc::c_void),
	launchTaskCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
	killTaskCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
	frameworkMessageCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
	shutdownCallBack: extern fn(*mut libc::c_void),
	errorCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
}

/*
struct
		void * executor
		void * driver
*/
#[repr(C)]
struct ExecutorPtrPair {
	executor: *mut libc::c_void,
	driver: *mut libc::c_void,
}

<commit_msg>Reformatted FFI declarations, enclosed in mod mesos<commit_after>mod mesos {
#![allow(dead_code)]
#![allow(non_snake_case)]

  extern crate libc;

  #[link(name="libmesos")]
  extern "C" {

    //////////////////////////////////////////////////////////////////
    // Scheduler driver methods
    //////////////////////////////////////////////////////////////////

    /*
    SchedulerDriverStatus scheduler_launchTasks() [int]
      SchedulerDriverPtr driver [void *]
      ProtobufObj * offerId [ProtobufObj *]
      ProtobufObj * tasks [ProtobufObj *]
      ProtobufObj * filters [ProtobufObj *]
    */
    fn scheduler_launchTasks(
      driver: *mut libc::c_void,
      offerId: *mut ProtobufObj,
      tasks: *mut ProtobufObj,
      filters: *mut ProtobufObj) -> libc::c_int;

    /*
    SchedulerDriverStatus scheduler_start() [int]
      SchedulerDriverPtr driver [void *]
    */
    fn scheduler_start(driver: *mut libc::c_void) -> libc::c_int;

    /*
    SchedulerDriverStatus scheduler_stop() [int]
      SchedulerDriverPtr driver [void *]
      int failover
    */
    fn scheduler_stop(
      driver: *mut libc::c_void,
      failover: libc::c_int) -> libc::c_int;

    /*
    SchedulerDriverStatus scheduler_abort() [int]
      SchedulerDriverPtr driver [void *]
    */
    fn scheduler_abort(driver: *mut libc::c_void) -> libc::c_int;

    /*
    SchedulerDriverStatus scheduler_join() [int]
      SchedulerDriverPtr driver [void *]
    */
    fn scheduler_join(driver: *mut libc::c_void) -> libc::c_int;

    /*
    SchedulerDriverStatus scheduler_run() [int]
      SchedulerDriverPtr driver [void *]
    */
    fn scheduler_run(driver: *mut libc::c_void) -> libc::c_int;

    /*
    SchedulerDriverStatus scheduler_requestResources() [int]
      SchedulerDriverPtr driver [void *]
      ProtobufObj * requestsData [ProtobufObj *]
    */
    fn scheduler_requestResources(
      driver: *mut libc::c_void,
      requestsData: *mut ProtobufObj) -> libc::c_int;

    /*
    SchedulerDriverStatus scheduler_declineOffer() [int]
      SchedulerDriverPtr driver [void *]
      ProtobufObj * offerId [ProtobufObj *]
      ProtobufObj * filters [ProtobufObj *]
    */
    fn scheduler_declineOffer(
      driver: *mut libc::c_void,
      offerId: *mut ProtobufObj,
      filters: *mut ProtobufObj) -> libc::c_int;

    /*
    SchedulerDriverStatus scheduler_killTask() [int]
      SchedulerDriverPtr driver [void *]
      ProtobufObj * taskId [ProtobufObj *]
    */
    fn scheduler_killTask(
      driver: *mut libc::c_void,
      taskId: *mut ProtobufObj) -> libc::c_int;

    /*
    SchedulerDriverStatus scheduler_reviveOffers() [int]
      SchedulerDriverPtr driver [void *]
    */
    fn scheduler_reviveOffers(driver: *mut libc::c_void) -> libc::c_int;

    /*
    SchedulerDriverStatus scheduler_sendFrameworkMessage() [int]
      SchedulerDriverPtr driver [void *]
      ProtobufObj * executor [ProtobufObj *]
      ProtobufObj * slaveId [ProtobufObj *]
      const char * data
    */
    fn scheduler_sendFrameworkMessage(
      driver: *mut libc::c_void,
      executor: *mut ProtobufObj,
      slaveId: *mut ProtobufObj,
      data: *const libc::c_char) -> libc::c_int;

    /*
    SchedulerPtrPair scheduler_init() [SchedulerPtrPair]
      SchedulerCallbacks * callbacks [SchedulerCallbacks *]
      void * payload
      ProtobufObj * framework [ProtobufObj *]
      const char * master
    */
    fn scheduler_init(
      callbacks: *mut SchedulerCallbacks,
      payload: *mut libc::c_void,
      framework: *mut ProtobufObj,
      master: *const libc::c_char) -> SchedulerPtrPair;

    /*
    void scheduler_destroy()
      void * driver
      void * scheduler
    */
    fn scheduler_destroy(
      driver: *mut libc::c_void,
      scheduler: *mut libc::c_void);

    //////////////////////////////////////////////////////////////////
    // Executor driver methods
    //////////////////////////////////////////////////////////////////

    /*
    ExecutorDriverStatus executor_start() [int]
      ExecutorDriverPtr driver [void *]
    */
    fn executor_start(driver: *mut libc::c_void) -> libc::c_int;

    /*
    ExecutorDriverStatus executor_stop() [int]
      ExecutorDriverPtr driver [void *]
    */
    fn executor_stop(driver: *mut libc::c_void) -> libc::c_int;

    /*
    ExecutorDriverStatus executor_abort() [int]
      ExecutorDriverPtr driver [void *]
    */
    fn executor_abort(driver: *mut libc::c_void) -> libc::c_int;

    /*
    ExecutorDriverStatus executor_join() [int]
      ExecutorDriverPtr driver [void *]
    */
    fn executor_join(driver: *mut libc::c_void) -> libc::c_int;

    /*
    ExecutorDriverStatus executor_run() [int]
      ExecutorDriverPtr driver [void *]
    */
    fn executor_run(driver: *mut libc::c_void) -> libc::c_int;

    /*
    ExecutorDriverStatus executor_sendStatusUpdate() [int]
      ExecutorDriverPtr driver [void *]
      ProtobufObj * status [ProtobufObj *]
    */
    fn executor_sendStatusUpdate(
      driver: *mut libc::c_void,
      status: *mut ProtobufObj) -> libc::c_int;

    /*
    ExecutorDriverStatus executor_sendFrameworkMessage() [int]
      ExecutorDriverPtr driver [void *]
      const char * data
    */
    fn executor_sendFrameworkMessage(
      driver: *mut libc::c_void,
      data: *const libc::c_char) -> libc::c_int;

    /*
    ExecutorPtrPair executor_init() [ExecutorPtrPair]
      ExecutorCallbacks * callbacks [ExecutorCallbacks *]
      void * payload
    */
    fn executor_init(
      callbacks: *mut ExecutorCallbacks,
      payload: *mut libc::c_void) -> ExecutorPtrPair;

    /*
    void executor_destroy()
      void * driver
      void * executor
    */
    fn executor_destroy(
      driver: *mut libc::c_void,
      executor: *mut libc::c_void);

  }

  /*
  struct
      void * data
      int size
  */
  #[repr(C)]
  struct ProtobufObj {
    data: *mut libc::c_void,
    size: libc::c_int,
  }

  /*
  struct
      scheduler_registeredCallBack_t registeredCallBack [void (*)(void *, ProtobufObj *, ProtobufObj *)]
      scheduler_reregisteredCallBack_t reregisteredCallBack [void (*)(void *, ProtobufObj *)]
      scheduler_resourceOffersCallBack_t resourceOffersCallBack [void (*)(void *, ProtobufObj *, int)]
      scheduler_statusUpdateCallBack_t statusUpdateCallBack [void (*)(void *, ProtobufObj *)]
      scheduler_disconnectedCallBack_t disconnectedCallBack [void (*)(void *)]
      scheduler_offerRescindedCallBack_t offerRescindedCallBack [void (*)(void *, ProtobufObj *)]
      scheduler_frameworkMessageCallBack_t frameworkMessageCallBack [void (*)(void *, ProtobufObj *, ProtobufObj *, ProtobufObj *)]
      scheduler_slaveLostCallBack_t slaveLostCallBack [void (*)(void *, ProtobufObj *)]
      scheduler_executorLostCallBack_t executorLostCallBack [void (*)(void *, ProtobufObj *, ProtobufObj *, int)]
      scheduler_errorCallBack_t errorCallBack [void (*)(void *, ProtobufObj *)]
  */
  #[repr(C)]
  struct SchedulerCallbacks {
    registeredCallBack: extern fn(
      *mut libc::c_void,
      *mut ProtobufObj,
      *mut ProtobufObj),

    reregisteredCallBack: extern fn(
      *mut libc::c_void,
      *mut ProtobufObj),

    resourceOffersCallBack: extern fn(
      *mut libc::c_void,
      *mut ProtobufObj,
      libc::c_int),

    statusUpdateCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),

    disconnectedCallBack: extern fn(*mut libc::c_void),

    offerRescindedCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),

    frameworkMessageCallBack: extern fn(
      *mut libc::c_void,
      *mut ProtobufObj,
      *mut ProtobufObj,
      *mut ProtobufObj),

    slaveLostCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),

    executorLostCallBack: extern fn(
      *mut libc::c_void,
      *mut ProtobufObj,
      *mut ProtobufObj,
      libc::c_int),

    errorCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
  }

  /*
  struct
      void * scheduler
      void * driver
  */
  #[repr(C)]
  struct SchedulerPtrPair {
    scheduler: *mut libc::c_void,
    driver: *mut libc::c_void,
  }

  /*
  struct
      executor_registeredCallBack_t registeredCallBack [void (*)(void *, ProtobufObj *, ProtobufObj *, ProtobufObj *)]
      executor_reregisteredCallBack_t reregisteredCallBack [void (*)(void *, ProtobufObj *)]
      executor_disconnectedCallBack_t disconnectedCallBack [void (*)(void *)]
      executor_launchTaskCallBack_t launchTaskCallBack [void (*)(void *, ProtobufObj *)]
      executor_killTaskCallBack_t killTaskCallBack [void (*)(void *, ProtobufObj *)]
      executor_frameworkMessageCallBack_t frameworkMessageCallBack [void (*)(void *, ProtobufObj *)]
      executor_shutdownCallBack_t shutdownCallBack [void (*)(void *)]
      executor_errorCallBack_t errorCallBack [void (*)(void *, ProtobufObj *)]
  */
  #[repr(C)]
  struct ExecutorCallbacks {

    registeredCallBack: extern fn(
      *mut libc::c_void,
      *mut ProtobufObj,
      *mut ProtobufObj,
      *mut ProtobufObj),

    reregisteredCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),

    disconnectedCallBack: extern fn(*mut libc::c_void),

    launchTaskCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),

    killTaskCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),

    frameworkMessageCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),

    shutdownCallBack: extern fn(*mut libc::c_void),

    errorCallBack: extern fn(*mut libc::c_void, *mut ProtobufObj),
  }

  /*
  struct
      void * executor
      void * driver
  */
  #[repr(C)]
  struct ExecutorPtrPair {
    executor: *mut libc::c_void,
    driver: *mut libc::c_void,
  }

}
<|endoftext|>


<commit_before>//! `textwrap` provides functions for word wrapping and filling text.

extern crate unicode_width;

use std::iter;
use unicode_width::UnicodeWidthStr;

/// A Wrapper holds settings for wrapping text.
pub struct Wrapper {
    width: usize,
}

impl Wrapper {
    /// Create a new Wrapper for wrapping at the specified width.
    pub fn new(width: usize) -> Wrapper {
        Wrapper { width: width }
    }

    /// Fill a line of text at `self.width` characters. Strings are
    /// wrapped based on their displayed width, not their size in
    /// bytes.
    ///
    /// The result is a string with newlines between each line. Use
    /// the `wrap` method if you need access to the individual lines.
    ///
    /// ```
    /// use textwrap::Wrapper;
    ///
    /// let wrapper = Wrapper::new(15);
    /// assert_eq!(wrapper.fill("Memory safety without garbage collection."),
    ///            "Memory safety\nwithout garbage\ncollection.");
    /// ```
    pub fn fill(&self, s: &str) -> String {
        self.wrap(&s).join("\n")
    }

    /// Wrap  a line of  text at `self.width` characters.  Strings are
    ///  wrapped based  on their  displayed width,  not their  size in
    /// bytes.
    ///
    /// ```
    /// use textwrap::Wrapper;
    ///
    /// let wrap15 = Wrapper::new(15);
    /// assert_eq!(wrap15.wrap("Concurrency without data races."),
    ///            vec!["Concurrency",
    ///                 "without data",
    ///                 "races."]);
    ///
    /// let wrap20 = Wrapper::new(20);
    /// assert_eq!(wrap20.wrap("Concurrency without data races."),
    ///            vec!["Concurrency without",
    ///                 "data races."]);
    /// ```
    pub fn wrap(&self, s: &str) -> Vec<String> {
        let mut result = Vec::new();
        let mut line = Vec::new();
        let mut line_width = 0;

        for mut word in s.split_whitespace() {
            while !word.is_empty() {
                let splits = self.split_word(&word);
                let (smallest, longest) = splits[0];
                let min_width = smallest.width();

                // Add a new line if even the smallest split doesn't
                // fit.
                if !line.is_empty() && line_width + line.len() + min_width > self.width {
                    result.push(line.join(" "));
                    line = Vec::new();
                    line_width = 0;
                }

                // Find a split that fits on the current line.
                for &(head, tail) in splits.iter().rev() {
                    if line_width + line.len() + head.width() <= self.width {
                        line.push(head);
                        line_width += head.width();
                        word = tail;
                        break;
                    }
                }

                // If nothing got added, we forcibly add the smallest
                // split and continue with the longest tail.
                if line_width == 0 {
                    result.push(String::from(smallest));
                    line_width = 0;
                    word = longest;
                }
            }
        }
        if !line.is_empty() {
            result.push(line.join(" "));
        }
        return result;
    }

    /// Split word into all possible parts (head, tail). Word must be
    /// non-empty. The returned vector will always be non-empty.
    fn split_word<'b>(&self, word: &'b str) -> Vec<(&'b str, &'b str)> {
        let hyphens = word.match_indices('-');
        let word_end = iter::once((word.len() - 1, ""));
        return hyphens.chain(word_end)
            .map(|(n, _)| word.split_at(n + 1))
            .collect();
    }
}

/// Fill a line of text at `width` characters. Strings are wrapped
/// based on their displayed width, not their size in bytes.
///
/// The result is a string with newlines between each line. Use `wrap`
/// if you need access to the individual lines.
///
/// ```
/// use textwrap::fill;
///
/// assert_eq!(fill("Memory safety without garbage collection.", 15),
///            "Memory safety\nwithout garbage\ncollection.");
/// ```
///
/// This function creates a Wrapper on the fly. If you need to wrap
/// many strings, it can be more efficient to create a single Wrapper
/// and call its [`fill` method](struct.Wrapper.html#method.fill).
pub fn fill(s: &str, width: usize) -> String {
    wrap(s, width).join("\n")
}

/// Wrap a line of text at `width` characters. Strings are wrapped
/// based on their displayed width, not their size in bytes.
///
/// ```
/// use textwrap::wrap;
///
/// assert_eq!(wrap("Concurrency without data races.", 15),
///            vec!["Concurrency",
///                 "without data",
///                 "races."]);
///
/// assert_eq!(wrap("Concurrency without data races.", 20),
///            vec!["Concurrency without",
///                 "data races."]);
/// ```
///
/// This function creates a Wrapper on the fly. If you need to wrap
/// many strings, it can be more efficient to create a single Wrapper
/// and call its [`wrap` method](struct.Wrapper.html#method.wrap).
pub fn wrap(s: &str, width: usize) -> Vec<String> {
    Wrapper::new(width).wrap(s)
}

/// Add prefix to each non-empty line.
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("Foo\nBar\n", "  "), "  Foo\n  Bar\n");
/// ```
///
/// Empty lines (lines consisting only of whitespace) are not indented
/// and the whitespace is replaced by a single newline (`\n`):
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("Foo\n\nBar\n  \t  \nBaz\n", "  "),
///            "  Foo\n\n  Bar\n\n  Baz\n");
/// ```
///
/// Leading and trailing whitespace on non-empty lines is kept
/// unchanged:
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent(" \t  Foo   ", "  "), "   \t  Foo   \n");
/// ```
pub fn indent(s: &str, prefix: &str) -> String {
    let mut result = String::new();
    for line in s.lines() {
        if line.chars().any(|c| !c.is_whitespace()) {
            result.push_str(prefix);
            result.push_str(line);
        }
        result.push('\n');
    }
    return result;
}

/// Removes common leading whitespace from each line.
///
/// This will look at each non-empty line and determine the maximum
/// amount of whitespace that can be removed from the line.
///
/// ```
/// use textwrap::dedent;
///
/// assert_eq!(dedent("  1st line\n  2nd line\n"),
///            "1st line\n2nd line\n");
/// ```
pub fn dedent(s: &str) -> String {
    let mut prefix = String::new();
    let mut lines = s.lines();

    // We first search for a non-empty line to find a prefix.
    for line in &mut lines {
        let whitespace = line.chars()
            .take_while(|c| c.is_whitespace())
            .collect::<String>();
        // Check if the line had anything but whitespace
        if whitespace.len() < line.len() {
            prefix = whitespace;
            break;
        }
    }

    // We then continue looking through the remaining lines to
    // possibly shorten the prefix.
    for line in &mut lines {
        let whitespace = line.chars()
            .zip(prefix.chars())
            .take_while(|&(a, b)| a == b)
            .map(|(_, b)| b)
            .collect::<String>();
        // Check if we have found a shorter prefix
        if whitespace.len() < prefix.len() {
            prefix = whitespace;
        }
    }

    // We now go over the lines a second time to build the result.
    let mut result = String::new();
    for line in s.lines() {
        if line.starts_with(&prefix) && line.chars().any(|c| !c.is_whitespace()) {
            let (_, tail) = line.split_at(prefix.len());
            result.push_str(tail);
        }
        result.push('\n');
    }
    return result;
}

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

    /// Add newlines. Ensures that the final line in the vector also
    /// has a newline.
    fn add_nl(lines: &Vec<&str>) -> String {
        lines.join("\n") + "\n"
    }

    #[test]
    fn no_wrap() {
        assert_eq!(wrap("foo", 10), vec!["foo"]);
    }

    #[test]
    fn simple() {
        assert_eq!(wrap("foo bar baz", 5), vec!["foo", "bar", "baz"]);
    }

    #[test]
    fn multi_word_on_line() {
        assert_eq!(wrap("foo bar baz", 10), vec!["foo bar", "baz"]);
    }

    #[test]
    fn long_word() {
        assert_eq!(wrap("foo", 0), vec!["foo"]);
    }

    #[test]
    fn long_words() {
        assert_eq!(wrap("foo bar", 0), vec!["foo", "bar"]);
    }

    #[test]
    fn whitespace_is_squeezed() {
        assert_eq!(wrap(" foo \t  bar  ", 10), vec!["foo bar"]);
    }

    #[test]
    fn wide_character_handling() {
        assert_eq!(wrap("Hello, World!", 15), vec!["Hello, World!"]);
        assert_eq!(wrap("Ｈｅｌｌｏ, Ｗｏｒｌｄ!", 15),
                   vec!["Ｈｅｌｌｏ,", "Ｗｏｒｌｄ!"]);
    }

    #[test]
    fn hyphens() {
        assert_eq!(wrap("foo-bar", 5), vec!["foo-", "bar"]);
    }

    #[test]
    fn trailing_hyphen() {
        assert_eq!(wrap("foobar-", 5), vec!["foobar-"]);
    }

    #[test]
    fn multiple_hyphens() {
        assert_eq!(wrap("foo-bar-baz", 5), vec!["foo-", "bar-", "baz"]);
    }

    #[test]
    fn multiple_splits() {
        assert_eq!(wrap("foo-bar-baz", 9), vec!["foo-bar-", "baz"]);
    }

    #[test]
    fn forced_split() {
        assert_eq!(wrap("foobar-baz", 5), vec!["foobar-", "baz"]);
    }

    #[test]
    fn test_fill() {
        assert_eq!(fill("foo bar baz", 10), "foo bar\nbaz");
    }

    #[test]
    fn test_indent_empty() {
        assert_eq!(indent("\n", "  "), "\n");
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_indent_nonempty() {
        let x = vec!["  foo",
                     "bar",
                     "  baz"];
        let y = vec!["//  foo",
                     "//bar",
                     "//  baz"];
        assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_indent_empty_line() {
        let x = vec!["  foo",
                     "bar",
                     "",
                     "  baz"];
        let y = vec!["//  foo",
                     "//bar",
                     "",
                     "//  baz"];
        assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y));
    }

    #[test]
    fn test_dedent_empty() {
        assert_eq!(dedent(""), "");
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_multi_line() {
        let x = vec!["    foo",
                     "  bar",
                     "    baz"];
        let y = vec!["  foo",
                     "bar",
                     "  baz"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_empty_line() {
        let x = vec!["    foo",
                     "  bar",
                     "   ",
                     "    baz"];
        let y = vec!["  foo",
                     "bar",
                     "",
                     "  baz"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_mixed_whitespace() {
        let x = vec!["\tfoo",
                     "  bar"];
        let y = vec!["\tfoo",
                     "  bar"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }
}
<commit_msg>split_word: rewrite with explicit Vec<commit_after>//! `textwrap` provides functions for word wrapping and filling text.

extern crate unicode_width;

use unicode_width::UnicodeWidthStr;

/// A Wrapper holds settings for wrapping text.
pub struct Wrapper {
    width: usize,
}

impl Wrapper {
    /// Create a new Wrapper for wrapping at the specified width.
    pub fn new(width: usize) -> Wrapper {
        Wrapper { width: width }
    }

    /// Fill a line of text at `self.width` characters. Strings are
    /// wrapped based on their displayed width, not their size in
    /// bytes.
    ///
    /// The result is a string with newlines between each line. Use
    /// the `wrap` method if you need access to the individual lines.
    ///
    /// ```
    /// use textwrap::Wrapper;
    ///
    /// let wrapper = Wrapper::new(15);
    /// assert_eq!(wrapper.fill("Memory safety without garbage collection."),
    ///            "Memory safety\nwithout garbage\ncollection.");
    /// ```
    pub fn fill(&self, s: &str) -> String {
        self.wrap(&s).join("\n")
    }

    /// Wrap  a line of  text at `self.width` characters.  Strings are
    ///  wrapped based  on their  displayed width,  not their  size in
    /// bytes.
    ///
    /// ```
    /// use textwrap::Wrapper;
    ///
    /// let wrap15 = Wrapper::new(15);
    /// assert_eq!(wrap15.wrap("Concurrency without data races."),
    ///            vec!["Concurrency",
    ///                 "without data",
    ///                 "races."]);
    ///
    /// let wrap20 = Wrapper::new(20);
    /// assert_eq!(wrap20.wrap("Concurrency without data races."),
    ///            vec!["Concurrency without",
    ///                 "data races."]);
    /// ```
    pub fn wrap(&self, s: &str) -> Vec<String> {
        let mut result = Vec::new();
        let mut line = Vec::new();
        let mut line_width = 0;

        for mut word in s.split_whitespace() {
            while !word.is_empty() {
                let splits = self.split_word(&word);
                let (smallest, longest) = splits[0];
                let min_width = smallest.width();

                // Add a new line if even the smallest split doesn't
                // fit.
                if !line.is_empty() && line_width + line.len() + min_width > self.width {
                    result.push(line.join(" "));
                    line = Vec::new();
                    line_width = 0;
                }

                // Find a split that fits on the current line.
                for &(head, tail) in splits.iter().rev() {
                    if line_width + line.len() + head.width() <= self.width {
                        line.push(head);
                        line_width += head.width();
                        word = tail;
                        break;
                    }
                }

                // If nothing got added, we forcibly add the smallest
                // split and continue with the longest tail.
                if line_width == 0 {
                    result.push(String::from(smallest));
                    line_width = 0;
                    word = longest;
                }
            }
        }
        if !line.is_empty() {
            result.push(line.join(" "));
        }
        return result;
    }

    /// Split word into all possible parts (head, tail). Word must be
    /// non-empty. The returned vector will always be non-empty.
    fn split_word<'b>(&self, word: &'b str) -> Vec<(&'b str, &'b str)> {
        let mut result = Vec::new();

        // Split on hyphens, smallest split first.
        for (n, _) in word.match_indices('-') {
            result.push(word.split_at(n + 1));
        }

        // Finally option is no split at all.
        result.push((word, ""));

        return result;
    }
}

/// Fill a line of text at `width` characters. Strings are wrapped
/// based on their displayed width, not their size in bytes.
///
/// The result is a string with newlines between each line. Use `wrap`
/// if you need access to the individual lines.
///
/// ```
/// use textwrap::fill;
///
/// assert_eq!(fill("Memory safety without garbage collection.", 15),
///            "Memory safety\nwithout garbage\ncollection.");
/// ```
///
/// This function creates a Wrapper on the fly. If you need to wrap
/// many strings, it can be more efficient to create a single Wrapper
/// and call its [`fill` method](struct.Wrapper.html#method.fill).
pub fn fill(s: &str, width: usize) -> String {
    wrap(s, width).join("\n")
}

/// Wrap a line of text at `width` characters. Strings are wrapped
/// based on their displayed width, not their size in bytes.
///
/// ```
/// use textwrap::wrap;
///
/// assert_eq!(wrap("Concurrency without data races.", 15),
///            vec!["Concurrency",
///                 "without data",
///                 "races."]);
///
/// assert_eq!(wrap("Concurrency without data races.", 20),
///            vec!["Concurrency without",
///                 "data races."]);
/// ```
///
/// This function creates a Wrapper on the fly. If you need to wrap
/// many strings, it can be more efficient to create a single Wrapper
/// and call its [`wrap` method](struct.Wrapper.html#method.wrap).
pub fn wrap(s: &str, width: usize) -> Vec<String> {
    Wrapper::new(width).wrap(s)
}

/// Add prefix to each non-empty line.
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("Foo\nBar\n", "  "), "  Foo\n  Bar\n");
/// ```
///
/// Empty lines (lines consisting only of whitespace) are not indented
/// and the whitespace is replaced by a single newline (`\n`):
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent("Foo\n\nBar\n  \t  \nBaz\n", "  "),
///            "  Foo\n\n  Bar\n\n  Baz\n");
/// ```
///
/// Leading and trailing whitespace on non-empty lines is kept
/// unchanged:
///
/// ```
/// use textwrap::indent;
///
/// assert_eq!(indent(" \t  Foo   ", "  "), "   \t  Foo   \n");
/// ```
pub fn indent(s: &str, prefix: &str) -> String {
    let mut result = String::new();
    for line in s.lines() {
        if line.chars().any(|c| !c.is_whitespace()) {
            result.push_str(prefix);
            result.push_str(line);
        }
        result.push('\n');
    }
    return result;
}

/// Removes common leading whitespace from each line.
///
/// This will look at each non-empty line and determine the maximum
/// amount of whitespace that can be removed from the line.
///
/// ```
/// use textwrap::dedent;
///
/// assert_eq!(dedent("  1st line\n  2nd line\n"),
///            "1st line\n2nd line\n");
/// ```
pub fn dedent(s: &str) -> String {
    let mut prefix = String::new();
    let mut lines = s.lines();

    // We first search for a non-empty line to find a prefix.
    for line in &mut lines {
        let whitespace = line.chars()
            .take_while(|c| c.is_whitespace())
            .collect::<String>();
        // Check if the line had anything but whitespace
        if whitespace.len() < line.len() {
            prefix = whitespace;
            break;
        }
    }

    // We then continue looking through the remaining lines to
    // possibly shorten the prefix.
    for line in &mut lines {
        let whitespace = line.chars()
            .zip(prefix.chars())
            .take_while(|&(a, b)| a == b)
            .map(|(_, b)| b)
            .collect::<String>();
        // Check if we have found a shorter prefix
        if whitespace.len() < prefix.len() {
            prefix = whitespace;
        }
    }

    // We now go over the lines a second time to build the result.
    let mut result = String::new();
    for line in s.lines() {
        if line.starts_with(&prefix) && line.chars().any(|c| !c.is_whitespace()) {
            let (_, tail) = line.split_at(prefix.len());
            result.push_str(tail);
        }
        result.push('\n');
    }
    return result;
}

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

    /// Add newlines. Ensures that the final line in the vector also
    /// has a newline.
    fn add_nl(lines: &Vec<&str>) -> String {
        lines.join("\n") + "\n"
    }

    #[test]
    fn no_wrap() {
        assert_eq!(wrap("foo", 10), vec!["foo"]);
    }

    #[test]
    fn simple() {
        assert_eq!(wrap("foo bar baz", 5), vec!["foo", "bar", "baz"]);
    }

    #[test]
    fn multi_word_on_line() {
        assert_eq!(wrap("foo bar baz", 10), vec!["foo bar", "baz"]);
    }

    #[test]
    fn long_word() {
        assert_eq!(wrap("foo", 0), vec!["foo"]);
    }

    #[test]
    fn long_words() {
        assert_eq!(wrap("foo bar", 0), vec!["foo", "bar"]);
    }

    #[test]
    fn whitespace_is_squeezed() {
        assert_eq!(wrap(" foo \t  bar  ", 10), vec!["foo bar"]);
    }

    #[test]
    fn wide_character_handling() {
        assert_eq!(wrap("Hello, World!", 15), vec!["Hello, World!"]);
        assert_eq!(wrap("Ｈｅｌｌｏ, Ｗｏｒｌｄ!", 15),
                   vec!["Ｈｅｌｌｏ,", "Ｗｏｒｌｄ!"]);
    }

    #[test]
    fn hyphens() {
        assert_eq!(wrap("foo-bar", 5), vec!["foo-", "bar"]);
    }

    #[test]
    fn trailing_hyphen() {
        assert_eq!(wrap("foobar-", 5), vec!["foobar-"]);
    }

    #[test]
    fn multiple_hyphens() {
        assert_eq!(wrap("foo-bar-baz", 5), vec!["foo-", "bar-", "baz"]);
    }

    #[test]
    fn multiple_splits() {
        assert_eq!(wrap("foo-bar-baz", 9), vec!["foo-bar-", "baz"]);
    }

    #[test]
    fn forced_split() {
        assert_eq!(wrap("foobar-baz", 5), vec!["foobar-", "baz"]);
    }

    #[test]
    fn test_fill() {
        assert_eq!(fill("foo bar baz", 10), "foo bar\nbaz");
    }

    #[test]
    fn test_indent_empty() {
        assert_eq!(indent("\n", "  "), "\n");
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_indent_nonempty() {
        let x = vec!["  foo",
                     "bar",
                     "  baz"];
        let y = vec!["//  foo",
                     "//bar",
                     "//  baz"];
        assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_indent_empty_line() {
        let x = vec!["  foo",
                     "bar",
                     "",
                     "  baz"];
        let y = vec!["//  foo",
                     "//bar",
                     "",
                     "//  baz"];
        assert_eq!(indent(&add_nl(&x), "//"), add_nl(&y));
    }

    #[test]
    fn test_dedent_empty() {
        assert_eq!(dedent(""), "");
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_multi_line() {
        let x = vec!["    foo",
                     "  bar",
                     "    baz"];
        let y = vec!["  foo",
                     "bar",
                     "  baz"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_empty_line() {
        let x = vec!["    foo",
                     "  bar",
                     "   ",
                     "    baz"];
        let y = vec!["  foo",
                     "bar",
                     "",
                     "  baz"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }

    #[test]
    #[cfg_attr(rustfmt, rustfmt_skip)]
    fn test_dedent_mixed_whitespace() {
        let x = vec!["\tfoo",
                     "  bar"];
        let y = vec!["\tfoo",
                     "  bar"];
        assert_eq!(dedent(&add_nl(&x)), add_nl(&y));
    }
}
<|endoftext|>


<commit_before>//! The `grok` library allows you to quickly parse and match potentially unstructured data
//! into a structed result. It is especially helpful when parsing logfiles of all kinds. This
//! [Rust](http://rust-lang.org) version is mainly a port from the [java version](https://github.com/thekrakken/java-grok)
//! which in drew inspiration from the original [ruby version](https://github.com/logstash-plugins/logstash-filter-grok).
#![doc(html_root_url = "https://docs.rs/grok/0.1.0")]
extern crate regex;

use regex::{Captures, Regex};
use std::collections::BTreeMap;

const GROK_PATTERN: &'static str = r"%\{(?P<name>(?P<pattern>[A-z0-9]+)(?::(?P<subname>[A-z0-9_:;/\s\.]+))?)(?:=(?P<definition>(?:(?:[^{}]+|\.+)+)+))?\}";

/// The `Matches` represent matched results from a `Pattern` against text.
pub struct Matches<'a> {
    captures: Captures<'a>,
    alias: &'a BTreeMap<String, String>
}

impl<'a> Matches<'a> {
    /// Instantiates the matches for a pattern after the match.
    pub fn new(captures: Captures<'a>, alias: &'a BTreeMap<String, String>) -> Self {
        Matches { captures: captures, alias: alias }
    }

    /// Gets the value for the name (or) alias if found, `None` otherwise.
    pub fn get(&self, name: &str) -> Option<&str> {
        match self.alias.get(name) {
            Some(real) => self.captures.name(real).map(|m| m.as_str()),
            None => None,
        }
    }

    /// Returns the number of matches.
    pub fn len(&self) -> usize {
        self.captures.len() - 1
    }

    /// Returns true if there are no matches, false otherwise.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

/// The `Pattern` represents a compiled regex, ready to be matched against arbitrary text.
pub struct Pattern {
    regex: Regex,
    alias: BTreeMap<String, String>,
}

impl Pattern {
    /// Creates a new pattern from a raw regex string and an alias map to identify the
    /// fields properly.
    pub fn new(regex: &str, alias: BTreeMap<String, String>) -> Self {
        Pattern {
            regex: Regex::new(regex).expect("Could not compile regex!"),
            alias: alias,
        }
    }

    /// Matches this compiled `Pattern` against the text and returns the matches.
    pub fn match_against<'a>(&'a self, text: &'a str) -> Option<Matches<'a>> {
        self.regex.captures(text).map(|cap| Matches::new(cap, &self.alias))
    }
}

/// The basic structure to manage patterns, entry point for common usage.
pub struct Grok {
    definitions: BTreeMap<String, String>,
}

impl Grok {
    /// Creates a new `Grok` instance with no patterns.
    pub fn empty() -> Self {
        Grok {
            definitions: BTreeMap::new(),
        }
    }

    /// Inserts a custom pattern.
    pub fn insert_definition<S: Into<String>>(&mut self, name: S, pattern: S) {
        self.definitions.insert(name.into(), pattern.into());
    }

    /// Compiles the given pattern, making it ready for matching.
    pub fn compile(&mut self, pattern: &str, named_only: bool) -> Pattern {
        let mut named_regex = String::from(pattern);
        let original_grok_pattern = pattern;
        let mut alias: BTreeMap<String, String> = BTreeMap::new();

        let mut index = 0;
        let mut iteration_left = 1000;
        let mut continue_iteration = true;

        let grok_regex = Regex::new(GROK_PATTERN).unwrap();
        while continue_iteration {
            continue_iteration = false;
            if iteration_left <= 0 {
                panic!(
                    "Deep recursion pattern compilation of {:?}",
                    original_grok_pattern
                );
            }
            iteration_left -= 1;

            let capture = named_regex.clone();
            if let Some(m) = grok_regex.captures(&capture) {
                continue_iteration = true;

                let mut name = String::from(m.name("name").unwrap().as_str());
                if let Some(definition) = m.name("definition") {
                    self.insert_definition(m.name("pattern").unwrap().as_str(), definition.as_str());
                    name = format!("{}={}", name, definition.as_str());
                }

                let n = format!("%{{{}}}", name);
                let count = named_regex.matches(&n).count();
                for _ in 0..count {
                    let definition_of_pattern = self.definitions.get(m.name("pattern").unwrap().as_str());
                    if definition_of_pattern.is_none() {
                        panic!("No definition for key '{}' found, aborting", m.name("pattern").unwrap().as_str());
                    }

                    let replacement = if named_only && m.name("subname").is_none() {
                        format!("(?:{})", definition_of_pattern.unwrap())
                    } else {
                        format!("(?P<name{}>{})", index, definition_of_pattern.unwrap())
                    };

                    let name_and_index = format!("name{}", index);
                    if m.name("subname").is_some() {
                        alias.insert(m.name("subname").unwrap().as_str().into(), name_and_index);
                    } else {
                        alias.insert(name.clone(), name_and_index);
                    }

                    let search_string = format!("%{{{}}}", name);
                    named_regex = named_regex.replacen(&search_string, &replacement, 1);
                    index += 1;
                }
            }
        }

        if named_regex.is_empty() {
            panic!("Pattern not found");
        }
        Pattern::new(&named_regex, alias)
    }
}

impl Default for Grok {
    fn default() -> Grok {
        Grok::empty()
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_simple_anonymous_pattern() {
        let mut grok = Grok::default();
        grok.insert_definition("USERNAME", r"[a-zA-Z0-9._-]+");
        let pattern = grok.compile("%{USERNAME}", false);

        let matches = pattern.match_against("root").expect("No matches found!");
        assert_eq!("root", matches.get("USERNAME").unwrap());
        assert_eq!(1, matches.len());
        let matches = pattern.match_against("john doe").expect("No matches found!");
        assert_eq!("john", matches.get("USERNAME").unwrap());
        assert_eq!(1, matches.len());
    }

    #[test]
    fn test_simple_named_pattern() {
        let mut grok = Grok::default();
        grok.insert_definition("USERNAME", r"[a-zA-Z0-9._-]+");
        let pattern = grok.compile("%{USERNAME:usr}", false);

        let matches = pattern.match_against("root").expect("No matches found!");
        assert_eq!("root", matches.get("usr").unwrap());
        assert_eq!(1, matches.len());
        let matches = pattern.match_against("john doe").expect("No matches found!");
        assert_eq!("john", matches.get("usr").unwrap());
        assert_eq!(1, matches.len());
    }

    #[test]
    fn test_alias_anonymous_pattern() {
        let mut grok = Grok::default();
        grok.insert_definition("USERNAME", r"[a-zA-Z0-9._-]+");
        grok.insert_definition("USER", r"%{USERNAME}");
        let pattern = grok.compile("%{USER}", false);

        let matches = pattern.match_against("root").expect("No matches found!");
        assert_eq!("root", matches.get("USER").unwrap());
        let matches = pattern.match_against("john doe").expect("No matches found!");
        assert_eq!("john", matches.get("USER").unwrap());
    }

    #[test]
    fn test_ailas_named_pattern() {
        let mut grok = Grok::default();
        grok.insert_definition("USERNAME", r"[a-zA-Z0-9._-]+");
        grok.insert_definition("USER", r"%{USERNAME}");
        let pattern = grok.compile("%{USER:usr}", false);

        let matches = pattern.match_against("root").expect("No matches found!");
        assert_eq!("root", matches.get("usr").unwrap());
        let matches = pattern.match_against("john doe").expect("No matches found!");
        assert_eq!("john", matches.get("usr").unwrap());
    }

    #[test]
    fn test_composite_or_pattern() {
        let mut grok = Grok::default();
        grok.insert_definition("MAC", r"(?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC})");
        grok.insert_definition("CISCOMAC", r"(?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4})");
        grok.insert_definition("WINDOWSMAC", r"(?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2})");
        grok.insert_definition("COMMONMAC", r"(?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})");
        let pattern = grok.compile("%{MAC}", false);

        let matches = pattern.match_against("5E:FF:56:A2:AF:15").expect("No matches found!");
        assert_eq!("5E:FF:56:A2:AF:15", matches.get("MAC").unwrap());
        assert_eq!(4, matches.len());
        let matches = pattern.match_against("hello! 5E:FF:56:A2:AF:15 what?").expect("No matches found!");
        assert_eq!("5E:FF:56:A2:AF:15", matches.get("MAC").unwrap());
        assert_eq!(true, pattern.match_against("5E:FF").is_none());
    }

    #[test]
    fn test_multiple_patterns() {
        let mut grok = Grok::default();
        grok.insert_definition("YEAR", r"(\d\d){1,2}");
        grok.insert_definition("MONTH", r"\b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\b");
        grok.insert_definition("DAY", r"(?:Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?)");
        let pattern = grok.compile("%{DAY} %{MONTH} %{YEAR}", false);

        let matches = pattern.match_against("Monday March 2012").expect("No matches found!");
        assert_eq!("Monday", matches.get("DAY").unwrap());
        assert_eq!("March", matches.get("MONTH").unwrap());
        assert_eq!("2012", matches.get("YEAR").unwrap());
        assert_eq!(None, matches.get("unknown"));
    }

    #[test]
    fn test_named_only() {
        let mut grok = Grok::default();
        grok.insert_definition("MAC", r"(?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC})");
        grok.insert_definition("CISCOMAC", r"(?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4})");
        grok.insert_definition("WINDOWSMAC", r"(?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2})");
        grok.insert_definition("COMMONMAC", r"(?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})");
        let pattern = grok.compile("%{MAC:macaddr}", true);

        let matches = pattern.match_against("5E:FF:56:A2:AF:15").expect("No matches found!");
        assert_eq!("5E:FF:56:A2:AF:15", matches.get("macaddr").unwrap());
        assert_eq!(1, matches.len());
        let matches = pattern.match_against("hello! 5E:FF:56:A2:AF:15 what?").expect("No matches found!");
        assert_eq!("5E:FF:56:A2:AF:15", matches.get("macaddr").unwrap());
        assert_eq!(true, pattern.match_against("5E:FF").is_none());
    }
}
<commit_msg>rename to alias consistently<commit_after>//! The `grok` library allows you to quickly parse and match potentially unstructured data
//! into a structed result. It is especially helpful when parsing logfiles of all kinds. This
//! [Rust](http://rust-lang.org) version is mainly a port from the [java version](https://github.com/thekrakken/java-grok)
//! which in drew inspiration from the original [ruby version](https://github.com/logstash-plugins/logstash-filter-grok).
#![doc(html_root_url = "https://docs.rs/grok/0.1.0")]
extern crate regex;

use regex::{Captures, Regex};
use std::collections::BTreeMap;

const GROK_PATTERN: &'static str = r"%\{(?P<name>(?P<pattern>[A-z0-9]+)(?::(?P<alias>[A-z0-9_:;/\s\.]+))?)(?:=(?P<definition>(?:(?:[^{}]+|\.+)+)+))?\}";

/// The `Matches` represent matched results from a `Pattern` against text.
pub struct Matches<'a> {
    captures: Captures<'a>,
    alias: &'a BTreeMap<String, String>
}

impl<'a> Matches<'a> {
    /// Instantiates the matches for a pattern after the match.
    pub fn new(captures: Captures<'a>, alias: &'a BTreeMap<String, String>) -> Self {
        Matches { captures: captures, alias: alias }
    }

    /// Gets the value for the name (or) alias if found, `None` otherwise.
    pub fn get(&self, name_or_alias: &str) -> Option<&str> {
        match self.alias.get(name_or_alias) {
            Some(real) => self.captures.name(real).map(|m| m.as_str()),
            None => None,
        }
    }

    /// Returns the number of matches.
    pub fn len(&self) -> usize {
        self.captures.len() - 1
    }

    /// Returns true if there are no matches, false otherwise.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

/// The `Pattern` represents a compiled regex, ready to be matched against arbitrary text.
pub struct Pattern {
    regex: Regex,
    alias: BTreeMap<String, String>,
}

impl Pattern {
    /// Creates a new pattern from a raw regex string and an alias map to identify the
    /// fields properly.
    pub fn new(regex: &str, alias: BTreeMap<String, String>) -> Self {
        Pattern {
            regex: Regex::new(regex).expect("Could not compile regex!"),
            alias: alias,
        }
    }

    /// Matches this compiled `Pattern` against the text and returns the matches.
    pub fn match_against<'a>(&'a self, text: &'a str) -> Option<Matches<'a>> {
        self.regex.captures(text).map(|cap| Matches::new(cap, &self.alias))
    }
}

/// The basic structure to manage patterns, entry point for common usage.
pub struct Grok {
    definitions: BTreeMap<String, String>,
}

impl Grok {
    /// Creates a new `Grok` instance with no patterns.
    pub fn empty() -> Self {
        Grok {
            definitions: BTreeMap::new(),
        }
    }

    /// Inserts a custom pattern.
    pub fn insert_definition<S: Into<String>>(&mut self, name: S, pattern: S) {
        self.definitions.insert(name.into(), pattern.into());
    }

    /// Compiles the given pattern, making it ready for matching.
    pub fn compile(&mut self, pattern: &str, with_alias_only: bool) -> Pattern {
        let mut named_regex = String::from(pattern);
        let original_grok_pattern = pattern;
        let mut alias: BTreeMap<String, String> = BTreeMap::new();

        let mut index = 0;
        let mut iteration_left = 1000;
        let mut continue_iteration = true;

        let grok_regex = Regex::new(GROK_PATTERN).unwrap();
        while continue_iteration {
            continue_iteration = false;
            if iteration_left <= 0 {
                panic!(
                    "Deep recursion pattern compilation of {:?}",
                    original_grok_pattern
                );
            }
            iteration_left -= 1;

            let capture = named_regex.clone();
            if let Some(m) = grok_regex.captures(&capture) {
                continue_iteration = true;

                let mut name = String::from(m.name("name").unwrap().as_str());
                if let Some(definition) = m.name("definition") {
                    self.insert_definition(m.name("pattern").unwrap().as_str(), definition.as_str());
                    name = format!("{}={}", name, definition.as_str());
                }

                let n = format!("%{{{}}}", name);
                let count = named_regex.matches(&n).count();
                for _ in 0..count {
                    let definition_of_pattern = self.definitions.get(m.name("pattern").unwrap().as_str());
                    if definition_of_pattern.is_none() {
                        panic!("No definition for key '{}' found, aborting", m.name("pattern").unwrap().as_str());
                    }

                    let replacement = if with_alias_only && m.name("alias").is_none() {
                        format!("(?:{})", definition_of_pattern.unwrap())
                    } else {
                        format!("(?P<name{}>{})", index, definition_of_pattern.unwrap())
                    };

                    let name_and_index = format!("name{}", index);
                    if m.name("alias").is_some() {
                        alias.insert(m.name("alias").unwrap().as_str().into(), name_and_index);
                    } else {
                        alias.insert(name.clone(), name_and_index);
                    }

                    let search_string = format!("%{{{}}}", name);
                    named_regex = named_regex.replacen(&search_string, &replacement, 1);
                    index += 1;
                }
            }
        }

        if named_regex.is_empty() {
            panic!("Pattern not found");
        }
        Pattern::new(&named_regex, alias)
    }
}

impl Default for Grok {
    fn default() -> Grok {
        Grok::empty()
    }
}

#[cfg(test)]
mod tests {

    use super::*;

    #[test]
    fn test_simple_anonymous_pattern() {
        let mut grok = Grok::default();
        grok.insert_definition("USERNAME", r"[a-zA-Z0-9._-]+");
        let pattern = grok.compile("%{USERNAME}", false);

        let matches = pattern.match_against("root").expect("No matches found!");
        assert_eq!("root", matches.get("USERNAME").unwrap());
        assert_eq!(1, matches.len());
        let matches = pattern.match_against("john doe").expect("No matches found!");
        assert_eq!("john", matches.get("USERNAME").unwrap());
        assert_eq!(1, matches.len());
    }

    #[test]
    fn test_simple_named_pattern() {
        let mut grok = Grok::default();
        grok.insert_definition("USERNAME", r"[a-zA-Z0-9._-]+");
        let pattern = grok.compile("%{USERNAME:usr}", false);

        let matches = pattern.match_against("root").expect("No matches found!");
        assert_eq!("root", matches.get("usr").unwrap());
        assert_eq!(1, matches.len());
        let matches = pattern.match_against("john doe").expect("No matches found!");
        assert_eq!("john", matches.get("usr").unwrap());
        assert_eq!(1, matches.len());
    }

    #[test]
    fn test_alias_anonymous_pattern() {
        let mut grok = Grok::default();
        grok.insert_definition("USERNAME", r"[a-zA-Z0-9._-]+");
        grok.insert_definition("USER", r"%{USERNAME}");
        let pattern = grok.compile("%{USER}", false);

        let matches = pattern.match_against("root").expect("No matches found!");
        assert_eq!("root", matches.get("USER").unwrap());
        let matches = pattern.match_against("john doe").expect("No matches found!");
        assert_eq!("john", matches.get("USER").unwrap());
    }

    #[test]
    fn test_ailas_named_pattern() {
        let mut grok = Grok::default();
        grok.insert_definition("USERNAME", r"[a-zA-Z0-9._-]+");
        grok.insert_definition("USER", r"%{USERNAME}");
        let pattern = grok.compile("%{USER:usr}", false);

        let matches = pattern.match_against("root").expect("No matches found!");
        assert_eq!("root", matches.get("usr").unwrap());
        let matches = pattern.match_against("john doe").expect("No matches found!");
        assert_eq!("john", matches.get("usr").unwrap());
    }

    #[test]
    fn test_composite_or_pattern() {
        let mut grok = Grok::default();
        grok.insert_definition("MAC", r"(?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC})");
        grok.insert_definition("CISCOMAC", r"(?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4})");
        grok.insert_definition("WINDOWSMAC", r"(?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2})");
        grok.insert_definition("COMMONMAC", r"(?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})");
        let pattern = grok.compile("%{MAC}", false);

        let matches = pattern.match_against("5E:FF:56:A2:AF:15").expect("No matches found!");
        assert_eq!("5E:FF:56:A2:AF:15", matches.get("MAC").unwrap());
        assert_eq!(4, matches.len());
        let matches = pattern.match_against("hello! 5E:FF:56:A2:AF:15 what?").expect("No matches found!");
        assert_eq!("5E:FF:56:A2:AF:15", matches.get("MAC").unwrap());
        assert_eq!(true, pattern.match_against("5E:FF").is_none());
    }

    #[test]
    fn test_multiple_patterns() {
        let mut grok = Grok::default();
        grok.insert_definition("YEAR", r"(\d\d){1,2}");
        grok.insert_definition("MONTH", r"\b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\b");
        grok.insert_definition("DAY", r"(?:Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|Sun(?:day)?)");
        let pattern = grok.compile("%{DAY} %{MONTH} %{YEAR}", false);

        let matches = pattern.match_against("Monday March 2012").expect("No matches found!");
        assert_eq!("Monday", matches.get("DAY").unwrap());
        assert_eq!("March", matches.get("MONTH").unwrap());
        assert_eq!("2012", matches.get("YEAR").unwrap());
        assert_eq!(None, matches.get("unknown"));
    }

    #[test]
    fn test_with_alias_only() {
        let mut grok = Grok::default();
        grok.insert_definition("MAC", r"(?:%{CISCOMAC}|%{WINDOWSMAC}|%{COMMONMAC})");
        grok.insert_definition("CISCOMAC", r"(?:(?:[A-Fa-f0-9]{4}\.){2}[A-Fa-f0-9]{4})");
        grok.insert_definition("WINDOWSMAC", r"(?:(?:[A-Fa-f0-9]{2}-){5}[A-Fa-f0-9]{2})");
        grok.insert_definition("COMMONMAC", r"(?:(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2})");
        let pattern = grok.compile("%{MAC:macaddr}", true);

        let matches = pattern.match_against("5E:FF:56:A2:AF:15").expect("No matches found!");
        assert_eq!("5E:FF:56:A2:AF:15", matches.get("macaddr").unwrap());
        assert_eq!(1, matches.len());
        let matches = pattern.match_against("hello! 5E:FF:56:A2:AF:15 what?").expect("No matches found!");
        assert_eq!("5E:FF:56:A2:AF:15", matches.get("macaddr").unwrap());
        assert_eq!(true, pattern.match_against("5E:FF").is_none());
    }
}
<|endoftext|>


<commit_before>#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts)]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![warn(unreachable_pub)]

extern crate snap;
#[macro_use]
extern crate rustc_middle;
extern crate rustc_ast;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_fs_util;
extern crate rustc_hir;
extern crate rustc_incremental;
extern crate rustc_index;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;

// This prevents duplicating functions and statics that are already part of the host rustc process.
#[allow(unused_extern_crates)]
extern crate rustc_driver;

use std::any::Any;

use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::CodegenResults;
use rustc_errors::ErrorReported;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc_middle::ty::query::Providers;
use rustc_session::config::OutputFilenames;
use rustc_session::Session;

use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::settings::{self, Configurable};

pub use crate::config::*;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod backend;
mod base;
mod cast;
mod codegen_i128;
mod common;
mod compiler_builtins;
mod config;
mod constant;
mod debuginfo;
mod discriminant;
mod driver;
mod inline_asm;
mod intrinsics;
mod linkage;
mod main_shim;
mod metadata;
mod num;
mod optimize;
mod pointer;
mod pretty_clif;
mod toolchain;
mod trap;
mod unsize;
mod value_and_place;
mod vtable;

mod prelude {
    pub(crate) use std::convert::{TryFrom, TryInto};

    pub(crate) use rustc_span::Span;

    pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
    pub(crate) use rustc_middle::bug;
    pub(crate) use rustc_middle::mir::{self, *};
    pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout};
    pub(crate) use rustc_middle::ty::{
        self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut,
        TypeFoldable, UintTy,
    };
    pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx};

    pub(crate) use rustc_data_structures::fx::FxHashMap;

    pub(crate) use rustc_index::vec::Idx;

    pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
    pub(crate) use cranelift_codegen::ir::function::Function;
    pub(crate) use cranelift_codegen::ir::types;
    pub(crate) use cranelift_codegen::ir::{
        AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc,
        StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value,
    };
    pub(crate) use cranelift_codegen::isa::{self, CallConv};
    pub(crate) use cranelift_codegen::Context;
    pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
    pub(crate) use cranelift_module::{self, DataContext, DataId, FuncId, Linkage, Module};

    pub(crate) use crate::abi::*;
    pub(crate) use crate::base::{codegen_operand, codegen_place};
    pub(crate) use crate::cast::*;
    pub(crate) use crate::common::*;
    pub(crate) use crate::debuginfo::{DebugContext, UnwindContext};
    pub(crate) use crate::pointer::Pointer;
    pub(crate) use crate::trap::*;
    pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue};
}

struct PrintOnPanic<F: Fn() -> String>(F);
impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
    fn drop(&mut self) {
        if ::std::thread::panicking() {
            println!("{}", (self.0)());
        }
    }
}

/// The codegen context holds any information shared between the codegen of individual functions
/// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
struct CodegenCx<'tcx> {
    tcx: TyCtxt<'tcx>,
    global_asm: String,
    cached_context: Context,
    debug_context: Option<DebugContext<'tcx>>,
    unwind_context: UnwindContext,
}

impl<'tcx> CodegenCx<'tcx> {
    fn new(
        tcx: TyCtxt<'tcx>,
        backend_config: BackendConfig,
        isa: &dyn TargetIsa,
        debug_info: bool,
    ) -> Self {
        assert_eq!(pointer_ty(tcx), isa.pointer_type());

        let unwind_context =
            UnwindContext::new(tcx, isa, matches!(backend_config.codegen_mode, CodegenMode::Aot));
        let debug_context = if debug_info { Some(DebugContext::new(tcx, isa)) } else { None };
        CodegenCx {
            tcx,
            global_asm: String::new(),
            cached_context: Context::new(),
            debug_context,
            unwind_context,
        }
    }
}

pub struct CraneliftCodegenBackend {
    pub config: Option<BackendConfig>,
}

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, sess: &Session) {
        use rustc_session::config::Lto;
        match sess.lto() {
            Lto::No | Lto::ThinLocal => {}
            Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."),
        }
    }

    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
        Box::new(crate::metadata::CraneliftMetadataLoader)
    }

    fn provide(&self, _providers: &mut Providers) {}
    fn provide_extern(&self, _providers: &mut Providers) {}

    fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
        vec![]
    }

    fn codegen_crate(
        &self,
        tcx: TyCtxt<'_>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
    ) -> Box<dyn Any> {
        tcx.sess.abort_if_errors();
        let config = if let Some(config) = self.config.clone() {
            config
        } else {
            BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
                .unwrap_or_else(|err| tcx.sess.fatal(&err))
        };
        match config.codegen_mode {
            CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module),
            CodegenMode::Jit | CodegenMode::JitLazy => {
                #[cfg(feature = "jit")]
                let _: ! = driver::jit::run_jit(tcx, config);

                #[cfg(not(feature = "jit"))]
                tcx.sess.fatal("jit support was disabled when compiling rustc_codegen_cranelift");
            }
        }
    }

    fn join_codegen(
        &self,
        ongoing_codegen: Box<dyn Any>,
        _sess: &Session,
    ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> {
        Ok(*ongoing_codegen
            .downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>()
            .unwrap())
    }

    fn link(
        &self,
        sess: &Session,
        codegen_results: CodegenResults,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        let target_cpu = crate::target_triple(sess).to_string();
        link_binary::<crate::archive::ArArchiveBuilder<'_>>(
            sess,
            &codegen_results,
            outputs,
            &codegen_results.crate_name.as_str(),
            &target_cpu,
        );

        Ok(())
    }
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    sess.target.llvm_target.parse().unwrap()
}

fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::TargetIsa + 'static> {
    use target_lexicon::BinaryFormat;

    let target_triple = crate::target_triple(sess);

    let mut flags_builder = settings::builder();
    flags_builder.enable("is_pic").unwrap();
    flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
    let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" };
    flags_builder.set("enable_verifier", enable_verifier).unwrap();

    let tls_model = match target_triple.binary_format {
        BinaryFormat::Elf => "elf_gd",
        BinaryFormat::Macho => "macho",
        BinaryFormat::Coff => "coff",
        _ => "none",
    };
    flags_builder.set("tls_model", tls_model).unwrap();

    flags_builder.set("enable_simd", "true").unwrap();

    flags_builder.set("enable_llvm_abi_extensions", "true").unwrap();

    use rustc_session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "none").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => {
            flags_builder.set("opt_level", "speed_and_size").unwrap();
        }
    }

    let flags = settings::Flags::new(flags_builder);

    let variant = cranelift_codegen::isa::BackendVariant::MachInst;

    let isa_builder = match sess.opts.cg.target_cpu.as_deref() {
        Some("native") => {
            let builder = cranelift_native::builder_with_options(variant, true).unwrap();
            builder
        }
        Some(value) => {
            let mut builder = cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
            if let Err(_) = builder.enable(value) {
                sess.fatal("The target cpu isn't currently supported by Cranelift.");
            }
            builder
        }
        None => {
            let mut builder = cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
            // Don't use "haswell" as the default, as it implies `has_lzcnt`.
            // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
            builder.enable("nehalem").unwrap();
            builder
        }
    };

    isa_builder.finish(flags)
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend { config: None })
}
<commit_msg>Update the error messsage<commit_after>#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts)]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![warn(unreachable_pub)]

extern crate snap;
#[macro_use]
extern crate rustc_middle;
extern crate rustc_ast;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_fs_util;
extern crate rustc_hir;
extern crate rustc_incremental;
extern crate rustc_index;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;

// This prevents duplicating functions and statics that are already part of the host rustc process.
#[allow(unused_extern_crates)]
extern crate rustc_driver;

use std::any::Any;

use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::CodegenResults;
use rustc_errors::ErrorReported;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
use rustc_middle::ty::query::Providers;
use rustc_session::config::OutputFilenames;
use rustc_session::Session;

use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::settings::{self, Configurable};

pub use crate::config::*;
use crate::prelude::*;

mod abi;
mod allocator;
mod analyze;
mod archive;
mod backend;
mod base;
mod cast;
mod codegen_i128;
mod common;
mod compiler_builtins;
mod config;
mod constant;
mod debuginfo;
mod discriminant;
mod driver;
mod inline_asm;
mod intrinsics;
mod linkage;
mod main_shim;
mod metadata;
mod num;
mod optimize;
mod pointer;
mod pretty_clif;
mod toolchain;
mod trap;
mod unsize;
mod value_and_place;
mod vtable;

mod prelude {
    pub(crate) use std::convert::{TryFrom, TryInto};

    pub(crate) use rustc_span::Span;

    pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
    pub(crate) use rustc_middle::bug;
    pub(crate) use rustc_middle::mir::{self, *};
    pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout};
    pub(crate) use rustc_middle::ty::{
        self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut,
        TypeFoldable, UintTy,
    };
    pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx};

    pub(crate) use rustc_data_structures::fx::FxHashMap;

    pub(crate) use rustc_index::vec::Idx;

    pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
    pub(crate) use cranelift_codegen::ir::function::Function;
    pub(crate) use cranelift_codegen::ir::types;
    pub(crate) use cranelift_codegen::ir::{
        AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc,
        StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value,
    };
    pub(crate) use cranelift_codegen::isa::{self, CallConv};
    pub(crate) use cranelift_codegen::Context;
    pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
    pub(crate) use cranelift_module::{self, DataContext, DataId, FuncId, Linkage, Module};

    pub(crate) use crate::abi::*;
    pub(crate) use crate::base::{codegen_operand, codegen_place};
    pub(crate) use crate::cast::*;
    pub(crate) use crate::common::*;
    pub(crate) use crate::debuginfo::{DebugContext, UnwindContext};
    pub(crate) use crate::pointer::Pointer;
    pub(crate) use crate::trap::*;
    pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue};
}

struct PrintOnPanic<F: Fn() -> String>(F);
impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
    fn drop(&mut self) {
        if ::std::thread::panicking() {
            println!("{}", (self.0)());
        }
    }
}

/// The codegen context holds any information shared between the codegen of individual functions
/// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
struct CodegenCx<'tcx> {
    tcx: TyCtxt<'tcx>,
    global_asm: String,
    cached_context: Context,
    debug_context: Option<DebugContext<'tcx>>,
    unwind_context: UnwindContext,
}

impl<'tcx> CodegenCx<'tcx> {
    fn new(
        tcx: TyCtxt<'tcx>,
        backend_config: BackendConfig,
        isa: &dyn TargetIsa,
        debug_info: bool,
    ) -> Self {
        assert_eq!(pointer_ty(tcx), isa.pointer_type());

        let unwind_context =
            UnwindContext::new(tcx, isa, matches!(backend_config.codegen_mode, CodegenMode::Aot));
        let debug_context = if debug_info { Some(DebugContext::new(tcx, isa)) } else { None };
        CodegenCx {
            tcx,
            global_asm: String::new(),
            cached_context: Context::new(),
            debug_context,
            unwind_context,
        }
    }
}

pub struct CraneliftCodegenBackend {
    pub config: Option<BackendConfig>,
}

impl CodegenBackend for CraneliftCodegenBackend {
    fn init(&self, sess: &Session) {
        use rustc_session::config::Lto;
        match sess.lto() {
            Lto::No | Lto::ThinLocal => {}
            Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."),
        }
    }

    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
        Box::new(crate::metadata::CraneliftMetadataLoader)
    }

    fn provide(&self, _providers: &mut Providers) {}
    fn provide_extern(&self, _providers: &mut Providers) {}

    fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
        vec![]
    }

    fn codegen_crate(
        &self,
        tcx: TyCtxt<'_>,
        metadata: EncodedMetadata,
        need_metadata_module: bool,
    ) -> Box<dyn Any> {
        tcx.sess.abort_if_errors();
        let config = if let Some(config) = self.config.clone() {
            config
        } else {
            BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
                .unwrap_or_else(|err| tcx.sess.fatal(&err))
        };
        match config.codegen_mode {
            CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module),
            CodegenMode::Jit | CodegenMode::JitLazy => {
                #[cfg(feature = "jit")]
                let _: ! = driver::jit::run_jit(tcx, config);

                #[cfg(not(feature = "jit"))]
                tcx.sess.fatal("jit support was disabled when compiling rustc_codegen_cranelift");
            }
        }
    }

    fn join_codegen(
        &self,
        ongoing_codegen: Box<dyn Any>,
        _sess: &Session,
    ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> {
        Ok(*ongoing_codegen
            .downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>()
            .unwrap())
    }

    fn link(
        &self,
        sess: &Session,
        codegen_results: CodegenResults,
        outputs: &OutputFilenames,
    ) -> Result<(), ErrorReported> {
        use rustc_codegen_ssa::back::link::link_binary;

        let target_cpu = crate::target_triple(sess).to_string();
        link_binary::<crate::archive::ArArchiveBuilder<'_>>(
            sess,
            &codegen_results,
            outputs,
            &codegen_results.crate_name.as_str(),
            &target_cpu,
        );

        Ok(())
    }
}

fn target_triple(sess: &Session) -> target_lexicon::Triple {
    sess.target.llvm_target.parse().unwrap()
}

fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::TargetIsa + 'static> {
    use target_lexicon::BinaryFormat;

    let target_triple = crate::target_triple(sess);

    let mut flags_builder = settings::builder();
    flags_builder.enable("is_pic").unwrap();
    flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
    let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" };
    flags_builder.set("enable_verifier", enable_verifier).unwrap();

    let tls_model = match target_triple.binary_format {
        BinaryFormat::Elf => "elf_gd",
        BinaryFormat::Macho => "macho",
        BinaryFormat::Coff => "coff",
        _ => "none",
    };
    flags_builder.set("tls_model", tls_model).unwrap();

    flags_builder.set("enable_simd", "true").unwrap();

    flags_builder.set("enable_llvm_abi_extensions", "true").unwrap();

    use rustc_session::config::OptLevel;
    match sess.opts.optimize {
        OptLevel::No => {
            flags_builder.set("opt_level", "none").unwrap();
        }
        OptLevel::Less | OptLevel::Default => {}
        OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => {
            flags_builder.set("opt_level", "speed_and_size").unwrap();
        }
    }

    let flags = settings::Flags::new(flags_builder);

    let variant = cranelift_codegen::isa::BackendVariant::MachInst;

    let isa_builder = match sess.opts.cg.target_cpu.as_deref() {
        Some("native") => {
            let builder = cranelift_native::builder_with_options(variant, true).unwrap();
            builder
        }
        Some(value) => {
            let mut builder = cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
            if let Err(_) = builder.enable(value) {
                sess.fatal("The specified target cpu isn't currently supported by Cranelift.");
            }
            builder
        }
        None => {
            let mut builder = cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
            // Don't use "haswell" as the default, as it implies `has_lzcnt`.
            // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
            builder.enable("nehalem").unwrap();
            builder
        }
    };

    isa_builder.finish(flags)
}

/// This is the entrypoint for a hot plugged rustc_codegen_cranelift
#[no_mangle]
pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
    Box::new(CraneliftCodegenBackend { config: None })
}
<|endoftext|>


<commit_before>#![crate_type = "rlib"]
#![feature(macro_rules,globs)]

#[macro_export]
macro_rules! monad(
    ($m:ident {
        let $p:pat <- $e:expr;
        $(let $p_rest:pat <- $e_rest:expr;)*
    } in $y:expr) => (
        $m::mbind($e,|$p| {
            monad!($m {
                $(let $p_rest <- $e_rest;)*
            } in $y)
        }));
    ($m:ident { } in $y:expr) => ($m::mpure($y));
)

pub struct OptionMonad;

impl OptionMonad {
    pub fn mpure<T>(value: T) -> Option<T> { Some(value) }
    pub fn mbind<T,U>(value: Option<T>, func: |T| -> Option<U>) -> Option<U> {
        match value {
            Some(v) => func(v),
            None => None
        }
    }
}

pub struct ResultMonad;

impl ResultMonad {
    pub fn mpure<T,E>(value: T) -> Result<T,E> { Ok(value) }
    pub fn mbind<T,U,E>(value: Result<T,E>, func: |T| -> Result<U,E>) -> Result<U,E> {
        match value {
            Ok(v) => func(v),
            Err(e) => Err(e)
        }
    }
}

pub struct IterMonad;

impl IterMonad {
    pub fn mpure<T>(value: T) -> std::option::Item<T> {
        Some(value).move_iter()
    }
    pub fn mbind<T,U,I:Iterator<T>,J:Iterator<U>>(value: I, func: |T| -> J)
                                                  -> std::vec::MoveItems<U> {
        value.flat_map(func).collect::<Vec<U>>().move_iter()
    }
}

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

    #[test]
    fn option() {
        let result = monad!(OptionMonad {
            let (a,x) <- Some((2i,6i));
            let (b,y) <- Some((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Some((2+3,6*7)));
    }

    #[test]
    fn option_fail() {
        let result = monad!(OptionMonad {
            let (a,x) <- None::<(int,int)>;
            let (b,y) <- Some((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, None);
    }

    #[test]
    fn result() {
        let result: Result<(int,int),()> = monad!(ResultMonad {
            let (a,x) <- Ok((2i,6i));
            let (b,y) <- Ok((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Ok((2+3,6*7)));
    }

    #[test]
    fn result_fail() {
        let result: Result<(int,int),()> = monad!(ResultMonad {
            let (a,x) <- Err::<(int,int),()>(());
            let (b,y) <- Ok((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Err(()));
    }

    #[test]
    fn iter() {
        let mut result = monad!(IterMonad {
            let a <- vec![1u,2,3].move_iter();
            let b <- vec!["hello"].move_iter();
        } in (a,b));

        assert_eq!(result.collect::<Vec<(uint,&'static str)>>(),
                   vec![(1u,"hello"),(2,"hello"),(3,"hello")]);
    }
}
<commit_msg>Fix some deprecation warnings<commit_after>#![crate_type = "rlib"]
#![feature(macro_rules,globs)]

#[macro_export]
macro_rules! monad(
    ($m:ident {
        let $p:pat <- $e:expr;
        $(let $p_rest:pat <- $e_rest:expr;)*
    } in $y:expr) => (
        $m::mbind($e,|$p| {
            monad!($m {
                $(let $p_rest <- $e_rest;)*
            } in $y)
        }));
    ($m:ident { } in $y:expr) => ($m::mpure($y));
)

pub struct OptionMonad;

impl OptionMonad {
    pub fn mpure<T>(value: T) -> Option<T> { Some(value) }
    pub fn mbind<T,U>(value: Option<T>, func: |T| -> Option<U>) -> Option<U> {
        match value {
            Some(v) => func(v),
            None => None
        }
    }
}

pub struct ResultMonad;

impl ResultMonad {
    pub fn mpure<T,E>(value: T) -> Result<T,E> { Ok(value) }
    pub fn mbind<T,U,E>(value: Result<T,E>, func: |T| -> Result<U,E>) -> Result<U,E> {
        match value {
            Ok(v) => func(v),
            Err(e) => Err(e)
        }
    }
}

pub struct IterMonad;

impl IterMonad {
    pub fn mpure<T>(value: T) -> std::option::Item<T> {
        Some(value).into_iter()
    }
    pub fn mbind<T,U,I:Iterator<T>,J:Iterator<U>>(value: I, func: |T| -> J)
                                                  -> std::vec::MoveItems<U> {
        value.flat_map(func).collect::<Vec<U>>().into_iter()
    }
}

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

    #[test]
    fn option() {
        let result = monad!(OptionMonad {
            let (a,x) <- Some((2i,6i));
            let (b,y) <- Some((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Some((2+3,6*7)));
    }

    #[test]
    fn option_fail() {
        let result = monad!(OptionMonad {
            let (a,x) <- None::<(int,int)>;
            let (b,y) <- Some((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, None);
    }

    #[test]
    fn result() {
        let result: Result<(int,int),()> = monad!(ResultMonad {
            let (a,x) <- Ok((2i,6i));
            let (b,y) <- Ok((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Ok((2+3,6*7)));
    }

    #[test]
    fn result_fail() {
        let result: Result<(int,int),()> = monad!(ResultMonad {
            let (a,x) <- Err::<(int,int),()>(());
            let (b,y) <- Ok((3i,7i));
        } in (a+b,x*y));

        assert_eq!(result, Err(()));
    }

    #[test]
    fn iter() {
        let mut result = monad!(IterMonad {
            let a <- vec![1u,2,3].move_iter();
            let b <- vec!["hello"].move_iter();
        } in (a,b));

        assert_eq!(result.collect::<Vec<(uint,&'static str)>>(),
                   vec![(1u,"hello"),(2,"hello"),(3,"hello")]);
    }
}
<|endoftext|>


<commit_before>// Future TimeSteward API goals:
//
// – groups
// I made up API functions for this before, but I'm not sure they were perfect.
// We can use RowId's for group ids, but what kinds of things can be stored IN a group? Previously I said only RowId's could, which doesn't seem ideal. I think it would work to allow anything hashable. That would basically make a group behave like a HashSet. But then, why not make it behave like a HashMap instead? But accessor itself already behaves like a HashMap over RowId's – the essential thing groups do is to allow iterating particular subsets of that HashMap.
//
// – conveniences for serializing snapshots (not sure what)
//
// – be able to construct a new TimeSteward from any snapshot
// Issues: should snapshots expose the predictors? Also, the predictors can't be serialized. So you'd probably actually have to construct a TimeSteward from snapshot + predictors. This requires a way to iterate all fields (and group data if we add groups) in a snapshot, which is similar to the previous 2 items (iterating the whole set, which is a special case of iterating a subset; and serializing requires you to iterate everything as well)
//
// – parallelism support for predictors and events
// When an event or predictor gets invalidated while it is still running, it would be nice for it to save time by exiting early.
// Moreover, it would probably be more efficient to discard invalidated fields than to preserve them for predictors/events that are in process. The natural way for the accessors to handle this is to have get() return None, which would mean that you can never safely unwrap() the result. We could provide a "unwrap or return" macro.
//
// – Optimization features
// one possibility: user can provide a function FieldId->[(PredictorId, RowId)] that lists predictors you KNOW will be invalidated by a change to that field, then have that predictor run its get() calls with an input called "promise_inferred" or something so that we don't spend time and memory recording the dependency
// another: a predictor might have a costly computation to find the exact time of a future event, which it won't need to do if it gets invalidated long before that time comes. For that, we can provide a defer_until(time) method
//
//
//

#![feature(unboxed_closures, fn_traits, specialization, never_type, shared, raw, get_type_id)]
// #![feature (plugin, custom_derive)]
// #![plugin (serde_macros)]
// #![plugin (quickcheck_macros)]
#![cfg_attr(test,feature(core_intrinsics))]

extern crate rand;
extern crate nalgebra;
extern crate siphasher;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate crossbeam;
extern crate quickcheck;
#[macro_use]
extern crate derivative;

macro_rules! printlnerr(
    ($($arg:tt)*) => { {use std::io::Write;
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

/// Used by TimeSteward implementations.
///
/// These are public in case someone wants to try implementing a TimeSteward
/// outside of this crate, sharing some of the details with my own implementations.
/// However, anything inside this module should be
/// considered very unstable at present.
#[macro_use]
pub mod implementation_support {
  #[macro_use]
  pub mod list_of_types;
  pub mod insert_only;
  pub mod data_structures;
  #[macro_use]
  pub mod common;
}

/*#[macro_use]
/// Allows dynamic dispatch to object-unsafe traits, with some caveats.
pub mod dynamic {
  #[macro_use]
  pub mod list_of_types;
  pub mod thin_arc;
}*/

mod deterministic_random_id;
pub use deterministic_random_id::*;
#[macro_use]
mod api;
#[macro_use]
mod api_macros;
pub use api::*;
pub use implementation_support::list_of_types::{ColumnType, EventType, PredictorType};

#[macro_use]
pub mod stewards {
  pub mod inefficient_flat;
  pub mod memoized_flat;
  pub mod amortized;
  //pub mod optimized;

  pub mod flat_to_inefficient_full;
  pub mod crossverified;
  pub mod simply_synchronized;
}

#[macro_use]
pub mod support {
  pub mod rounding_error_tolerant_math;
  pub mod time_functions;
  pub mod collision_detection;
}

pub mod rowless {
  #[macro_use]
  pub mod implementation_support { #[macro_use] pub mod common; }
  #[macro_use]
  pub mod serialization;
  #[macro_use]
  pub mod api;
  pub mod api_impls;
  #[macro_use]
  pub mod support { #[macro_use] pub mod simple_timeline; }
  pub mod stewards {
    pub mod simple_flat;
    #[macro_use]
    pub mod simple_full;
    pub mod auditing;
  }
}

<commit_msg>fix `cargo test` error<commit_after>// Future TimeSteward API goals:
//
// – groups
// I made up API functions for this before, but I'm not sure they were perfect.
// We can use RowId's for group ids, but what kinds of things can be stored IN a group? Previously I said only RowId's could, which doesn't seem ideal. I think it would work to allow anything hashable. That would basically make a group behave like a HashSet. But then, why not make it behave like a HashMap instead? But accessor itself already behaves like a HashMap over RowId's – the essential thing groups do is to allow iterating particular subsets of that HashMap.
//
// – conveniences for serializing snapshots (not sure what)
//
// – be able to construct a new TimeSteward from any snapshot
// Issues: should snapshots expose the predictors? Also, the predictors can't be serialized. So you'd probably actually have to construct a TimeSteward from snapshot + predictors. This requires a way to iterate all fields (and group data if we add groups) in a snapshot, which is similar to the previous 2 items (iterating the whole set, which is a special case of iterating a subset; and serializing requires you to iterate everything as well)
//
// – parallelism support for predictors and events
// When an event or predictor gets invalidated while it is still running, it would be nice for it to save time by exiting early.
// Moreover, it would probably be more efficient to discard invalidated fields than to preserve them for predictors/events that are in process. The natural way for the accessors to handle this is to have get() return None, which would mean that you can never safely unwrap() the result. We could provide a "unwrap or return" macro.
//
// – Optimization features
// one possibility: user can provide a function FieldId->[(PredictorId, RowId)] that lists predictors you KNOW will be invalidated by a change to that field, then have that predictor run its get() calls with an input called "promise_inferred" or something so that we don't spend time and memory recording the dependency
// another: a predictor might have a costly computation to find the exact time of a future event, which it won't need to do if it gets invalidated long before that time comes. For that, we can provide a defer_until(time) method
//
//
//

#![feature(unboxed_closures, fn_traits, specialization, never_type, shared, raw, get_type_id)]
// #![feature (plugin, custom_derive)]
// #![plugin (serde_macros)]
// #![plugin (quickcheck_macros)]
#![cfg_attr(test,feature(core_intrinsics))]

extern crate rand;
extern crate nalgebra;
extern crate siphasher;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate crossbeam;
#[cfg_attr(test, macro_use)]
extern crate quickcheck;
#[macro_use]
extern crate derivative;

macro_rules! printlnerr(
    ($($arg:tt)*) => { {use std::io::Write;
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

/// Used by TimeSteward implementations.
///
/// These are public in case someone wants to try implementing a TimeSteward
/// outside of this crate, sharing some of the details with my own implementations.
/// However, anything inside this module should be
/// considered very unstable at present.
#[macro_use]
pub mod implementation_support {
  #[macro_use]
  pub mod list_of_types;
  pub mod insert_only;
  pub mod data_structures;
  #[macro_use]
  pub mod common;
}

/*#[macro_use]
/// Allows dynamic dispatch to object-unsafe traits, with some caveats.
pub mod dynamic {
  #[macro_use]
  pub mod list_of_types;
  pub mod thin_arc;
}*/

mod deterministic_random_id;
pub use deterministic_random_id::*;
#[macro_use]
mod api;
#[macro_use]
mod api_macros;
pub use api::*;
pub use implementation_support::list_of_types::{ColumnType, EventType, PredictorType};

#[macro_use]
pub mod stewards {
  pub mod inefficient_flat;
  pub mod memoized_flat;
  pub mod amortized;
  //pub mod optimized;

  pub mod flat_to_inefficient_full;
  pub mod crossverified;
  pub mod simply_synchronized;
}

#[macro_use]
pub mod support {
  pub mod rounding_error_tolerant_math;
  pub mod time_functions;
  pub mod collision_detection;
}

pub mod rowless {
  #[macro_use]
  pub mod implementation_support { #[macro_use] pub mod common; }
  #[macro_use]
  pub mod serialization;
  #[macro_use]
  pub mod api;
  pub mod api_impls;
  #[macro_use]
  pub mod support { #[macro_use] pub mod simple_timeline; }
  pub mod stewards {
    pub mod simple_flat;
    #[macro_use]
    pub mod simple_full;
    pub mod auditing;
  }
}

<|endoftext|>