|
1 | 1 | {-# LANGUAGE CPP #-} |
2 | 2 | {-# LANGUAGE BangPatterns #-} |
3 | | -{-# LANGUAGE DeriveDataTypeable #-} |
4 | 3 | {-# LANGUAGE DeriveLift #-} |
| 4 | +{-# LANGUAGE StandaloneDeriving #-} |
5 | 5 | {-# LANGUAGE TypeFamilies #-} |
6 | 6 | {-# LANGUAGE Unsafe #-} |
| 7 | + |
| 8 | +#ifdef HS_BYTESTRING_ASSERTIONS |
| 9 | +{-# LANGUAGE PatternSynonyms #-} |
| 10 | +#endif |
| 11 | + |
7 | 12 | {-# OPTIONS_HADDOCK not-home #-} |
8 | 13 |
|
9 | 14 | -- | |
|
24 | 29 | module Data.ByteString.Lazy.Internal ( |
25 | 30 |
|
26 | 31 | -- * The lazy @ByteString@ type and representation |
27 | | - ByteString(..), |
| 32 | + ByteString(Empty, Chunk), |
28 | 33 | LazyByteString, |
29 | 34 | chunk, |
30 | 35 | foldrChunks, |
@@ -64,23 +69,45 @@ import Control.DeepSeq (NFData, rnf) |
64 | 69 |
|
65 | 70 | import Data.String (IsString(..)) |
66 | 71 |
|
67 | | -import Data.Typeable (Typeable) |
68 | 72 | import Data.Data (Data(..), mkNoRepType) |
69 | 73 |
|
70 | 74 | import GHC.Exts (IsList(..)) |
71 | 75 |
|
72 | 76 | import qualified Language.Haskell.TH.Syntax as TH |
73 | 77 |
|
| 78 | +#ifdef HS_BYTESTRING_ASSERTIONS |
| 79 | +import Control.Exception (assert) |
| 80 | +#endif |
| 81 | + |
| 82 | + |
74 | 83 | -- | A space-efficient representation of a 'Word8' vector, supporting many |
75 | 84 | -- efficient operations. |
76 | 85 | -- |
77 | 86 | -- A lazy 'ByteString' contains 8-bit bytes, or by using the operations |
78 | 87 | -- from "Data.ByteString.Lazy.Char8" it can be interpreted as containing |
79 | 88 | -- 8-bit characters. |
80 | 89 | -- |
81 | | -data ByteString = Empty | Chunk {-# UNPACK #-} !S.ByteString ByteString |
82 | | - deriving (Typeable, TH.Lift) |
83 | | --- See 'invariant' function later in this module for internal invariants. |
| 90 | +#ifndef HS_BYTESTRING_ASSERTIONS |
| 91 | +data ByteString = Empty | Chunk {-# UNPACK #-} !S.ByteString ByteString |
| 92 | + -- INVARIANT: The S.ByteString field of any Chunk is not empty. |
| 93 | + -- (See also the 'invariant' and 'checkInvariant' functions.) |
| 94 | + |
| 95 | + -- To make testing of this invariant convenient, we add an |
| 96 | + -- assertion to that effect when the HS_BYTESTRING_ASSERTIONS |
| 97 | + -- preprocessor macro is defined, by renaming the actual constructor |
| 98 | + -- and providing a pattern synonym that does the checking: |
| 99 | +#else |
| 100 | +data ByteString = Empty | Chunk_ {-# UNPACK #-} !S.ByteString ByteString |
| 101 | + |
| 102 | +pattern Chunk :: S.ByteString -> ByteString -> ByteString |
| 103 | +pattern Chunk c cs <- Chunk_ c cs where |
| 104 | + Chunk c@(S.BS _ len) cs = assert (len > 0) Chunk_ c cs |
| 105 | + |
| 106 | +{-# COMPLETE Empty, Chunk #-} |
| 107 | +#endif |
| 108 | + |
| 109 | +deriving instance TH.Lift ByteString |
| 110 | + |
84 | 111 |
|
85 | 112 | -- | Type synonym for the lazy flavour of 'ByteString'. |
86 | 113 | -- |
@@ -158,15 +185,21 @@ unpackChars (Chunk c cs) = S.unpackAppendCharsLazy c (unpackChars cs) |
158 | 185 |
|
159 | 186 | ------------------------------------------------------------------------ |
160 | 187 |
|
| 188 | +-- We no longer use these invariant-checking functions internally, |
| 189 | +-- preferring an assertion on `Chunk` itself, controlled by the |
| 190 | +-- HS_BYTESTRING_ASSERTIONS preprocessor macro. |
| 191 | + |
161 | 192 | -- | The data type invariant: |
162 | | --- Every ByteString is either 'Empty' or consists of non-null 'S.ByteString's. |
163 | | --- All functions must preserve this, and the QC properties must check this. |
| 193 | +-- Every ByteString is either 'Empty' or consists of non-null |
| 194 | +-- 'S.StrictByteString's. All functions must preserve this. |
164 | 195 | -- |
165 | 196 | invariant :: ByteString -> Bool |
166 | 197 | invariant Empty = True |
167 | 198 | invariant (Chunk (S.BS _ len) cs) = len > 0 && invariant cs |
168 | 199 |
|
169 | | --- | In a form that checks the invariant lazily. |
| 200 | +-- | Lazily checks that the given 'ByteString' satisfies the data type's |
| 201 | +-- "no empty chunks" invariant, raising an exception in place of the |
| 202 | +-- first chunk that does not satisfy the invariant. |
170 | 203 | checkInvariant :: ByteString -> ByteString |
171 | 204 | checkInvariant Empty = Empty |
172 | 205 | checkInvariant (Chunk c@(S.BS _ len) cs) |
|
0 commit comments