Skip to content

Instantly share code, notes, and snippets.

@sayurin
Created June 19, 2019 22:39
Show Gist options
  • Save sayurin/bd135b537b77766e2e82966eb2e93d98 to your computer and use it in GitHub Desktop.
Save sayurin/bd135b537b77766e2e82966eb2e93d98 to your computer and use it in GitHub Desktop.
namespace Sayuri.IO.Compression
open System.IO
open System.IO.Compression
module ZLib =
[<Literal>]
let private ModuloAdler = 65521u
let private adler32 (buffer : byte[]) =
let mutable a = 1u
let mutable b = 0u
#if original
for byte in buffer do
a <- (a + uint32 byte) % ModuloAdler
b <- (b + a) % ModuloAdler
#else
let mutable len = buffer.Length
let mutable offset = 0
while len > 0 do
let mutable tlen = min len 5550
len <- len - tlen
while tlen > 0 do
a <- a + uint32 buffer.[offset]
b <- b + a
tlen <- tlen - 1
offset <- offset + 1
a <- a % ModuloAdler
b <- b % ModuloAdler
#endif
[| b >>> 8 |> byte; byte b; a >>> 8 |> byte; byte a; |]
[<CompiledName "Compress">]
let compress inBuffer =
use compressed = new MemoryStream()
use deflate = new DeflateStream(compressed, CompressionLevel.Optimal)
deflate.Write(inBuffer, 0, inBuffer.Length)
let adler32 = adler32 inBuffer
Array.concat [| [| 0x78uy; 0xDAuy; |]; compressed.ToArray(); adler32; |]
[<CompiledName "Uncompress">]
let uncompress inBuffer inLength outBuffer =
use compressed = new MemoryStream(inBuffer, 2, inLength - 6)
use inflate = new DeflateStream(compressed, CompressionMode.Decompress)
let read = inflate.Read(outBuffer, 0, outBuffer.Length)
assert (read = outBuffer.Length)
assert (adler32 outBuffer = inBuffer.[inLength - 4 .. inLength - 1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment