make BsonDoc a 'type' rather then 'newtype'

All the wraping/unwraping for the newtype was really cumbersome and
protection isn't really needed here.
This commit is contained in:
Scott R. Parish 2010-01-20 22:29:27 -06:00
parent 66ad002718
commit f8652ed11a
2 changed files with 43 additions and 52 deletions

View file

@ -377,7 +377,7 @@ delete c col sel = do
putI32 0 putI32 0
putCol col putCol col
putI32 0 putI32 0
put sel putBsonDoc sel
(reqID, msg) <- packMsg c OP_DELETE body (reqID, msg) <- packMsg c OP_DELETE body
L.hPut (cHandle c) msg L.hPut (cHandle c) msg
return reqID return reqID
@ -392,7 +392,7 @@ insert c col doc = do
let body = runPut $ do let body = runPut $ do
putI32 0 putI32 0
putCol col putCol col
put doc putBsonDoc doc
(reqID, msg) <- packMsg c OP_INSERT body (reqID, msg) <- packMsg c OP_INSERT body
L.hPut (cHandle c) msg L.hPut (cHandle c) msg
return reqID return reqID
@ -403,7 +403,7 @@ insertMany c col docs = do
let body = runPut $ do let body = runPut $ do
putI32 0 putI32 0
putCol col putCol col
forM_ docs put forM_ docs putBsonDoc
(reqID, msg) <- packMsg c OP_INSERT body (reqID, msg) <- packMsg c OP_INSERT body
L.hPut (cHandle c) msg L.hPut (cHandle c) msg
return reqID return reqID
@ -444,10 +444,11 @@ query c col opts nskip ret sel fsel = do
putCol col putCol col
putI32 nskip putI32 nskip
putI32 ret putI32 ret
put sel putBsonDoc sel
case fsel of case fsel of
[] -> putNothing [] -> putNothing
_ -> put $ toBsonDoc $ List.zip fsel $ repeat $ BsonInt32 1 _ -> putBsonDoc $ toBsonDoc $ List.zip fsel $
repeat $ BsonInt32 1
(reqID, msg) <- packMsg c OP_QUERY body (reqID, msg) <- packMsg c OP_QUERY body
L.hPut h msg L.hPut h msg
@ -476,8 +477,8 @@ update c col flags sel obj = do
putI32 0 putI32 0
putCol col putCol col
putI32 $ fromUpdateFlags flags putI32 $ fromUpdateFlags flags
put sel putBsonDoc sel
put obj putBsonDoc obj
(reqID, msg) <- packMsg c OP_UPDATE body (reqID, msg) <- packMsg c OP_UPDATE body
L.hPut (cHandle c) msg L.hPut (cHandle c) msg
return reqID return reqID
@ -566,7 +567,7 @@ allDocs' cur = do
getFirstDoc :: L.ByteString -> (BsonDoc, L.ByteString) getFirstDoc :: L.ByteString -> (BsonDoc, L.ByteString)
getFirstDoc docBytes = flip runGet docBytes $ do getFirstDoc docBytes = flip runGet docBytes $ do
doc <- get doc <- getBsonDoc
docBytes' <- getRemainingLazyByteString docBytes' <- getRemainingLazyByteString
return (doc, docBytes') return (doc, docBytes')

View file

@ -27,13 +27,15 @@ module Database.MongoDB.BSON
( (
-- * Types -- * Types
BsonValue(..), BsonValue(..),
BsonDoc(..), BsonDoc,
toBsonDoc,
BinarySubType(..), BinarySubType(..),
-- * BsonDoc Operations -- * BsonDoc Operations
empty, lookup, empty, lookup,
-- * Conversion -- * Type Conversion
fromBson, toBson fromBson, toBson,
fromBsonDoc, toBsonDoc,
-- * Binary encoding/decoding
getBsonDoc, putBsonDoc,
) )
where where
import Prelude hiding (lookup) import Prelude hiding (lookup)
@ -83,35 +85,29 @@ instance Typeable BsonValue where
-- strings ('Data.ByteString.Lazu.UTF8.ByteString') and 'BsonValue's. -- strings ('Data.ByteString.Lazu.UTF8.ByteString') and 'BsonValue's.
-- It can be constructed either from a 'Map' (eg @'BsonDoc' myMap@) or -- It can be constructed either from a 'Map' (eg @'BsonDoc' myMap@) or
-- from a associative list (eg @'toBsonDoc' myAL@). -- from a associative list (eg @'toBsonDoc' myAL@).
newtype BsonDoc = BsonDoc { type BsonDoc = Map.Map L8.ByteString BsonValue
bdFromBsonDoc :: Map.Map L8.ByteString BsonValue
}
deriving (Eq, Ord, Show)
instance Typeable BsonDoc where
typeOf _ = mkTypeName "BsonDoc"
class BsonDocOps a where class BsonDocOps a where
-- | Construct a BsonDoc from an associative list -- | Construct a BsonDoc from an associative list
toBsonDoc :: [(a, BsonValue)] -> BsonDoc toBsonDoc :: [(a, BsonValue)] -> BsonDoc
-- | Unwrap BsonDoc to be a Map -- | Unwrap BsonDoc to be a Map
fromBsonDoc :: BsonDoc -> Map.Map a BsonValue fromBsonDoc :: BsonDoc -> [(a, BsonValue)]
-- | Return the BsonValue for given key, if any. -- | Return the BsonValue for given key, if any.
lookup :: a -> BsonDoc -> Maybe BsonValue lookup :: a -> BsonDoc -> Maybe BsonValue
-- | An empty BsonDoc -- | An empty BsonDoc
empty :: BsonDoc empty :: BsonDoc
empty = BsonDoc Map.empty empty = Map.empty
instance BsonDocOps L8.ByteString where instance BsonDocOps L8.ByteString where
toBsonDoc = BsonDoc . Map.fromList toBsonDoc = Map.fromList
fromBsonDoc = bdFromBsonDoc fromBsonDoc = Map.toList
lookup k = Map.lookup k . fromBsonDoc lookup k = Map.lookup k
instance BsonDocOps String where instance BsonDocOps String where
toBsonDoc = BsonDoc . Map.mapKeys L8.fromString .Map.fromList toBsonDoc = Map.mapKeys L8.fromString .Map.fromList
fromBsonDoc = Map.mapKeys L8.toString . bdFromBsonDoc fromBsonDoc = Map.toList . Map.mapKeys L8.toString
lookup k = Map.lookup (L8.fromString k) . fromBsonDoc lookup k = Map.lookup (L8.fromString k)
data DataType = data DataType =
Data_min_key | -- -1 Data_min_key | -- -1
@ -164,9 +160,11 @@ fromBinarySubType :: BinarySubType -> Int
fromBinarySubType BSTUserDefined = 0x80 fromBinarySubType BSTUserDefined = 0x80
fromBinarySubType d = fromEnum d fromBinarySubType d = fromEnum d
instance Binary BsonDoc where getBsonDoc :: Get BsonDoc
get = liftM snd getDoc getBsonDoc = liftM snd getDoc
put = putObj
putBsonDoc :: BsonDoc -> Put
putBsonDoc = putObj
getVal :: DataType -> Get (Integer, BsonValue) getVal :: DataType -> Get (Integer, BsonValue)
getVal Data_number = getFloat64le >>= return . (,) 8 . BsonDouble getVal Data_number = getFloat64le >>= return . (,) 8 . BsonDouble
@ -207,25 +205,24 @@ getVal Data_long = getI64 >>= return . (,) 8 . BsonInt64
getVal Data_min_key = return (0, BsonMinKey) getVal Data_min_key = return (0, BsonMinKey)
getVal Data_max_key = return (0, BsonMaxKey) getVal Data_max_key = return (0, BsonMaxKey)
getInnerObj :: Int32 -> Get (Map.Map L8.ByteString BsonValue) getInnerObj :: Int32 -> BsonDoc -> Get BsonDoc
-> Get (Map.Map L8.ByteString BsonValue) getInnerObj 1 obj = return obj
getInnerObj 1 obj = obj
getInnerObj bytesLeft obj = do getInnerObj bytesLeft obj = do
typ <- getDataType typ <- getDataType
(keySz, key) <- getS (keySz, key) <- getS
(valSz, val) <- getVal typ (valSz, val) <- getVal typ
getInnerObj (bytesLeft - 1 - fromIntegral keySz - fromIntegral valSz) $ getInnerObj (bytesLeft - 1 - fromIntegral keySz - fromIntegral valSz) $
liftM (Map.insert key val) obj (Map.insert key val) obj
getRawObj :: Get (Integer, Map.Map L8.ByteString BsonValue) getRawObj :: Get (Integer, BsonDoc)
getRawObj = do getRawObj = do
bytes <- getI32 bytes <- getI32
obj <- getInnerObj (bytes - 4) $ return Map.empty obj <- getInnerObj (bytes - 4) empty
getNull getNull
return (fromIntegral bytes, obj) return (fromIntegral bytes, obj)
getDoc :: Get (Integer, BsonDoc) getDoc :: Get (Integer, BsonDoc)
getDoc = getRawObj >>= \(len, obj) -> return (len, BsonDoc obj) getDoc = getRawObj
getDataType :: Get DataType getDataType :: Get DataType
getDataType = liftM toDataType getI8 getDataType = liftM toDataType getI8
@ -280,7 +277,7 @@ putVal BsonMaxKey = putNothing
putObj :: BsonDoc -> Put putObj :: BsonDoc -> Put
putObj obj = putOutterObj bs putObj obj = putOutterObj bs
where bs = runPut $ forM_ (Map.toList (fromBsonDoc obj)) $ \(k, v) -> where bs = runPut $ forM_ (fromBsonDoc obj) $ \(k, v) ->
putType v >> putS k >> putVal v putType v >> putS k >> putVal v
putOutterObj :: L.ByteString -> Put putOutterObj :: L.ByteString -> Put
@ -344,17 +341,14 @@ instance Convertible [S8.ByteString] BsonValue where
instance Convertible BsonDoc BsonValue where instance Convertible BsonDoc BsonValue where
safeConvert = return . BsonObject safeConvert = return . BsonObject
instance Convertible [(String, BsonValue)] BsonValue where instance Convertible (Map.Map String BsonValue) BsonValue where
safeConvert = return . BsonObject . toBsonDoc safeConvert = return . BsonObject . Map.mapKeys L8.fromString
instance Convertible [(L8.ByteString, BsonValue)] BsonValue where instance Convertible [(L8.ByteString, BsonValue)] BsonValue where
safeConvert = return . BsonObject . toBsonDoc safeConvert = return . BsonObject . toBsonDoc
instance Convertible (Map.Map String BsonValue) BsonValue where instance Convertible [(String, BsonValue)] BsonValue where
safeConvert = return . BsonObject . BsonDoc . Map.mapKeys L8.fromString safeConvert = return . BsonObject . toBsonDoc
instance Convertible (Map.Map L8.ByteString BsonValue) BsonValue where
safeConvert = return . BsonObject . BsonDoc
instance Convertible [Bool] BsonValue where instance Convertible [Bool] BsonValue where
safeConvert bs = BsonArray `liftM` mapM safeConvert bs safeConvert bs = BsonArray `liftM` mapM safeConvert bs
@ -431,20 +425,16 @@ instance Convertible BsonValue BsonDoc where
safeConvert (BsonObject o) = return o safeConvert (BsonObject o) = return o
safeConvert v = unsupportedError v safeConvert v = unsupportedError v
instance Convertible BsonValue (Map.Map L8.ByteString BsonValue) where
safeConvert (BsonObject o) = return $ fromBsonDoc $ o
safeConvert v = unsupportedError v
instance Convertible BsonValue (Map.Map String BsonValue) where instance Convertible BsonValue (Map.Map String BsonValue) where
safeConvert (BsonObject o) = return $ fromBsonDoc $ o safeConvert (BsonObject o) = return $ Map.mapKeys L8.toString o
safeConvert v = unsupportedError v safeConvert v = unsupportedError v
instance Convertible BsonValue [(String, BsonValue)] where instance Convertible BsonValue [(String, BsonValue)] where
safeConvert (BsonObject o) = return $ Map.toList $ fromBsonDoc o safeConvert (BsonObject o) = return $ fromBsonDoc o
safeConvert v = unsupportedError v safeConvert v = unsupportedError v
instance Convertible BsonValue [(L8.ByteString, BsonValue)] where instance Convertible BsonValue [(L8.ByteString, BsonValue)] where
safeConvert (BsonObject o) = return $ Map.toList $ fromBsonDoc o safeConvert (BsonObject o) = return $ fromBsonDoc o
safeConvert v = unsupportedError v safeConvert v = unsupportedError v
instance Convertible BsonValue [Double] where instance Convertible BsonValue [Double] where