{-# language CPP #-}

-- | Reading and writing Nix cache files
module Nix.Cache where

import           Nix.Prelude
import qualified Data.ByteString.Lazy          as BSL
import           Nix.Expr.Types.Annotated

#if defined (__linux__)
-- This is about: https://hackage.haskell.org/package/compact
#define USE_COMPACT 1
#endif

#ifdef USE_COMPACT
import qualified Data.Compact                  as C
import qualified Data.Compact.Serialize        as C
#endif
import qualified Codec.Serialise               as S

readCache :: Path -> IO NExprLoc
readCache :: Path -> IO NExprLoc
readCache Path
path = do
#if USE_COMPACT
  eres <- C.unsafeReadCompact path
  either
    (\ err  -> fail $ "Error reading cache file: " <> err)
    (\ expr -> pure $ C.getCompact expr)
    eres
#else
  Either DeserialiseFailure NExprLoc
eres <- forall a. Serialise a => ByteString -> Either DeserialiseFailure a
S.deserialiseOrFail forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO ByteString
BSL.readFile (coerce :: forall a b. Coercible a b => a -> b
coerce Path
path)
  forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either
    (\ DeserialiseFailure
err  -> forall (m :: * -> *) a. MonadFail m => FilePath -> m a
fail forall a b. (a -> b) -> a -> b
$ FilePath
"Error reading cache file: " forall a. Semigroup a => a -> a -> a
<> forall b a. (Show a, IsString b) => a -> b
show DeserialiseFailure
err)
    forall (f :: * -> *) a. Applicative f => a -> f a
pure
    Either DeserialiseFailure NExprLoc
eres
#endif

writeCache :: Path -> NExprLoc -> IO ()
writeCache :: Path -> NExprLoc -> IO ()
writeCache Path
path NExprLoc
expr =
#ifdef USE_COMPACT
  C.writeCompact path =<< C.compact expr
#else
  FilePath -> ByteString -> IO ()
BSL.writeFile (coerce :: forall a b. Coercible a b => a -> b
coerce Path
path) (forall a. Serialise a => a -> ByteString
S.serialise NExprLoc
expr)
#endif