@@ -13,7 +13,6 @@ module System.Nix.Hash
1313 , NamedAlgo (.. )
1414 , algoToText
1515 , textToAlgo
16- , SomeNamedDigest (.. )
1716 , mkNamedDigest
1817
1918 , mkStorePathHash
@@ -22,13 +21,17 @@ module System.Nix.Hash
2221 , encodeDigestWith
2322 , decodeDigestWith
2423
24+ , algoDigestBuilder
2525 , digestBuilder
2626 ) where
2727
2828import Crypto.Hash (Digest , HashAlgorithm , MD5 (.. ), SHA1 (.. ), SHA256 (.. ), SHA512 (.. ))
2929import Data.ByteString (ByteString )
3030import Data.Constraint.Extras (Has (has ))
3131import Data.Constraint.Extras.TH (deriveArgDict )
32+ import Data.Dependent.Sum (DSum ((:=>) ))
33+ import Data.GADT.Compare.TH (deriveGEq , deriveGCompare )
34+ import Data.GADT.Show.TH (deriveGShow )
3235import Data.Kind (Type )
3336import Data.Some (Some (Some ))
3437import Data.Text (Text )
@@ -81,13 +84,16 @@ data HashAlgo :: Type -> Type where
8184 HashAlgo_SHA256 :: HashAlgo SHA256
8285 HashAlgo_SHA512 :: HashAlgo SHA512
8386
87+ deriveGEq ''HashAlgo
88+ deriveGCompare ''HashAlgo
89+ deriveGShow ''HashAlgo
8490deriveArgDict ''HashAlgo
8591
8692algoToText :: forall t . HashAlgo t -> Text
8793algoToText x = has @ NamedAlgo x (algoName @ t )
8894
89- _hashAlgoValue :: HashAlgo a -> a
90- _hashAlgoValue = \ case
95+ hashAlgoValue :: HashAlgo a -> a
96+ hashAlgoValue = \ case
9197 HashAlgo_MD5 -> MD5
9298 HashAlgo_SHA1 -> SHA1
9399 HashAlgo_SHA256 -> SHA256
@@ -101,44 +107,20 @@ textToAlgo = \case
101107 " sha512" -> Right $ Some HashAlgo_SHA512
102108 name -> Left $ " Unknown hash name: " <> Data.Text. unpack name
103109
104- -- | A digest whose 'NamedAlgo' is not known at compile time.
105- data SomeNamedDigest = forall a . NamedAlgo a => SomeDigest (Digest a )
106-
107- instance Arbitrary SomeNamedDigest where
110+ instance Arbitrary (DSum HashAlgo Digest ) where
108111 arbitrary = oneof
109- [ SomeDigest @ MD5 <$> arbitrary
110- , SomeDigest @ SHA1 <$> arbitrary
111- , SomeDigest @ SHA256 <$> arbitrary
112- , SomeDigest @ SHA512 <$> arbitrary
112+ [ ( HashAlgo_MD5 :=> ) <$> arbitrary
113+ , ( HashAlgo_SHA1 :=> ) <$> arbitrary
114+ , ( HashAlgo_SHA256 :=> ) <$> arbitrary
115+ , ( HashAlgo_SHA512 :=> ) <$> arbitrary
113116 ]
114117
115- instance Show SomeNamedDigest where
116- show sd = case sd of
117- SomeDigest (digest :: Digest hashType ) ->
118- Data.Text. unpack $ " SomeDigest"
119- <> " "
120- <> algoName @ hashType
121- <> " :"
122- <> encodeDigestWith NixBase32 digest
123-
124- instance Eq SomeNamedDigest where
125- (==) (SomeDigest (a :: Digest aType ))
126- (SomeDigest (b :: Digest bType ))
127- = algoName @ aType == algoName @ bType
128- && encodeDigestWith NixBase32 a == encodeDigestWith NixBase32 b
129-
130- instance Ord SomeNamedDigest where
131- (<=) (SomeDigest (a :: Digest aType ))
132- (SomeDigest (b :: Digest bType ))
133- = algoName @ aType <= algoName @ bType
134- && encodeDigestWith NixBase32 a <= encodeDigestWith NixBase32 b
135-
136- -- | Make @SomeNamedDigest@ based on provided SRI hash name
118+ -- | Make @DSum HashAlgo Digest@ based on provided SRI hash name
137119-- and its encoded form
138120mkNamedDigest
139121 :: Text -- ^ SRI name
140122 -> Text -- ^ base encoded hash
141- -> Either String SomeNamedDigest
123+ -> Either String ( DSum HashAlgo Digest )
142124mkNamedDigest name sriHash =
143125 let (sriName, h) = Data.Text. breakOnEnd " -" sriHash in
144126 if sriName == " " || sriName == name <> " -"
@@ -154,13 +136,10 @@ mkNamedDigest name sriHash =
154136 <> " "
155137 <> name
156138 where
157- mkDigest h = case name of
158- " md5" -> SomeDigest <$> decodeGo MD5 h
159- " sha1" -> SomeDigest <$> decodeGo SHA1 h
160- " sha256" -> SomeDigest <$> decodeGo SHA256 h
161- " sha512" -> SomeDigest <$> decodeGo SHA512 h
162- _ -> Left $ " Unknown hash name: " <> Data.Text. unpack name
163- decodeGo :: forall a . NamedAlgo a => a -> Text -> Either String (Digest a )
139+ mkDigest h =
140+ textToAlgo name
141+ >>= \ (Some a) -> has @ HashAlgorithm a $ fmap (a :=> ) $ decodeGo a h
142+ decodeGo :: HashAlgorithm a => HashAlgo a -> Text -> Either String (Digest a )
164143 decodeGo a h
165144 | size == base16Len = decodeDigestWith Base16 h
166145 | size == base32Len = decodeDigestWith NixBase32 h
@@ -181,7 +160,7 @@ mkNamedDigest name sriHash =
181160 <> Data.Text. pack (show [base16Len, base32Len, base64Len])
182161 where
183162 size = Data.Text. length h
184- hsize = Crypto.Hash. hashDigestSize a
163+ hsize = Crypto.Hash. hashDigestSize (hashAlgoValue a)
185164 base16Len = hsize * 2
186165 base32Len = ((hsize * 8 - 1 ) `div` 5 ) + 1 ;
187166 base64Len = ((4 * hsize `div` 3 ) + 3 ) `div` 4 * 4 ;
@@ -227,3 +206,10 @@ digestBuilder digest =
227206 <> " :"
228207 <> Data.Text.Lazy.Builder. fromText
229208 (System.Nix.Hash. encodeDigestWith NixBase32 digest)
209+
210+ -- | Builder for @DSum HashAlgo Digest@s
211+ algoDigestBuilder :: DSum HashAlgo Digest -> Builder
212+ algoDigestBuilder (a :=> d) =
213+ Data.Text.Lazy.Builder. fromText (System.Nix.Hash. algoToText a)
214+ <> " :"
215+ <> Data.Text.Lazy.Builder. fromText (encodeDigestWith NixBase32 d)
0 commit comments