Remove old/. View tag v0.4.2 instead
This commit is contained in:
parent
d0ddc814a9
commit
4085572e60
3 changed files with 0 additions and 1749 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,627 +0,0 @@
|
|||
{-
|
||||
|
||||
Copyright (C) 2010 Scott R Parish <srp@srparish.net>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
-}
|
||||
|
||||
module Database.MongoDB.BSON
|
||||
(
|
||||
-- * Types
|
||||
BsonValue(..),
|
||||
BsonDoc,
|
||||
BinarySubType(..),
|
||||
-- * BsonDoc Operations
|
||||
empty,
|
||||
-- * Type Conversion
|
||||
fromBson, toBson,
|
||||
fromBsonDoc, toBsonDoc,
|
||||
-- * Binary encoding/decoding
|
||||
getBsonDoc, putBsonDoc,
|
||||
-- * ObjectId creation
|
||||
ObjectIdGen, mkObjectIdGen, genObjectId,
|
||||
)
|
||||
where
|
||||
import Prelude hiding (lookup)
|
||||
|
||||
import qualified Control.Arrow as Arrow
|
||||
import Control.Exception
|
||||
import Control.Monad
|
||||
import Data.Binary
|
||||
import Data.Binary.Get
|
||||
import Data.Binary.IEEE754
|
||||
import Data.Binary.Put
|
||||
import Data.Bits
|
||||
import Data.ByteString.Char8 as C8 hiding (empty)
|
||||
import qualified Data.ByteString.Lazy as L
|
||||
import qualified Data.ByteString.Lazy.UTF8 as L8
|
||||
import qualified Data.ByteString.UTF8 as S8
|
||||
import Data.Digest.OpenSSL.MD5
|
||||
import Data.Int
|
||||
import Data.IORef
|
||||
import qualified Data.List as List
|
||||
import qualified Data.Map as Map
|
||||
import Data.Time.Clock.POSIX
|
||||
import Data.Typeable
|
||||
import Database.MongoDB.Util
|
||||
import Network.BSD
|
||||
import Numeric
|
||||
import System.IO.Unsafe
|
||||
import System.Posix.Process
|
||||
|
||||
-- | BsonValue is the type that can be used as a value in a 'BsonDoc'.
|
||||
data BsonValue
|
||||
= BsonDouble Double
|
||||
| BsonString L8.ByteString
|
||||
| BsonDoc BsonDoc
|
||||
| BsonArray [BsonValue]
|
||||
| BsonUndefined
|
||||
| BsonBinary BinarySubType L.ByteString
|
||||
| BsonObjectId Integer
|
||||
| BsonBool !Bool
|
||||
| BsonDate POSIXTime
|
||||
| BsonNull
|
||||
| BsonRegex L8.ByteString String
|
||||
| BsonJSCode L8.ByteString
|
||||
| BsonSymbol L8.ByteString
|
||||
| BsonJSCodeWScope L8.ByteString BsonDoc
|
||||
| BsonInt32 Int32
|
||||
| BsonInt64 Int64
|
||||
| BsonMinKey
|
||||
| BsonMaxKey
|
||||
deriving (Show, Eq, Ord)
|
||||
|
||||
type BsonDoc = [(L8.ByteString, BsonValue)]
|
||||
|
||||
-- | An empty BsonDoc
|
||||
empty :: BsonDoc
|
||||
empty = []
|
||||
|
||||
data DataType =
|
||||
DataMinKey | -- -1
|
||||
DataNumber | -- 1
|
||||
DataString | -- 2
|
||||
DataDoc | -- 3
|
||||
DataArray | -- 4
|
||||
DataBinary | -- 5
|
||||
DataUndefined | -- 6
|
||||
DataOid | -- 7
|
||||
DataBoolean | -- 8
|
||||
DataDate | -- 9
|
||||
DataNull | -- 10
|
||||
DataRegex | -- 11
|
||||
DataRef | -- 12
|
||||
DataJSCode | -- 13
|
||||
DataSymbol | -- 14
|
||||
DataJSCodeWScope | -- 15
|
||||
DataInt | -- 16
|
||||
DataTimestamp | -- 17
|
||||
DataLong | -- 18
|
||||
DataMaxKey -- 127
|
||||
deriving (Show, Read, Enum, Eq, Ord)
|
||||
|
||||
toDataType :: Int -> DataType
|
||||
toDataType (-1) = DataMinKey
|
||||
toDataType 127 = DataMaxKey
|
||||
toDataType d = toEnum d
|
||||
|
||||
fromDataType :: DataType -> Int8
|
||||
fromDataType DataMinKey = - 1
|
||||
fromDataType DataMaxKey = 127
|
||||
fromDataType d = fromIntegral $ fromEnum d
|
||||
|
||||
data BinarySubType =
|
||||
BSTUNDEFINED1 |
|
||||
BSTFunction | -- 1
|
||||
BSTByteArray | -- 2
|
||||
BSTUUID | -- 3
|
||||
BSTUNDEFINED2 |
|
||||
BSTMD5 | -- 5
|
||||
BSTUserDefined
|
||||
deriving (Show, Read, Enum, Eq, Ord)
|
||||
|
||||
toBinarySubType :: Int -> BinarySubType
|
||||
toBinarySubType 0x80 = BSTUserDefined
|
||||
toBinarySubType d = toEnum d
|
||||
|
||||
fromBinarySubType :: BinarySubType -> Int8
|
||||
fromBinarySubType BSTUserDefined = 0x80
|
||||
fromBinarySubType d = fromIntegral $ fromEnum d
|
||||
|
||||
data ObjectIdGen = ObjectIdGen {
|
||||
oigMachine :: Integer,
|
||||
oigInc :: IORef Integer
|
||||
}
|
||||
|
||||
globalObjectIdInc :: IORef Integer
|
||||
{-# NOINLINE globalObjectIdInc #-}
|
||||
globalObjectIdInc = unsafePerformIO (newIORef 0)
|
||||
|
||||
-- | Create a new 'ObjectIdGen', the structure that must be passed to
|
||||
-- genObjectId to create a 'ObjectId'.
|
||||
mkObjectIdGen :: IO ObjectIdGen
|
||||
mkObjectIdGen = do
|
||||
host <- liftM (fst . (!! 0) . readHex . List.take 6 . md5sum . C8.pack)
|
||||
getHostName
|
||||
return ObjectIdGen {oigMachine = host, oigInc = globalObjectIdInc}
|
||||
|
||||
-- | Create a new 'ObjectId'.
|
||||
genObjectId :: ObjectIdGen -> IO BsonValue
|
||||
genObjectId oig = do
|
||||
now <- liftM (truncate . (realToFrac :: POSIXTime -> Double)) getPOSIXTime
|
||||
pid <- liftM fromIntegral getProcessID
|
||||
inc <- atomicModifyIORef (oigInc oig) $ \i -> ((i+1) `rem` 0x10000, i)
|
||||
return $ BsonObjectId
|
||||
((now `shiftL` 64) .|.
|
||||
oigMachine oig `shiftL` 40 .|.
|
||||
(0xffff .&. pid) `shiftL` 24 .|.
|
||||
(inc `div` 0x100) `shiftL` 8 .|. (inc `rem` 0x100))
|
||||
|
||||
-- | Decode binary bytes into 'BsonDoc'.
|
||||
getBsonDoc :: Get BsonDoc
|
||||
getBsonDoc = liftM snd getDoc
|
||||
|
||||
-- | Encode 'BsonDoc' into binary bytes.
|
||||
putBsonDoc :: BsonDoc -> Put
|
||||
putBsonDoc = putObj
|
||||
|
||||
getVal :: DataType -> Get (Integer, BsonValue)
|
||||
getVal DataNumber = liftM ((,) 8 . BsonDouble) getFloat64le
|
||||
getVal DataString = do
|
||||
sLen1 <- getI32
|
||||
(_sLen2, s) <- getS
|
||||
return (fromIntegral $ 4 + sLen1, BsonString s)
|
||||
getVal DataDoc = getDoc >>= \(len, obj) -> return (len, BsonDoc obj)
|
||||
getVal DataArray = do
|
||||
bytes <- getI32
|
||||
arr <- getInnerArray (bytes - 4)
|
||||
getNull
|
||||
return (fromIntegral bytes, BsonArray arr)
|
||||
getVal DataBinary = do
|
||||
len1 <- getI32
|
||||
st <- getI8
|
||||
(len, hdrLen) <- if toBinarySubType st == BSTByteArray
|
||||
then do
|
||||
len2 <- getI32
|
||||
assert (len1 - 4 == len2) $ return ()
|
||||
return (len2, 4 + 1 + 4)
|
||||
else return (len1, 4 + 1)
|
||||
bs <- getLazyByteString $ fromIntegral len
|
||||
return (hdrLen + fromIntegral len, BsonBinary (toBinarySubType st) bs)
|
||||
|
||||
getVal DataUndefined = return (1, BsonUndefined)
|
||||
getVal DataOid = do
|
||||
oid1 <- getWord64be
|
||||
oid2 <- getWord32be
|
||||
let oid = (fromIntegral oid1 `shiftL` 32) .|. fromIntegral oid2
|
||||
return (12, BsonObjectId oid)
|
||||
getVal DataBoolean = liftM ((,) (1::Integer) . BsonBool . (/= (0::Int))) getI8
|
||||
getVal DataDate = liftM ((,) 8 . BsonDate . flip (/) 1000 . realToFrac) getI64
|
||||
getVal DataNull = return (1, BsonNull)
|
||||
getVal DataRegex = fail "DataJSCode not yet supported" -- TODO
|
||||
getVal DataRef = fail "DataRef is deprecated"
|
||||
getVal DataJSCode = do
|
||||
sLen1 <- getI32
|
||||
(_sLen2, s) <- getS
|
||||
return (fromIntegral $ 4 + sLen1, BsonJSCode s)
|
||||
getVal DataSymbol = do
|
||||
sLen1 <- getI32
|
||||
(_sLen2, s) <- getS
|
||||
return (fromIntegral $ 4 + sLen1, BsonString s)
|
||||
getVal DataJSCodeWScope = do
|
||||
sLen1 <- getI32
|
||||
(_, qry) <- getS
|
||||
(_, scope) <- getDoc
|
||||
return (fromIntegral sLen1, BsonJSCodeWScope qry scope)
|
||||
getVal DataInt = liftM ((,) 4 . BsonInt32 . fromIntegral) getI32
|
||||
getVal DataTimestamp = fail "DataTimestamp not yet supported" -- TODO
|
||||
|
||||
getVal DataLong = liftM ((,) 8 . BsonInt64) getI64
|
||||
getVal DataMinKey = return (0, BsonMinKey)
|
||||
getVal DataMaxKey = return (0, BsonMaxKey)
|
||||
|
||||
getInnerObj :: Int32 -> Get BsonDoc
|
||||
getInnerObj 1 = return []
|
||||
getInnerObj bytesLeft = do
|
||||
typ <- getDataType
|
||||
(keySz, key) <- getS
|
||||
(valSz, val) <- getVal typ
|
||||
rest <- getInnerObj (bytesLeft - 1 - fromIntegral keySz - fromIntegral valSz)
|
||||
return $ (key, val) : rest
|
||||
|
||||
getRawObj :: Get (Integer, BsonDoc)
|
||||
getRawObj = do
|
||||
bytes <- getI32
|
||||
obj <- getInnerObj (bytes - 4)
|
||||
getNull
|
||||
return (fromIntegral bytes, obj)
|
||||
|
||||
getInnerArray :: Int32 -> Get [BsonValue]
|
||||
getInnerArray 1 = return []
|
||||
getInnerArray bytesLeft = do
|
||||
typ <- getDataType
|
||||
(keySz, _key) <- getS
|
||||
(valSz, val) <- getVal typ
|
||||
rest <- getInnerArray
|
||||
(bytesLeft - 1 - fromIntegral keySz - fromIntegral valSz)
|
||||
return $ val : rest
|
||||
|
||||
getDoc :: Get (Integer, BsonDoc)
|
||||
getDoc = getRawObj
|
||||
|
||||
getDataType :: Get DataType
|
||||
getDataType = liftM toDataType getI8
|
||||
|
||||
putType :: BsonValue -> Put
|
||||
putType BsonDouble{} = putDataType DataNumber
|
||||
putType BsonString{} = putDataType DataString
|
||||
putType BsonDoc{} = putDataType DataDoc
|
||||
putType BsonArray{} = putDataType DataArray
|
||||
putType BsonBinary{} = putDataType DataBinary
|
||||
putType BsonUndefined = putDataType DataUndefined
|
||||
putType BsonObjectId{} = putDataType DataOid
|
||||
putType BsonBool{} = putDataType DataBoolean
|
||||
putType BsonDate{} = putDataType DataDate
|
||||
putType BsonNull = putDataType DataNull
|
||||
putType BsonRegex{} = putDataType DataRegex
|
||||
-- putType = putDataType DataRef
|
||||
putType BsonJSCode {} = putDataType DataJSCode
|
||||
putType BsonSymbol{} = putDataType DataSymbol
|
||||
putType BsonJSCodeWScope{} = putDataType DataJSCodeWScope
|
||||
putType BsonInt32 {} = putDataType DataInt
|
||||
putType BsonInt64 {} = putDataType DataLong
|
||||
-- putType = putDataType DataTimestamp
|
||||
putType BsonMinKey = putDataType DataMinKey
|
||||
putType BsonMaxKey = putDataType DataMaxKey
|
||||
|
||||
putVal :: BsonValue -> Put
|
||||
putVal (BsonDouble d) = putFloat64le d
|
||||
putVal (BsonString s) = putStrSz s
|
||||
putVal (BsonDoc o) = putObj o
|
||||
putVal (BsonArray es) = putOutterObj bs
|
||||
where bs = runPut $ forM_ (List.zip [(0::Int) .. ] es) $ \(i, e) ->
|
||||
putType e >> putS (L8.fromString $ show i) >> putVal e
|
||||
putVal (BsonBinary t bs) = do
|
||||
putI32 $ fromIntegral $ (if t == BSTByteArray then 4 else 0) + L.length bs
|
||||
putI8 $ fromBinarySubType t
|
||||
when (t == BSTByteArray) $ putI32 $ fromIntegral $ L.length bs
|
||||
putLazyByteString bs
|
||||
putVal BsonUndefined = putNothing
|
||||
putVal (BsonObjectId o) = putWord64be (fromIntegral $ o `shiftR` 32) >>
|
||||
putWord32be (fromIntegral $ o .&. 0xffffffff)
|
||||
putVal (BsonBool False) = putI8 0
|
||||
putVal (BsonBool True) = putI8 1
|
||||
putVal (BsonDate pt) = putI64 $ round $ 1000 * (realToFrac pt :: Double)
|
||||
putVal BsonNull = putNothing
|
||||
putVal (BsonRegex r opt)= do putS r
|
||||
putByteString $ pack $ List.sort opt
|
||||
putNull
|
||||
putVal (BsonJSCode c) = putStrSz c
|
||||
putVal (BsonSymbol s) = putStrSz s
|
||||
putVal (BsonJSCodeWScope q s) =
|
||||
let bytes = runPut (putStrSz q >> putObj s)
|
||||
in putI32 ((+4) $ fromIntegral $ L.length bytes) >> putLazyByteString bytes
|
||||
putVal (BsonInt32 i) = putI32 i
|
||||
putVal (BsonInt64 i) = putI64 i
|
||||
putVal BsonMinKey = putNothing
|
||||
putVal BsonMaxKey = putNothing
|
||||
|
||||
putObj :: BsonDoc -> Put
|
||||
putObj obj = putOutterObj bs
|
||||
where bs = runPut $ forM_ obj $ \(k, v) -> putType v >> putS k >> putVal v
|
||||
|
||||
putOutterObj :: L.ByteString -> Put
|
||||
putOutterObj bytes = do
|
||||
-- the length prefix and null term are included in the length
|
||||
putI32 $ fromIntegral $ 4 + 1 + L.length bytes
|
||||
putLazyByteString bytes
|
||||
putNull
|
||||
|
||||
putDataType :: DataType -> Put
|
||||
putDataType = putI8 . fromDataType
|
||||
|
||||
class BsonDocConv a where
|
||||
-- | Convert a BsonDoc into another form such as a Map or a tuple
|
||||
-- list with String keys.
|
||||
fromBsonDoc :: BsonDoc -> a
|
||||
-- | Convert a Map or a tuple list with String keys into a BsonDoc.
|
||||
toBsonDoc :: a -> BsonDoc
|
||||
|
||||
instance BsonDocConv [(L8.ByteString, BsonValue)] where
|
||||
fromBsonDoc = id
|
||||
toBsonDoc = id
|
||||
|
||||
instance BsonDocConv [(String, BsonValue)] where
|
||||
fromBsonDoc = List.map $ Arrow.first L8.toString
|
||||
toBsonDoc = List.map $ Arrow.first L8.fromString
|
||||
|
||||
instance BsonDocConv (Map.Map L8.ByteString BsonValue) where
|
||||
fromBsonDoc = Map.fromList
|
||||
toBsonDoc = Map.toList
|
||||
|
||||
instance BsonDocConv (Map.Map String BsonValue) where
|
||||
fromBsonDoc = Map.fromList . fromBsonDoc
|
||||
toBsonDoc = toBsonDoc . Map.toList
|
||||
|
||||
data BsonUnsupportedConversion = BsonUnsupportedConversion
|
||||
deriving (Eq, Show, Read)
|
||||
|
||||
bsonUnsupportedConversion :: TyCon
|
||||
bsonUnsupportedConversion =
|
||||
mkTyCon "Database.MongoDB.BSON.BsonUnsupportedConversion "
|
||||
|
||||
instance Typeable BsonUnsupportedConversion where
|
||||
typeOf _ = mkTyConApp bsonUnsupportedConversion []
|
||||
|
||||
instance Exception BsonUnsupportedConversion
|
||||
|
||||
throwUnsupConv :: a
|
||||
throwUnsupConv = throw BsonUnsupportedConversion
|
||||
|
||||
class BsonConv a where
|
||||
-- | Convert a native Haskell type into a BsonValue.
|
||||
toBson :: a -> BsonValue
|
||||
-- | Convert a BsonValue into a native Haskell type.
|
||||
fromBson :: BsonValue -> a
|
||||
|
||||
instance BsonConv Double where
|
||||
toBson = BsonDouble
|
||||
fromBson (BsonDouble d) = d
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Float where
|
||||
toBson = BsonDouble . realToFrac
|
||||
fromBson (BsonDouble d) = realToFrac d
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv L8.ByteString where
|
||||
toBson = BsonString
|
||||
fromBson (BsonString s) = s
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv String where
|
||||
toBson = BsonString . L8.fromString
|
||||
fromBson (BsonString s) = L8.toString s
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv S8.ByteString where
|
||||
toBson bs = BsonString $ L.fromChunks [bs]
|
||||
fromBson (BsonString s) = C8.concat $ L.toChunks s
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv BsonDoc where
|
||||
toBson = BsonDoc
|
||||
fromBson (BsonDoc d) = d
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [(String, BsonValue)] where
|
||||
toBson = toBson . toBsonDoc
|
||||
fromBson (BsonDoc d) = fromBsonDoc d
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv (Map.Map L8.ByteString BsonValue) where
|
||||
toBson = toBson . toBsonDoc
|
||||
fromBson (BsonDoc d) = fromBsonDoc d
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv (Map.Map String BsonValue) where
|
||||
toBson = toBson . toBsonDoc
|
||||
fromBson (BsonDoc d) = fromBsonDoc d
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv POSIXTime where
|
||||
toBson = BsonDate
|
||||
fromBson (BsonDate d) = d
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Bool where
|
||||
toBson = BsonBool
|
||||
fromBson (BsonBool b) = b
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Int where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Int8 where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Int16 where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Int32 where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Int64 where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Integer where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Word where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Word8 where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Word16 where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Word32 where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv Word64 where
|
||||
toBson i | i >= fromIntegral (minBound::Int32) &&
|
||||
i <= fromIntegral (maxBound::Int32) = BsonInt32 $ fromIntegral i
|
||||
| otherwise = BsonInt64 $ fromIntegral i
|
||||
fromBson (BsonInt32 i) = fromIntegral i
|
||||
fromBson (BsonInt64 i) = fromIntegral i
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Double] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Float] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Int] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Int8] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Int16] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Int32] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Int64] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Integer] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Word] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Word8] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Word16] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Word32] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Word64] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [Bool] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [POSIXTime] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [String] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [L8.ByteString] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [S8.ByteString] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance BsonConv [BsonDoc] where
|
||||
toBson = BsonArray . List.map toBson
|
||||
fromBson (BsonArray ss) = List.map fromBson ss
|
||||
fromBson _ = throwUnsupConv
|
||||
|
||||
instance (BsonConv a) => BsonConv (Maybe a) where
|
||||
toBson Nothing = BsonNull
|
||||
toBson (Just a) = toBson a
|
||||
fromBson BsonNull = Nothing
|
||||
fromBson a = Just $ fromBson a
|
|
@ -1,83 +0,0 @@
|
|||
{-
|
||||
|
||||
Copyright (C) 2010 Scott R Parish <srp@srparish.net>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
-}
|
||||
|
||||
module Database.MongoDB.Util
|
||||
(
|
||||
putI8, putI16, putI32, putI64, putNothing, putNull, putS,
|
||||
getI8, getI32, getI64, getC, getS, getNull, putStrSz,
|
||||
)
|
||||
where
|
||||
import Control.Exception (assert)
|
||||
import Control.Monad
|
||||
import Data.Binary
|
||||
import Data.Binary.Get
|
||||
import Data.Binary.Put
|
||||
import Data.ByteString.Char8
|
||||
import qualified Data.ByteString.Lazy as L
|
||||
import qualified Data.ByteString.Lazy.UTF8 as L8
|
||||
import Data.Char (chr)
|
||||
import Data.Int
|
||||
|
||||
getC :: Get Char
|
||||
getC = liftM chr getI8
|
||||
|
||||
getI8 :: (Integral a) => Get a
|
||||
getI8 = liftM fromIntegral getWord8
|
||||
|
||||
getI32 :: Get Int32
|
||||
getI32 = liftM fromIntegral getWord32le
|
||||
|
||||
getI64 :: Get Int64
|
||||
getI64 = liftM fromIntegral getWord64le
|
||||
|
||||
getS :: Get (Integer, L8.ByteString)
|
||||
getS = getLazyByteStringNul >>= \s -> return (fromIntegral $ L.length s + 1, s)
|
||||
|
||||
getNull :: Get ()
|
||||
getNull = do {c <- getC; assert (c == '\0') $ return ()}
|
||||
|
||||
putI8 :: Int8 -> Put
|
||||
putI8 = putWord8 . fromIntegral
|
||||
|
||||
putI16 :: Int16 -> Put
|
||||
putI16 = putWord16le . fromIntegral
|
||||
|
||||
putI32 :: Int32 -> Put
|
||||
putI32 = putWord32le . fromIntegral
|
||||
|
||||
putI64 :: Int64 -> Put
|
||||
putI64 = putWord64le . fromIntegral
|
||||
|
||||
putNothing :: Put
|
||||
putNothing = putByteString $ pack ""
|
||||
|
||||
putNull :: Put
|
||||
putNull = putI8 0
|
||||
|
||||
putS :: L8.ByteString -> Put
|
||||
putS s = putLazyByteString s >> putNull
|
||||
|
||||
putStrSz :: L8.ByteString -> Put
|
||||
putStrSz s = putI32 (fromIntegral $ 1 + L.length s) >> putS s
|
Loading…
Reference in a new issue