Skip to content

Commit

Permalink
try
Browse files Browse the repository at this point in the history
  • Loading branch information
SyMind committed Dec 16, 2024
1 parent 6e4df5f commit a2968fd
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 27 deletions.
66 changes: 66 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ rustc-hash = "2.1.0"
dashmap = "6.1.0"
memchr = "2.7.4"
itertools = "0.13"

ouroboros = "0.18.4"

codspeed-criterion-compat = { version = "2.7.2", default-features = false, optional = true }
static_assertions = "1.1.0"
Expand Down
85 changes: 59 additions & 26 deletions src/cached_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,58 +49,81 @@ use crate::{
/// "Hello World\nconsole.log('test');\nconsole.log('test2');\nHello2\n"
/// );
/// ```
pub struct CachedSource<T> {
pub struct CachedSource<T: 'static> {
inner: CachedSourceInner<T>,
}

#[ouroboros::self_referencing]
pub struct CachedSourceInner<T: 'static> {
inner: Arc<T>,
#[not_covariant]
#[borrows(inner)]
cached_rope: Arc<OnceLock<Rope<'this>>>,
cached_hash: Arc<OnceLock<u64>>,
cached_maps:
Arc<DashMap<MapOptions, Option<SourceMap>, BuildHasherDefault<FxHasher>>>,
}

impl<T: Source> CachedSource<T> {
fn get_rope(&self) -> &Rope<'_> {
self
.inner
.with(|cache| cache.cached_rope.get_or_init(|| cache.inner.rope()))
}
}

impl<T> CachedSource<T> {
/// Create a [CachedSource] with the original [Source].
pub fn new(inner: T) -> Self {
Self {
inner: Arc::new(inner),
cached_hash: Default::default(),
cached_maps: Default::default(),
inner: CachedSourceInner::new(
Arc::new(inner),
|_| Default::default(),
Default::default(),
Default::default(),
),
}
}

/// Get the original [Source].
pub fn original(&self) -> &T {
&self.inner
self.inner.borrow_inner()
}
}

impl<T: Source + Hash + PartialEq + Eq + 'static> Source for CachedSource<T> {
fn source(&self) -> Cow<str> {
self.inner.source()
Cow::Owned(self.get_rope().to_string())
}

fn rope(&self) -> Rope<'_> {
self.inner.rope()
self.get_rope().clone()
}

fn buffer(&self) -> Cow<[u8]> {
self.inner.buffer()
self.inner.borrow_inner().buffer()
}

fn size(&self) -> usize {
self.source().len()
}

fn map(&self, options: &MapOptions) -> Option<SourceMap> {
if let Some(map) = self.cached_maps.get(options) {
if let Some(map) = self.inner.borrow_cached_maps().get(options) {
map.clone()
} else {
let map = self.inner.map(options);
self.cached_maps.insert(options.clone(), map.clone());
let map = self.inner.borrow_inner().map(options);
self
.inner
.borrow_cached_maps()
.insert(options.clone(), map.clone());
map
}
}

fn to_writer(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()> {
self.inner.to_writer(writer)
self.inner.borrow_inner().to_writer(writer)
}
}

Expand All @@ -114,7 +137,7 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> StreamChunks
on_source: crate::helpers::OnSource<'_, 'a>,
on_name: crate::helpers::OnName<'_, 'a>,
) -> crate::helpers::GeneratedInfo {
let cached_map = self.cached_maps.entry(options.clone());
let cached_map = self.inner.borrow_cached_maps().entry(options.clone());
match cached_map {
Entry::Occupied(entry) => {
let source = self.rope();
Expand All @@ -138,7 +161,7 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> StreamChunks
}
Entry::Vacant(entry) => {
let (generated_info, map) = stream_and_get_source_and_map(
&self.inner as &T,
self.inner.borrow_inner() as &T,
options,
on_chunk,
on_source,
Expand All @@ -153,19 +176,21 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> StreamChunks

impl<T> Clone for CachedSource<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
cached_hash: self.cached_hash.clone(),
cached_maps: self.cached_maps.clone(),
}
// Self {
// inner: self.inner.clone(),
// cached_rope: Default::default(),
// cached_hash: self.cached_hash.clone(),
// cached_maps: self.cached_maps.clone(),
// }
todo!()
}
}

impl<T: Source + Hash + PartialEq + Eq + 'static> Hash for CachedSource<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
(self.cached_hash.get_or_init(|| {
(self.inner.borrow_cached_hash().get_or_init(|| {
let mut hasher = FxHasher::default();
self.inner.hash(&mut hasher);
self.original().hash(&mut hasher);
hasher.finish()
}))
.hash(state);
Expand All @@ -174,7 +199,7 @@ impl<T: Source + Hash + PartialEq + Eq + 'static> Hash for CachedSource<T> {

impl<T: PartialEq> PartialEq for CachedSource<T> {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
self.inner.borrow_inner() == other.inner.borrow_inner()
}
}

Expand All @@ -186,9 +211,12 @@ impl<T: std::fmt::Debug> std::fmt::Debug for CachedSource<T> {
f: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
f.debug_struct("CachedSource")
.field("inner", self.inner.as_ref())
.field("cached_hash", self.cached_hash.as_ref())
.field("cached_maps", &(!self.cached_maps.is_empty()))
.field("inner", self.inner.borrow_inner().as_ref())
.field("cached_hash", self.inner.borrow_cached_hash().as_ref())
.field(
"cached_maps",
&(!self.inner.borrow_cached_maps().is_empty()),
)
.finish()
}
}
Expand Down Expand Up @@ -236,7 +264,12 @@ mod tests {
source.map(&map_options);

assert_eq!(
*clone.cached_maps.get(&map_options).unwrap().value(),
*clone
.inner
.borrow_cached_maps()
.get(&map_options)
.unwrap()
.value(),
source.map(&map_options)
);
}
Expand Down

0 comments on commit a2968fd

Please sign in to comment.