@@ -13,7 +13,6 @@ module System.Nix.Hash
13
13
, NamedAlgo (.. )
14
14
, algoToText
15
15
, textToAlgo
16
- , SomeNamedDigest (.. )
17
16
, mkNamedDigest
18
17
19
18
, mkStorePathHash
@@ -22,13 +21,17 @@ module System.Nix.Hash
22
21
, encodeDigestWith
23
22
, decodeDigestWith
24
23
24
+ , algoDigestBuilder
25
25
, digestBuilder
26
26
) where
27
27
28
28
import Crypto.Hash (Digest , HashAlgorithm , MD5 (.. ), SHA1 (.. ), SHA256 (.. ), SHA512 (.. ))
29
29
import Data.ByteString (ByteString )
30
30
import Data.Constraint.Extras (Has (has ))
31
31
import 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 )
32
35
import Data.Kind (Type )
33
36
import Data.Some (Some (Some ))
34
37
import Data.Text (Text )
@@ -81,13 +84,16 @@ data HashAlgo :: Type -> Type where
81
84
HashAlgo_SHA256 :: HashAlgo SHA256
82
85
HashAlgo_SHA512 :: HashAlgo SHA512
83
86
87
+ deriveGEq ''HashAlgo
88
+ deriveGCompare ''HashAlgo
89
+ deriveGShow ''HashAlgo
84
90
deriveArgDict ''HashAlgo
85
91
86
92
algoToText :: forall t . HashAlgo t -> Text
87
93
algoToText x = has @ NamedAlgo x (algoName @ t )
88
94
89
- _hashAlgoValue :: HashAlgo a -> a
90
- _hashAlgoValue = \ case
95
+ hashAlgoValue :: HashAlgo a -> a
96
+ hashAlgoValue = \ case
91
97
HashAlgo_MD5 -> MD5
92
98
HashAlgo_SHA1 -> SHA1
93
99
HashAlgo_SHA256 -> SHA256
@@ -101,44 +107,20 @@ textToAlgo = \case
101
107
" sha512" -> Right $ Some HashAlgo_SHA512
102
108
name -> Left $ " Unknown hash name: " <> Data.Text. unpack name
103
109
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
108
111
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
113
116
]
114
117
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
137
119
-- and its encoded form
138
120
mkNamedDigest
139
121
:: Text -- ^ SRI name
140
122
-> Text -- ^ base encoded hash
141
- -> Either String SomeNamedDigest
123
+ -> Either String ( DSum HashAlgo Digest )
142
124
mkNamedDigest name sriHash =
143
125
let (sriName, h) = Data.Text. breakOnEnd " -" sriHash in
144
126
if sriName == " " || sriName == name <> " -"
@@ -154,13 +136,10 @@ mkNamedDigest name sriHash =
154
136
<> " "
155
137
<> name
156
138
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 )
164
143
decodeGo a h
165
144
| size == base16Len = decodeDigestWith Base16 h
166
145
| size == base32Len = decodeDigestWith NixBase32 h
@@ -181,7 +160,7 @@ mkNamedDigest name sriHash =
181
160
<> Data.Text. pack (show [base16Len, base32Len, base64Len])
182
161
where
183
162
size = Data.Text. length h
184
- hsize = Crypto.Hash. hashDigestSize a
163
+ hsize = Crypto.Hash. hashDigestSize (hashAlgoValue a)
185
164
base16Len = hsize * 2
186
165
base32Len = ((hsize * 8 - 1 ) `div` 5 ) + 1 ;
187
166
base64Len = ((4 * hsize `div` 3 ) + 3 ) `div` 4 * 4 ;
@@ -227,3 +206,10 @@ digestBuilder digest =
227
206
<> " :"
228
207
<> Data.Text.Lazy.Builder. fromText
229
208
(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