Skip to content

Commit 1d5383a

Browse files
authored
perf: RawBufferSource value_as_string (#167)
1 parent 79e2dfc commit 1d5383a

File tree

3 files changed

+104
-23
lines changed

3 files changed

+104
-23
lines changed

Cargo.lock

Lines changed: 56 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ itertools = "0.13"
4242
codspeed-criterion-compat = { version = "2.7.2", default-features = false, optional = true }
4343
static_assertions = "1.1.0"
4444
simd-json = "0.14.3"
45+
ouroboros = "0.18.5"
4546

4647
[dev-dependencies]
4748
twox-hash = "2.1.0"

src/raw_source.rs

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use std::{
44
sync::OnceLock,
55
};
66

7+
use ouroboros::self_referencing;
8+
79
use crate::{
810
helpers::{
911
get_generated_source_info, stream_chunks_of_raw_source, OnChunk, OnName,
@@ -362,61 +364,85 @@ impl StreamChunks for RawStringSource {
362364
/// assert_eq!(s.map(&MapOptions::default()), None);
363365
/// assert_eq!(s.size(), 16);
364366
/// ```
365-
#[derive(Clone, PartialEq, Eq)]
367+
#[self_referencing]
366368
pub struct RawBufferSource {
367369
value: Vec<u8>,
368-
value_as_string: OnceLock<String>,
370+
#[borrows(value)]
371+
#[not_covariant]
372+
value_as_string: OnceLock<Cow<'this, str>>,
373+
}
374+
375+
impl RawBufferSource {
376+
fn get_or_init_value_as_string(&self) -> &str {
377+
self.with(|fields| {
378+
fields
379+
.value_as_string
380+
.get_or_init(|| String::from_utf8_lossy(fields.value))
381+
})
382+
}
369383
}
370384

385+
impl Clone for RawBufferSource {
386+
fn clone(&self) -> Self {
387+
RawBufferSourceBuilder {
388+
value: self.borrow_value().clone(),
389+
value_as_string_builder: |_: &Vec<u8>| Default::default(),
390+
}
391+
.build()
392+
}
393+
}
394+
395+
impl PartialEq for RawBufferSource {
396+
fn eq(&self, other: &Self) -> bool {
397+
self.borrow_value() == other.borrow_value()
398+
}
399+
}
400+
401+
impl Eq for RawBufferSource {}
402+
371403
impl From<Vec<u8>> for RawBufferSource {
372404
fn from(value: Vec<u8>) -> Self {
373-
Self {
405+
RawBufferSourceBuilder {
374406
value,
375-
value_as_string: Default::default(),
407+
value_as_string_builder: |_: &Vec<u8>| Default::default(),
376408
}
409+
.build()
377410
}
378411
}
379412

380413
impl From<&[u8]> for RawBufferSource {
381414
fn from(value: &[u8]) -> Self {
382-
Self {
415+
RawBufferSourceBuilder {
383416
value: value.to_vec(),
384-
value_as_string: Default::default(),
417+
value_as_string_builder: |_: &Vec<u8>| Default::default(),
385418
}
419+
.build()
386420
}
387421
}
388422

389423
impl Source for RawBufferSource {
390424
fn source(&self) -> Cow<str> {
391-
Cow::Borrowed(
392-
self
393-
.value_as_string
394-
.get_or_init(|| String::from_utf8_lossy(&self.value).to_string()),
395-
)
425+
Cow::Borrowed(self.get_or_init_value_as_string())
396426
}
397427

398428
fn rope(&self) -> Rope<'_> {
399-
Rope::from(
400-
self
401-
.value_as_string
402-
.get_or_init(|| String::from_utf8_lossy(&self.value).to_string()),
403-
)
429+
Rope::from(self.get_or_init_value_as_string())
404430
}
405431

406432
fn buffer(&self) -> Cow<[u8]> {
407-
Cow::Borrowed(&self.value)
433+
Cow::Borrowed(self.borrow_value())
408434
}
409435

410436
fn size(&self) -> usize {
411-
self.value.len()
437+
self.borrow_value().len()
412438
}
413439

414440
fn map(&self, _: &MapOptions) -> Option<SourceMap> {
415441
None
416442
}
417443

418444
fn to_writer(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()> {
419-
writer.write_all(&self.value)
445+
writer.write_all(self.borrow_value())
420446
}
421447
}
422448

@@ -430,7 +456,7 @@ impl std::fmt::Debug for RawBufferSource {
430456
write!(
431457
f,
432458
"{indent_str}RawBufferSource::from({:?}).boxed()",
433-
self.value
459+
self.borrow_value()
434460
)
435461
}
436462
}
@@ -454,9 +480,7 @@ impl StreamChunks for RawBufferSource {
454480
get_generated_source_info(&*self.source())
455481
} else {
456482
stream_chunks_of_raw_source(
457-
&**self
458-
.value_as_string
459-
.get_or_init(|| String::from_utf8_lossy(&self.value).to_string()),
483+
self.get_or_init_value_as_string(),
460484
options,
461485
on_chunk,
462486
on_source,

0 commit comments

Comments
 (0)