use std::error::Error as StdError;
use std::fmt;
use std::path::PathBuf;
use std::pin::Pin;
use async_trait::async_trait;
use futures_core::Stream;
use tokio_util::sync::CancellationToken;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Generation(u64);
impl Generation {
pub const ZERO: Self = Self(0);
#[must_use]
pub const fn new(value: u64) -> Self {
Self(value)
}
#[must_use]
pub const fn next(self) -> Self {
Self(self.0.saturating_add(1))
}
#[must_use]
pub const fn get(self) -> u64 {
self.0
}
}
impl fmt::Display for Generation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "gen#{}", self.0)
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct Snapshot<R> {
pub generation: Generation,
pub data: R,
}
impl<R> Snapshot<R> {
pub const fn new(generation: Generation, data: R) -> Self {
Self { generation, data }
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum Cause {
Initial,
Rescan,
External,
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct GenerationEvent {
pub generation: Generation,
pub cause: Cause,
}
impl GenerationEvent {
#[must_use]
pub const fn new(generation: Generation, cause: Cause) -> Self {
Self { generation, cause }
}
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum RescanScope {
All,
Paths(Vec<PathBuf>),
}
#[non_exhaustive]
#[derive(Debug, Clone)]
pub struct RescanTicket {
generation: Generation,
}
impl RescanTicket {
#[must_use]
pub const fn new(generation: Generation) -> Self {
Self { generation }
}
#[must_use]
pub const fn generation(&self) -> Generation {
self.generation
}
}
#[derive(Clone)]
pub struct Progress {
inner: ProgressInner,
}
#[derive(Clone)]
enum ProgressInner {
Noop,
}
impl Progress {
#[must_use]
pub fn noop() -> Self {
Self {
inner: ProgressInner::Noop,
}
}
pub fn report(&self, _message: &str, _percentage: Option<u32>) {
match self.inner {
ProgressInner::Noop => {}
}
}
}
impl fmt::Debug for Progress {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Progress").finish_non_exhaustive()
}
}
impl Default for Progress {
fn default() -> Self {
Self::noop()
}
}
pub type GenerationEventStream = Pin<Box<dyn Stream<Item = GenerationEvent> + Send + 'static>>;
#[async_trait]
pub trait EngineApi: Send + Sync + 'static {
type Report: Send + Sync + 'static;
type Query: Send + Sync;
type Error: StdError + Send + Sync + 'static;
fn generation(&self) -> Generation;
async fn report(
&self,
query: Self::Query,
cancel: CancellationToken,
) -> Result<Snapshot<Self::Report>, Self::Error>;
async fn rescan(
&self,
scope: RescanScope,
progress: Progress,
) -> Result<RescanTicket, Self::Error>;
fn subscribe(&self) -> GenerationEventStream;
async fn shutdown(&self) -> Result<(), Self::Error>;
}