on master help sign in
Add a Binary instance for strict Text
d70ce27Bryan O'Sullivan
Data/Text.hs+10−60
@@ -195,7 +195,7 @@ module Data.Text
195
195
196import Prelude (Char, Bool(..), Int, Maybe(..), String,
196import Prelude (Char, Bool(..), Int, Maybe(..), String,
197 Eq(..), Ord(..), Ordering(..), (++),
197 Eq(..), Ord(..), Ordering(..), (++),
198− Read(..), Show(..),
198+ Read(..),
199 (&&), (||), (+), (-), (.), ($), ($!), (>>),
199 (&&), (||), (+), (-), (.), ($), ($!), (>>),
200 not, return, otherwise, quot)
200 not, return, otherwise, quot)
201#if defined(HAVE_DEEPSEQ)
201#if defined(HAVE_DEEPSEQ)
@@ -211,17 +211,20 @@ import Control.Monad (foldM)
211import Control.Monad.ST (ST)
211import Control.Monad.ST (ST)
212import qualified Data.Text.Array as A
212import qualified Data.Text.Array as A
213import qualified Data.List as L
213import qualified Data.List as L
214+import Data.Binary (Binary(get, put))
214import Data.Monoid (Monoid(..))
215import Data.Monoid (Monoid(..))
215import Data.String (IsString(..))
216import Data.String (IsString(..))
216import qualified Data.Text.Internal.Fusion as S
217import qualified Data.Text.Internal.Fusion as S
217import qualified Data.Text.Internal.Fusion.Common as S
218import qualified Data.Text.Internal.Fusion.Common as S
219+import Data.Text.Encoding (decodeUtf8, encodeUtf8)
218import Data.Text.Internal.Fusion (stream, reverseStream, unstream)
220import Data.Text.Internal.Fusion (stream, reverseStream, unstream)
219import Data.Text.Internal.Private (span_)
221import Data.Text.Internal.Private (span_)
220−import Data.Text.Internal (Text(..), empty, empty_, firstf, mul, safe, text)
222+import Data.Text.Internal (Text(..), empty, firstf, mul, safe, text)
223+import Data.Text.Show (singleton, unpack)
221import qualified Prelude as P
224import qualified Prelude as P
222import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
225import Data.Text.Unsafe (Iter(..), iter, iter_, lengthWord16, reverseIter,
223 reverseIter_, unsafeHead, unsafeTail)
226 reverseIter_, unsafeHead, unsafeTail)
224−import Data.Text.Internal.Unsafe.Char (unsafeChr, unsafeWrite)
227+import Data.Text.Internal.Unsafe.Char (unsafeChr)
225import qualified Data.Text.Internal.Functions as F
228import qualified Data.Text.Internal.Functions as F
226import qualified Data.Text.Internal.Encoding.Utf16 as U16
229import qualified Data.Text.Internal.Encoding.Utf16 as U16
227import Data.Text.Internal.Search (indices)
230import Data.Text.Internal.Search (indices)
@@ -230,15 +233,9 @@ import Data.ByteString (ByteString)
230import qualified Data.Text.Lazy as L
233import qualified Data.Text.Lazy as L
231import Data.Int (Int64)
234import Data.Int (Int64)
232#endif
235#endif
233−#if __GLASGOW_HASKELL__ >= 702
234−import qualified GHC.CString as GHC
235−#else
236−import qualified GHC.Base as GHC
237−#endif
238#if __GLASGOW_HASKELL__ >= 708
236#if __GLASGOW_HASKELL__ >= 708
239import qualified GHC.Exts as Exts
237import qualified GHC.Exts as Exts
240#endif
238#endif
241−import GHC.Prim (Addr#)
242
239
243-- $strict
240-- $strict
244--
241--
@@ -324,9 +321,6 @@ instance Eq Text where
324instance Ord Text where
321instance Ord Text where
325 compare = compareText
322 compare = compareText
326
323
327−instance Show Text where
328− showsPrec p ps r = showsPrec p (unpack ps) r
329−
330instance Read Text where
324instance Read Text where
331 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
325 readsPrec p str = [(pack x,y) | (x,y) <- readsPrec p str]
332
326
@@ -349,6 +343,10 @@ instance Exts.IsList Text where
349instance NFData Text where rnf !_ = ()
343instance NFData Text where rnf !_ = ()
350#endif
344#endif
351
345
346+instance Binary Text where
347+ put t = put (encodeUtf8 t)
348+ get = P.fmap decodeUtf8 get
349+
352-- | This instance preserves data abstraction at the cost of inefficiency.
350-- | This instance preserves data abstraction at the cost of inefficiency.
353-- We omit reflection services for the sake of data abstraction.
351-- We omit reflection services for the sake of data abstraction.
354--
352--
@@ -401,54 +399,6 @@ pack :: String -> Text
401pack = unstream . S.map safe . S.streamList
399pack = unstream . S.map safe . S.streamList
402{-# INLINE [1] pack #-}
400{-# INLINE [1] pack #-}
403
401
404−-- | /O(n)/ Convert a 'Text' into a 'String'. Subject to fusion.
405−unpack :: Text -> String
406−unpack = S.unstreamList . stream
407−{-# INLINE [1] unpack #-}
408−
409−-- | /O(n)/ Convert a literal string into a Text. Subject to fusion.
410−unpackCString# :: Addr# -> Text
411−unpackCString# addr# = unstream (S.streamCString# addr#)
412−{-# NOINLINE unpackCString# #-}
413−
414−{-# RULES "TEXT literal" forall a.
415− unstream (S.map safe (S.streamList (GHC.unpackCString# a)))
416− = unpackCString# a #-}
417−
418−{-# RULES "TEXT literal UTF8" forall a.
419− unstream (S.map safe (S.streamList (GHC.unpackCStringUtf8# a)))
420− = unpackCString# a #-}
421−
422−{-# RULES "TEXT empty literal"
423− unstream (S.map safe (S.streamList []))
424− = empty_ #-}
425−
426−{-# RULES "TEXT singleton literal" forall a.
427− unstream (S.map safe (S.streamList [a]))
428− = singleton_ a #-}
429−
430−-- | /O(1)/ Convert a character into a Text. Subject to fusion.
431−-- Performs replacement on invalid scalar values.
432−singleton :: Char -> Text
433−singleton = unstream . S.singleton . safe
434−{-# INLINE [1] singleton #-}
435−
436−{-# RULES "TEXT singleton" forall a.
437− unstream (S.singleton (safe a))
438− = singleton_ a #-}
439−
440−-- This is intended to reduce inlining bloat.
441−singleton_ :: Char -> Text
442−singleton_ c = Text (A.run x) 0 len
443− where x :: ST s (A.MArray s)
444− x = do arr <- A.new len
445− _ <- unsafeWrite arr 0 d
446− return arr
447− len | d < '\x10000' = 1
448− | otherwise = 2
449− d = safe c
450−{-# NOINLINE singleton_ #-}
451−
452-- -----------------------------------------------------------------------------
402-- -----------------------------------------------------------------------------
453-- * Basic functions
403-- * Basic functions
454
404
Data/Text/Encoding.hs+1−1
@@ -84,12 +84,12 @@ import Control.Exception (evaluate, try)
84import Control.Monad.ST (runST)
84import Control.Monad.ST (runST)
85import Data.ByteString as B
85import Data.ByteString as B
86import Data.ByteString.Internal as B hiding (c2w)
86import Data.ByteString.Internal as B hiding (c2w)
87−import Data.Text ()
88import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
87import Data.Text.Encoding.Error (OnDecodeError, UnicodeException, strictDecode)
89import Data.Text.Internal (Text(..), safe, text)
88import Data.Text.Internal (Text(..), safe, text)
90import Data.Text.Internal.Private (runText)
89import Data.Text.Internal.Private (runText)
91import Data.Text.Internal.Unsafe.Char (unsafeWrite)
90import Data.Text.Internal.Unsafe.Char (unsafeWrite)
92import Data.Text.Internal.Unsafe.Shift (shiftR)
91import Data.Text.Internal.Unsafe.Shift (shiftR)
92+import Data.Text.Show ()
93import Data.Text.Unsafe (unsafeDupablePerformIO)
93import Data.Text.Unsafe (unsafeDupablePerformIO)
94import Data.Word (Word8, Word32)
94import Data.Word (Word8, Word32)
95import Foreign.C.Types (CSize(..))
95import Foreign.C.Types (CSize(..))
Data/Text/Show.hsnew file+85
@@ -0,0 +1,85 @@
1+{-# LANGUAGE CPP, MagicHash #-}
2+{-# OPTIONS_GHC -fno-warn-orphans #-}
3+#if __GLASGOW_HASKELL__ >= 702
4+{-# LANGUAGE Trustworthy #-}
5+#endif
6+
7+-- |
8+-- Module : Data.Text.Show
9+-- Copyright : (c) 2009-2015 Bryan O'Sullivan
10+--
11+-- License : BSD-style
12+-- Maintainer : bos@serpentine.com
13+-- Stability : experimental
14+-- Portability : GHC
15+
16+module Data.Text.Show
17+ (
18+ singleton
19+ , unpack
20+ ) where
21+
22+import Control.Monad.ST (ST)
23+import Data.Text.Internal (Text(..), empty_, safe)
24+import Data.Text.Internal.Fusion (stream, unstream)
25+import Data.Text.Internal.Unsafe.Char (unsafeWrite)
26+import GHC.Prim (Addr#)
27+import qualified Data.Text.Array as A
28+import qualified Data.Text.Internal.Fusion.Common as S
29+
30+#if __GLASGOW_HASKELL__ >= 702
31+import qualified GHC.CString as GHC
32+#else
33+import qualified GHC.Base as GHC
34+#endif
35+
36+instance Show Text where
37+ showsPrec p ps r = showsPrec p (unpack ps) r
38+
39+-- | /O(n)/ Convert a 'Text' into a 'String'. Subject to fusion.
40+unpack :: Text -> String
41+unpack = S.unstreamList . stream
42+{-# INLINE [1] unpack #-}
43+
44+-- | /O(n)/ Convert a literal string into a Text. Subject to fusion.
45+unpackCString# :: Addr# -> Text
46+unpackCString# addr# = unstream (S.streamCString# addr#)
47+{-# NOINLINE unpackCString# #-}
48+
49+{-# RULES "TEXT literal" forall a.
50+ unstream (S.map safe (S.streamList (GHC.unpackCString# a)))
51+ = unpackCString# a #-}
52+
53+{-# RULES "TEXT literal UTF8" forall a.
54+ unstream (S.map safe (S.streamList (GHC.unpackCStringUtf8# a)))
55+ = unpackCString# a #-}
56+
57+{-# RULES "TEXT empty literal"
58+ unstream (S.map safe (S.streamList []))
59+ = empty_ #-}
60+
61+{-# RULES "TEXT singleton literal" forall a.
62+ unstream (S.map safe (S.streamList [a]))
63+ = singleton_ a #-}
64+
65+-- | /O(1)/ Convert a character into a Text. Subject to fusion.
66+-- Performs replacement on invalid scalar values.
67+singleton :: Char -> Text
68+singleton = unstream . S.singleton . safe
69+{-# INLINE [1] singleton #-}
70+
71+{-# RULES "TEXT singleton" forall a.
72+ unstream (S.singleton (safe a))
73+ = singleton_ a #-}
74+
75+-- This is intended to reduce inlining bloat.
76+singleton_ :: Char -> Text
77+singleton_ c = Text (A.run x) 0 len
78+ where x :: ST s (A.MArray s)
79+ x = do arr <- A.new len
80+ _ <- unsafeWrite arr 0 d
81+ return arr
82+ len | d < '\x10000' = 1
83+ | otherwise = 2
84+ d = safe c
85+{-# NOINLINE singleton_ #-}
tests/text-tests.cabal+2
@@ -114,6 +114,7 @@ library
114 Data.Text.Internal.Lazy.Search
114 Data.Text.Internal.Lazy.Search
115 Data.Text.Internal.Private
115 Data.Text.Internal.Private
116 Data.Text.Read
116 Data.Text.Read
117+ Data.Text.Show
117 Data.Text.Internal.Read
118 Data.Text.Internal.Read
118 Data.Text.Internal.Search
119 Data.Text.Internal.Search
119 Data.Text.Unsafe
120 Data.Text.Unsafe
@@ -135,6 +136,7 @@ library
135 build-depends:
136 build-depends:
136 array,
137 array,
137 base == 4.*,
138 base == 4.*,
139+ binary,
138 bytestring,
140 bytestring,
139 deepseq,
141 deepseq,
140 ghc-prim,
142 ghc-prim,
text.cabal+5
@@ -121,9 +121,13 @@ library
121 Data.Text.Read
121 Data.Text.Read
122 Data.Text.Unsafe
122 Data.Text.Unsafe
123
123
124+ other-modules:
125+ Data.Text.Show
126+
124 build-depends:
127 build-depends:
125 array >= 0.3,
128 array >= 0.3,
126 base >= 4.2 && < 5,
129 base >= 4.2 && < 5,
130+ binary,
127 deepseq >= 1.1.0.0,
131 deepseq >= 1.1.0.0,
128 ghc-prim >= 0.2
132 ghc-prim >= 0.2
129
133
@@ -164,6 +168,7 @@ test-suite tests
164 QuickCheck >= 2.7,
168 QuickCheck >= 2.7,
165 array,
169 array,
166 base,
170 base,
171+ binary,
167 bytestring,
172 bytestring,
168 deepseq,
173 deepseq,
169 directory,
174 directory,