Skip to content

Commit 19217bd

Browse files
committed
Add Read instances for SockAddr/SockEndpoint, make Show instances follow contract
The old Show behaviour is moved into the 'showSockAddr' function, with a new function 'readSockAddr' that acts as its opposite.
1 parent d25c4c3 commit 19217bd

File tree

5 files changed

+26
-15
lines changed

5 files changed

+26
-15
lines changed

Network/Socket.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ module Network.Socket
190190
, resolveEndpoint
191191
-- * Basic socket address type
192192
, SockAddr(..)
193+
, readSockAddr
194+
, showSockAddr
193195
, sockAddrFamily
194196
, isSupportedSockAddr
195197
, getPeerName

Network/Socket/Info.hsc

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,9 @@ defaultHints = AddrInfo {
242242
--
243243
-- >>> addr:_ <- getAddrInfo (Just hints) (Just "127.0.0.1") (Just "http")
244244
-- >>> addrAddress addr
245-
-- 127.0.0.1:80
245+
-- SockAddrInet 80 16777343
246+
-- >>> showSockAddr (addrAddress addr)
247+
-- "127.0.0.1:80"
246248

247249
getAddrInfo
248250
:: Maybe AddrInfo -- ^ preferred socket type or protocol
@@ -415,22 +417,29 @@ unpackBits ((k,v):xs) r
415417
-----------------------------------------------------------------------------
416418
-- SockAddr
417419

418-
instance Show SockAddr where
420+
-- | Read a string representing a socket address.
421+
readSockAddr :: PortNumber -> String -> Either String SockAddr
422+
readSockAddr defPort hostport = readSockEndpoint defPort hostport >>= \r -> case r of
423+
EndpointByName h _ -> Left $ "expected address but got hostname: " <> h
424+
EndpointByAddr a -> Right a
425+
426+
showSockAddr :: SockAddr -> String
419427
#if defined(DOMAIN_SOCKET_SUPPORT)
420-
showsPrec _ (SockAddrUnix str) = showString str
428+
showSockAddr (SockAddrUnix str) = showString str ""
421429
#else
422-
showsPrec _ SockAddrUnix{} = error "showsPrec: not supported"
430+
showSockAddr SockAddrUnix{} = error "showsPrec: not supported"
423431
#endif
424-
showsPrec _ (SockAddrInet port ha)
432+
showSockAddr (SockAddrInet port ha)
425433
= showHostAddress ha
426434
. showString ":"
427435
. shows port
428-
showsPrec _ (SockAddrInet6 port _ ha6 _)
436+
$ ""
437+
showSockAddr (SockAddrInet6 port _ ha6 _)
429438
= showChar '['
430439
. showHostAddress6 ha6
431440
. showString "]:"
432441
. shows port
433-
442+
$ ""
434443

435444
-- Taken from on the implementation of showIPv4 in Data.IP.Addr
436445
showHostAddress :: HostAddress -> ShowS
@@ -512,7 +521,7 @@ readSockEndpoint defPort hostport = case hostport of
512521
showSockEndpoint :: SockEndpoint -> String
513522
showSockEndpoint n = case n of
514523
EndpointByName h p -> h <> ":" <> show p
515-
EndpointByAddr a -> show a
524+
EndpointByAddr a -> showSockAddr a
516525

517526
-- | Resolve a socket endpoint into a list of socket addresses.
518527
-- The result is always non-empty; Haskell throws an exception if name

Network/Socket/Syscall.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ import Network.Socket.Types
6868
-- >>> sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
6969
-- >>> Network.Socket.bind sock (addrAddress addr)
7070
-- >>> getSocketName sock
71-
-- 127.0.0.1:5000
71+
-- SockAddrInet 5000 16777343
7272
socket :: Family -- Family Name (usually AF_INET)
7373
-> SocketType -- Socket Type (usually Stream)
7474
-> ProtocolNumber -- Protocol Number (getProtocolByName to find value)

Network/Socket/Types.hsc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,7 @@ type ScopeID = Word32
10581058
data SockEndpoint
10591059
= EndpointByName !String !PortNumber
10601060
| EndpointByAddr !SockAddr
1061-
deriving (Eq, Ord)
1061+
deriving (Eq, Ord, Read, Show)
10621062

10631063
-- | Socket addresses.
10641064
-- The existence of a constructor does not necessarily imply that
@@ -1076,7 +1076,7 @@ data SockAddr
10761076
-- | The path must have fewer than 104 characters. All of these characters must have code points less than 256.
10771077
| SockAddrUnix
10781078
String -- sun_path
1079-
deriving (Eq, Ord)
1079+
deriving (Eq, Ord, Read, Show)
10801080

10811081
instance NFData SockAddr where
10821082
rnf (SockAddrInet _ _) = ()

tests/Network/SocketSpec.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,20 +320,20 @@ spec = do
320320
describe "show SocketAddr" $ do
321321
it "works for IPv4 address" $
322322
let addr = SockAddrInet 80 (tupleToHostAddress (127, 0, 0, 1)) in
323-
show addr `shouldBe` "127.0.0.1:80"
323+
showSockAddr addr `shouldBe` "127.0.0.1:80"
324324

325325
it "works for IPv6 address" $
326326
let addr = SockAddrInet6 80 0
327327
(tupleToHostAddress6 (0x2001, 0x0db8, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7)) 0 in
328-
show addr `shouldBe` "[2001:db8:2:3:4:5:6:7]:80"
328+
showSockAddr addr `shouldBe` "[2001:db8:2:3:4:5:6:7]:80"
329329

330330
it "works for IPv6 address with zeros" $
331331
let addr = SockAddrInet6 80 0
332332
(tupleToHostAddress6 (0x2001, 0x0db8, 0x2, 0x3, 0x0, 0x0, 0x0, 0x7)) 0 in
333-
show addr `shouldBe` "[2001:db8:2:3::7]:80"
333+
showSockAddr addr `shouldBe` "[2001:db8:2:3::7]:80"
334334

335335
it "works for multicast IPv6 address with reserved scope" $ do
336336
let addr = SockAddrInet6 80 0
337337
(tupleToHostAddress6 (0xff01, 0x1234, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7)) 0
338-
show addr `shouldBe` "[ff01:1234:2:3:4:5:6:7]:80"
338+
showSockAddr addr `shouldBe` "[ff01:1234:2:3:4:5:6:7]:80"
339339

0 commit comments

Comments
 (0)