objectid (empty) → 0.1.0.2
raw patch · 5 files changed
+206/−0 lines, 5 filesdep +QuickCheckdep +basedep +blaze-buildersetup-changed
Dependencies added: QuickCheck, base, blaze-builder, bytestring, bytestring-arbitrary, cereal, cryptohash, objectid, tasty, tasty-quickcheck
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- objectid.cabal +46/−0
- src/Data/ObjectID.hs +57/−0
- tests/TestAll.hs +71/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, jay groven++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of jay groven nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ objectid.cabal view
@@ -0,0 +1,46 @@+-- Initial objectid.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/++name: objectid+version: 0.1.0.2+synopsis: Rather unique identifier for things that need to be stored+-- description: +homepage: https://github.com/tsuraan/objectid+license: BSD3+license-file: LICENSE+author: jay groven+maintainer: tsuraan@gmail.com+-- copyright: +category: Data+build-type: Simple+-- extra-source-files: +cabal-version: >=1.10++library+ exposed-modules: Data.ObjectID+ -- other-modules: + -- other-extensions: + build-depends: base >=4.6 && <4.8+ , blaze-builder+ , bytestring >= 0.10.0.0+ , cereal+ , cryptohash >= 0.5.1+ hs-source-dirs: src+ default-language: Haskell2010+ ghc-options: -Wall++test-suite test-all+ type: exitcode-stdio-1.0+ main-is: TestAll.hs+ build-depends: base >= 4.6 && < 4.8+ , bytestring+ , bytestring-arbitrary+ , cereal+ , objectid+ , QuickCheck >= 2.1+ , tasty+ , tasty-quickcheck+ hs-source-dirs: tests+ default-language: Haskell2010+ ghc-options: -Wall+
+ src/Data/ObjectID.hs view
@@ -0,0 +1,57 @@+{-# LANGUAGE FlexibleInstances #-}+-- |+-- Module : Data.ObjectID+-- Copyright : Jeremy Groven+-- License : BSD3+--+-- Opaque type to uniquely identify things. Objects to be identified must+-- implement the 'uniqueByteString' of 'IsObject', ideally in some way that+-- different objects have different bytestrings, while two instances of the+-- same object will have the same bytestring.++module Data.ObjectID+( ObjectID+, calculateSerialize+, calculateBuilder+, calculateByteString+) where++import Crypto.Hash.Skein256 ( hash )+import Blaze.ByteString.Builder ( Builder, toByteString )+import Data.ByteString ( ByteString )+import Data.Serialize ( Serialize(..), encode, decode )+import Data.Serialize.Get ( getWord64be )+import Data.Serialize.Put ( putWord64be )+import Data.Word ( Word64 )++-- |Opaque type used to uniquely identify objects+data ObjectID = ObjectID !Word64 !Word64 !Word64 !Word64+ deriving ( Show, Eq, Ord )++instance Serialize ObjectID where+ put (ObjectID a b c d) = do+ putWord64be a+ putWord64be b+ putWord64be c+ putWord64be d++ get = do+ a <- getWord64be+ b <- getWord64be+ c <- getWord64be+ d <- getWord64be+ return $ ObjectID a b c d++-- |Get the 'ObjectID' from a 'Serialize' instance+calculateSerialize :: Serialize a => a -> ObjectID+calculateSerialize = calculateByteString . encode++calculateBuilder :: Builder -> ObjectID+calculateBuilder = calculateByteString . toByteString++calculateByteString :: ByteString -> ObjectID+calculateByteString bs =+ let hsh = hash 256 bs+ Right oid = decode hsh+ in oid+
+ tests/TestAll.hs view
@@ -0,0 +1,71 @@+module Main+( main+) where++import Data.ObjectID++import qualified Data.ByteString as ByteString+import Data.ByteString.Arbitrary+import Data.Serialize ( encode, decode )+import Data.Word ( Word64 )+import Test.Tasty+import Test.Tasty.QuickCheck ( testProperty )++main :: IO ()+main = defaultMain $+ testGroup "ObjectID"+ [ testProperty "ByteString" bytestring+ , testProperty "Integer" integer+ , testProperty "Double" double+ , testProperty "Word" word+ , testProperty "Neg ByteString" neg_bytestring+ , testProperty "Neg Integer" neg_integer+ , testProperty "Neg Double" neg_double+ , testProperty "Neg Word" neg_word+ ]+ where++ bytestring :: ArbByteString -> Bool+ bytestring (ABS bs) =+ let oid = calculateByteString bs+ ser = encode oid+ Right des = decode ser+ in oid == des++ integer :: Integer -> Bool+ integer = seri++ double :: Double -> Bool+ double = seri++ word :: Word64 -> Bool+ word = seri++ seri s =+ let oid = calculateSerialize s+ ser = encode oid+ Right des = decode ser+ in oid == des++ neg_bytestring :: ArbByteString -> Bool+ neg_bytestring (ABS bs) =+ let oid = calculateSerialize bs+ ser = ByteString.reverse $ encode oid+ Right des = decode ser+ in oid /= des++ neg_integer :: Integer -> Bool+ neg_integer = neg_seri++ neg_double :: Double -> Bool+ neg_double = neg_seri++ neg_word :: Word64 -> Bool+ neg_word = neg_seri++ neg_seri s =+ let oid = calculateSerialize s+ ser = ByteString.reverse $ encode oid+ Right des = decode ser+ in oid /= des+