{-# LANGUAGE TypeFamilies #-} -- Module : Data.UUID.Builder -- Copyright : (c) 2009 Mark Lentczner -- -- License : BSD-style -- -- Maintainer : markl@glyphic.com -- Stability : experimental -- Portability : portable -- -- This module provides a system that can call a function that takes -- a sequence of some number of Word8 arguments. -- -- The twist is that the Word8 arguments can be supplied directly -- from Word8s, or from other sources that may provide more than -- one Word8 apiece. Examples are Word16 and Word32 that supply -- two and four Word8s respectively. Other ByteSource instances -- can be defined. -- -- This module is admittedly overkill. There are only three places -- in the uuid package that need to call buildFromBytes with 16 -- Word8 values, but each place uses Words of different lengths: -- version 1 uuids: 32-16-16-16-8-8-8-8-8-8 -- version 4 uuids: 24-24-32-24-24 -- version 5 uuids: 32-32-32-32 -- Originally, these three constructions were hand coded but the -- code was ungainly. Using this module makes the code very -- concise, and turns out to optimize to just as fast, or faster! module Data.UUID.Builder (ByteSource(..) ,ByteSink ,Takes1Byte ,Takes2Bytes ,Takes3Bytes ,Takes4Bytes ) where import Data.Bits import Data.Word type Takes1Byte g = Word8 -> g type Takes2Bytes g = Word8 -> Word8 -> g type Takes3Bytes g = Word8 -> Word8 -> Word8 -> g type Takes4Bytes g = Word8 -> Word8 -> Word8 -> Word8 -> g -- | Type of function that a given ByteSource needs. -- This function must take as many Word8 arguments as the ByteSource provides type family ByteSink w g type instance ByteSink Word8 g = Takes1Byte g type instance ByteSink Word16 g = Takes2Bytes g type instance ByteSink Word32 g = Takes4Bytes g type instance ByteSink Int g = Takes4Bytes g -- | Class of types that can add Word8s to a Builder. -- Instances for Word8, Word16, Word32 and Int provide 1, 2, 4 and 4 bytes, -- respectively, into a ByteSink class ByteSource w where -- | Apply the source's bytes to the sink (/-/) :: ByteSink w g -> w -> g infixl 6 /-/ instance ByteSource Word8 where f /-/ w = f w instance ByteSource Word16 where f /-/ w = f b1 b2 where b1 = fromIntegral (w `shiftR` 8) b2 = fromIntegral w instance ByteSource Word32 where f /-/ w = f b1 b2 b3 b4 where b1 = fromIntegral (w `shiftR` 24) b2 = fromIntegral (w `shiftR` 16) b3 = fromIntegral (w `shiftR` 8) b4 = fromIntegral w instance ByteSource Int where f /-/ w = f b1 b2 b3 b4 where b1 = fromIntegral (w `shiftR` 24) b2 = fromIntegral (w `shiftR` 16) b3 = fromIntegral (w `shiftR` 8) b4 = fromIntegral w