Skip to content

Commit

Permalink
Added a fragment cache
Browse files Browse the repository at this point in the history
  • Loading branch information
HU90m committed Jul 12, 2023
1 parent a28ae68 commit f300527
Showing 1 changed file with 34 additions and 17 deletions.
51 changes: 34 additions & 17 deletions lychee-lib/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
clippy::default_trait_access,
clippy::used_underscore_binding
)]
use std::path::Path;
use std::{collections::HashSet, time::Duration};
use tokio::fs::File;
use tokio::io::AsyncReadExt;
use std::{
collections::{hash_map::Entry, HashMap, HashSet},
path::Path,
sync::Arc,
time::Duration,
};
use tokio::{fs::File, io::AsyncReadExt, sync::Mutex};

#[cfg(all(feature = "email-check", feature = "native-tls"))]
use check_if_email_exists::{check_email, CheckEmailInput, Reachable};
Expand Down Expand Up @@ -381,6 +384,7 @@ impl ClientBuilder {
require_https: self.require_https,
quirks,
include_fragments: self.include_fragments,
fragment_cache: Default::default(),
})
}
}
Expand Down Expand Up @@ -430,6 +434,9 @@ pub struct Client {

/// Enable the checking of fragments in links.
include_fragments: bool,

/// Caches Fragments
fragment_cache: Arc<Mutex<HashMap<String, HashSet<String>>>>,
}

impl Client {
Expand Down Expand Up @@ -669,30 +676,40 @@ impl Client {
return ErrorKind::InvalidFilePath(uri.clone()).into();
}
if self.include_fragments {
Self::check_fragment(&path, uri).await
self.check_fragment(&path, uri).await
} else {
Status::Ok(StatusCode::OK)
}
}

/// Checks a `file` URI's fragment.
pub async fn check_fragment(path: &Path, uri: &Uri) -> Status {
pub async fn check_fragment(&self, path: &Path, uri: &Uri) -> Status {
let is_md = path
.extension()
.map_or(false, |ext| ext.eq_ignore_ascii_case("md"));

if let (true, Some(frag)) = (is_md, uri.url.fragment()) {
let mut content = String::new();
File::open(path)
.await
.expect("Couldn't open a file expected to exist.")
.read_to_string(&mut content)
.await
.expect("Couldn't read a linked file.");

let frags = extract_markdown_fragments(&content);

if !frags.contains(frag) {
let url_without_frag: String = {
let mut u = uri.url.clone();
u.set_fragment(None);
u.into()
};
let frag_exists = match self.fragment_cache.lock().await.entry(url_without_frag) {
Entry::Vacant(entry) => {
let mut content = String::new();
File::open(path)
.await
.expect("Couldn't open a file expected to exist.")
.read_to_string(&mut content)
.await
.expect("Couldn't read a linked file.");

let file_frags = extract_markdown_fragments(&content);
entry.insert(file_frags).contains(frag)
}
Entry::Occupied(entry) => entry.get().contains(frag),
};
if !frag_exists {
return ErrorKind::InvalidFragment(uri.clone()).into();
}
}
Expand Down

0 comments on commit f300527

Please sign in to comment.