@@ -1,84 +1,86 @@
1−{-# LANGUAGE DeriveDataTypeable, TypeFamilies, CPP #-}
2+{-# LANGUAGE DeriveDataTypeable #-}
3+{-# LANGUAGE TypeFamilies #-}
4+{-# LANGUAGE ViewPatterns #-}
5+{-# LANGUAGE Unsafe #-}
6+{-# LANGUAGE DeriveLift #-}
7+{-# LANGUAGE StandaloneDeriving #-}
8+{-# OPTIONS_HADDOCK hide #-}
4−-- Module : Data.UUID
11+-- Module : Data.UUID.Types.Internal
12+-- Copyright : (c) 2017-2018 Herbert Valerio Riedel
5−-- Copyright : (c) 2008-2009, 2012 Antoine Latter
13+-- (c) 2008-2009, 2012 Antoine Latter
6-- (c) 2009 Mark Lentczner
14-- (c) 2009 Mark Lentczner
8-- License : BSD-style
16-- License : BSD-style
10−-- Maintainer : aslatter@gmail.com
18+-- Maintainer : hvr@gnu.org
11−-- Stability : experimental
12-- Portability : portable
19-- Portability : portable
14−module Data.UUID.Internal
21+module Data.UUID.Types.Internal
15− (UUID(..)
22+ ( UUID(..)
18− ,fromByteString
25+ , fromByteString
19− ,toByteString
26+ , toByteString
20− ,fromString
27+ , fromString
21− ,toString
28+ , toString
22− ,fromWords
31+ , fromWords
23− ,toWords
32+ , toWords
25− ,buildFromBytes
36+ , buildFromBytes
26− ,buildFromWords
37+ , buildFromWords
27− ,fromASCIIBytes
38+ , fromASCIIBytes
28− ,toASCIIBytes
39+ , toASCIIBytes
29− ,fromLazyASCIIBytes
40+ , fromLazyASCIIBytes
30− ,toLazyASCIIBytes
41+ , toLazyASCIIBytes
31− ,UnpackedUUID(..)
42+ , UnpackedUUID(..)
36−import Prelude hiding (null)
47+import Prelude hiding (null)
38−import Control.Applicative ((<*>))
39−import Control.DeepSeq (NFData(..))
49+import Control.DeepSeq (NFData (..))
40−import Control.Monad (liftM4, guard)
50+import Control.Monad (guard, liftM2)
41−import Data.Functor ((<$>))
43−import Data.Bits
51+import Data.Bits
44−import Data.Hashable
54+import Data.Hashable
45−import Data.List (elemIndices)
55+import Data.List (elemIndices)
46−import Foreign.Ptr (Ptr)
56+import Foreign.Ptr (Ptr)
48−#if MIN_VERSION_base(4,0,0)
51−import Data.Generics.Basics
54−import Foreign.Storable
58+import Foreign.Storable
56−import Data.Binary
60+import Data.Binary
57−import Data.Binary.Put
58−import Data.Binary.Get
61+import Data.Binary.Get
62+import Data.Binary.Put
59−import qualified Data.ByteString as B
63+import qualified Data.ByteString as B
60−import qualified Data.ByteString.Internal as BI
64+import qualified Data.ByteString.Internal as BI
61−import qualified Data.ByteString.Lazy as BL
65+import qualified Data.ByteString.Lazy as BL
62−import qualified Data.ByteString.Unsafe as BU
66+import qualified Data.ByteString.Unsafe as BU
63−
67+import Data.Text (Text)
68+import qualified Data.Text.Encoding as T
64−import Data.UUID.Builder
70+import Data.UUID.Types.Internal.Builder
65−import Data.Word.Util
71+
66−
72+import System.Random (Random (..), uniform)
67−import System.Random
73+import System.Random.Stateful (Uniform (..), uniformWord64)
69−
75+import Language.Haskell.TH.Syntax (Lift)
70−-- |The UUID type. A 'Random' instance is provided which produces
76+
71−-- version 4 UUIDs as specified in RFC 4122. The 'Storable' and
77+-- | Type representing <https://en.wikipedia.org/wiki/UUID Universally Unique Identifiers (UUID)> as specified in
72−-- 'Binary' instances are compatible with RFC 4122, storing the fields
78+-- <http://tools.ietf.org/html/rfc4122 RFC 4122>.
73−-- in network order as 16 bytes.
79+data UUID = UUID {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64
76− {-# UNPACK #-} !Word32
77− {-# UNPACK #-} !Word32
78− {-# UNPACK #-} !Word32
79− {-# UNPACK #-} !Word32
80− deriving (Eq, Ord, Typeable)
80+ deriving (Eq, Ord)
82+ Prior to uuid-types-1.0.4:
83+ !Word32 !Word32 !Word32 !Word32
82 Other representations that we tried are:
84 Other representations that we tried are:
83 Mimic V1 structure: !Word32 !Word16 !Word16 !Word16
85 Mimic V1 structure: !Word32 !Word16 !Word16 !Word16
84 !Word8 !Word8 !Word8 !Word8 !Word8 !Word8
86 !Word8 !Word8 !Word8 !Word8 !Word8 !Word8
@@ -90,40 +92,75 @@ data UUID
90 None was as fast, overall, as the representation used here.
92 None was as fast, overall, as the representation used here.
93−-- | Covert a 'UUID' into a sequence of 'Word32' values.
95+-- | Convert a 'UUID' into a sequence of 'Word32' values.
94−-- Usefull for when you need to serialize a UUID and
96+-- Useful for when you need to serialize a UUID and
95-- neither 'Storable' nor 'Binary' are appropriate.
97-- neither 'Storable' nor 'Binary' are appropriate.
96−-- Introduced in version 1.2.2.
98+--
99+-- >>> toWords <$> fromString "550e8400-e29b-41d4-a716-446655440000"
100+-- Just (1427014656,3801825748,2803254374,1430519808)
102+-- See also 'toWords64'.
104+-- /Since: @uuid-1.2.2@/
97toWords :: UUID -> (Word32, Word32, Word32, Word32)
107toWords :: UUID -> (Word32, Word32, Word32, Word32)
98−toWords (UUID w1 w2 w3 w4) = (w1, w2, w3, w4)
108+toWords (UUID w12 w34) = (w1, w2, w3, w4)
110+ w1 = fromIntegral (w12 `unsafeShiftR` 32)
111+ w2 = fromIntegral w12
112+ w3 = fromIntegral (w34 `unsafeShiftR` 32)
113+ w4 = fromIntegral w34
100-- | Create a 'UUID' from a sequence of 'Word32'. The
115-- | Create a 'UUID' from a sequence of 'Word32'. The
101−-- opposite of 'toWords'. Useful when you need a total
116+-- inverse of 'toWords'. Useful when you need a total
102-- function for constructing 'UUID' values.
117-- function for constructing 'UUID' values.
103−-- Introduced in version 1.2.2.
118+--
119+-- See also 'fromWords64'.
121+-- /Since: @uuid-1.2.2@/
104fromWords :: Word32 -> Word32 -> Word32 -> Word32 -> UUID
124fromWords :: Word32 -> Word32 -> Word32 -> Word32 -> UUID
105−fromWords = UUID
125+fromWords w1 w2 w3 w4 = UUID (w32to64 w1 w2) (w32to64 w3 w4)
127+-- | Convert a 'UUID' into a pair of 'Word64's.
129+-- >>> toWords64 <$> fromString "550e8400-e29b-41d4-a716-446655440000"
130+-- Just (6128981282234515924,12039885860129472512)
132+-- See also 'toWords'.
135+toWords64 :: UUID -> (Word64, Word64)
136+toWords64 (UUID w12 w34) = (w12,w34)
138+-- | Create a 'UUID' from a pair of 'Word64's.
140+-- Inverse of 'toWords64'. See also 'fromWords'.
143+fromWords64 :: Word64 -> Word64 -> UUID
107data UnpackedUUID =
146data UnpackedUUID =
108 UnpackedUUID {
147 UnpackedUUID {
109− time_low :: Word32 -- 0-3
148+ time_low :: Word32 -- 0-3
110− , time_mid :: Word16 -- 4-5
149+ , time_mid :: Word16 -- 4-5
111 , time_hi_and_version :: Word16 -- 6-7
150 , time_hi_and_version :: Word16 -- 6-7
112− , clock_seq_hi_res :: Word8 -- 8
151+ , clock_seq_hi_res :: Word8 -- 8
113− , clock_seq_low :: Word8 -- 9
152+ , clock_seq_low :: Word8 -- 9
114− , node_0 :: Word8
153+ , node_0 :: Word8
115− , node_1 :: Word8
154+ , node_1 :: Word8
116− , node_2 :: Word8
155+ , node_2 :: Word8
117− , node_3 :: Word8
156+ , node_3 :: Word8
118− , node_4 :: Word8
157+ , node_4 :: Word8
119− , node_5 :: Word8
158+ , node_5 :: Word8
121 deriving (Read, Show, Eq, Ord)
160 deriving (Read, Show, Eq, Ord)
123unpack :: UUID -> UnpackedUUID
162unpack :: UUID -> UnpackedUUID
124−unpack (UUID w0 w1 w2 w3) =
163+unpack (UUID w0 w1) = build /-/ w0 /-/ w1
125− build /-/ w0 /-/ w1 /-/ w2 /-/ w3
128 build x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF =
165 build x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF =
129 UnpackedUUID {
166 UnpackedUUID {
@@ -142,13 +179,13 @@ unpack (UUID w0 w1 w2 w3) =
143pack :: UnpackedUUID -> UUID
180pack :: UnpackedUUID -> UUID
144pack unpacked =
181pack unpacked =
145− makeFromBytes /-/ (time_low unpacked)
182+ makeFromBytes /-/ (time_low unpacked)
146− /-/ (time_mid unpacked)
183+ /-/ (time_mid unpacked)
147− /-/ (time_hi_and_version unpacked)
184+ /-/ (time_hi_and_version unpacked)
148− /-/ (clock_seq_hi_res unpacked)
185+ /-/ (clock_seq_hi_res unpacked)
149 /-/ (clock_seq_low unpacked)
186 /-/ (clock_seq_low unpacked)
150− /-/ (node_0 unpacked) /-/ (node_1 unpacked)
187+ /-/ (node_0 unpacked) /-/ (node_1 unpacked)
151− /-/ (node_2 unpacked) /-/ (node_3 unpacked)
188+ /-/ (node_2 unpacked) /-/ (node_3 unpacked)
152 /-/ (node_4 unpacked) /-/ (node_5 unpacked)
189 /-/ (node_4 unpacked) /-/ (node_5 unpacked)
@@ -158,15 +195,26 @@ pack unpacked =
159-- |Build a Word32 from four Word8 values, presented in big-endian order
196-- |Build a Word32 from four Word8 values, presented in big-endian order
160word :: Word8 -> Word8 -> Word8 -> Word8 -> Word32
197word :: Word8 -> Word8 -> Word8 -> Word8 -> Word32
161−word a b c d = (fromIntegral a `shiftL` 24)
198+word a b c d = (fromIntegral a `unsafeShiftL` 24)
162− .|. (fromIntegral b `shiftL` 16)
199+ .|. (fromIntegral b `unsafeShiftL` 16)
163− .|. (fromIntegral c `shiftL` 8)
200+ .|. (fromIntegral c `unsafeShiftL` 8)
164− .|. (fromIntegral d )
201+ .|. (fromIntegral d )
166−-- |Extract a Word8 from a Word32. Bytes, high to low, are numbered from 3 to 0,
203+-- |Extract a Word8 from a Word64. Bytes, high to low, are numbered from 7 to 0,
167−byte :: Int -> Word32 -> Word8
204+byte :: Int -> Word64 -> Word8
168byte i w = fromIntegral (w `shiftR` (i * 8))
205byte i w = fromIntegral (w `shiftR` (i * 8))
207+-- |Build a Word16 from two Word8 values, presented in big-endian order.
208+w8to16 :: Word8 -> Word8 -> Word16
210+ (w0 `unsafeShiftL` 8) .|. w1
212+ w0 = fromIntegral w0s
213+ w1 = fromIntegral w1s
215+-- | Construct 'Word64' from low/high 'Word32's
216+w32to64 :: Word32 -> Word32 -> Word64
217+w32to64 w0 w1 = (fromIntegral w0 `unsafeShiftL` 32) .|. (fromIntegral w1)
171-- |Make a UUID from sixteen Word8 values
219-- |Make a UUID from sixteen Word8 values
172makeFromBytes :: Word8 -> Word8 -> Word8 -> Word8
220makeFromBytes :: Word8 -> Word8 -> Word8 -> Word8
@@ -175,16 +223,12 @@ makeFromBytes :: Word8 -> Word8 -> Word8 -> Word8
175 -> Word8 -> Word8 -> Word8 -> Word8
223 -> Word8 -> Word8 -> Word8 -> Word8
177makeFromBytes b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
225makeFromBytes b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
178− = UUID w0 w1 w2 w3
226+ = fromWords w0 w1 w2 w3
179 where w0 = word b0 b1 b2 b3
227 where w0 = word b0 b1 b2 b3
180 w1 = word b4 b5 b6 b7
228 w1 = word b4 b5 b6 b7
181 w2 = word b8 b9 ba bb
229 w2 = word b8 b9 ba bb
182 w3 = word bc bd be bf
230 w3 = word bc bd be bf
184−-- |Make a UUID from four Word32 values
185−makeFromWords :: Word32 -> Word32 -> Word32 -> Word32 -> UUID
188-- |A Builder for constructing a UUID of a given version.
232-- |A Builder for constructing a UUID of a given version.
189buildFromBytes :: Word8
233buildFromBytes :: Word8
190 -> Word8 -> Word8 -> Word8 -> Word8
234 -> Word8 -> Word8 -> Word8 -> Word8
@@ -197,20 +241,20 @@ buildFromBytes v b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf =
197 where b6' = b6 .&. 0x0f .|. (v `shiftL` 4)
241 where b6' = b6 .&. 0x0f .|. (v `shiftL` 4)
198 b8' = b8 .&. 0x3f .|. 0x80
242 b8' = b8 .&. 0x3f .|. 0x80
200−-- |Build a UUID of a given version from Word32 values.
244+-- |Build a UUID of a given version from 'Word32' values.
201buildFromWords :: Word8 -> Word32 -> Word32 -> Word32 -> Word32 -> UUID
245buildFromWords :: Word8 -> Word32 -> Word32 -> Word32 -> Word32 -> UUID
202−buildFromWords v w0 w1 w2 w3 = makeFromWords w0 w1' w2' w3
246+buildFromWords v w0 w1 w2 w3 = fromWords w0 w1' w2' w3
203 where w1' = w1 .&. 0xffff0fff .|. ((fromIntegral v) `shiftL` 12)
247 where w1' = w1 .&. 0xffff0fff .|. ((fromIntegral v) `shiftL` 12)
204 w2' = w2 .&. 0x3fffffff .|. 0x80000000
248 w2' = w2 .&. 0x3fffffff .|. 0x80000000
207-- |Return the bytes that make up the UUID
251-- |Return the bytes that make up the UUID
208toList :: UUID -> [Word8]
252toList :: UUID -> [Word8]
209−toList (UUID w0 w1 w2 w3) =
253+toList (UUID w0 w1) =
210− [byte 3 w0, byte 2 w0, byte 1 w0, byte 0 w0,
254+ [byte 7 w0, byte 6 w0, byte 5 w0, byte 4 w0,
211− byte 3 w1, byte 2 w1, byte 1 w1, byte 0 w1,
255+ byte 3 w0, byte 2 w0, byte 1 w0, byte 0 w0,
212− byte 3 w2, byte 2 w2, byte 1 w2, byte 0 w2,
256+ byte 7 w1, byte 6 w1, byte 5 w1, byte 4 w1,
213− byte 3 w3, byte 2 w3, byte 1 w3, byte 0 w3]
257+ byte 3 w1, byte 2 w1, byte 1 w1, byte 0 w1]
215-- |Construct a UUID from a list of Word8. Returns Nothing if the list isn't
259-- |Construct a UUID from a list of Word8. Returns Nothing if the list isn't
216-- exactly sixteen bytes long
260-- exactly sixteen bytes long
@@ -231,10 +275,10 @@ null = (== nil)
231 -- null (UUID 0 0 0 0) = True
275 -- null (UUID 0 0 0 0) = True
232 -- null _ = False
276 -- null _ = False
234−-- |The nil UUID, as defined in RFC 4122.
278+-- |The 'nil' UUID, as defined in <http://tools.ietf.org/html/rfc4122 RFC 4122>.
235−-- It is a UUID of all zeros. @'null' u@ iff @'u' == 'nil'@.
279+-- It is a UUID of all zeros. @'null' u@ /iff/ @'u' == 'nil'@.
236nil :: UUID
280nil :: UUID
237−nil = UUID 0 0 0 0
281+nil = UUID 0 0
239-- |Extract a UUID from a 'ByteString' in network byte order.
283-- |Extract a UUID from a 'ByteString' in network byte order.
240-- The argument must be 16 bytes long, otherwise 'Nothing' is returned.
284-- The argument must be 16 bytes long, otherwise 'Nothing' is returned.
@@ -242,6 +286,8 @@ fromByteString :: BL.ByteString -> Maybe UUID
242fromByteString = fromList . BL.unpack
286fromByteString = fromList . BL.unpack
244-- |Encode a UUID into a 'ByteString' in network order.
288-- |Encode a UUID into a 'ByteString' in network order.
290+-- This uses the same encoding as the 'Binary' instance.
245toByteString :: UUID -> BL.ByteString
291toByteString :: UUID -> BL.ByteString
246toByteString = BL.pack . toList
292toByteString = BL.pack . toList
@@ -249,9 +295,8 @@ toByteString = BL.pack . toList
249-- The hyphens may not be omitted.
295-- The hyphens may not be omitted.
250-- Example:
296-- Example:
253−-- fromString \"c2cc10e1-57d6-4b6f-9899-38d972112d8c\"
298+-- >>> fromString "c2cc10e1-57d6-4b6f-9899-38d972112d8c"
254−-- @
299+-- Just c2cc10e1-57d6-4b6f-9899-38d972112d8c
256-- Hex digits may be upper or lower-case.
301-- Hex digits may be upper or lower-case.
257fromString :: String -> Maybe UUID
302fromString :: String -> Maybe UUID
@@ -266,7 +311,7 @@ fromString' s0 = do
266 (w2, s3) <- hexWord s2
311 (w2, s3) <- hexWord s2
267 (w3, s4) <- hexWord s3
312 (w3, s4) <- hexWord s3
268 if s4 /= "" then Nothing
313 if s4 /= "" then Nothing
269− else Just $ UUID w0 w1 w2 w3
314+ else Just $ fromWords w0 w1 w2 w3
270 where hexWord :: String -> Maybe (Word32, String)
315 where hexWord :: String -> Maybe (Word32, String)
271 hexWord s = Just (0, s) >>= hexByte >>= hexByte
316 hexWord s = Just (0, s) >>= hexByte >>= hexByte
272 >>= hexByte >>= hexByte
317 >>= hexByte >>= hexByte
@@ -283,21 +328,39 @@ fromString' s0 = do
283-- | Convert a UUID into a hypenated string using lower-case letters.
328-- | Convert a UUID into a hypenated string using lower-case letters.
284-- Example:
329-- Example:
287−-- toString \<$\> fromString \"550e8400-e29b-41d4-a716-446655440000\"
331+-- >>> toString <$> fromString "550e8400-e29b-41d4-a716-446655440000"
288−-- @
332+-- Just "550e8400-e29b-41d4-a716-446655440000"
289toString :: UUID -> String
335toString :: UUID -> String
290−toString (UUID w0 w1 w2 w3) = hexw w0 $ hexw' w1 $ hexw' w2 $ hexw w3 ""
336+toString uuid = hexw0 w0 $ hexw1 w1 ""
291− where hexw :: Word32 -> String -> String
337+ where hexw0 :: Word64 -> String -> String
338+ hexw0 w s = hexn w 60 : hexn w 56 : hexn w 52 : hexn w 48
339+ : hexn w 44 : hexn w 40 : hexn w 36 : hexn w 32
292− hexw w s = hexn w 28 : hexn w 24 : hexn w 20 : hexn w 16
340+ : '-' : hexn w 28 : hexn w 24 : hexn w 20 : hexn w 16
293− : hexn w 12 : hexn w 8 : hexn w 4 : hexn w 0 : s
341+ : '-' : hexn w 12 : hexn w 8 : hexn w 4 : hexn w 0
344+ hexw1 :: Word64 -> String -> String
345+ hexw1 w s = '-' : hexn w 60 : hexn w 56 : hexn w 52 : hexn w 48
346+ : '-' : hexn w 44 : hexn w 40 : hexn w 36 : hexn w 32
347+ : hexn w 28 : hexn w 24 : hexn w 20 : hexn w 16
348+ : hexn w 12 : hexn w 8 : hexn w 4 : hexn w 0
351+ hexn :: Word64 -> Int -> Char
352+ hexn w r = intToDigit $ fromIntegral ((w `shiftR` r) .&. 0xf)
295− hexw' :: Word32 -> String -> String
354+ (w0,w1) = toWords64 uuid
296− hexw' w s = '-' : hexn w 28 : hexn w 24 : hexn w 20 : hexn w 16
297− : '-' : hexn w 12 : hexn w 8 : hexn w 4 : hexn w 0 : s
299− hexn :: Word32 -> Int -> Char
356+-- | If the passed in `Text` can be parsed as an ASCII representation of
300− hexn w r = intToDigit $ fromIntegral ((w `shiftR` r) .&. 0xf)
357+-- a `UUID`, it will be. The hyphens may not be omitted.
358+fromText :: Text -> Maybe UUID
359+fromText = fromASCIIBytes . T.encodeUtf8
361+-- | Convert a UUID into a hyphentated string using lower-case letters.
362+toText :: UUID -> Text
363+toText = T.decodeLatin1 . toASCIIBytes
302-- | Convert a UUID into a hyphentated string using lower-case letters, packed
365-- | Convert a UUID into a hyphentated string using lower-case letters, packed
303-- as ASCII bytes into `B.ByteString`.
366-- as ASCII bytes into `B.ByteString`.
@@ -391,7 +454,9 @@ fromASCIIBytes bs = do
392-- | Similar to `toASCIIBytes` except we produce a lazy `BL.ByteString`.
455-- | Similar to `toASCIIBytes` except we produce a lazy `BL.ByteString`.
393toLazyASCIIBytes :: UUID -> BL.ByteString
456toLazyASCIIBytes :: UUID -> BL.ByteString
394−toLazyASCIIBytes = BL.fromStrict . toASCIIBytes
457+toLazyASCIIBytes =
396-- | Similar to `fromASCIIBytes` except parses from a lazy `BL.ByteString`.
461-- | Similar to `fromASCIIBytes` except parses from a lazy `BL.ByteString`.
397fromLazyASCIIBytes :: BL.ByteString -> Maybe UUID
462fromLazyASCIIBytes :: BL.ByteString -> Maybe UUID
@@ -402,27 +467,18 @@ fromLazyASCIIBytes bs =
402-- Class Instances
467-- Class Instances
470+-- | This 'Random' instance produces __insecure__ version 4 UUIDs as
471+-- specified in <http://tools.ietf.org/html/rfc4122 RFC 4122>.
405instance Random UUID where
472instance Random UUID where
406− random g = (fromGenNext w0 w1 w2 w3 w4, g4)
473+ random = uniform
407− where (w0, g0) = next g
412 randomR _ = random -- range is ignored
474 randomR _ = random -- range is ignored
414−-- |Build a UUID from the results of five calls to next on a StdGen.
476+-- @since 1.0.4
415−-- While next on StdGet returns an Int, it doesn't provide 32 bits of
477+instance Uniform UUID where
416−-- randomness. This code relies on at last 28 bits of randomness in the
478+ uniformM gen = do
417−-- and optimizes its use so as to make only five random values, not six.
479+ w0 <- uniformWord64 gen
418−fromGenNext :: Int -> Int -> Int -> Int -> Int -> UUID
480+ w1 <- uniformWord64 gen
419−fromGenNext w0 w1 w2 w3 w4 =
420− buildFromBytes 4 /-/ (ThreeByte w0)
481+ pure $ buildFromBytes 4 /-/ w0 /-/ w1
422− /-/ w2 -- use all 4 bytes because we know the version
423− -- field will "cover" the upper, non-random bits
427-- |A ByteSource to extract only three bytes from an Int, since next on StdGet
483-- |A ByteSource to extract only three bytes from an Int, since next on StdGet
428-- only returns 31 bits of randomness.
484-- only returns 31 bits of randomness.
@@ -430,24 +486,29 @@ type instance ByteSink ThreeByte g = Takes3Bytes g
430newtype ThreeByte = ThreeByte Int
486newtype ThreeByte = ThreeByte Int
431instance ByteSource ThreeByte where
487instance ByteSource ThreeByte where
432 f /-/ (ThreeByte w) = f b1 b2 b3
488 f /-/ (ThreeByte w) = f b1 b2 b3
433− where b1 = fromIntegral (w `shiftR` 16)
489+ where b1 = fromIntegral (w `unsafeShiftR` 16)
434− b2 = fromIntegral (w `shiftR` 8)
490+ b2 = fromIntegral (w `unsafeShiftR` 8)
435 b3 = fromIntegral w
491 b3 = fromIntegral w
437instance NFData UUID where
493instance NFData UUID where
438− rnf = rnf . toWords
494+ rnf = flip seq ()
440instance Hashable UUID where
496instance Hashable UUID where
441− hash (UUID w0 w1 w2 w3) =
497+ hash (toWords -> (w0,w1,w2,w3)) =
442 hash w0 `hashWithSalt` w1
498 hash w0 `hashWithSalt` w1
443 `hashWithSalt` w2
499 `hashWithSalt` w2
444 `hashWithSalt` w3
500 `hashWithSalt` w3
445− hashWithSalt s (UUID w0 w1 w2 w3) =
501+ hashWithSalt s (toWords -> (w0,w1,w2,w3)) =
446 s `hashWithSalt` w0
502 s `hashWithSalt` w0
447 `hashWithSalt` w1
503 `hashWithSalt` w1
448 `hashWithSalt` w2
504 `hashWithSalt` w2
449 `hashWithSalt` w3
505 `hashWithSalt` w3
507+-- | Pretty prints a 'UUID' (without quotation marks). See also 'toString'.
510+-- "00000000-0000-0000-0000-000000000000"
451instance Show UUID where
512instance Show UUID where
452 show = toString
513 show = toString
@@ -458,7 +519,7 @@ instance Read UUID where
458 Nothing -> []
519 Nothing -> []
459 Just u -> [(u,drop 36 noSpaces)]
520 Just u -> [(u,drop 36 noSpaces)]
461−
522+-- | This 'Storable' instance uses the memory layout as described in <http://tools.ietf.org/html/rfc4122 RFC 4122>, but in contrast to the 'Binary' instance, __the fields are stored in host byte order__.
462instance Storable UUID where
523instance Storable UUID where
463 sizeOf _ = 16
524 sizeOf _ = 16
464 alignment _ = 4
525 alignment _ = 4
@@ -495,10 +556,10 @@ instance Storable UUID where
495 pokeByteOff p (off+14) x9
556 pokeByteOff p (off+14) x9
496 pokeByteOff p (off+15) x10
557 pokeByteOff p (off+15) x10
559+-- | This 'Binary' instance is compatible with <http://tools.ietf.org/html/rfc4122 RFC 4122>, storing the fields in network order as 16 bytes.
498instance Binary UUID where
560instance Binary UUID where
499− put (UUID w0 w1 w2 w3) =
561+ put (UUID w0 w1) = putWord64be w0 >> putWord64be w1
500− putWord32be w0 >> putWord32be w1 >> putWord32be w2 >> putWord32be w3
562+ get = liftM2 UUID getWord64be getWord64be
501− get = liftM4 UUID getWord32be getWord32be getWord32be getWord32be
504-- My goal with this instance was to make it work just enough to do what
565-- My goal with this instance was to make it work just enough to do what
@@ -509,10 +570,6 @@ instance Data UUID where
509 dataTypeOf _ = uuidType
570 dataTypeOf _ = uuidType
511uuidType :: DataType
572uuidType :: DataType
512−uuidType = mkNoRepType "Data.UUID.UUID"
573+uuidType = mkNoRepType "Data.UUID.Types.UUID"
514−#if !(MIN_VERSION_base(4,2,0))
515−mkNoRepType :: String -> DataType
516−mkNoRepType = mkNorepType
575+deriving instance Lift UUID