on master help sign in
renamed files, directories, and content
commitb491348f9478c4aa3e2f5db576e3b0c1a9f155a5 authorhsloan <ishaqsloan@gmail.com> dateTue 22 Aug 2017, 15:34 (9 years ago) parentf7a61d4
2 files changed+74
obelisk-asset-th/obelisk-asset-th.cabal+28 obelisk-asset-th/src/Obelisk/Asset/TH.hs+46
obelisk-asset-th/obelisk-asset-th.cabalnew file+28
@@ -0,0 +1,28 @@
1+Name: obelisk-asset-th
2+Version: 0.1
3+Synopsis: Project Synopsis Here
4+Description: Project Description Here
5+License: AllRightsReserved
6+Author: Author
7+Maintainer: maintainer@example.com
8+Stability: Experimental
9+Category: Web
10+Build-type: Simple
11+Cabal-version: >=1.2
12+
13+library
14+ hs-source-dirs: src
15+
16+ build-depends:
17+ base
18+ , bytestring
19+ , SHA
20+ , filepath
21+ , template-haskell
22+ , text
23+ , vector
24+ exposed-modules:
25+ Obelisk.Asset.TH
26+
27+ other-extensions: TemplateHaskell
28+ ghc-options: -threaded -Wall -Werror -fno-warn-unused-do-bind -fwarn-tabs -funbox-strict-fields -O2 -fprof-auto-calls -rtsopts
obelisk-asset-th/src/Obelisk/Asset/TH.hsnew file+46
@@ -0,0 +1,46 @@
1+module Obelisk.Asset.TH where
2+
3+import Language.Haskell.TH.Syntax
4+import System.FilePath
5+import qualified Data.Text as T
6+import qualified Data.ByteString as BS
7+import qualified Data.ByteString.Lazy as LBS
8+import qualified Data.ByteString.Lazy.Builder as LBS
9+import Data.Digest.Pure.SHA
10+import Data.Text.Encoding
11+import Data.Monoid
12+import Data.Bits
13+import qualified Data.Vector.Unboxed as UV
14+import Data.Char
15+import Data.Word
16+
17+-- | Warning: does not support negative numbers (will result in infinite loop)
18+toNixBase32 :: LBS.ByteString -> LBS.ByteString
19+toNixBase32 x = LBS.toLazyByteString $ mconcat $ map (LBS.word8 . (symbols UV.!) . fromIntegral) vals
20+ where vals = byteStringToQuintets x
21+ symbols = UV.fromList $ map (fromIntegral . ord) $ filter (`notElem` "eotu") $ ['0'..'9'] <> ['a'..'z']
22+
23+
24+-- See https://github.com/NixOS/nix/blob/6f1743b1a5116ca57a60b481ee4083c891b7a334/src/libutil/hash.cc#L109
25+byteStringToQuintets :: LBS.ByteString -> [Word8]
26+byteStringToQuintets hash = map f [len-1, len-2 .. 0]
27+ where hashSize = fromIntegral $ LBS.length hash
28+ len = (hashSize * 8 - 1) `div` 5 + 1
29+ f n = let b = n * 5
30+ (i, j) = b `divMod` 8
31+ j' = fromIntegral j
32+ c = ((hash `LBS.index` i) `shift` (-j')) .|. (if i >= hashSize - 1 then 0 else (hash `LBS.index` (i + 1)) `shift` (8 - j')) --TODO: This is probably pretty slow; replace with something that doesn't use LBS.index
33+ in c .&. 0x1f
34+
35+assetPath' :: FilePath -> FilePath -> Q FilePath
36+assetPath' root relativePath = do
37+ let path = root </> relativePath
38+ qAddDependentFile path
39+ contents <- fmap LBS.fromStrict $ runIO $ BS.readFile path
40+ let hashPrefix = T.unpack $ decodeUtf8 $ LBS.toStrict $ toNixBase32 $ bytestringDigest $ sha256 contents
41+ (dir, filename) = splitFileName relativePath
42+ return $ dir </> (hashPrefix <> "-" <> filename)
43+
44+assetPath :: FilePath -> FilePath -> Q Exp
45+assetPath root relativePath =
46+ LitE . StringL <$> assetPath' root relativePath