rspack_cacheable 0.100.0-rc.2

rspack_cacheable
Documentation
use rkyv::{
  Archive, Archived, Deserialize, Place, Resolver, Serialize,
  rancor::Fallible,
  ser::{Allocator, Writer},
  with::{ArchiveWith, DeserializeWith, SerializeWith},
};
use rspack_cacheable_macros::enable_cacheable as cacheable;
use rspack_sources::{
  BoxSource, ObjectPool, RawBufferSource, Source, SourceExt, SourceMap, SourceMapSource,
  WithoutOriginalOptions,
};

use super::AsPreset;
use crate::{Error, Result};

#[cacheable(crate=crate)]
pub struct CacheableSource {
  buffer: Vec<u8>,
  map: Option<String>,
}

pub struct InnerResolver {
  source: CacheableSource,
  resolver: Resolver<CacheableSource>,
}

impl ArchiveWith<BoxSource> for AsPreset {
  type Archived = Archived<CacheableSource>;
  type Resolver = InnerResolver;

  #[inline]
  fn resolve_with(_field: &BoxSource, resolver: Self::Resolver, out: Place<Self::Archived>) {
    let InnerResolver { source, resolver } = resolver;
    source.resolve(resolver, out)
  }
}

impl<S> SerializeWith<BoxSource, S> for AsPreset
where
  S: Fallible<Error = Error> + Allocator + Writer,
{
  fn serialize_with(field: &BoxSource, serializer: &mut S) -> Result<Self::Resolver> {
    let map = field
      .map(&ObjectPool::default(), &Default::default())
      .map(|m| m.to_json());
    let source = CacheableSource {
      buffer: field.buffer().to_vec(),
      map,
    };
    Ok(InnerResolver {
      resolver: source.serialize(serializer)?,
      source,
    })
  }
}

impl<D> DeserializeWith<Archived<CacheableSource>, BoxSource, D> for AsPreset
where
  D: Fallible<Error = Error>,
{
  fn deserialize_with(
    field: &Archived<CacheableSource>,
    deserializer: &mut D,
  ) -> Result<BoxSource> {
    let CacheableSource { buffer, map } = field.deserialize(deserializer)?;
    if let Some(map) = &map
      && let Ok(source_map) = SourceMap::from_json(map)
    {
      return Ok(
        SourceMapSource::new(WithoutOriginalOptions {
          value: String::from_utf8_lossy(&buffer),
          name: "persistent-cache",
          source_map,
        })
        .boxed(),
      );
    }
    Ok(RawBufferSource::from(buffer).boxed())
  }
}