Skip to content

Commit 2e1cab2

Browse files
committed
move ContentAddressableAddress builder and parser to core, add roundtrip prop
1 parent b80ee47 commit 2e1cab2

File tree

8 files changed

+106
-99
lines changed

8 files changed

+106
-99
lines changed

hnix-store-core/hnix-store-core.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ test-suite format-tests
123123
main-is: Driver.hs
124124
other-modules:
125125
Derivation
126+
ContentAddressableAddress
126127
NarFormat
127128
Hash
128129
StorePath

hnix-store-core/src/System/Nix/Internal/StorePath.hs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# OPTIONS_GHC -Wno-orphans #-}
12
{-|
23
Description : Representation of Nix store paths.
34
-}
@@ -14,6 +15,9 @@ module System.Nix.Internal.StorePath
1415
, StorePathHashPart(..)
1516
, mkStorePathHashPart
1617
, ContentAddressableAddress(..)
18+
, contentAddressableAddressBuilder
19+
, contentAddressableAddressParser
20+
, digestBuilder
1721
, NarHashMode(..)
1822
, -- * Manipulating 'StorePathName'
1923
makeStorePathName
@@ -33,25 +37,33 @@ module System.Nix.Internal.StorePath
3337
where
3438

3539
import Data.Default.Class (Default(def))
40+
import Data.Text.Lazy.Builder (Builder)
3641
import qualified Relude.Unsafe as Unsafe
42+
import qualified System.Nix.Hash
3743
import System.Nix.Internal.Hash
3844
import System.Nix.Internal.Base
3945
import qualified System.Nix.Internal.Base32 as Nix.Base32
4046

4147
import qualified Data.ByteString.Char8 as Bytes.Char8
4248
import qualified Data.Char as Char
4349
import qualified Data.Text as Text
50+
import qualified Data.Text.Encoding
51+
import qualified Data.Text.Lazy.Builder
4452
import Data.Attoparsec.Text.Lazy ( Parser
4553
, (<?>)
4654
)
55+
import qualified Data.Attoparsec.ByteString.Char8
4756
import qualified Data.Attoparsec.Text.Lazy as Parser.Text.Lazy
4857
import qualified System.FilePath as FilePath
4958
import Crypto.Hash ( SHA256
5059
, Digest
5160
, HashAlgorithm
61+
, hash
5262
)
5363

54-
import Test.QuickCheck
64+
import Test.QuickCheck (Arbitrary(arbitrary), listOf, elements)
65+
import Test.QuickCheck.Arbitrary.Generic (GenericArbitrary(..))
66+
import Test.QuickCheck.Instances ()
5567

5668
-- | A path in a Nix store.
5769
--
@@ -116,6 +128,7 @@ mkStorePathHashPart
116128
-> StorePathHashPart
117129
mkStorePathHashPart = StorePathHashPart . mkStorePathHash @hashAlgo
118130

131+
-- TODO(srk): split into its own module + .Builder/.Parser
119132
-- | An address for a content-addressable store path, i.e. one whose
120133
-- store path hash is purely a function of its contents (as opposed to
121134
-- paths that are derivation outputs, whose hashes are a function of
@@ -136,6 +149,66 @@ data ContentAddressableAddress
136149
Fixed !NarHashMode !SomeNamedDigest
137150
deriving (Eq, Generic, Ord, Show)
138151

152+
-- TODO(srk): extend to all hash types
153+
instance Arbitrary (Digest SHA256) where
154+
arbitrary = hash @ByteString <$> arbitrary
155+
156+
instance Arbitrary SomeNamedDigest where
157+
arbitrary = SomeDigest @SHA256 <$> arbitrary
158+
159+
deriving via GenericArbitrary ContentAddressableAddress
160+
instance Arbitrary ContentAddressableAddress
161+
162+
-- | Builder for `ContentAddressableAddress`
163+
contentAddressableAddressBuilder :: ContentAddressableAddress -> Builder
164+
contentAddressableAddressBuilder (Text digest) =
165+
"text:"
166+
<> digestBuilder digest
167+
contentAddressableAddressBuilder (Fixed narHashMode (SomeDigest (digest :: Digest hashAlgo))) =
168+
"fixed:"
169+
<> (if narHashMode == Recursive then "r:" else mempty)
170+
-- <> Data.Text.Lazy.Builder.fromText (System.Nix.Hash.algoName @hashAlgo)
171+
<> digestBuilder digest
172+
173+
-- | Builder for @Digest@s
174+
digestBuilder :: forall hashAlgo . (NamedAlgo hashAlgo) => Digest hashAlgo -> Builder
175+
digestBuilder digest =
176+
Data.Text.Lazy.Builder.fromText (System.Nix.Hash.algoName @hashAlgo)
177+
<> ":"
178+
<> Data.Text.Lazy.Builder.fromText (encodeDigestWith NixBase32 digest)
179+
180+
-- | Parser for content addressable field
181+
contentAddressableAddressParser :: Data.Attoparsec.ByteString.Char8.Parser ContentAddressableAddress
182+
contentAddressableAddressParser = caText <|> caFixed
183+
where
184+
-- | Parser for @text:sha256:<h>@
185+
--caText :: Parser ContentAddressableAddress
186+
caText = do
187+
_ <- "text:sha256:"
188+
digest <- decodeDigestWith @SHA256 NixBase32 <$> parseHash
189+
either fail pure $ Text <$> digest
190+
191+
-- | Parser for @fixed:<r?>:<ht>:<h>@
192+
--caFixed :: Parser ContentAddressableAddress
193+
caFixed = do
194+
_ <- "fixed:"
195+
narHashMode <- (Recursive <$ "r:") <|> (RegularFile <$ "")
196+
digest <- parseTypedDigest
197+
either fail pure $ Fixed narHashMode <$> digest
198+
199+
--parseTypedDigest :: Parser (Either String SomeNamedDigest)
200+
parseTypedDigest = mkNamedDigest <$> parseHashType <*> parseHash
201+
202+
--parseHashType :: Parser Text
203+
parseHashType =
204+
Data.Text.Encoding.decodeUtf8
205+
<$> ("sha256" <|> "sha512" <|> "sha1" <|> "md5") <* (":" <|> "-")
206+
207+
--parseHash :: Parser Text
208+
parseHash =
209+
Data.Text.Encoding.decodeUtf8
210+
<$> Data.Attoparsec.ByteString.Char8.takeWhile1 (/= ':')
211+
139212
-- | Schemes for hashing a Nix archive.
140213
--
141214
-- For backwards-compatibility reasons, there are two different modes
@@ -148,6 +221,9 @@ data NarHashMode
148221
Recursive
149222
deriving (Eq, Enum, Generic, Hashable, Ord, Show)
150223

224+
deriving via GenericArbitrary NarHashMode
225+
instance Arbitrary NarHashMode
226+
151227
-- | Reason why a path is not valid
152228
data InvalidPathError =
153229
EmptyName

hnix-store-core/src/System/Nix/StorePath.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ module System.Nix.StorePath
1010
, mkStorePathHashPart
1111
, unStorePathHashPart
1212
, ContentAddressableAddress(..)
13+
, contentAddressableAddressBuilder
14+
, contentAddressableAddressParser
15+
, digestBuilder
1316
, NarHashMode(..)
1417
, -- * Manipulating 'StorePathName'
1518
makeStorePathName
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
module ContentAddressableAddress where
3+
4+
import Test.Tasty.QuickCheck
5+
import System.Nix.StorePath (ContentAddressableAddress, contentAddressableAddressBuilder, contentAddressableAddressParser)
6+
7+
import qualified Data.Attoparsec.ByteString.Char8
8+
import qualified Data.Text.Lazy
9+
import qualified Data.Text.Lazy.Builder
10+
import qualified Data.Text.Encoding
11+
12+
prop_caAddrRoundTrip :: ContentAddressableAddress -> Property
13+
prop_caAddrRoundTrip = \caAddr ->
14+
Data.Attoparsec.ByteString.Char8.parseOnly contentAddressableAddressParser
15+
( Data.Text.Encoding.encodeUtf8
16+
. Data.Text.Lazy.toStrict
17+
. Data.Text.Lazy.Builder.toLazyText
18+
$ contentAddressableAddressBuilder caAddr
19+
)
20+
=== pure caAddr
21+

hnix-store-remote/hnix-store-remote.cabal

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ library
7171
, System.Nix.Store.Remote.Binary
7272
, System.Nix.Store.Remote.Serialize
7373
, System.Nix.Store.Remote.Serialize.Prim
74-
, System.Nix.Store.Remote.Builders
7574
, System.Nix.Store.Remote.Logger
76-
, System.Nix.Store.Remote.Parsers
7775
, System.Nix.Store.Remote.Protocol
7876
, System.Nix.Store.Remote.Types
7977
, System.Nix.Store.Remote.Util

hnix-store-remote/src/System/Nix/Store/Remote.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import Data.HashSet (HashSet)
3939
import Data.Map (Map)
4040
import Data.Text (Text)
4141
import qualified Control.Monad
42+
import qualified Data.Attoparsec.ByteString.Char8
4243
import qualified Data.Text.Encoding
4344
--
4445
import qualified Data.ByteString.Lazy as BSL
@@ -66,7 +67,6 @@ import qualified Data.Map.Strict
6667
import qualified Data.Set
6768

6869
import qualified System.Nix.StorePath
69-
import qualified System.Nix.Store.Remote.Parsers
7070

7171
import System.Nix.Store.Remote.Binary
7272
import System.Nix.Store.Remote.Types
@@ -257,7 +257,9 @@ queryPathInfoUncached path = do
257257

258258
contentAddressableAddress =
259259
case
260-
System.Nix.Store.Remote.Parsers.parseContentAddressableAddress caString
260+
Data.Attoparsec.ByteString.Char8.parseOnly
261+
System.Nix.StorePath.contentAddressableAddressParser
262+
caString
261263
of
262264
Left e -> error e
263265
Right x -> Just x

hnix-store-remote/src/System/Nix/Store/Remote/Builders.hs

Lines changed: 0 additions & 36 deletions
This file was deleted.

hnix-store-remote/src/System/Nix/Store/Remote/Parsers.hs

Lines changed: 0 additions & 58 deletions
This file was deleted.

0 commit comments

Comments
 (0)