pub mod email;
pub mod file;
pub mod http;
pub mod twitter;
pub use self::email::Email;
pub use self::file::File;
pub use self::http::Http;
pub use self::twitter::Twitter;
use crate::entry::Entry;
use crate::error::source::EmailError;
use crate::error::source::Error as SourceError;
use crate::read_filter::ReadFilter;
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
pub enum Source {
WithSharedReadFilter {
rf: Option<Arc<RwLock<ReadFilter>>>,
kind: WithSharedRF,
},
WithCustomReadFilter(WithCustomRF),
}
#[derive(Debug)]
pub struct WithSharedRF(Vec<WithSharedRFKind>);
#[derive(Debug)]
pub enum WithSharedRFKind {
File(File),
Http(Http),
Twitter(Twitter),
}
#[derive(Debug)]
pub enum WithCustomRF {
Email(Email),
}
impl Source {
pub async fn get(
&mut self,
) -> Result<Vec<Entry>, SourceError> {
match self {
Source::WithSharedReadFilter { kind, .. } => kind.get().await,
Source::WithCustomReadFilter(x) => x.get().await,
}
}
}
impl WithSharedRF {
pub fn new(sources: Vec<WithSharedRFKind>) -> Result<Self, SourceError> {
match sources.len() {
0 => return Err(SourceError::EmptySourceList),
1 => (),
_ => {
for variants in sources.windows(2) {
use std::mem::discriminant as disc;
if disc(&variants[0]) != disc(&variants[1]) {
return Err(SourceError::SourceListHasDifferentVariants);
}
}
}
}
Ok(Self(sources))
}
pub async fn get(&mut self) -> Result<Vec<Entry>, SourceError> {
use WithSharedRFKind as K;
let mut entries = Vec::new();
for s in &mut self.0 {
entries.extend(match s {
K::Http(x) => vec![x.get().await?],
K::Twitter(x) => x.get().await?,
K::File(x) => vec![x.get().await?],
});
}
Ok(entries)
}
}
impl WithCustomRF {
pub async fn get(&mut self) -> Result<Vec<Entry>, SourceError> {
Ok(match self {
Self::Email(x) => x.get().await?,
})
}
#[allow(clippy::missing_errors_doc)]
pub async fn mark_as_read(&mut self, id: &str) -> Result<(), SourceError> {
match self {
Self::Email(x) => x
.mark_as_read(id)
.await
.map_err(|e| Box::new(EmailError::Imap(e)))?,
};
Ok(())
}
#[allow(clippy::ptr_arg)]
pub fn remove_read(&self, _entries: &mut Vec<Entry>) {
match self {
Self::Email(_) => (), }
}
}
impl TryFrom<Vec<WithSharedRFKind>> for WithSharedRF {
type Error = SourceError;
fn try_from(value: Vec<WithSharedRFKind>) -> Result<Self, Self::Error> {
Self::new(value)
}
}
impl std::ops::Deref for WithSharedRF {
type Target = [WithSharedRFKind];
fn deref(&self) -> &Self::Target {
self.0.as_slice()
}
}