46 lines
1.3 KiB
Haskell
46 lines
1.3 KiB
Haskell
module ContentStore.Object
|
|
( Domain(..)
|
|
, ObjectHash
|
|
, StorePath(..)
|
|
, hashObject
|
|
, hashToText
|
|
, textToHashBytes
|
|
, shardForHash
|
|
) where
|
|
|
|
import Crypto.Hash (Digest, SHA256, hash)
|
|
import Data.ByteArray (convert)
|
|
import Data.ByteString.Base16 (decode, encode)
|
|
import Data.Text (Text)
|
|
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
|
|
|
|
import qualified Data.ByteString as BS
|
|
import qualified Data.Text as T
|
|
|
|
newtype Domain = Domain { unDomain :: Text }
|
|
deriving (Eq, Ord, Show)
|
|
|
|
type ObjectHash = Text
|
|
|
|
newtype StorePath = StorePath { unStorePath :: FilePath }
|
|
deriving (Eq, Ord, Show)
|
|
|
|
hashObject :: Domain -> BS.ByteString -> ObjectHash
|
|
hashObject (Domain domain) payload = hashToText digest
|
|
where
|
|
digest :: Digest SHA256
|
|
digest = hash (encodeUtf8 domain <> BS.pack [0x00] <> payload)
|
|
|
|
hashToText :: Digest SHA256 -> Text
|
|
hashToText = decodeUtf8 . encode . (convert :: Digest SHA256 -> BS.ByteString)
|
|
|
|
textToHashBytes :: Text -> Either String BS.ByteString
|
|
textToHashBytes h = case decode (encodeUtf8 h) of
|
|
Left _ -> Left "invalid hexadecimal hash"
|
|
Right raw
|
|
| BS.length raw == 32 -> Right raw
|
|
| otherwise -> Left "hash must decode to 32 bytes"
|
|
|
|
shardForHash :: ObjectHash -> FilePath
|
|
shardForHash = T.unpack . T.take 3
|