All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sjsonnet.CachedResolvedFile.scala Maven / Gradle / Ivy

package sjsonnet

import java.io.{BufferedInputStream, File, FileInputStream}
import java.nio.charset.StandardCharsets
import java.nio.file.Files

import fastparse.ParserInput

/**
 * A class that encapsulates a resolved import. This is used to cache the result of
 * resolving an import. If the import is deemed too large (IE it's a large file), then we will avoid keeping it in
 * memory and instead will re-read it from disk.
 *
 * @param resolvedImportPath The path of the file on disk that was resolved
 * @param memoryLimitBytes The maximum size of a file that we will resolve. This is not the size of
 * the buffer, but a mechanism to fail when being asked to resolve (and downstream parse) a file
 * that is beyond this limit.
 * @param cacheThresholdBytes The maximum size of a file that we will cache in memory. If the file
 * is larger than this, then we will serve it from disk
 */
class CachedResolvedFile(val resolvedImportPath: OsPath, memoryLimitBytes: Long, cacheThresholdBytes: Long = 1024 * 1024) extends ResolvedFile {

  private val jFile: File = resolvedImportPath.p.toIO

  assert(jFile.exists(), s"Resolved import path ${resolvedImportPath} does not exist")
  // Assert that the file is less than limit
  assert(jFile.length() <= memoryLimitBytes, s"Resolved import path ${resolvedImportPath} is too large: ${jFile.length()} bytes > ${memoryLimitBytes} bytes")

  private[this] val resolvedImportContent: StaticResolvedFile = {
    if (jFile.length() > cacheThresholdBytes) {
      // If the file is too large, then we will just read it from disk
      null
    } else {
      StaticResolvedFile(readString(jFile))
    }
  }

  private[this] def readString(jFile: File): String = {
    new String(Files.readAllBytes(jFile.toPath), StandardCharsets.UTF_8);
  }

  /**
   * A method that will return a reader for the resolved import. If the import is too large, then this will return
   * a reader that will read the file from disk. Otherwise, it will return a reader that reads from memory.
   */
  def getParserInput(): ParserInput = {
    if (resolvedImportContent == null) {
      FileParserInput(jFile)
    } else {
      resolvedImportContent.getParserInput()
    }
  }

  override def readString(): String = {
    if (resolvedImportContent == null) {
      // If the file is too large, then we will just read it from disk
      readString(jFile)
    } else {
      // Otherwise, we will read it from memory
      resolvedImportContent.readString()
    }
  }

  override lazy val contentHash: String = {
    if (resolvedImportContent == null) {
      // If the file is too large, then we will just read it from disk
      Platform.hashFile(jFile)
    } else {
      resolvedImportContent.contentHash
    }
  }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy