PageRenderTime 178ms CodeModel.GetById 114ms RepoModel.GetById 1ms app.codeStats 0ms

/interpreter/ghc/libraries/ghc-binary/src/Data/Binary.hs

https://github.com/khskrede/mehh
Haskell | 719 lines | 293 code | 101 blank | 325 comment | 4 complexity | ad838306b259565d2053ec4c80442720 MD5 | raw file
  1. {-# LANGUAGE CPP, FlexibleInstances, FlexibleContexts #-}
  2. -----------------------------------------------------------------------------
  3. -- |
  4. -- Module : Data.Binary
  5. -- Copyright : Lennart Kolmodin
  6. -- License : BSD3-style (see LICENSE)
  7. --
  8. -- Maintainer : Lennart Kolmodin <kolmodin@dtek.chalmers.se>
  9. -- Stability : unstable
  10. -- Portability : portable to Hugs and GHC. Requires the FFI and some flexible instances
  11. --
  12. -- Binary serialisation of Haskell values to and from lazy ByteStrings.
  13. -- The Binary library provides methods for encoding Haskell values as
  14. -- streams of bytes directly in memory. The resulting @ByteString@ can
  15. -- then be written to disk, sent over the network, or futher processed
  16. -- (for example, compressed with gzip).
  17. --
  18. -- The 'Binary' package is notable in that it provides both pure, and
  19. -- high performance serialisation.
  20. --
  21. -- Values are always encoded in network order (big endian) form, and
  22. -- encoded data should be portable across machine endianess, word size,
  23. -- or compiler version. For example, data encoded using the Binary class
  24. -- could be written from GHC, and read back in Hugs.
  25. --
  26. -----------------------------------------------------------------------------
  27. module Data.Binary (
  28. -- * The Binary class
  29. Binary(..)
  30. -- $example
  31. -- * The Get and Put monads
  32. , Get
  33. , Put
  34. -- * Useful helpers for writing instances
  35. , putWord8
  36. , getWord8
  37. -- * Binary serialisation
  38. , encode -- :: Binary a => a -> ByteString
  39. , decode -- :: Binary a => ByteString -> a
  40. -- * IO functions for serialisation
  41. , encodeFile -- :: Binary a => FilePath -> a -> IO ()
  42. , decodeFile -- :: Binary a => FilePath -> IO a
  43. -- Lazy put and get
  44. -- , lazyPut
  45. -- , lazyGet
  46. , module Data.Word -- useful
  47. ) where
  48. import Data.Word
  49. import Data.Binary.Put
  50. import Data.Binary.Get
  51. import Control.Monad
  52. import Foreign
  53. import System.IO
  54. import Data.ByteString.Lazy (ByteString)
  55. import qualified Data.ByteString.Lazy as L
  56. import Data.Char (chr,ord)
  57. import Data.List (unfoldr)
  58. -- And needed for the instances:
  59. import qualified Data.ByteString as B
  60. import qualified Data.Map as Map
  61. import qualified Data.Set as Set
  62. import qualified Data.IntMap as IntMap
  63. import qualified Data.IntSet as IntSet
  64. import qualified Data.Ratio as R
  65. import qualified Data.Tree as T
  66. import Data.Array.Unboxed
  67. --
  68. -- This isn't available in older Hugs or older GHC
  69. --
  70. #if __GLASGOW_HASKELL__ >= 606
  71. import qualified Data.Sequence as Seq
  72. import qualified Data.Foldable as Fold
  73. #endif
  74. ------------------------------------------------------------------------
  75. -- | The @Binary@ class provides 'put' and 'get', methods to encode and
  76. -- decode a Haskell value to a lazy ByteString. It mirrors the Read and
  77. -- Show classes for textual representation of Haskell types, and is
  78. -- suitable for serialising Haskell values to disk, over the network.
  79. --
  80. -- For parsing and generating simple external binary formats (e.g. C
  81. -- structures), Binary may be used, but in general is not suitable
  82. -- for complex protocols. Instead use the Put and Get primitives
  83. -- directly.
  84. --
  85. -- Instances of Binary should satisfy the following property:
  86. --
  87. -- > decode . encode == id
  88. --
  89. -- That is, the 'get' and 'put' methods should be the inverse of each
  90. -- other. A range of instances are provided for basic Haskell types.
  91. --
  92. class Binary t where
  93. -- | Encode a value in the Put monad.
  94. put :: t -> Put
  95. -- | Decode a value in the Get monad
  96. get :: Get t
  97. -- $example
  98. -- To serialise a custom type, an instance of Binary for that type is
  99. -- required. For example, suppose we have a data structure:
  100. --
  101. -- > data Exp = IntE Int
  102. -- > | OpE String Exp Exp
  103. -- > deriving Show
  104. --
  105. -- We can encode values of this type into bytestrings using the
  106. -- following instance, which proceeds by recursively breaking down the
  107. -- structure to serialise:
  108. --
  109. -- > instance Binary Exp where
  110. -- > put (IntE i) = do put (0 :: Word8)
  111. -- > put i
  112. -- > put (OpE s e1 e2) = do put (1 :: Word8)
  113. -- > put s
  114. -- > put e1
  115. -- > put e2
  116. -- >
  117. -- > get = do t <- get :: Get Word8
  118. -- > case t of
  119. -- > 0 -> do i <- get
  120. -- > return (IntE i)
  121. -- > 1 -> do s <- get
  122. -- > e1 <- get
  123. -- > e2 <- get
  124. -- > return (OpE s e1 e2)
  125. --
  126. -- Note how we write an initial tag byte to indicate each variant of the
  127. -- data type.
  128. --
  129. -- We can simplify the writing of 'get' instances using monadic
  130. -- combinators:
  131. --
  132. -- > get = do tag <- getWord8
  133. -- > case tag of
  134. -- > 0 -> liftM IntE get
  135. -- > 1 -> liftM3 OpE get get get
  136. --
  137. -- The generation of Binary instances has been automated by a script
  138. -- using Scrap Your Boilerplate generics. Use the script here:
  139. -- <http://darcs.haskell.org/binary/tools/derive/BinaryDerive.hs>.
  140. --
  141. -- To derive the instance for a type, load this script into GHCi, and
  142. -- bring your type into scope. Your type can then have its Binary
  143. -- instances derived as follows:
  144. --
  145. -- > $ ghci -fglasgow-exts BinaryDerive.hs
  146. -- > *BinaryDerive> :l Example.hs
  147. -- > *Main> deriveM (undefined :: Drinks)
  148. -- >
  149. -- > instance Binary Main.Drinks where
  150. -- > put (Beer a) = putWord8 0 >> put a
  151. -- > put Coffee = putWord8 1
  152. -- > put Tea = putWord8 2
  153. -- > put EnergyDrink = putWord8 3
  154. -- > put Water = putWord8 4
  155. -- > put Wine = putWord8 5
  156. -- > put Whisky = putWord8 6
  157. -- > get = do
  158. -- > tag_ <- getWord8
  159. -- > case tag_ of
  160. -- > 0 -> get >>= \a -> return (Beer a)
  161. -- > 1 -> return Coffee
  162. -- > 2 -> return Tea
  163. -- > 3 -> return EnergyDrink
  164. -- > 4 -> return Water
  165. -- > 5 -> return Wine
  166. -- > 6 -> return Whisky
  167. -- >
  168. --
  169. -- To serialise this to a bytestring, we use 'encode', which packs the
  170. -- data structure into a binary format, in a lazy bytestring
  171. --
  172. -- > > let e = OpE "*" (IntE 7) (OpE "/" (IntE 4) (IntE 2))
  173. -- > > let v = encode e
  174. --
  175. -- Where 'v' is a binary encoded data structure. To reconstruct the
  176. -- original data, we use 'decode'
  177. --
  178. -- > > decode v :: Exp
  179. -- > OpE "*" (IntE 7) (OpE "/" (IntE 4) (IntE 2))
  180. --
  181. -- The lazy ByteString that results from 'encode' can be written to
  182. -- disk, and read from disk using Data.ByteString.Lazy IO functions,
  183. -- such as hPutStr or writeFile:
  184. --
  185. -- > > writeFile "/tmp/exp.txt" (encode e)
  186. --
  187. -- And read back with:
  188. --
  189. -- > > readFile "/tmp/exp.txt" >>= return . decode :: IO Exp
  190. -- > OpE "*" (IntE 7) (OpE "/" (IntE 4) (IntE 2))
  191. --
  192. -- We can also directly serialise a value to and from a Handle, or a file:
  193. --
  194. -- > > v <- decodeFile "/tmp/exp.txt" :: IO Exp
  195. -- > OpE "*" (IntE 7) (OpE "/" (IntE 4) (IntE 2))
  196. --
  197. -- And write a value to disk
  198. --
  199. -- > > encodeFile "/tmp/a.txt" v
  200. --
  201. ------------------------------------------------------------------------
  202. -- Wrappers to run the underlying monad
  203. -- | Encode a value using binary serialisation to a lazy ByteString.
  204. --
  205. encode :: Binary a => a -> ByteString
  206. encode = runPut . put
  207. {-# INLINE encode #-}
  208. -- | Decode a value from a lazy ByteString, reconstructing the original structure.
  209. --
  210. decode :: Binary a => ByteString -> a
  211. decode = runGet get
  212. ------------------------------------------------------------------------
  213. -- Convenience IO operations
  214. -- | Lazily serialise a value to a file
  215. --
  216. -- This is just a convenience function, it's defined simply as:
  217. --
  218. -- > encodeFile f = B.writeFile f . encode
  219. --
  220. -- So for example if you wanted to compress as well, you could use:
  221. --
  222. -- > B.writeFile f . compress . encode
  223. --
  224. encodeFile :: Binary a => FilePath -> a -> IO ()
  225. encodeFile f v = L.writeFile f (encode v)
  226. -- | Lazily reconstruct a value previously written to a file.
  227. --
  228. -- This is just a convenience function, it's defined simply as:
  229. --
  230. -- > decodeFile f = return . decode =<< B.readFile f
  231. --
  232. -- So for example if you wanted to decompress as well, you could use:
  233. --
  234. -- > return . decode . decompress =<< B.readFile f
  235. --
  236. -- After contructing the data from the input file, 'decodeFile' checks
  237. -- if the file is empty, and in doing so will force the associated file
  238. -- handle closed, if it is indeed empty. If the file is not empty,
  239. -- it is up to the decoding instance to consume the rest of the data,
  240. -- or otherwise finalise the resource.
  241. --
  242. decodeFile :: Binary a => FilePath -> IO a
  243. decodeFile f = do
  244. s <- L.readFile f
  245. return $ runGet (do v <- get
  246. m <- isEmpty
  247. m `seq` return v) s
  248. -- needs bytestring 0.9.1.x to work
  249. ------------------------------------------------------------------------
  250. -- Lazy put and get
  251. -- lazyPut :: (Binary a) => a -> Put
  252. -- lazyPut a = put (encode a)
  253. -- lazyGet :: (Binary a) => Get a
  254. -- lazyGet = fmap decode get
  255. ------------------------------------------------------------------------
  256. -- Simple instances
  257. -- The () type need never be written to disk: values of singleton type
  258. -- can be reconstructed from the type alone
  259. instance Binary () where
  260. put () = return ()
  261. get = return ()
  262. -- Bools are encoded as a byte in the range 0 .. 1
  263. instance Binary Bool where
  264. put = putWord8 . fromIntegral . fromEnum
  265. get = liftM (toEnum . fromIntegral) getWord8
  266. -- Values of type 'Ordering' are encoded as a byte in the range 0 .. 2
  267. instance Binary Ordering where
  268. put = putWord8 . fromIntegral . fromEnum
  269. get = liftM (toEnum . fromIntegral) getWord8
  270. ------------------------------------------------------------------------
  271. -- Words and Ints
  272. -- Words8s are written as bytes
  273. instance Binary Word8 where
  274. put = putWord8
  275. get = getWord8
  276. -- Words16s are written as 2 bytes in big-endian (network) order
  277. instance Binary Word16 where
  278. put = putWord16be
  279. get = getWord16be
  280. -- Words32s are written as 4 bytes in big-endian (network) order
  281. instance Binary Word32 where
  282. put = putWord32be
  283. get = getWord32be
  284. -- Words64s are written as 8 bytes in big-endian (network) order
  285. instance Binary Word64 where
  286. put = putWord64be
  287. get = getWord64be
  288. -- Int8s are written as a single byte.
  289. instance Binary Int8 where
  290. put i = put (fromIntegral i :: Word8)
  291. get = liftM fromIntegral (get :: Get Word8)
  292. -- Int16s are written as a 2 bytes in big endian format
  293. instance Binary Int16 where
  294. put i = put (fromIntegral i :: Word16)
  295. get = liftM fromIntegral (get :: Get Word16)
  296. -- Int32s are written as a 4 bytes in big endian format
  297. instance Binary Int32 where
  298. put i = put (fromIntegral i :: Word32)
  299. get = liftM fromIntegral (get :: Get Word32)
  300. -- Int64s are written as a 4 bytes in big endian format
  301. instance Binary Int64 where
  302. put i = put (fromIntegral i :: Word64)
  303. get = liftM fromIntegral (get :: Get Word64)
  304. ------------------------------------------------------------------------
  305. -- Words are are written as Word64s, that is, 8 bytes in big endian format
  306. instance Binary Word where
  307. put i = put (fromIntegral i :: Word64)
  308. get = liftM fromIntegral (get :: Get Word64)
  309. -- Ints are are written as Int64s, that is, 8 bytes in big endian format
  310. instance Binary Int where
  311. put i = put (fromIntegral i :: Int64)
  312. get = liftM fromIntegral (get :: Get Int64)
  313. ------------------------------------------------------------------------
  314. --
  315. -- Portable, and pretty efficient, serialisation of Integer
  316. --
  317. -- Fixed-size type for a subset of Integer
  318. type SmallInt = Int32
  319. -- Integers are encoded in two ways: if they fit inside a SmallInt,
  320. -- they're written as a byte tag, and that value. If the Integer value
  321. -- is too large to fit in a SmallInt, it is written as a byte array,
  322. -- along with a sign and length field.
  323. instance Binary Integer where
  324. {-# INLINE put #-}
  325. put n | n >= lo && n <= hi = do
  326. putWord8 0
  327. put (fromIntegral n :: SmallInt) -- fast path
  328. where
  329. lo = fromIntegral (minBound :: SmallInt) :: Integer
  330. hi = fromIntegral (maxBound :: SmallInt) :: Integer
  331. put n = do
  332. putWord8 1
  333. put sign
  334. put (unroll (abs n)) -- unroll the bytes
  335. where
  336. sign = fromIntegral (signum n) :: Word8
  337. {-# INLINE get #-}
  338. get = do
  339. tag <- get :: Get Word8
  340. case tag of
  341. 0 -> liftM fromIntegral (get :: Get SmallInt)
  342. _ -> do sign <- get
  343. bytes <- get
  344. let v = roll bytes
  345. return $! if sign == (1 :: Word8) then v else - v
  346. --
  347. -- Fold and unfold an Integer to and from a list of its bytes
  348. --
  349. unroll :: Integer -> [Word8]
  350. unroll = unfoldr step
  351. where
  352. step 0 = Nothing
  353. step i = Just (fromIntegral i, i `shiftR` 8)
  354. roll :: [Word8] -> Integer
  355. roll = foldr unstep 0
  356. where
  357. unstep b a = a `shiftL` 8 .|. fromIntegral b
  358. {-
  359. --
  360. -- An efficient, raw serialisation for Integer (GHC only)
  361. --
  362. -- TODO This instance is not architecture portable. GMP stores numbers as
  363. -- arrays of machine sized words, so the byte format is not portable across
  364. -- architectures with different endianess and word size.
  365. import Data.ByteString.Base (toForeignPtr,unsafePackAddress, memcpy)
  366. import GHC.Base hiding (ord, chr)
  367. import GHC.Prim
  368. import GHC.Ptr (Ptr(..))
  369. import GHC.IOBase (IO(..))
  370. instance Binary Integer where
  371. put (S# i) = putWord8 0 >> put (I# i)
  372. put (J# s ba) = do
  373. putWord8 1
  374. put (I# s)
  375. put (BA ba)
  376. get = do
  377. b <- getWord8
  378. case b of
  379. 0 -> do (I# i#) <- get
  380. return (S# i#)
  381. _ -> do (I# s#) <- get
  382. (BA a#) <- get
  383. return (J# s# a#)
  384. instance Binary ByteArray where
  385. -- Pretty safe.
  386. put (BA ba) =
  387. let sz = sizeofByteArray# ba -- (primitive) in *bytes*
  388. addr = byteArrayContents# ba
  389. bs = unsafePackAddress (I# sz) addr
  390. in put bs -- write as a ByteString. easy, yay!
  391. -- Pretty scary. Should be quick though
  392. get = do
  393. (fp, off, n@(I# sz)) <- liftM toForeignPtr get -- so decode a ByteString
  394. assert (off == 0) $ return $ unsafePerformIO $ do
  395. (MBA arr) <- newByteArray sz -- and copy it into a ByteArray#
  396. let to = byteArrayContents# (unsafeCoerce# arr) -- urk, is this safe?
  397. withForeignPtr fp $ \from -> memcpy (Ptr to) from (fromIntegral n)
  398. freezeByteArray arr
  399. -- wrapper for ByteArray#
  400. data ByteArray = BA {-# UNPACK #-} !ByteArray#
  401. data MBA = MBA {-# UNPACK #-} !(MutableByteArray# RealWorld)
  402. newByteArray :: Int# -> IO MBA
  403. newByteArray sz = IO $ \s ->
  404. case newPinnedByteArray# sz s of { (# s', arr #) ->
  405. (# s', MBA arr #) }
  406. freezeByteArray :: MutableByteArray# RealWorld -> IO ByteArray
  407. freezeByteArray arr = IO $ \s ->
  408. case unsafeFreezeByteArray# arr s of { (# s', arr' #) ->
  409. (# s', BA arr' #) }
  410. -}
  411. instance (Binary a,Integral a) => Binary (R.Ratio a) where
  412. put r = put (R.numerator r) >> put (R.denominator r)
  413. get = liftM2 (R.%) get get
  414. ------------------------------------------------------------------------
  415. -- Char is serialised as UTF-8
  416. instance Binary Char where
  417. put a | c <= 0x7f = put (fromIntegral c :: Word8)
  418. | c <= 0x7ff = do put (0xc0 .|. y)
  419. put (0x80 .|. z)
  420. | c <= 0xffff = do put (0xe0 .|. x)
  421. put (0x80 .|. y)
  422. put (0x80 .|. z)
  423. | c <= 0x10ffff = do put (0xf0 .|. w)
  424. put (0x80 .|. x)
  425. put (0x80 .|. y)
  426. put (0x80 .|. z)
  427. | otherwise = error "Not a valid Unicode code point"
  428. where
  429. c = ord a
  430. z, y, x, w :: Word8
  431. z = fromIntegral (c .&. 0x3f)
  432. y = fromIntegral (shiftR c 6 .&. 0x3f)
  433. x = fromIntegral (shiftR c 12 .&. 0x3f)
  434. w = fromIntegral (shiftR c 18 .&. 0x7)
  435. get = do
  436. let getByte = liftM (fromIntegral :: Word8 -> Int) get
  437. shiftL6 = flip shiftL 6 :: Int -> Int
  438. w <- getByte
  439. r <- case () of
  440. _ | w < 0x80 -> return w
  441. | w < 0xe0 -> do
  442. x <- liftM (xor 0x80) getByte
  443. return (x .|. shiftL6 (xor 0xc0 w))
  444. | w < 0xf0 -> do
  445. x <- liftM (xor 0x80) getByte
  446. y <- liftM (xor 0x80) getByte
  447. return (y .|. shiftL6 (x .|. shiftL6
  448. (xor 0xe0 w)))
  449. | otherwise -> do
  450. x <- liftM (xor 0x80) getByte
  451. y <- liftM (xor 0x80) getByte
  452. z <- liftM (xor 0x80) getByte
  453. return (z .|. shiftL6 (y .|. shiftL6
  454. (x .|. shiftL6 (xor 0xf0 w))))
  455. return $! chr r
  456. ------------------------------------------------------------------------
  457. -- Instances for the first few tuples
  458. instance (Binary a, Binary b) => Binary (a,b) where
  459. put (a,b) = put a >> put b
  460. get = liftM2 (,) get get
  461. instance (Binary a, Binary b, Binary c) => Binary (a,b,c) where
  462. put (a,b,c) = put a >> put b >> put c
  463. get = liftM3 (,,) get get get
  464. instance (Binary a, Binary b, Binary c, Binary d) => Binary (a,b,c,d) where
  465. put (a,b,c,d) = put a >> put b >> put c >> put d
  466. get = liftM4 (,,,) get get get get
  467. instance (Binary a, Binary b, Binary c, Binary d, Binary e) => Binary (a,b,c,d,e) where
  468. put (a,b,c,d,e) = put a >> put b >> put c >> put d >> put e
  469. get = liftM5 (,,,,) get get get get get
  470. --
  471. -- and now just recurse:
  472. --
  473. instance (Binary a, Binary b, Binary c, Binary d, Binary e, Binary f)
  474. => Binary (a,b,c,d,e,f) where
  475. put (a,b,c,d,e,f) = put (a,(b,c,d,e,f))
  476. get = do (a,(b,c,d,e,f)) <- get ; return (a,b,c,d,e,f)
  477. instance (Binary a, Binary b, Binary c, Binary d, Binary e, Binary f, Binary g)
  478. => Binary (a,b,c,d,e,f,g) where
  479. put (a,b,c,d,e,f,g) = put (a,(b,c,d,e,f,g))
  480. get = do (a,(b,c,d,e,f,g)) <- get ; return (a,b,c,d,e,f,g)
  481. instance (Binary a, Binary b, Binary c, Binary d, Binary e,
  482. Binary f, Binary g, Binary h)
  483. => Binary (a,b,c,d,e,f,g,h) where
  484. put (a,b,c,d,e,f,g,h) = put (a,(b,c,d,e,f,g,h))
  485. get = do (a,(b,c,d,e,f,g,h)) <- get ; return (a,b,c,d,e,f,g,h)
  486. instance (Binary a, Binary b, Binary c, Binary d, Binary e,
  487. Binary f, Binary g, Binary h, Binary i)
  488. => Binary (a,b,c,d,e,f,g,h,i) where
  489. put (a,b,c,d,e,f,g,h,i) = put (a,(b,c,d,e,f,g,h,i))
  490. get = do (a,(b,c,d,e,f,g,h,i)) <- get ; return (a,b,c,d,e,f,g,h,i)
  491. instance (Binary a, Binary b, Binary c, Binary d, Binary e,
  492. Binary f, Binary g, Binary h, Binary i, Binary j)
  493. => Binary (a,b,c,d,e,f,g,h,i,j) where
  494. put (a,b,c,d,e,f,g,h,i,j) = put (a,(b,c,d,e,f,g,h,i,j))
  495. get = do (a,(b,c,d,e,f,g,h,i,j)) <- get ; return (a,b,c,d,e,f,g,h,i,j)
  496. ------------------------------------------------------------------------
  497. -- Container types
  498. instance Binary a => Binary [a] where
  499. put l = put (length l) >> mapM_ put l
  500. get = do n <- get :: Get Int
  501. getMany n
  502. -- | 'getMany n' get 'n' elements in order, without blowing the stack.
  503. getMany :: Binary a => Int -> Get [a]
  504. getMany n = go [] n
  505. where
  506. go xs 0 = return $! reverse xs
  507. go xs i = do x <- get
  508. -- we must seq x to avoid stack overflows due to laziness in
  509. -- (>>=)
  510. x `seq` go (x:xs) (i-1)
  511. {-# INLINE getMany #-}
  512. instance (Binary a) => Binary (Maybe a) where
  513. put Nothing = putWord8 0
  514. put (Just x) = putWord8 1 >> put x
  515. get = do
  516. w <- getWord8
  517. case w of
  518. 0 -> return Nothing
  519. _ -> liftM Just get
  520. instance (Binary a, Binary b) => Binary (Either a b) where
  521. put (Left a) = putWord8 0 >> put a
  522. put (Right b) = putWord8 1 >> put b
  523. get = do
  524. w <- getWord8
  525. case w of
  526. 0 -> liftM Left get
  527. _ -> liftM Right get
  528. ------------------------------------------------------------------------
  529. -- ByteStrings (have specially efficient instances)
  530. instance Binary B.ByteString where
  531. put bs = do put (B.length bs)
  532. putByteString bs
  533. get = get >>= getByteString
  534. --
  535. -- Using old versions of fps, this is a type synonym, and non portable
  536. --
  537. -- Requires 'flexible instances'
  538. --
  539. instance Binary ByteString where
  540. put bs = do put (fromIntegral (L.length bs) :: Int)
  541. putLazyByteString bs
  542. get = get >>= getLazyByteString
  543. ------------------------------------------------------------------------
  544. -- Maps and Sets
  545. instance (Ord a, Binary a) => Binary (Set.Set a) where
  546. put s = put (Set.size s) >> mapM_ put (Set.toAscList s)
  547. get = liftM Set.fromDistinctAscList get
  548. instance (Ord k, Binary k, Binary e) => Binary (Map.Map k e) where
  549. put m = put (Map.size m) >> mapM_ put (Map.toAscList m)
  550. get = liftM Map.fromDistinctAscList get
  551. instance Binary IntSet.IntSet where
  552. put s = put (IntSet.size s) >> mapM_ put (IntSet.toAscList s)
  553. get = liftM IntSet.fromDistinctAscList get
  554. instance (Binary e) => Binary (IntMap.IntMap e) where
  555. put m = put (IntMap.size m) >> mapM_ put (IntMap.toAscList m)
  556. get = liftM IntMap.fromDistinctAscList get
  557. ------------------------------------------------------------------------
  558. -- Queues and Sequences
  559. #if __GLASGOW_HASKELL__ >= 606
  560. --
  561. -- This is valid Hugs, but you need the most recent Hugs
  562. --
  563. instance (Binary e) => Binary (Seq.Seq e) where
  564. put s = put (Seq.length s) >> Fold.mapM_ put s
  565. get = do n <- get :: Get Int
  566. rep Seq.empty n get
  567. where rep xs 0 _ = return $! xs
  568. rep xs n g = xs `seq` n `seq` do
  569. x <- g
  570. rep (xs Seq.|> x) (n-1) g
  571. #endif
  572. ------------------------------------------------------------------------
  573. -- Floating point
  574. instance Binary Double where
  575. put d = put (decodeFloat d)
  576. get = liftM2 encodeFloat get get
  577. instance Binary Float where
  578. put f = put (decodeFloat f)
  579. get = liftM2 encodeFloat get get
  580. ------------------------------------------------------------------------
  581. -- Trees
  582. instance (Binary e) => Binary (T.Tree e) where
  583. put (T.Node r s) = put r >> put s
  584. get = liftM2 T.Node get get
  585. ------------------------------------------------------------------------
  586. -- Arrays
  587. instance (Binary i, Ix i, Binary e) => Binary (Array i e) where
  588. put a = do
  589. put (bounds a)
  590. put (rangeSize $ bounds a) -- write the length
  591. mapM_ put (elems a) -- now the elems.
  592. get = do
  593. bs <- get
  594. n <- get -- read the length
  595. xs <- getMany n -- now the elems.
  596. return (listArray bs xs)
  597. --
  598. -- The IArray UArray e constraint is non portable. Requires flexible instances
  599. --
  600. instance (Binary i, Ix i, Binary e, IArray UArray e) => Binary (UArray i e) where
  601. put a = do
  602. put (bounds a)
  603. put (rangeSize $ bounds a) -- now write the length
  604. mapM_ put (elems a)
  605. get = do
  606. bs <- get
  607. n <- get
  608. xs <- getMany n
  609. return (listArray bs xs)