1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#![doc(html_playground_url = "https://play.rust-lang.org/")]
//! Chase: File following
//!
//! Chase a file through thick and thin:
//!
//!   * Provide line numbers with each line yielded
//!   * Ability to exit the watch loop programmatically
//!   * Deals with file rotations automatically
//!   * Cross-platform async
//!   * Configurable (which line to start on, delays and retries)
//!   * Easy to use synchronously
//!   * Async modes (incl. support for Future Streams)
//!
//! # Examples
//!
//! ## Sync
//!
//! Here, we enter a synchronous watch loop and use Control::Stop and Control::Continue
//! to decide when we want to exit the loop
//!
//! ```
//! # extern crate chase;
//! # extern crate tempdir;
//! # use chase::*;
//! # use tempdir::*;
//! # use std::io::Write;
//! # use std::fs::OpenOptions;
//! # fn main () {
//! let temp_dir = TempDir::new("chase-test-sync-docs").unwrap();
//! let file_path = temp_dir.path().join("test.log");
//! let mut chaser = Chaser::new(&file_path);
//!
//! let mut file_write = OpenOptions::new()
//!   .write(true)
//!   .append(true)
//!   .create(true)
//!   .open(&file_path)
//!   .unwrap();
//!
//! write!(file_write, "Hello, world 1\n").unwrap();
//! write!(file_write, "Hello, world 2\n").unwrap();
//! write!(file_write, "Hello, world 3\n").unwrap();
//!
//! let mut seen = Vec::with_capacity(3);
//!
//! // This is a synchronous loop; so we need to exit manually
//! chaser.run(|line, _, _| {
//!     seen.push(line.to_string());
//!     if seen.len() < 3 {
//!         Ok(Control::Continue)
//!     } else {
//!         Ok(Control::Stop)
//!     }
//! }).unwrap();
//!
//! assert_eq!(seen, vec!["Hello, world 1".to_string(), "Hello, world 2".to_string(), "Hello, world 3".to_string()]);
//! drop(file_write);
//! temp_dir.close().unwrap();
//! # }
//! ```
//!
//! ## Async
//!
//! This is how you would use Chase with standard lib Channels, though
//! Future Stream usage, available through a feature, is similar.
//!
//! In async modes, simply drop the receiving end and the watch loop will stop. Any
//! elements that it tries to send you afterwards will bubble up to you as the Err
//! result of joining the thread, which is the same as how channels normally act.
//!
//! ```
//! # extern crate chase;
//! # extern crate tempdir;
//! # use chase::*;
//! # use tempdir::*;
//! # use std::io::Write;
//! # use std::fs::OpenOptions;
//! # fn main () {
//! let temp_dir = TempDir::new("chase-test-lib").unwrap();
//! let file_path = temp_dir.path().join("test.log");
//! let chaser = Chaser::new(&file_path);
//!
//! let mut file_write = OpenOptions::new()
//!   .write(true)
//!   .append(true)
//!   .create(true)
//!   .open(&file_path)
//!   .unwrap();
//!
//! write!(file_write, "Hello, world 1\n").unwrap();
//! write!(file_write, "Hello, world 2\n").unwrap();
//!
//! let mut seen = String::new();
//!
//! let (receiver, _) = chaser.run_channel().unwrap();
//!
//! seen.push_str(&receiver.recv().unwrap().0);
//! seen.push_str(&receiver.recv().unwrap().0);
//!
//! assert_eq!(seen.as_str(), "Hello, world 1Hello, world 2");
//!
//! write!(file_write, "Hello, world 3\n").unwrap();
//! seen.push_str(&receiver.recv().unwrap().0);
//! assert_eq!(seen.as_str(), "Hello, world 1Hello, world 2Hello, world 3");
//!
//! drop(receiver);
//! drop(file_write);
//! temp_dir.close().unwrap();
//! # }
//! ```
//!
#[cfg(feature = "stream")]
extern crate futures;

#[cfg(test)]
extern crate tempdir;

mod data;
mod sync;
mod async;
mod errors;
mod control;

#[cfg(feature = "with-serde")]
#[cfg_attr(feature = "with-serde", macro_use)]
extern crate serde_derive;

pub use data::{Chaser, Line, Pos, DEFAULT_NOT_ROTATED_WAIT_MILLIS,
               DEFAULT_ROTATION_CHECK_WAIT_MILLIS};

pub use errors::ChaseError;

pub use control::Control;