on 8917b68 help sign in
typeable/uuid/Data/UUID/Builder.hs
88 lines 2.8 kB history raw
1{-# LANGUAGE TypeFamilies #-}
3-- Module : Data.UUID.Builder
4-- Copyright : (c) 2009 Mark Lentczner
5--
6-- License : BSD-style
7--
8-- Maintainer : markl@glyphic.com
9-- Stability : experimental
10-- Portability : portable
11--
12-- This module provides a system that can call a function that takes
13-- a sequence of some number of Word8 arguments.
14--
15-- The twist is that the Word8 arguments can be supplied directly
16-- from Word8s, or from other sources that may provide more than
17-- one Word8 apiece. Examples are Word16 and Word32 that supply
18-- two and four Word8s respectively. Other ByteSource instances
19-- can be defined.
20--
21-- This module is admittedly overkill. There are only three places
22-- in the uuid package that need to call buildFromBytes with 16
23-- Word8 values, but each place uses Words of different lengths:
24-- version 1 uuids: 32-16-16-16-8-8-8-8-8-8
25-- version 4 uuids: 24-24-32-24-24
26-- version 5 uuids: 32-32-32-32
27-- Originally, these three constructions were hand coded but the
28-- code was ungainly. Using this module makes the code very
29-- concise, and turns out to optimize to just as fast, or faster!
31module Data.UUID.Builder
32 (ByteSource(..)
33 ,ByteSink
34 ,Takes1Byte
35 ,Takes2Bytes
36 ,Takes3Bytes
37 ,Takes4Bytes
38 ) where
40import Data.Bits
41import Data.Word
45type Takes1Byte g = Word8 -> g
46type Takes2Bytes g = Word8 -> Word8 -> g
47type Takes3Bytes g = Word8 -> Word8 -> Word8 -> g
48type Takes4Bytes g = Word8 -> Word8 -> Word8 -> Word8 -> g
50-- | Type of function that a given ByteSource needs.
51-- This function must take as many Word8 arguments as the ByteSource provides
52type family ByteSink w g
53type instance ByteSink Word8 g = Takes1Byte g
54type instance ByteSink Word16 g = Takes2Bytes g
55type instance ByteSink Word32 g = Takes4Bytes g
56type instance ByteSink Int g = Takes4Bytes g
59-- | Class of types that can add Word8s to a Builder.
60-- Instances for Word8, Word16, Word32 and Int provide 1, 2, 4 and 4 bytes,
61-- respectively, into a ByteSink
62class ByteSource w where
63 -- | Apply the source's bytes to the sink
64 (/-/) :: ByteSink w g -> w -> g
66infixl 6 /-/
68instance ByteSource Word8 where
69 f /-/ w = f w
71instance ByteSource Word16 where
72 f /-/ w = f b1 b2
73 where b1 = fromIntegral (w `shiftR` 8)
74 b2 = fromIntegral w
76instance ByteSource Word32 where
77 f /-/ w = f b1 b2 b3 b4
78 where b1 = fromIntegral (w `shiftR` 24)
79 b2 = fromIntegral (w `shiftR` 16)
80 b3 = fromIntegral (w `shiftR` 8)
81 b4 = fromIntegral w
83instance ByteSource Int where
84 f /-/ w = f b1 b2 b3 b4
85 where b1 = fromIntegral (w `shiftR` 24)
86 b2 = fromIntegral (w `shiftR` 16)
87 b3 = fromIntegral (w `shiftR` 8)
88 b4 = fromIntegral w