Skip to content

Commit

Permalink
Load virtual data as byte arrays without using UTF-8 encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
lwronski committed Jul 26, 2023
1 parent 601b458 commit 61e53ff
Show file tree
Hide file tree
Showing 16 changed files with 84 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ object CrossSources {
val baseReqs0 = baseReqs(m.scopePath)
WithBuildRequirements(
m.requirements.fold(baseReqs0)(_ orElse baseReqs0),
Sources.InMemory(m.originalPath, m.relPath, m.code, m.wrapperParamsOpt)
Sources.InMemory(m.originalPath, m.relPath, m.content, m.wrapperParamsOpt)
) -> m.directivesPositions
}
val unwrappedScriptsWithDirectivePositions
Expand Down
4 changes: 3 additions & 1 deletion modules/build/src/main/scala/scala/build/ScopedSources.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package scala.build

import java.nio.charset.StandardCharsets

import scala.build.info.{BuildInfo, ScopedBuildInfo}
import scala.build.options.{BuildOptions, HasScope, Scope}
import scala.build.preprocessing.ScriptPreprocessor
Expand Down Expand Up @@ -63,7 +65,7 @@ final case class ScopedSources(
Seq(Sources.InMemory(
Left("build-info"),
os.rel / "BuildInfo.scala",
buildInfo(combinedOptions).generateContents(),
buildInfo(combinedOptions).generateContents().getBytes(StandardCharsets.UTF_8),
None
))
else Nil
Expand Down
13 changes: 10 additions & 3 deletions modules/build/src/main/scala/scala/build/Sources.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package scala.build
import coursier.cache.ArchiveCache
import coursier.util.Task

import java.nio.charset.StandardCharsets

import scala.build.info.BuildInfo
import scala.build.input.Inputs
import scala.build.internal.{CodeWrapper, WrapperParams}
Expand Down Expand Up @@ -39,7 +41,7 @@ final case class Sources(
for (inMemSource <- inMemory) yield {
os.write.over(
generatedSrcRoot / inMemSource.generatedRelPath,
inMemSource.generatedContent.getBytes("UTF-8"),
inMemSource.content,
createFolders = true
)
(
Expand Down Expand Up @@ -75,7 +77,7 @@ object Sources {
final case class InMemory(
originalPath: Either[String, (os.SubPath, os.Path)],
generatedRelPath: os.RelPath,
generatedContent: String,
content: Array[Byte],
wrapperParamsOpt: Option[WrapperParams]
)

Expand All @@ -86,7 +88,12 @@ object Sources {
) {
def wrap(wrapper: CodeWrapper): InMemory = {
val (content, wrapperParams) = wrapScriptFun(wrapper)
InMemory(originalPath, generatedRelPath, content, Some(wrapperParams))
InMemory(
originalPath,
generatedRelPath,
content.getBytes(StandardCharsets.UTF_8),
Some(wrapperParams)
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,31 +25,19 @@ case object DataPreprocessor extends Preprocessor {
input match {
case file: VirtualData =>
val res = either {
val content = new String(file.content, StandardCharsets.UTF_8)
val preprocessedDirectives: PreprocessedDirectives = value {
DirectivesPreprocessor.preprocess(
content,
Left(file.subPath.toString),
file.scopePath,
logger,
allowRestrictedFeatures,
suppressWarningOptions,
maybeRecoverOnError
)
}
val inMemory = Seq(
PreprocessedSource.InMemory(
originalPath = Left(file.source),
relPath = file.subPath,
code = content,
content = file.content,
wrapperParamsOpt = None,
options = Some(preprocessedDirectives.globalUsings),
optionsWithTargetRequirements = preprocessedDirectives.usingsWithReqs,
options = None,
optionsWithTargetRequirements = Nil,
requirements = Some(BuildRequirements()),
scopedRequirements = Nil,
mainClassOpt = None,
scopePath = file.scopePath,
preprocessedDirectives.directivesPositions
directivesPositions = None
)
)
inMemory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ final case class JavaPreprocessor(
val s = PreprocessedSource.InMemory(
originalPath = Left(v.source),
relPath = relPath,
code = content,
content = v.content,
wrapperParamsOpt = None,
options = Some(preprocessedDirectives.globalUsings),
optionsWithTargetRequirements = preprocessedDirectives.usingsWithReqs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ case object MarkdownPreprocessor extends Preprocessor {
PreprocessedSource.InMemory(
originalPath = reportingPath.map(subPath -> _),
relPath = os.rel / (subPath / os.up) / s"${subPath.last}$generatedSourceNameSuffix",
processedCode,
processedCode.getBytes(StandardCharsets.UTF_8),
wrapperParamsOpt = None,
options = Some(processingOutput.opts),
optionsWithTargetRequirements = processingOutput.optsWithReqs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ object PreprocessedSource {
final case class InMemory(
originalPath: Either[String, (os.SubPath, os.Path)],
relPath: os.RelPath,
code: String,
content: Array[Byte],
wrapperParamsOpt: Option[WrapperParams],
options: Option[BuildOptions],
optionsWithTargetRequirements: List[WithBuildRequirements[BuildOptions]],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ case object ScalaPreprocessor extends Preprocessor {
PreprocessedSource.InMemory(
originalPath = Right((f.subPath, f.path)),
relPath = f.subPath,
code = updatedCode,
content = updatedCode.getBytes(StandardCharsets.UTF_8),
wrapperParamsOpt = None,
options = Some(options),
optionsWithTargetRequirements = optionsWithReqs,
Expand Down Expand Up @@ -161,7 +161,7 @@ case object ScalaPreprocessor extends Preprocessor {
val s = PreprocessedSource.InMemory(
originalPath = Left(v.source),
relPath = relPath,
updatedContentOpt.getOrElse(content),
updatedContentOpt.map(_.getBytes(StandardCharsets.UTF_8)).getOrElse(v.content),
wrapperParamsOpt = None,
options = Some(options),
optionsWithTargetRequirements = optionsWithTargetRequirements,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import coursier.cache.{ArchiveCache, Cache}
import coursier.util.{Artifact, Task}
import dependency.*

import java.nio.charset.StandardCharsets
import scala.build.Ops.*
import scala.build.{CrossSources, Position, Sources}
import scala.build.internal.ObjectCodeWrapper
Expand Down Expand Up @@ -310,7 +311,8 @@ class SourcesTests extends munit.FunSuite {
val sources =
scopedSources.sources(Scope.Main, crossSources.sharedOptions(BuildOptions()))

val parsedCodes: Seq[String] = sources.inMemory.map(_.generatedContent)
val parsedCodes: Seq[String] =
sources.inMemory.map(_.content).map(s => new String(s, StandardCharsets.UTF_8))

parsedCodes.zip(expectedParsedCodes).foreach { case (parsedCode, expectedCode) =>
expect(parsedCode.contains(expectedCode))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ object Package extends ScalaCommand[PackageOptions] with BuildCommandHelpers {
val prefix = if (originalOpt.isEmpty) os.rel else generatedSourcesPrefix
val generated = (
prefix / inMemSource.generatedRelPath,
inMemSource.generatedContent.getBytes(StandardCharsets.UTF_8),
inMemSource.content,
lastModified
)
Iterator(generated) ++ originalOpt.iterator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ final case class JsonProjectDescriptor(
projectName: Option[String] = None,
logger: Logger
) extends ProjectDescriptor {
private val charSet = StandardCharsets.UTF_8

def `export`(
optionsMain: BuildOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@ final case class MillProjectDescriptor(
logger: Logger
) extends ProjectDescriptor {

private val charSet = StandardCharsets.UTF_8

private def sourcesSettings(mainSources: Sources, testSources: Sources): MillProject = {
val mainSources0 = ProjectDescriptor.sources(mainSources, charSet)
val testSources0 = ProjectDescriptor.sources(testSources, charSet)
val mainSources0 = ProjectDescriptor.sources(mainSources)
val testSources0 = ProjectDescriptor.sources(testSources)
MillProject(mainSources = mainSources0, testSources = testSources0)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ abstract class ProjectDescriptor extends Product with Serializable {
}

object ProjectDescriptor {
def sources(sources: Sources, charSet: Charset): Seq[(os.SubPath, String, Array[Byte])] = {
def sources(sources: Sources): Seq[(os.SubPath, String, Array[Byte])] = {

val mainSources = sources.paths.map {
case (path, relPath) =>
Expand All @@ -33,7 +33,7 @@ object ProjectDescriptor {
(
inMemSource.generatedRelPath.asSubPath,
language,
inMemSource.generatedContent.getBytes(charSet)
inMemSource.content
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@ final case class SbtProjectDescriptor(
extraSettings: Seq[String],
logger: Logger
) extends ProjectDescriptor {
private val charSet = StandardCharsets.UTF_8
private val q = "\""
private val nl = System.lineSeparator()
private val q = "\""
private val nl = System.lineSeparator()

private def sources(sourcesMain: Sources, sourcesTest: Sources): SbtProject = {
val mainSources = ProjectDescriptor.sources(sourcesMain, charSet)
val testSources = ProjectDescriptor.sources(sourcesTest, charSet)
val mainSources = ProjectDescriptor.sources(sourcesMain)
val testSources = ProjectDescriptor.sources(sourcesTest)
SbtProject(
mainSources = mainSources,
testSources = testSources
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final case class TestInputs(maybeCharset: Option[Charset], files: (os.RelPath, S
def asZip[T](f: (os.Path, os.Path) => T): T =
TestInputs.withTmpDir { tmpDir =>
val zipArchivePath = tmpDir / s"${tmpDir.last}.zip"
compress(zipArchivePath, files)
compress(zipArchivePath, files.map { case (relPath, content) => (relPath, content, charset) })
f(tmpDir, zipArchivePath)
}
def fromRoot[T](f: os.Path => T): T =
Expand All @@ -46,11 +46,11 @@ object TestInputs {

def empty: TestInputs = TestInputs()

def compress(zipFilepath: os.Path, files: Seq[(os.RelPath, String)]) = {
def compress(zipFilepath: os.Path, files: Seq[(os.RelPath, String, Charset)]) = {
val zip = new ZipOutputStream(new FileOutputStream(zipFilepath.toString()))
try for ((relPath, content) <- files) {
try for ((relPath, content, charset) <- files) {
zip.putNextEntry(new ZipEntry(relPath.toString()))
val in: Array[Byte] = content.getBytes
val in: Array[Byte] = content.getBytes(charset)
zip.write(in)
zip.closeEntry()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package scala.cli.integration

import com.eed3si9n.expecty.Expecty.expect

import java.nio.charset.{Charset, StandardCharsets}

import scala.cli.integration.TestInputs.compress

trait RunZipTestDefinitions { _: RunTestDefinitions =>
test("Zip with multiple Scala files") {
val inputs = TestInputs(
Expand All @@ -24,6 +28,47 @@ trait RunZipTestDefinitions { _: RunTestDefinitions =>
expect(output == message)
}
}
test("load virtual data with UTF_16 encoding") {
val zipInputs: Seq[(os.RelPath, String, Charset)] = Seq(
(
os.rel / "Hello.scala",
s"""//> using resourceDir "./"
|import scala.io.Source
|import java.nio.charset.StandardCharsets
|import java.io.{BufferedReader, InputStreamReader}
|import java.util.stream.Collectors
|
|object Hello extends App {
| val inputStream = getClass().getResourceAsStream("input")
| val nativeResourceText = new BufferedReader(
| new InputStreamReader(inputStream, StandardCharsets.UTF_16)
| ).lines().collect(Collectors.joining("\\n"));
| println(nativeResourceText)
|}
|""".stripMargin,
StandardCharsets.UTF_8
),
(
os.rel / "input",
s"""1
|2
|""".stripMargin,
StandardCharsets.UTF_16
)
)
TestInputs().fromRoot { root =>
val zipArchivePath = root / "hello.zip"
compress(zipArchivePath, zipInputs)

val output = os.proc(TestUtil.cli, extraOptions, zipArchivePath.toString)
.call(cwd = root)
.out.trim()

val expectedOutput = "1\n2"

expect(output == expectedOutput)
}
}

test("Zip with Scala containing resource directive") {
val inputs = TestInputs(
Expand Down

0 comments on commit 61e53ff

Please sign in to comment.