Skip to content

Commit

Permalink
Refactor parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
erikvanoosten committed Oct 21, 2024
1 parent 8c47b7d commit 5711be9
Show file tree
Hide file tree
Showing 11 changed files with 240 additions and 122 deletions.
2 changes: 1 addition & 1 deletion bzip2/src/main/scala/zio/compress/Bzip2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Bzip2Compressor private (blockSize: Option[Bzip2BlockSize]) extends Compre
override def compress: ZPipeline[Any, Throwable, Byte, Byte] =
viaOutputStreamByte { outputStream =>
blockSize match {
case Some(bs) => new BZip2CompressorOutputStream(outputStream, bs.jValue)
case Some(bs) => new BZip2CompressorOutputStream(outputStream, bs.hundredKbIncrements)
case None => new BZip2CompressorOutputStream(outputStream)
}
}
Expand Down
49 changes: 22 additions & 27 deletions bzip2/src/main/scala/zio/compress/Bzip2BlockSize.scala
Original file line number Diff line number Diff line change
@@ -1,36 +1,31 @@
package zio.compress

sealed abstract class Bzip2BlockSize(val jValue: Int)
/** Bzip2 block size.
*
* @param hundredKbIncrements
* a bzip2 block size in 100KB increments, valid values: 1 to 9
*/
final case class Bzip2BlockSize(hundredKbIncrements: Int)

object Bzip2BlockSize {
case object BlockSize100KB extends Bzip2BlockSize(1)
case object BlockSize200KB extends Bzip2BlockSize(2)
case object BlockSize300KB extends Bzip2BlockSize(3)
case object BlockSize400KB extends Bzip2BlockSize(4)
case object BlockSize500KB extends Bzip2BlockSize(5)
case object BlockSize600KB extends Bzip2BlockSize(6)
case object BlockSize700KB extends Bzip2BlockSize(7)
case object BlockSize800KB extends Bzip2BlockSize(8)
case object BlockSize900KB extends Bzip2BlockSize(9)

private val Values: Seq[Bzip2BlockSize] =
Seq(
BlockSize100KB,
BlockSize200KB,
BlockSize300KB,
BlockSize400KB,
BlockSize500KB,
BlockSize600KB,
BlockSize700KB,
BlockSize800KB,
BlockSize900KB,
)

/** Converts a bzip2 block size from `Int` to [[Bzip2BlockSize]].
/** Makes a bzip2 block size.
*
* @param blockSize100KB
* @param hundredKbIncrements
* a bzip2 block size in 100KB increments, valid values: 1 to 9
* @return
* a [[Bzip2BlockSize]] or `None` if the block size is not valid
*/
def fromBzip2BlockSize(blockSize100KB: Int): Option[Bzip2BlockSize] =
Values.find(_.jValue == blockSize100KB)
def apply(hundredKbIncrements: Int): Option[Bzip2BlockSize] =
if (1 <= hundredKbIncrements && hundredKbIncrements <= 9) Some(new Bzip2BlockSize(hundredKbIncrements)) else None

val BlockSize100KB = new Bzip2BlockSize(1)
val BlockSize200KB = new Bzip2BlockSize(2)
val BlockSize300KB = new Bzip2BlockSize(3)
val BlockSize400KB = new Bzip2BlockSize(4)
val BlockSize500KB = new Bzip2BlockSize(5)
val BlockSize600KB = new Bzip2BlockSize(6)
val BlockSize700KB = new Bzip2BlockSize(7)
val BlockSize800KB = new Bzip2BlockSize(8)
val BlockSize900KB = new Bzip2BlockSize(9)
}
37 changes: 37 additions & 0 deletions core/src/main/scala/zio/compress/DeflateCompressionLevel.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package zio.compress

/** Deflate compression level, used for ZIP and GZIP.
*
* @param level
* compression level, valid values: 0 (no compression) to 9 (maximum compression)
*/
final case class DeflateCompressionLevel private (level: Int)

object DeflateCompressionLevel {

/** Deflate compression level, used for ZIP and GZIP.
*
* @param level
* compression level, valid values: 0 (no compression) to 9 (maximum compression)
* @return
* a [[DeflateCompressionLevel]] or `None` if the level is not valid
*/
def apply(level: Int): Option[DeflateCompressionLevel] =
if (0 <= level && level <= 9) Some(new DeflateCompressionLevel(level)) else None

val CompressionLevel0 = new DeflateCompressionLevel(0)
val CompressionLevel1 = new DeflateCompressionLevel(1)
val CompressionLevel2 = new DeflateCompressionLevel(2)
val CompressionLevel3 = new DeflateCompressionLevel(3)
val CompressionLevel4 = new DeflateCompressionLevel(4)
val CompressionLevel5 = new DeflateCompressionLevel(5)
val CompressionLevel6 = new DeflateCompressionLevel(6)
val CompressionLevel7 = new DeflateCompressionLevel(7)
val CompressionLevel8 = new DeflateCompressionLevel(8)
val CompressionLevel9 = new DeflateCompressionLevel(9)

val NoCompressionLevel: DeflateCompressionLevel = CompressionLevel0
val FastestCompressionLevel: DeflateCompressionLevel = CompressionLevel1
val DefaultCompressionLevel: DeflateCompressionLevel = CompressionLevel5
val BestCompressionLevel: DeflateCompressionLevel = CompressionLevel9
}
8 changes: 8 additions & 0 deletions gzip/src/main/scala/zio/compress/DeflateStrategy.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package zio.compress

sealed trait DeflateStrategy

object DeflateStrategy {
case object Filtered extends DeflateStrategy
case object HuffmanOnly extends DeflateStrategy
}
87 changes: 43 additions & 44 deletions gzip/src/main/scala/zio/compress/Gzip.scala
Original file line number Diff line number Diff line change
@@ -1,70 +1,38 @@
package zio.compress

import zio.compress.DeflateStrategy.{Filtered, HuffmanOnly}
import zio.stream._
import zio.stream.compression.CompressionLevel._
import zio.stream.compression.CompressionStrategy._
import zio.stream.compression.{CompressionLevel, CompressionStrategy}

object GzipCompressor {
private val CompressionLevels = Seq(
DefaultCompression,
NoCompression,
BestSpeed,
CompressionLevel2,
CompressionLevel3,
CompressionLevel4,
CompressionLevel5,
CompressionLevel6,
CompressionLevel7,
CompressionLevel8,
BestCompression,
)
private val CompressionStrategies = Seq(DefaultStrategy, Filtered, HuffmanOnly)

/** Converts a deflate compression level from `Int` to [[zio.stream.compression.CompressionLevel]].
*
* @param level
* a deflate compression level, valid values: -1 (default), 0 (no compression), 1 (fastest) to 9 (best compression)
*/
def intToCompressionLevel(level: Int): Option[CompressionLevel] =
CompressionLevels.find(_.jValue == level)

/** Converts a deflate compression strategy from `Int` to [[zio.stream.compression.CompressionStrategy]].
*
* @param strategy
* a deflate compression strategy, valid values: 0 (default), 1 (filtered) or 2 (huffman only)
*/
def intToCompressionStrategy(strategy: Int): Option[CompressionStrategy] =
CompressionStrategies.find(_.jValue == strategy)

/** Make a pipeline that accepts a stream of bytes and produces a stream with Gzip compressed bytes.
*
* @param deflateLevel
* the deflate compression level
* @param deflateStrategy
* a deflate compression strategy, valid values: 0 (default), 1 (filtered) or 2 (huffman only)
* a deflate compression strategy
* @param bufferSize
* the maximum chunk size of the outgoing ZStream. Defaults to 64KiB.
*/
def make(
deflateLevel: Option[CompressionLevel] = None,
deflateStrategy: Option[CompressionStrategy] = None,
deflateLevel: Option[DeflateCompressionLevel] = None,
deflateStrategy: Option[DeflateStrategy] = None,
bufferSize: Int = Defaults.DefaultChunkSize,
): GzipCompressor =
new GzipCompressor(
deflateLevel.getOrElse(DefaultCompression),
deflateStrategy.getOrElse(CompressionStrategy.DefaultStrategy),
bufferSize,
)
new GzipCompressor(deflateLevel, deflateStrategy, bufferSize)
}

class GzipCompressor private (
deflateLevel: CompressionLevel,
deflateStrategy: CompressionStrategy,
deflateLevel: Option[DeflateCompressionLevel],
deflateStrategy: Option[DeflateStrategy],
bufferSize: Int,
) extends Compressor {
override def compress: ZPipeline[Any, Nothing, Byte, Byte] =
ZPipeline.gzip(bufferSize, deflateLevel, deflateStrategy)
ZPipeline.gzip(
bufferSize,
Parameters.levelToZio(deflateLevel),
Parameters.strategyToZio(deflateStrategy),
)
}

object GzipDecompressor {
Expand All @@ -82,3 +50,34 @@ class GzipDecompressor private (bufferSize: Int) extends Decompressor {
override def decompress: ZPipeline[Any, Throwable, Byte, Byte] =
ZPipeline.gunzip(bufferSize)
}

private object Parameters {
private val ZioCompressionLevels = IndexedSeq(
zio.stream.compression.CompressionLevel.NoCompression,
zio.stream.compression.CompressionLevel.BestSpeed,
zio.stream.compression.CompressionLevel.CompressionLevel2,
zio.stream.compression.CompressionLevel.CompressionLevel3,
zio.stream.compression.CompressionLevel.CompressionLevel4,
zio.stream.compression.CompressionLevel.CompressionLevel5,
zio.stream.compression.CompressionLevel.CompressionLevel6,
zio.stream.compression.CompressionLevel.CompressionLevel7,
zio.stream.compression.CompressionLevel.CompressionLevel8,
zio.stream.compression.CompressionLevel.BestCompression,
)

def levelToZio(level: Option[DeflateCompressionLevel]): zio.stream.compression.CompressionLevel =
level match {
case Some(l) => ZioCompressionLevels
.find(_.jValue == l.level)
.getOrElse(sys.error(s"BUG: Invalid compression level: ${l.level}"))
case None =>
zio.stream.compression.CompressionLevel.DefaultCompression
}

def strategyToZio(strategy: Option[DeflateStrategy]): zio.stream.compression.CompressionStrategy =
strategy match {
case Some(Filtered) => zio.stream.compression.CompressionStrategy.Filtered
case Some(HuffmanOnly) => zio.stream.compression.CompressionStrategy.HuffmanOnly
case None => zio.stream.compression.CompressionStrategy.DefaultStrategy
}
}
36 changes: 7 additions & 29 deletions lz4/src/main/scala/zio/compress/Lz4.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,6 @@ import zio.stream._

import java.io.BufferedInputStream

sealed trait Lz4CompressorBlockSize
object Lz4CompressorBlockSize {
case object BlockSize64KiB extends Lz4CompressorBlockSize
case object BlockSize256KiB extends Lz4CompressorBlockSize
case object BlockSize1MiB extends Lz4CompressorBlockSize
case object BlockSize4MiB extends Lz4CompressorBlockSize

/** Converts a Lz4 block size indicator into a [[Lz4CompressorBlockSize]].
*
* @param indicator
* the Lz4 block size indicator, valid values: 4 (64KiB), 5 (256KiB), 6 (1MiB), 7 (4MiB)
*/
def fromLz4BlockSizeIndicator(indicator: Int): Option[Lz4CompressorBlockSize] =
indicator match {
case 4 => Some(BlockSize64KiB)
case 5 => Some(BlockSize256KiB)
case 6 => Some(BlockSize1MiB)
case 7 => Some(BlockSize4MiB)
case _ => None
}
}

object Lz4Compressor {

/** Make a pipeline that accepts a stream of bytes and produces a stream with Lz4 compressed bytes.
Expand All @@ -38,22 +16,22 @@ object Lz4Compressor {
*/
def make(
blockSize: Lz4CompressorBlockSize = Lz4CompressorBlockSize.BlockSize256KiB
): Lz4Compressor = {
): Lz4Compressor =
new Lz4Compressor(blockSize)
}

class Lz4Compressor private (blockSize: Lz4CompressorBlockSize) extends Compressor {
override def compress: ZPipeline[Any, Throwable, Byte, Byte] = {
val lz4BlockSize = blockSize match {
case Lz4CompressorBlockSize.BlockSize64KiB => BLOCKSIZE.SIZE_64KB
case Lz4CompressorBlockSize.BlockSize256KiB => BLOCKSIZE.SIZE_256KB
case Lz4CompressorBlockSize.BlockSize1MiB => BLOCKSIZE.SIZE_1MB
case Lz4CompressorBlockSize.BlockSize4MiB => BLOCKSIZE.SIZE_4MB
}
new Lz4Compressor(lz4BlockSize)
viaOutputStreamByte(new LZ4FrameOutputStream(_, lz4BlockSize))
}
}

class Lz4Compressor private (blockSize: LZ4FrameOutputStream.BLOCKSIZE) extends Compressor {
override def compress: ZPipeline[Any, Throwable, Byte, Byte] =
viaOutputStreamByte(new LZ4FrameOutputStream(_, blockSize))
}

object Lz4Decompressor {

/** Makes a pipeline that accepts a Lz4 compressed byte stream and produces a decompressed byte stream.
Expand Down
24 changes: 24 additions & 0 deletions lz4/src/main/scala/zio/compress/Lz4CompressorBlockSize.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package zio.compress

sealed trait Lz4CompressorBlockSize

object Lz4CompressorBlockSize {
case object BlockSize64KiB extends Lz4CompressorBlockSize
case object BlockSize256KiB extends Lz4CompressorBlockSize
case object BlockSize1MiB extends Lz4CompressorBlockSize
case object BlockSize4MiB extends Lz4CompressorBlockSize

/** Converts a Lz4 block size indicator into a [[Lz4CompressorBlockSize]].
*
* @param indicator
* the Lz4 block size indicator, valid values: 4 (64KiB), 5 (256KiB), 6 (1MiB), 7 (4MiB)
*/
def fromLz4BlockSizeIndicator(indicator: Int): Option[Lz4CompressorBlockSize] =
indicator match {
case 4 => Some(BlockSize64KiB)
case 5 => Some(BlockSize256KiB)
case 6 => Some(BlockSize1MiB)
case 7 => Some(BlockSize4MiB)
case _ => None
}
}
31 changes: 16 additions & 15 deletions zip/src/main/scala/zio/compress/Zip.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,41 @@ import zio.compress.ArchiveEntry.{ArchiveEntryFromUnderlying, ArchiveEntryToUnde
import zio.compress.JavaIoInterop._
import zio.compress.Zip._
import zio.stream._
import zio.stream.compression.CompressionLevel

import java.io.IOException
import java.nio.file.attribute.FileTime
import java.util.zip.{ZipEntry, ZipInputStream, ZipOutputStream}

sealed abstract class ZipMethod(val jValue: Int)
object ZipMethod {
case object Stored extends ZipMethod(ZipEntry.STORED)
case object Deflated extends ZipMethod(ZipEntry.DEFLATED)
}

object ZipArchiver {

/** Makes a pipeline that accepts a stream of archive entries, and produces a byte stream of a Zip archive.
*
* @param level
* compression level (only applicable for method 'deflated'). Currently defaults to level 6.
* @param method
* compression method: stored or deflated. Defaults to `ZipMethod.Deflated`.
* @param zipMethod
* zip method: stored (no compression) or deflated. Defaults to deflated.
*/
def make(
level: Option[CompressionLevel] = None,
method: ZipMethod = ZipMethod.Deflated,
level: Option[DeflateCompressionLevel] = None,
zipMethod: Option[ZipMethod] = None,
): ZipArchiver =
new ZipArchiver(level.filter(_ != CompressionLevel.DefaultCompression), method)
new ZipArchiver(level, zipMethod)
}

class ZipArchiver private (level: Option[CompressionLevel], method: ZipMethod) extends Archiver[Option] {
class ZipArchiver private (
level: Option[DeflateCompressionLevel],
zipMethod: Option[ZipMethod],
) extends Archiver[Option] {
override def archive: ZPipeline[Any, Throwable, (ArchiveEntry[Option, Any], ZStream[Any, Throwable, Byte]), Byte] =
viaOutputStream { outputStream =>
val zipOutputStream = new ZipOutputStream(outputStream)
level.foreach(l => zipOutputStream.setLevel(l.jValue))
zipOutputStream.setMethod(method.jValue)
level.foreach(l => zipOutputStream.setLevel(l.level))
zipMethod
.map {
case ZipMethod.Deflated => ZipEntry.DEFLATED
case ZipMethod.Stored => ZipEntry.STORED
}
.foreach(zipOutputStream.setMethod)
zipOutputStream
} { case (entryStream, zipOutputStream) =>
entryStream
Expand Down
8 changes: 8 additions & 0 deletions zip/src/main/scala/zio/compress/ZipMethod.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package zio.compress

sealed trait ZipMethod

object ZipMethod {
case object Stored extends ZipMethod
case object Deflated extends ZipMethod
}
Loading

0 comments on commit 5711be9

Please sign in to comment.