@@ -44,7 +44,10 @@ data HashAlgorithm
4444
4545-- | The result of running a 'HashAlgorithm'.
4646newtype Digest (a :: HashAlgorithm ) =
47- Digest BS. ByteString deriving (Show , Eq , Ord , DataHashable.Hashable )
47+ Digest BS. ByteString deriving (Eq , Ord , DataHashable.Hashable )
48+
49+ instance Show (Digest a ) where
50+ show = (" Digest " ++ ) . show . encodeBase32
4851
4952-- | The primitive interface for incremental hashing for a given
5053-- 'HashAlgorithm'. Every 'HashAlgorithm' should have an instance.
@@ -63,18 +66,52 @@ class ValidAlgo (a :: HashAlgorithm) where
6366-- purposes (e.g. SRI hashes)
6467class NamedAlgo (a :: HashAlgorithm ) where
6568 algoName :: Text
69+ hashSize :: Int
6670
6771instance NamedAlgo 'MD5 where
6872 algoName = " md5"
73+ hashSize = 16
6974
7075instance NamedAlgo 'SHA1 where
7176 algoName = " sha1"
77+ hashSize = 20
7278
7379instance NamedAlgo 'SHA256 where
7480 algoName = " sha256"
81+ hashSize = 32
82+
83+ {-
84+ instance NamedAlgo 'SHA512 where
85+ algoName = "sha512"
86+ hashSize = 64
87+ -}
7588
7689-- | A digest whose 'NamedAlgo' is not known at compile time.
77- data SomeNamedDigest = forall a . NamedAlgo a => SomeDigest (Digest a )
90+ data SomeNamedDigest = forall a . (NamedAlgo a , ValidAlgo a ) => SomeDigest (Digest a )
91+
92+ instance Show SomeNamedDigest where
93+ show sd = case sd of
94+ SomeDigest (digest :: Digest hashType ) -> T. unpack $ " SomeDigest " <> algoName @ hashType <> " :" <> encodeBase32 digest
95+
96+ mkNamedDigest :: Text -> Text -> Either String SomeNamedDigest
97+ mkNamedDigest name hash = case name of
98+ " md5" -> SomeDigest <$> decode @ 'MD5
99+ " sha1" -> SomeDigest <$> decode @ 'SHA1
100+ " sha256" -> SomeDigest <$> decode @ 'SHA256
101+ _ -> Left $ " Unknown hash name: " ++ T. unpack name
102+ where
103+ size = T. length hash
104+ decode :: forall a . (NamedAlgo a , ValidAlgo a ) => Either String (Digest a )
105+ decode
106+ | size == base16Len = decodeBase16 hash
107+ | size == base32Len = decodeBase32 hash
108+ -- | size == base64Len = decodeBase64 s -- TODO
109+ | otherwise = Left $ T. unpack hash ++ " is not a valid " ++ T. unpack name ++ " hash."
110+ where
111+ hsize = hashSize @ a
112+ base16Len = hsize * 2
113+ base32Len = ((hsize * 8 - 1 ) `div` 5 ) + 1 ;
114+ -- base64Len = ((4 * hsize / 3) + 3) & ~3;
78115
79116-- | Hash an entire (strict) 'BS.ByteString' as a single call.
80117--
0 commit comments