Skip to content

Commit b60eec8

Browse files
committed
FIX bijective read/show for negative CInt values
refactors definitions of _parse and _show in Network.Socket.ReadShow to be specific to Int-like types, with a single-quote character separating the two tuple elements introduces _readInt and _showInt for representation and parsing of negative numbers encoded with underscore ('_') instead of minus ('-') changes variable names in defRead and defShow to more appropriate descriptors explicitly reimplements bijections for Family and SocketType to use `_readInt` and `_showInt` instead of regular `read` and `show` methods of CInt; SocketOptions and CmsgId code unchanged as _parse and _show are internally reimplemented but their calls are unchanged
1 parent 1b374cf commit b60eec8

File tree

2 files changed

+32
-17
lines changed

2 files changed

+32
-17
lines changed

Network/Socket/ReadShow.hs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,31 +50,46 @@ forward Bijection{..} = lookForward defFwd pairs
5050
backward :: (Eq b) => Bijection a b -> b -> a
5151
backward Bijection{..} = lookBackward defBwd pairs
5252

53-
-- | parse an underscore-separated pair into a tuple
53+
-- | show function for Int-like types that encodes negative numbers
54+
-- with leading '_' instead of '-'
55+
_showInt :: (Show a, Num a, Ord a) => a -> String
56+
_showInt n | n < 0 = let ('-':s) = show n in '_':s
57+
| otherwise = show n
58+
59+
-- | parse function for Int-like types that interprets leading '_'
60+
-- as if it were '-' instead
61+
_readInt :: (Read a) => String -> a
62+
_readInt ('_':s) = read $ '-':s
63+
_readInt s = read s
64+
65+
66+
-- | parse a quote-separated pair into a tuple of Int-like values
5467
-- should not be used if either type might have
55-
-- literal underscores in the Read pre-image
68+
-- literal quote-characters in the Read pre-image
5669
_parse :: (Read a, Read b) => String -> (a, b)
5770
_parse xy =
58-
let (xs, '_':ys) = break (=='_') xy
59-
in (read xs, read ys)
71+
let (xs, '\'':ys) = break (=='\'') xy
72+
in (_readInt xs, _readInt ys)
6073
{-# INLINE _parse #-}
6174

6275
-- | inverse function to _parse
63-
-- show a tuple as underscore-separated strings
64-
_show :: (Show a, Show b) => (a, b) -> String
65-
_show (x, y) = show x ++ "_" ++ show y
76+
-- show a tuple of Int-like values as quote-separated strings
77+
_show :: (Show a, Num a, Ord a, Show b, Num b, Ord b) => (a, b) -> String
78+
_show (x, y) = _showInt x ++ "'" ++ _showInt y
79+
{-# INLINE _show #-}
6680

67-
{-# INLINE defShow #-}
6881
defShow :: Eq a => String -> (a -> b) -> (b -> String) -> (a -> String)
69-
defShow name get sho = \x -> name ++ (sho . get $ x)
82+
defShow name unwrap sho = \x -> name ++ (sho . unwrap $ x)
83+
{-# INLINE defShow #-}
7084

71-
{-# INLINE defRead #-}
7285
defRead :: Read a => String -> (b -> a) -> (String -> b) -> (String -> a)
73-
defRead name set red = \s ->
86+
defRead name wrap red = \s ->
7487
case splitAt (length name) s of
75-
(x, sn) | x == name -> set $ red sn
88+
(x, sn) | x == name -> wrap $ red sn
7689
_ -> error $ "defRead: unable to parse " ++ show s
90+
{-# INLINE defRead #-}
7791

78-
{-# INLINE tokenize #-}
92+
-- | Apply a precedence-invariant one-token parse function within ReadPrec monad
7993
tokenize :: (String -> a) -> P.ReadPrec a
8094
tokenize f = P.lexP >>= \(P.Ident x) -> return $ f x
95+
{-# INLINE tokenize #-}

Network/Socket/Types.hsc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,8 +1331,8 @@ socktypeBijection :: Bijection SocketType String
13311331
socktypeBijection = Bijection{..}
13321332
where
13331333
gst = "GeneralSocketType"
1334-
defFwd = defShow gst packSocketType show
1335-
defBwd = defRead gst unpackSocketType read
1334+
defFwd = defShow gst packSocketType _showInt
1335+
defBwd = defRead gst unpackSocketType _readInt
13361336
pairs = socktypePairs
13371337

13381338
instance Show SocketType where
@@ -1416,8 +1416,8 @@ familyBijection :: Bijection Family String
14161416
familyBijection = Bijection{..}
14171417
where
14181418
gf = "GeneralFamily"
1419-
defFwd = defShow gf packFamily show
1420-
defBwd = defRead gf unpackFamily read
1419+
defFwd = defShow gf packFamily _showInt
1420+
defBwd = defRead gf unpackFamily _readInt
14211421
pairs = familyPairs
14221422

14231423
instance Show Family where

0 commit comments

Comments
 (0)