{----------------------------------------------------------------------------------------- Module name: BufferedSocketReader Made by: Tomas Möre 2015 Usage: This module is mean to be imported qualified This is an addition to BufferedSocket ex: import Headers qualified BS Notes: This reader modules purpose is to make it easto to read diffrent kinds of data types. This is of course only if the socket isn't encrypted. WARNINGS: Nah Nothing ------------------------------------------------------------------------------------------} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE FlexibleInstances #-} module Network.BufferedSocket.Reader ( readText , readTextLazy , readNativeString , readWord8 , readWord16 , readWord32 , readWord64 , readInt8 , readInt16 , readInt32 , readInt64 , read , Readable , readString , ReadableString ) where import Prelude hiding (getLine, read) import qualified Data.ByteString as B import qualified Data.ByteString.Internal as BI import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Builder as BB import qualified Data.ByteString.Char8 as BC8 import qualified Data.Text as T import qualified Data.Text.Lazy as TL import qualified Data.Text.Encoding as ENC import qualified Data.Text.Lazy.Encoding as ENCL import qualified Data.Text.Encoding.Error as ENCERROR import Data.Maybe (isJust) import Control.Monad import Data.Functor import Data.Monoid import Data.Word import Data.String import Data.Int import qualified Network.BufferedSocket.Core as BS import Data.Bits listToValue :: (Bits a, Num a) => [a] -> a listToValue = foldl xor zeroBits convertToShiftedList:: (Bits b, Num b) => [Word8] -> Int -> [b] convertToShiftedList [] _ = [] convertToShiftedList (x:xs) byteIndex = let n = byteIndex - 1 -- Since we want the size of the result data the actual index -||- is (-1) in (shift (fromIntegral x) (8 * n): convertToShiftedList xs n) readText:: BS.BufferedSocket -> BS.ReadSize -> IO T.Text readText bSocket readSize = do byteData <- BS.readRaw bSocket readSize return $ ENC.decodeUtf8With (ENCERROR.replace '\xfffd') byteData readTextLazy:: BS.BufferedSocket -> BS.ReadSize -> IO TL.Text readTextLazy bSocket readSize = do byteData <- BS.readLazy bSocket readSize return $ ENCL.decodeUtf8With (ENCERROR.replace '\xfffd') byteData readNativeString:: BS.BufferedSocket -> BS.ReadSize -> IO String readNativeString bSock readSize = do byteString <- readText bSock readSize return $ T.unpack byteString readWord8:: BS.BufferedSocket -> IO Word8 readWord8 = BS.readByte readWord16:: BS.BufferedSocket -> IO Word16 readWord16 bSocket = do bytes <- B.unpack <$> BS.readRaw bSocket byteSize let result = convertToShiftedList bytes byteSize:: [Word16] return $ listToValue result where byteSize = 2 readWord32:: BS.BufferedSocket -> IO Word32 readWord32 bSocket = do bytes <- B.unpack <$> BS.readRaw bSocket byteSize let result = convertToShiftedList bytes byteSize:: [Word32] return $ listToValue result where byteSize = 4 readWord64:: BS.BufferedSocket -> IO Word64 readWord64 bSocket = do bytes <- B.unpack <$> BS.readRaw bSocket byteSize let result = convertToShiftedList bytes byteSize:: [Word64] return $ listToValue result where byteSize = 8 readInt8:: BS.BufferedSocket -> IO Int8 readInt8 = (fromIntegral <$>) . readWord8 readInt16:: BS.BufferedSocket -> IO Int16 readInt16 = (fromIntegral <$>) . readWord16 readInt32:: BS.BufferedSocket -> IO Int32 readInt32 = (fromIntegral <$>) . readWord32 readInt64:: BS.BufferedSocket -> IO Int64 readInt64 = (fromIntegral <$>) . readWord64 class Readable r where read :: (BS.BufferedSocket -> IO r) instance Readable Word8 where read = readWord8 instance Readable Word16 where read = readWord16 instance Readable Word32 where read = readWord32 instance Readable Word64 where read = readWord64 instance Readable Int8 where read = readInt8 instance Readable Int16 where read = readInt16 instance Readable Int32 where read = readInt32 instance Readable Int64 where read = readInt64 class ReadableString s where readString :: (BS.BufferedSocket -> Int -> IO s) instance ReadableString B.ByteString where readString = BS.readRaw instance ReadableString BL.ByteString where readString = BS.readLazy {-- instance ReadableString T.Text where readString = readText instance ReadableString TL.Text where readString = readTextLazy instance ReadableString String where readString = readNativeString --}