pub mod fallback;
pub mod marker;
pub mod start_directory;
pub mod state;
use std::marker::PhantomData;
pub use self::fallback::Fallback;
pub use self::marker::Marker;
pub use self::start_directory::StartDirectory;
pub use self::state::Marked;
pub use self::state::State;
use self::state::Unmarked;
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Search<S: State> {
start: StartDirectory,
markers: Vec<Marker>,
fallback: Fallback,
state: PhantomData<S>,
}
impl Search<Unmarked> {
pub fn start(start: impl Into<StartDirectory>) -> Self {
Self {
start: start.into(),
markers: Vec::new(),
fallback: Fallback::Error,
state: PhantomData,
}
}
pub fn working_directory() -> Self {
Self::start(".")
}
}
impl<S: State> Search<S> {
pub fn marker(self, marker: impl Into<Marker>) -> Search<Marked> {
let mut markers = self.markers;
markers.push(marker.into());
Search {
start: self.start,
markers,
fallback: self.fallback,
state: PhantomData,
}
}
pub fn fallback(&self) -> Fallback {
self.fallback
}
pub fn markers(&self) -> &[Marker] {
&self.markers
}
pub fn or_start(mut self) -> Self {
self.fallback = Fallback::Start;
self
}
pub fn start_directory(&self) -> &StartDirectory {
&self.start
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::missing_panics_doc)]
use super::*;
#[test]
fn marker_with_two_markers_keeps_the_order_of_the_calls() {
let search = Search::start(".").marker(".git").marker("src/main.rs");
let markers: Vec<_> = search.markers().iter().map(Marker::get).collect();
assert_eq!(
markers,
vec![
std::path::Path::new(".git"),
std::path::Path::new("src/main.rs")
]
);
}
#[test]
fn search_is_send_and_sync() {
fn assert_send_and_sync<T: Send + Sync>() {}
assert_send_and_sync::<Search<Marked>>();
}
}