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
//! A few useful predicates for media messages.

use crate::contexts::fields::Document;
use futures::future::BoxFuture;
use std::{ops::Deref, path::Path, sync::Arc};

/// Checks if the document's extension matches one of the given extensions.
pub fn match_extension<'a, I, T, C>(
    extensions: I,
) -> impl Fn(Arc<C>) -> BoxFuture<'a, bool> + Send + Sync + 'a
where
    for<'b> &'b I: IntoIterator<Item = &'b T>,
    T: Deref<Target = str>,
    I: Send + Sync + 'a,
    C: Document + Send + Sync + 'a,
{
    let extensions = Arc::new(extensions);

    move |context: Arc<C>| {
        let extensions = Arc::clone(&extensions);

        Box::pin(async move {
            let Some(file_name) = context.document().file_name.as_ref() else {
                return false;
            };

            let Some(extension) = Path::new(&file_name).extension() else {
                return false;
            };

            let extension = extension.to_string_lossy();

            extensions.into_iter().any(|x| **x == *extension)
        })
    }
}