store 0.4.0 → 0.4.1
raw patch · 4 files changed
+39/−50 lines, 4 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Data.Store.Version: VersionCheckException :: StoreVersion -> StoreVersion -> VersionCheckException
- Data.Store.Version: WithVersion :: a -> StoreVersion -> WithVersion a
- Data.Store.Version: [expectedVersion] :: VersionCheckException -> StoreVersion
- Data.Store.Version: [receivedVersion] :: VersionCheckException -> StoreVersion
- Data.Store.Version: checkVersion :: Data a => VersionConfig a -> Q Exp
- Data.Store.Version: data VersionCheckException
- Data.Store.Version: data WithVersion a
- Data.Store.Version: instance Data.Data.Data a => Data.Data.Data (Data.Store.Version.WithVersion a)
- Data.Store.Version: instance Data.Store.Impl.Store a => Data.Store.Impl.Store (Data.Store.Version.WithVersion a)
- Data.Store.Version: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Store.Version.WithVersion a)
- Data.Store.Version: instance GHC.Classes.Ord a => GHC.Classes.Ord (Data.Store.Version.WithVersion a)
- Data.Store.Version: instance GHC.Exception.Exception Data.Store.Version.VersionCheckException
- Data.Store.Version: instance GHC.Generics.Generic (Data.Store.Version.WithVersion a)
- Data.Store.Version: instance GHC.Show.Show Data.Store.Version.VersionCheckException
- Data.Store.Version: instance GHC.Show.Show a => GHC.Show.Show (Data.Store.Version.WithVersion a)
- Data.Store.Version: wrapVersion :: Data a => VersionConfig a -> Q Exp
+ Data.Store.Internal: peekMagic :: (Eq a, Show a, Store a) => String -> a -> Peek ()
+ Data.Store.Version: decodeWithVersionQ :: Data a => VersionConfig a -> Q Exp
+ Data.Store.Version: encodeWithVersionQ :: Data a => VersionConfig a -> Q Exp
Files
- ChangeLog.md +11/−1
- src/Data/Store/Internal.hs +5/−5
- src/Data/Store/Version.hs +22/−43
- store.cabal +1/−1
ChangeLog.md view
@@ -1,6 +1,6 @@ # ChangeLog -## 0.4.0+## 0.4.1 * Breaking change in the encoding of Map / Set / IntMap / IntSet, to use ascending key order. Attempting to decode data written by@@ -15,6 +15,16 @@ * Performance improvement of the 'Peek' monad, by introducing more strictness. This required a change to the internal API.++* API and behavior of 'Data.Store.Version' changed. Previously, it+ would check the version tag after decoding the contents. It now+ also stores a magic Word32 tag at the beginning, so that it fails+ more gracefully when decoding input that lacks encoded version+ info.++## 0.4.0++Deprecated in favor of 0.4.1 ## 0.3.1
src/Data/Store/Internal.hs view
@@ -56,6 +56,7 @@ , GStorePeek, genericPeek -- ** Peek utilities , skip, isolate+ , peekMagic -- ** Static Size type -- -- This portion of the library is still work-in-progress.@@ -250,11 +251,11 @@ -- Throws a 'PeekException' if the value isn't present. peekMagic :: (Eq a, Show a, Store a)- => a -> Peek ()-peekMagic x = do+ => String -> a -> Peek ()+peekMagic markedThing x = do x' <- peek when (x' /= x) $- fail ("Expected marker: " ++ show x ++ " but got: " ++ show x')+ fail ("Expected marker for " ++ markedThing ++ ": " ++ show x ++ " but got: " ++ show x') {-# INLINE peekMagic #-} -- | Like 'sizeMap' but should only be used for ordered containers where@@ -284,7 +285,7 @@ -- 'Map.fromDistinctAscList'. -> Peek t peekOrdMapWith f = do- peekMagic markMapPokedInAscendingOrder+ peekMagic "ascending Map / IntMap" markMapPokedInAscendingOrder f <$> peek {-# INLINE peekOrdMapWith #-} @@ -824,4 +825,3 @@ $(reifyManyWithoutInstances ''Store [''Info] (const True) >>= -- mapM (\name -> deriveStore [] (ConT name) .dtCons =<< reifyDataType name)) mapM (\name -> return (deriveGenericInstance [] (ConT name))))-
src/Data/Store/Version.hs view
@@ -23,16 +23,13 @@ -- will be minimized when directly feasible. module Data.Store.Version ( StoreVersion(..)- , WithVersion(..) , VersionConfig(..) , hashedVersionConfig , namedVersionConfig- , wrapVersion- , checkVersion- , VersionCheckException(..)+ , encodeWithVersionQ+ , decodeWithVersionQ ) where -import Control.Exception import Control.Monad import Control.Monad.Trans.State import qualified Crypto.Hash.SHA1 as SHA1@@ -48,6 +45,7 @@ import Data.Text.Encoding.Error (lenientDecode) import qualified Data.Text.IO as T import Data.Typeable.Internal (TypeRep(..))+import Data.Word (Word32) import GHC.Generics (Generic) import Language.Haskell.TH import System.Directory@@ -59,11 +57,6 @@ newtype StoreVersion = StoreVersion { unStoreVersion :: BS.ByteString } deriving (Eq, Show, Ord, Data, Typeable, Generic, Store) -data WithVersion a = WithVersion a StoreVersion- deriving (Eq, Show, Ord, Data, Typeable, Generic)--instance Store a => Store (WithVersion a)- -- | Configuration for the version checking of a particular type. data VersionConfig a = VersionConfig { vcExpectedHash :: Maybe String@@ -92,13 +85,13 @@ , vcRenames = M.empty } -wrapVersion :: Data a => VersionConfig a -> Q Exp-wrapVersion = impl Wrap+encodeWithVersionQ :: Data a => VersionConfig a -> Q Exp+encodeWithVersionQ = impl Encode -checkVersion :: Data a => VersionConfig a -> Q Exp-checkVersion = impl Check+decodeWithVersionQ :: Data a => VersionConfig a -> Q Exp+decodeWithVersionQ = impl Decode -data WhichFunc = Wrap | Check+data WhichFunc = Encode | Decode impl :: forall a. Data a => WhichFunc -> VersionConfig a -> Q Exp impl wf vc = do@@ -131,15 +124,16 @@ ", but " ++ show expectedHash ++ " is specified.\n" ++ "The data used to construct the hash has been written to " ++ show newPath ++ extraMsg ++ "\n"+ let atype = typeRepToType (typeRep proxy) case wf of- Wrap -> [e| (\x -> (x :: $(typeRepToType (typeRep proxy))) `WithVersion` $(version)) |]- Check -> [e| (\(WithVersion x gotVersion) ->- if gotVersion /= $(version)- then Left (VersionCheckException- { expectedVersion = $(version)- , receivedVersion = gotVersion- })- else Right x) |]+ Encode -> [e| \x -> ( getSize markEncodedVersion + getSize $(version) + getSize x+ , poke markEncodedVersion >> poke $(version) >> poke (x :: $(atype))) |]+ Decode -> [e| do+ peekMagic "version tag" markEncodedVersion+ gotVersion <- peek+ if gotVersion /= $(version)+ then fail (displayVersionError $(version) gotVersion)+ else peek :: Peek $(atype) |] {- txtWithComments <- runIO $ T.readFile path@@ -286,26 +280,11 @@ tyConOf :: Typeable a => Proxy a -> TyCon tyConOf = typeRepTyCon . typeRep -data VersionCheckException = VersionCheckException- { expectedVersion :: StoreVersion- , receivedVersion :: StoreVersion- } deriving-#if MIN_VERSION_base(4,8,0)- (Typeable, Show)--instance Exception VersionCheckException where- displayException = displayVCE-#else- (Typeable)--instance Show VersionCheckException where- show = displayVCE--instance Exception VersionCheckException-#endif--displayVCE :: VersionCheckException -> String-displayVCE VersionCheckException{..} =+displayVersionError :: StoreVersion -> StoreVersion -> String+displayVersionError expectedVersion receivedVersion = "Mismatch detected by Data.Store.Version - expected " ++ T.unpack (decodeUtf8With lenientDecode (unStoreVersion expectedVersion)) ++ " but got " ++ T.unpack (decodeUtf8With lenientDecode (unStoreVersion receivedVersion))++markEncodedVersion :: Word32+markEncodedVersion = 3908297288
store.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: store-version: 0.4.0+version: 0.4.1 synopsis: Fast binary serialization category: Serialization, Data homepage: https://github.com/fpco/store#readme