module Network.DBus.Type
(
ObjectPath
, DbusType(..)
, putType
, getType
, sigType
) where
import Data.Word
import Data.Int
import Data.ByteString (ByteString)
import Network.DBus.Wire
import Network.DBus.Signature
import qualified Network.DBus.IEEE754 as IEEE754
import Control.Applicative ((<$>))
type ObjectPath = ByteString
data DbusType =
DbusByte Word8
| DbusBoolean Bool
| DbusInt16 Int16
| DbusUInt16 Word16
| DbusInt32 Int32
| DbusUInt32 Word32
| DbusInt64 Int64
| DbusUInt64 Word64
| DbusDouble Double
| DbusString ByteString
| DbusObjectPath ObjectPath
| DbusSignature Signature
| DbusArray SignatureElem [DbusType]
| DbusStruct Signature [DbusType]
| DbusDict DbusType DbusType
| DbusVariant DbusType
| DbusUnixFD Word32
deriving (Show,Eq)
sigType :: DbusType -> SignatureElem
sigType (DbusByte _) = SigByte
sigType (DbusBoolean _) = SigBool
sigType (DbusInt16 _) = SigInt16
sigType (DbusUInt16 _) = SigUInt16
sigType (DbusInt32 _) = SigInt32
sigType (DbusUInt32 _) = SigUInt32
sigType (DbusInt64 _) = SigInt64
sigType (DbusUInt64 _) = SigUInt64
sigType (DbusDouble _) = SigDouble
sigType (DbusString _) = SigString
sigType (DbusObjectPath _) = SigObjectPath
sigType (DbusSignature _) = SigSignature
sigType (DbusStruct s _) = SigStruct s
sigType (DbusVariant _) = SigVariant
sigType (DbusArray s _) = SigArray s
sigType (DbusDict k v) = SigDict (sigType k) (sigType v)
sigType (DbusUnixFD _) = SigUnixFD
alignSigElement :: SignatureElem -> Int
alignSigElement SigByte = 1
alignSigElement SigBool = 1
alignSigElement SigInt16 = 2
alignSigElement SigUInt16 = 2
alignSigElement SigInt32 = 4
alignSigElement SigUInt32 = 4
alignSigElement SigInt64 = 8
alignSigElement SigUInt64 = 8
alignSigElement SigDouble = 8
alignSigElement SigString = 4
alignSigElement SigObjectPath = 4
alignSigElement SigSignature = 1
alignSigElement (SigDict _ _) = 8
alignSigElement (SigStruct _) = 8
alignSigElement SigVariant = 1
alignSigElement (SigArray _) = 4
alignSigElement SigUnixFD = 4
putType :: DbusType -> PutWire
putType (DbusByte w) = putw8 w
putType (DbusBoolean b) = putw32 (if b then 1 else 0)
putType (DbusInt16 i) = putw16 $ fromIntegral i
putType (DbusUInt16 w) = putw16 w
putType (DbusInt32 i) = putw32 $ fromIntegral i
putType (DbusUInt32 w) = putw32 w
putType (DbusInt64 i) = putw64 $ fromIntegral i
putType (DbusUInt64 w) = putw64 w
putType (DbusDouble d) = putw64 $ IEEE754.encode d
putType (DbusString s) = putString s
putType (DbusObjectPath s) = putString s
putType (DbusSignature s) = putSignature s
putType (DbusUnixFD fd) = putw32 fd
putType (DbusStruct _ l) = alignWrite 8 >> mapM_ putType l
putType (DbusDict k v) = putType (DbusStruct [] [k,v])
putType (DbusVariant t) = putSignature [sigType t] >> putType t
putType (DbusArray s l) = putw32 (fromIntegral len) >> alignWrite alignElement >> mapM_ putType l
where
len = length l * sizeofElement
sizeofElement = 4
alignElement = alignSigElement s
getType :: SignatureElem -> GetWire DbusType
getType SigByte = DbusByte <$> getw8
getType SigBool = DbusBoolean . iToB <$> getw32 where iToB i = i == 1
getType SigInt16 = DbusInt16 . fromIntegral <$> getw16
getType SigUInt16 = DbusUInt16 <$> getw16
getType SigInt32 = DbusInt32 . fromIntegral <$> getw32
getType SigUInt32 = DbusUInt32 <$> getw32
getType SigInt64 = DbusInt64 . fromIntegral <$> getw64
getType SigUInt64 = DbusUInt64 <$> getw64
getType SigDouble = DbusDouble . IEEE754.decode <$> getw64
getType SigString = DbusString <$> getString
getType SigObjectPath = DbusObjectPath <$> getObjectPath
getType SigSignature = DbusSignature <$> getSignature
getType (SigDict k v) = getType (SigStruct [k,v])
getType SigUnixFD = DbusUnixFD <$> getw32
getType SigVariant = getVariant >>= getType >>= return . DbusVariant
getType (SigStruct sigs) =
alignRead 8 >> mapM getType sigs >>= return . DbusStruct sigs
getType (SigArray t) = do
len <- getw32
alignRead (alignSigElement t)
l <- getMultiple (fromIntegral len) (getType t)
return $ DbusArray t l