@@ -9,7 +9,11 @@ module Data.Utf8
12+import Data.Binary (Binary(..), Get)
13+import Data.Binary.Put (putBuilder)
14+import Data.Binary.Get.Internal (readN)
12import Data.Bits ((.&.), shiftR)
15import Data.Bits ((.&.), shiftR)
16+import qualified Data.ByteString.Internal as B
13import qualified Data.ByteString.Builder.Internal as B
17import qualified Data.ByteString.Builder.Internal as B
14import Foreign.ForeignPtr (ForeignPtr, touchForeignPtr)
18import Foreign.ForeignPtr (ForeignPtr, touchForeignPtr)
15import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
19import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
@@ -25,7 +29,7 @@ import GHC.Exts
25 , writeWord8Array#, writeWord16Array#
29 , writeWord8Array#, writeWord16Array#
27import GHC.IO
31import GHC.IO
28−import GHC.ST (ST(ST))
32+import GHC.ST (ST(ST), runST)
29import GHC.Prim
33import GHC.Prim
30import GHC.Word (Word8(W8#), Word16(W16#))
34import GHC.Word (Word8(W8#), Word16(W16#))
@@ -54,6 +58,64 @@ instance Eq Utf8 where
64+instance Ord Utf8 where
65+ compare (Utf8 ba1#) (Utf8 ba2#) =
67+ !len1# = sizeofByteArray# ba1#
68+ !len2# = sizeofByteArray# ba2#
69+ !len# = if isTrue# (len1# <# len2#) then len1# else len2#
70+ !cmp# = compareByteArrays# ba1# 0# ba2# 0# len#
73+ _ | isTrue# (cmp# <# 0#) -> LT
74+ | isTrue# (cmp# ># 0#) -> GT
75+ | isTrue# (len1# <# len2#) -> LT
76+ | isTrue# (len1# ># len2#) -> GT
84+instance Binary Utf8 where
85+ put utf8@(Utf8 ba#) =
86+ put (I# (sizeofByteArray# ba#)) <> putBuilder (toBuilder utf8)
91+{-# INLINE getUtf8 #-}
92+getUtf8 :: Int -> Get Utf8
95+ readN n (fromByteString n)
101+fromByteString :: Int -> B.ByteString -> Utf8
102+fromByteString len (B.PS fptr offset _) =
103+ unsafeDupablePerformIO
105+ do mba <- stToIO (newByteArray len)
106+ stToIO (copyFromPtr (unsafeForeignPtrToPtr fptr `plusPtr` offset) mba 0 len)
107+ touchForeignPtr fptr
108+ stToIO (unsafeFreeze mba)
112+{-# NOINLINE empty #-}
115+ runST (unsafeFreeze =<< newByteArray 0)