1
1
-- | Internal functions
2
2
module Network.Transport.Internal
3
3
( -- * Encoders/decoders
4
- encodeInt32
5
- , decodeInt32
6
- , encodeInt16
7
- , decodeInt16
4
+ encodeWord32
5
+ , decodeWord32
6
+ , encodeEnum32
7
+ , decodeNum32
8
+ , encodeWord16
9
+ , decodeWord16
10
+ , encodeEnum16
11
+ , decodeNum16
8
12
, prependLength
9
13
-- * Miscellaneous abstractions
10
14
, mapIOException
@@ -24,7 +28,6 @@ import Prelude hiding (catch)
24
28
#endif
25
29
26
30
import Foreign.Storable (pokeByteOff , peekByteOff )
27
- import Foreign.C (CInt (.. ), CShort (.. ))
28
31
import Foreign.ForeignPtr (withForeignPtr )
29
32
import Data.ByteString (ByteString )
30
33
import qualified Data.ByteString as BS (length )
@@ -33,6 +36,7 @@ import qualified Data.ByteString.Internal as BSI
33
36
, toForeignPtr
34
37
, inlinePerformIO
35
38
)
39
+ import Data.Word (Word32 , Word16 )
36
40
import Control.Monad.IO.Class (MonadIO , liftIO )
37
41
import Control.Exception
38
42
( IOException
@@ -53,57 +57,73 @@ import System.Timeout (timeout)
53
57
54
58
#ifdef mingw32_HOST_OS
55
59
56
- foreign import stdcall unsafe " htonl" htonl :: CInt -> CInt
57
- foreign import stdcall unsafe " ntohl" ntohl :: CInt -> CInt
58
- foreign import stdcall unsafe " htons" htons :: CShort -> CShort
59
- foreign import stdcall unsafe " ntohs" ntohs :: CShort -> CShort
60
+ foreign import stdcall unsafe " htonl" htonl :: Word32 -> Word32
61
+ foreign import stdcall unsafe " ntohl" ntohl :: Word32 -> Word32
62
+ foreign import stdcall unsafe " htons" htons :: Word16 -> Word16
63
+ foreign import stdcall unsafe " ntohs" ntohs :: Word16 -> Word16
60
64
61
65
#else
62
66
63
- foreign import ccall unsafe " htonl" htonl :: CInt -> CInt
64
- foreign import ccall unsafe " ntohl" ntohl :: CInt -> CInt
65
- foreign import ccall unsafe " htons" htons :: CShort -> CShort
66
- foreign import ccall unsafe " ntohs" ntohs :: CShort -> CShort
67
+ foreign import ccall unsafe " htonl" htonl :: Word32 -> Word32
68
+ foreign import ccall unsafe " ntohl" ntohl :: Word32 -> Word32
69
+ foreign import ccall unsafe " htons" htons :: Word16 -> Word16
70
+ foreign import ccall unsafe " ntohs" ntohs :: Word16 -> Word16
67
71
68
72
#endif
69
73
70
74
-- | Serialize 32-bit to network byte order
71
- encodeInt32 :: Enum a => a -> ByteString
72
- encodeInt32 i32 =
75
+ encodeWord32 :: Word32 -> ByteString
76
+ encodeWord32 w32 =
73
77
BSI. unsafeCreate 4 $ \ p ->
74
- pokeByteOff p 0 (htonl . fromIntegral . fromEnum $ i32 )
78
+ pokeByteOff p 0 (htonl w32 )
75
79
76
80
-- | Deserialize 32-bit from network byte order
77
- -- Throws an IO exception if this is not a valid integer .
78
- decodeInt32 :: Num a => ByteString -> a
79
- decodeInt32 bs
80
- | BS. length bs /= 4 = throw $ userError " decodeInt32: Invalid length "
81
+ -- Throws an IO exception if this is not exactly 32 bits .
82
+ decodeWord32 :: ByteString -> Word32
83
+ decodeWord32 bs
84
+ | BS. length bs /= 4 = throw $ userError " decodeWord32: not 4 bytes "
81
85
| otherwise = BSI. inlinePerformIO $ do
82
86
let (fp, offset, _) = BSI. toForeignPtr bs
83
- withForeignPtr fp $ \ p -> do
84
- w32 <- peekByteOff p offset
85
- return (fromIntegral . ntohl $ w32)
87
+ withForeignPtr fp $ \ p -> ntohl <$> peekByteOff p offset
86
88
87
89
-- | Serialize 16-bit to network byte order
88
- encodeInt16 :: Enum a => a -> ByteString
89
- encodeInt16 i16 =
90
+ encodeWord16 :: Word16 -> ByteString
91
+ encodeWord16 w16 =
90
92
BSI. unsafeCreate 2 $ \ p ->
91
- pokeByteOff p 0 (htons . fromIntegral . fromEnum $ i16 )
93
+ pokeByteOff p 0 (htons w16 )
92
94
93
95
-- | Deserialize 16-bit from network byte order
94
- -- Throws an IO exception if this is not a valid integer
95
- decodeInt16 :: Num a => ByteString -> a
96
- decodeInt16 bs
97
- | BS. length bs /= 2 = throw $ userError " decodeInt16: Invalid length "
96
+ -- Throws an IO exception if this is not exactly 16 bits.
97
+ decodeWord16 :: ByteString -> Word16
98
+ decodeWord16 bs
99
+ | BS. length bs /= 2 = throw $ userError " decodeWord16: not 2 bytes "
98
100
| otherwise = BSI. inlinePerformIO $ do
99
101
let (fp, offset, _) = BSI. toForeignPtr bs
100
- withForeignPtr fp $ \ p -> do
101
- w16 <- peekByteOff p offset
102
- return (fromIntegral . ntohs $ w16)
102
+ withForeignPtr fp $ \ p -> ntohs <$> peekByteOff p offset
103
+
104
+ -- | Encode an Enum in 32 bits by encoding its signed Int equivalent (beware
105
+ -- of truncation, an Enum may contain more than 2^32 points).
106
+ encodeEnum32 :: Enum a => a -> ByteString
107
+ encodeEnum32 = encodeWord32 . fromIntegral . fromEnum
108
+
109
+ -- | Decode any Num type from 32 bits by using fromIntegral to convert from
110
+ -- a Word32.
111
+ decodeNum32 :: Num a => ByteString -> a
112
+ decodeNum32 = fromIntegral . decodeWord32
113
+
114
+ -- | Encode an Enum in 16 bits by encoding its signed Int equivalent (beware
115
+ -- of truncation, an Enum may contain more than 2^16 points).
116
+ encodeEnum16 :: Enum a => a -> ByteString
117
+ encodeEnum16 = encodeWord16 . fromIntegral . fromEnum
118
+
119
+ -- | Decode any Num type from 16 bits by using fromIntegral to convert from
120
+ -- a Word16.
121
+ decodeNum16 :: Num a => ByteString -> a
122
+ decodeNum16 = fromIntegral . decodeWord16
103
123
104
124
-- | Prepend a list of bytestrings with their total length
105
125
prependLength :: [ByteString ] -> [ByteString ]
106
- prependLength bss = encodeInt32 ( sum . map BS. length $ bss) : bss
126
+ prependLength bss = encodeWord32 ( fromIntegral . sum . map BS. length $ bss) : bss
107
127
108
128
-- | Translate exceptions that arise in IO computations
109
129
mapIOException :: Exception e => (IOException -> e ) -> IO a -> IO a
0 commit comments