Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
machines-zlib
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Skete
machines-zlib
Merge requests
!1
Wip/davean/safe st
Code
Review changes
Check out branch
Download
Patches
Plain diff
Merged
Wip/davean/safe st
wip/davean/safeST
into
master
Overview
0
Commits
16
Pipelines
0
Changes
4
Merged
davean
requested to merge
wip/davean/safeST
into
master
5 years ago
Overview
0
Commits
16
Pipelines
0
Changes
4
Expand
0
0
Merge request reports
Compare
master
master (base)
and
latest version
latest version
35b258fb
16 commits,
5 years ago
4 files
+
101
−
96
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
Files
4
Search (e.g. *.vue) (Ctrl+P)
src/Data/Machine/Zlib.hs
+
45
−
63
Options
{-# LANGUAGE ScopedTypeVariables #-}
module
Data.Machine.Zlib
(
gzipper
,
gunzipper
(
gunzipper
,
WindowBits
(
..
)
)
where
import
Control.Applicative
import
Control.Exception
(
throw
)
import
Control.Monad
import
Control.Applicative
import
Control.Monad
import
Control.Monad.Catch
import
Control.Monad.Primitive
import
Control.Monad.Trans
import
qualified
Data.ByteString
as
BS
import
Data.Machine
import
Data.Machine.Stack
import
Data.Streaming.Zlib
import
System.IO.Unsafe
import
Data.Machine
import
Data.Machine.Stack
import
Data.Streaming.Zlib
unsafeM
::
Monad
n
=>
IO
a
->
n
a
unsafeM
ma
=
pure
.
unsafePerformIO
$!
ma
handleRes
::
Applicative
m
=>
PopperRes
->
m
(
Maybe
BS
.
ByteString
)
handleRes
PRDone
=
pure
$
Nothing
handleRes
(
PRNext
bs
)
=
pure
$
Just
bs
handleRes
(
PRError
e
)
=
throw
e
gunzipper
::
forall
m
.
(
Monad
m
)
=>
MachineT
m
(
Stack
BS
.
ByteString
)
BS
.
ByteString
gunzipper
=
construct
$
go
=<<
(
unsafeM
$
initInflate
(
WindowBits
0
))
-- Use what the header says.
gunzipper
::
forall
m
.
(
MonadThrow
m
,
PrimMonad
m
,
Monad
m
)
=>
MachineT
m
(
Stack
BS
.
ByteString
)
BS
.
ByteString
gunzipper
=
construct
$
do
i
<-
doPrim
$
initInflate
(
WindowBits
0
)
start
i
where
go
::
Inflate
->
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
()
go
inflate
=
do
bs
<-
awaits
Pop
<|>
stop
popper
<-
unsafeM
<$>
unsafeM
(
feedInflate
inflate
bs
)
exhaust
(
handleRes
=<<
popper
)
complete
<-
unsafeM
$
isCompleteInflate
inflate
if
complete
then
void
$
finish
else
go'
where
go'
::
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
()
go'
=
do
bs
<-
awaits
Pop
<|>
finish
popper
<-
unsafeM
<$>
unsafeM
(
feedInflate
inflate
bs
)
exhaust
(
handleRes
=<<
popper
)
complete
<-
unsafeM
$
isCompleteInflate
inflate
if
complete
then
void
$
finish
else
go'
finish
::
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
BS
.
ByteString
finish
=
do
r
<-
unsafeM
$
finishInflate
inflate
yield
r
unused
<-
unsafeM
$
getUnusedInflate
inflate
awaits
(
Push
unused
)
stop
gzipper
::
forall
m
.
Monad
m
=>
Int
->
WindowBits
->
ProcessT
m
BS
.
ByteString
BS
.
ByteString
gzipper
lvl
wb
=
construct
$
go
=<<
(
unsafeM
$
initDeflate
lvl
wb
)
where
go
::
Deflate
->
PlanT
(
Is
BS
.
ByteString
)
BS
.
ByteString
m
()
go
deflate
=
go'
doPrim
::
IO
a
->
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
a
doPrim
=
lift
.
unsafePrimToPrim
yield'
::
BS
.
ByteString
->
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
()
yield'
d
=
unless
(
BS
.
null
d
)
$
yield
d
push'
::
BS
.
ByteString
->
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
()
push'
d
=
unless
(
BS
.
null
d
)
$
push
d
-- This is all stupid. Its based on the exact behavior of the base API.
start
::
Inflate
->
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
()
start
i
=
go
where
go'
::
PlanT
(
Is
BS
.
ByteString
)
BS
.
ByteString
m
()
go'
=
do
bs
<-
await
<|>
finish
popper
<-
unsafeM
<$>
unsafeM
(
feedDeflate
deflate
bs
)
exhaust
(
handleRes
=<<
popper
)
go'
finish
=
do
let
popper
=
unsafeM
(
finishDeflate
deflate
)
exhaust
(
handleRes
=<<
popper
)
stop
drain
::
Popper
->
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
()
drain
popper
=
do
md
<-
doPrim
popper
case
md
of
PRNext
d
->
yield'
d
>>
drain
popper
PRDone
->
do
-- This magic tries to detect if we've reached the end of a substream.
l
<-
doPrim
(
getUnusedInflate
i
)
if
BS
.
null
l
then
go
else
do
yield'
=<<
doPrim
(
flushInflate
i
)
push
l
PRError
e
->
lift
$
throwM
e
getMore
::
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
()
getMore
=
drain
=<<
(
doPrim
.
feedInflate
i
)
=<<
pop
allDone
::
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
()
allDone
=
do
yield'
=<<
doPrim
(
flushInflate
i
)
push'
=<<
doPrim
(
getUnusedInflate
i
)
go
::
PlanT
(
Stack
BS
.
ByteString
)
BS
.
ByteString
m
()
go
=
getMore
<|>
allDone
Loading