-- |
-- Module      : Data.UUID.V3
-- Copyright   : (c) 2010 Antoine Latter
--
-- License     : BSD-style
--
-- Maintainer  : aslatter@gmail.com
-- Stability   : experimental
-- Portability : portable
--
--
-- This module implements Version 3 UUIDs as specified
-- in RFC 4122.
--
-- These UUIDs identify an object within a namespace,
-- and are deterministic.
--
-- The namespace is identified by a UUID.  Several sample
-- namespaces are enclosed.

module Data.UUID.V3
    (generateNamed
    ,Shared.namespaceDNS
    ,Shared.namespaceURL
    ,Shared.namespaceOID
    ,Shared.namespaceX500
    ) where

import Data.Word
import Data.Bits

import Data.UUID.Internal
import qualified Data.UUID.Named as Shared
import qualified Data.Digest.MD5 as MD5


-- |Generate a 'UUID' within the specified namespace out of the given
-- object.
--
-- Uses an MD5 hash. The UUID is built from first 128 bits of the hash of
-- the namespace UUID and the name (as a series of Word8).
generateNamed :: UUID    -- ^Namespace
              -> [Word8] -- ^Object
              -> UUID
generateNamed = Shared.generateNamed hash 3

hash :: [Word8] -> (Word32, Word32, Word32, Word32)
hash bytes
    = case map f $ chunk 4 $ MD5.hash bytes of
        w1:w2:w3:w4:_ -> (w1, w2, w3, w4)
        _ -> error "Data.UUID.V3.hash: fatal error"

 where f [b1, b2, b3, b4]
           = sum
             [ fromIntegral b4
             , fromIntegral b3 `shiftL` 8
             , fromIntegral b2 `shiftL` 16
             , fromIntegral b1 `shiftL` 24
             ]
       f _ = error "Data.UUID.V3.hash: fatal error"

chunk :: Int -> [a] -> [[a]]
chunk n = go n []
 where go _ [] [] = []
       go _ ys [] = reverse ys:[]
       go 0 ys xs = reverse ys:go n [] xs
       go m ys (x:xs) = go (m-1) (x:ys) xs
