packages feed

network-effectful (empty) → 0.2.0.0

raw patch · 5 files changed

+568/−0 lines, 5 filesdep +basedep +bytestringdep +effectful-core

Dependencies added: base, bytestring, effectful-core, network

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for socket-effectful++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2024, Cajunvoodoo+++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of the copyright holder nor the names of its+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ network-effectful.cabal view
@@ -0,0 +1,45 @@+cabal-version:   3.0+name:            network-effectful+version:         0.2.0.0+synopsis:+  Adaptation of the network library for the effectful ecosystem.++description:+  Adaptation of the @<https://hackage.haskell.org/package/network network>@ library for the @<https://hackage.haskell.org/package/effectful effectful>@ ecosystem.++homepage:        https://github.com/Cajunvoodoo/network-effectful#readme+bug-reports:     https://github.com/Cajunvoodoo/network-effectful/issues+license:         BSD-3-Clause+license-file:    LICENSE+author:          Cajunvoodoo+maintainer:      cajunvoodoo (discord)++-- copyright:+category:        Network+build-type:      Simple+extra-doc-files: CHANGELOG.md++source-repository head+  type:     git+  location: https://github.com/Cajunvoodoo/network-effectful++-- extra-source-files:+common warnings+  ghc-options: -Wall++library+  import:           warnings+  exposed-modules:+    Effectful.Network+    Effectful.Network.Lazy++  -- other-modules:+  -- other-extensions:+  build-depends:+    , base            <5+    , bytestring      <0.13+    , effectful-core  >=1.0 && <3.0+    , network         >=3.0 && <4.0++  hs-source-dirs:   src+  default-language: GHC2021
+ src/Effectful/Network.hs view
@@ -0,0 +1,442 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ImportQualifiedPost #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -Wno-deprecations #-}++-- | Wrapper of 'Network.Socket' for the 'effectful' ecosystem. Please see the+-- documentation of 'Network.Socket' on how to use this library.+module Effectful.Network+  ( Network+  , runNetwork+  , accept+  , bind+  , close+  , close'+  , connect+  , fdSocket+  , getAddrInfo+  , getCloseOnExec+  , getNameInfo+  , getNonBlock+  , getPeerCredential+  , getPeerName+  , getSockOpt+  , getSocketName+  , getSocketOption+  , getSocketType+  , gracefulClose+  , ifIndexToName+  , ifNameToIndex+  , listen+  , mkSocket+  , openSocket+  , recvBuf+  , recvBufFrom+  , recvBufMsg+  , recvFd+  , sendBuf+  , sendBufMsg+  , sendBufTo+  , sendFd+  , setCloseOnExecIfNeeded+  , setNonBlockIfNeeded+  , setSockOpt+  , setSocketOption+  , shutdown+  , socket+  , socketPair+  , socketPort+  , socketPortSafe+  , socketToFd+  , socketToHandle+  , touchSocket+  , unsafeFdSocket+  , whenSupported+  , withFdSocket+  , withSocketsDo+  , recvFrom+  , recv+  , sendAllTo+  , sendTo+  , sendAll+  , send+  , module Data.Word+  , module Foreign.C.Types+  , module Foreign.Ptr+  , module Foreign.Storable+  , module GHC.IO.Handle.Types+  , module Network.Socket+  , module System.IO+  ) where++import Effectful+  ( Dispatch (Static)+  , DispatchOf+  , Eff+  , Effect+  , IOE+  , type (:>)+  )+import Effectful.Dispatch.Static+  ( SideEffects (WithSideEffects)+  , StaticRep+  , evalStaticRep+  , unsafeEff_+  , unsafeLiftMapIO+  , unsafeSeqUnliftIO+  )++import Data.ByteString (StrictByteString)+import Data.Word (Word8)+import Foreign.C.Types (CInt, CUInt)+import Foreign.Ptr (Ptr)+import Foreign.Storable (Storable)+import GHC.IO.Handle.Types (Handle)+import Network.Socket+  ( AddrInfo (..)+  , Cmsg (..)+  , Family (..)+  , HostName+  , MsgFlag (..)+  , NameInfoFlag (..)+  , PortNumber+  , ProtocolNumber+  , ServiceName+  , ShutdownCmd (..)+  , SockAddr (..)+  , Socket+  , SocketOption (..)+  , SocketType (..)+  )+import Network.Socket qualified as S+import Network.Socket.ByteString qualified as S+import System.IO (IOMode)++-- | The Network effect.+data Network :: Effect++type instance DispatchOf Network = 'Static 'WithSideEffects+newtype instance StaticRep Network = Unit ()++-- | Run the 'Network' effect.+runNetwork :: (IOE :> es) => Eff (Network : es) a -> Eff es a+runNetwork = evalStaticRep (Unit ())++-- | Wraps 'S.getAddrInfo'.+getAddrInfo+  :: (Network :> es)+  => Maybe AddrInfo+  -> Maybe HostName+  -> Maybe ServiceName+  -> Eff es [AddrInfo]+getAddrInfo addrInfo hostName serviceName = unsafeEff_ $ S.getAddrInfo addrInfo hostName serviceName+{-# INLINE getAddrInfo #-}++-- | Wraps 'S.withSocketsDo'.+withSocketsDo :: (Network :> es) => Eff es a -> Eff es a+withSocketsDo = unsafeLiftMapIO S.withSocketsDo+{-# INLINE withSocketsDo #-}++-- | Wraps 'S.connect'.+connect :: (Network :> es) => Socket -> SockAddr -> Eff es ()+connect sock sockAddr = unsafeEff_ $ S.connect sock sockAddr+{-# INLINE connect #-}++-- | Wraps 'S.bind'.+bind :: (Network :> es) => Socket -> SockAddr -> Eff es ()+bind sock sockAddr = unsafeEff_ $ S.bind sock sockAddr+{-# INLINE bind #-}++-- | Wraps 'S.listen'.+listen :: (Network :> es) => Socket -> Int -> Eff es ()+listen sock n = unsafeEff_ $ S.listen sock n+{-# INLINE listen #-}++-- | Wraps 'S.accept'.+accept :: (Network :> es) => Socket -> Eff es (Socket, SockAddr)+accept sock = unsafeEff_ $ S.accept sock+{-# INLINE accept #-}++-- | Wraps 'S.close'.+close :: (Network :> es) => Socket -> Eff es ()+close = unsafeEff_ . S.close+{-# INLINE close #-}++-- | Wraps 'S.close''.+close' :: (Network :> es) => Socket -> Eff es ()+close' = unsafeEff_ . S.close+{-# INLINE close' #-}++-- | Wraps 'S.gracefulClose'.+gracefulClose :: (Network :> es) => Socket -> Int -> Eff es ()+gracefulClose sock = unsafeEff_ . S.gracefulClose sock+{-# INLINE gracefulClose #-}++-- | Wraps 'S.shutdown'.+shutdown+  :: (Network :> es) => Socket -> ShutdownCmd -> Eff es ()+shutdown sock = unsafeEff_ . S.shutdown sock+{-# INLINE shutdown #-}++-- | Wraps 'S.whenSupported'.+whenSupported+  :: (Network :> es) => SocketOption -> Eff es a -> Eff es ()+whenSupported = unsafeLiftMapIO . S.whenSupported+{-# INLINE whenSupported #-}++-- | Wraps 'S.getSocketOption'.+getSocketOption+  :: (Network :> es) => Socket -> SocketOption -> Eff es Int+getSocketOption sock = unsafeEff_ . S.getSocketOption sock+{-# INLINE getSocketOption #-}++-- | Wraps 'S.setSocketOption'.+setSocketOption+  :: (Network :> es) => Socket -> SocketOption -> Int -> Eff es ()+setSocketOption sock sockOpt = unsafeEff_ . S.setSocketOption sock sockOpt+{-# INLINE setSocketOption #-}++-- | Wraps 'S.getSockOpt'.+getSockOpt+  :: (Network :> es)+  => forall a+   . (Storable a)+  => Socket+  -> SocketOption+  -> Eff es a+getSockOpt sock = unsafeEff_ . S.getSockOpt sock+{-# INLINE getSockOpt #-}++-- | Wraps 'S.setSockOpt'.+setSockOpt+  :: (Network :> es) => (Storable a) => Socket -> SocketOption -> a -> Eff es ()+setSockOpt sock sockOpt = unsafeEff_ . S.setSockOpt sock sockOpt+{-# INLINE setSockOpt #-}++-- | Wraps 'S.socket'.+socket+  :: (Network :> es) => Family -> SocketType -> ProtocolNumber -> Eff es Socket+socket fam sockType = unsafeEff_ . S.socket fam sockType+{-# INLINE socket #-}++-- | Wraps 'S.openSocket'.+openSocket :: (Network :> es) => AddrInfo -> Eff es Socket+openSocket = unsafeEff_ . S.openSocket+{-# INLINE openSocket #-}++-- | Wraps 'S.withFdSocket'.+withFdSocket+  :: (Network :> es) => Socket -> (CInt -> Eff es r) -> Eff es r+withFdSocket sock cb = unsafeSeqUnliftIO $ \unlift -> do+  S.withFdSocket sock (unlift . cb)+{-# INLINE withFdSocket #-}++-- | Wraps 'S.unsafeFdSocket'.+unsafeFdSocket :: (Network :> es) => Socket -> Eff es CInt+unsafeFdSocket = unsafeEff_ . S.unsafeFdSocket+{-# INLINE unsafeFdSocket #-}++-- | Wraps 'S.touchSocket'.+touchSocket :: (Network :> es) => Socket -> Eff es ()+touchSocket = unsafeEff_ . S.touchSocket+{-# INLINE touchSocket #-}++-- | Wraps 'S.socketToFd'.+socketToFd :: (Network :> es) => Socket -> Eff es CInt+socketToFd = unsafeEff_ . S.socketToFd+{-# INLINE socketToFd #-}++-- | Wraps 'S.fdSocket'.+fdSocket :: (Network :> es) => Socket -> Eff es CInt+fdSocket = unsafeEff_ . S.fdSocket+{-# INLINE fdSocket #-}+{-# DEPRECATED fdSocket "Use withFdSocket or unsafeFdSocket instead" #-}++-- | Wraps 'S.mkSocket'.+mkSocket :: (Network :> es) => CInt -> Eff es Socket+mkSocket = unsafeEff_ . S.mkSocket+{-# INLINE mkSocket #-}++-- | Wraps 'S.socketToHandle'.+socketToHandle+  :: (Network :> es) => Socket -> IOMode -> Eff es Handle+socketToHandle sock = unsafeEff_ . S.socketToHandle sock+{-# INLINE socketToHandle #-}++-- | Wraps 'S.getSocketType'.+getSocketType :: (Network :> es) => Socket -> Eff es SocketType+getSocketType = unsafeEff_ . S.getSocketType+{-# INLINE getSocketType #-}++-- | Wraps 'S.getPeerName'.+getPeerName :: (Network :> es) => Socket -> Eff es SockAddr+getPeerName = unsafeEff_ . S.getPeerName+{-# INLINE getPeerName #-}++-- | Wraps 'S.getSocketName'.+getSocketName :: (Network :> es) => Socket -> Eff es SockAddr+getSocketName = unsafeEff_ . S.getSocketName+{-# INLINE getSocketName #-}++-- | Wraps 'S.ifNameToIndex'.+ifNameToIndex :: (Network :> es) => String -> Eff es (Maybe Int)+ifNameToIndex = unsafeEff_ . S.ifNameToIndex+{-# INLINE ifNameToIndex #-}++-- | Wraps 'S.ifIndexToName'.+ifIndexToName :: (Network :> es) => Int -> Eff es (Maybe String)+ifIndexToName = unsafeEff_ . S.ifIndexToName+{-# INLINE ifIndexToName #-}++-- | Wraps 'S.socketPortSafe'.+socketPortSafe+  :: (Network :> es) => Socket -> Eff es (Maybe PortNumber)+socketPortSafe = unsafeEff_ . S.socketPortSafe+{-# INLINE socketPortSafe #-}++-- | Wraps 'S.socketPort'.+socketPort :: (Network :> es) => Socket -> Eff es PortNumber+socketPort = unsafeEff_ . S.socketPort+{-# INLINE socketPort #-}++-- | Wraps 'S.socketPair'.+socketPair+  :: (Network :> es)+  => Family+  -> SocketType+  -> ProtocolNumber+  -> Eff es (Socket, Socket)+socketPair fam sock = unsafeEff_ . S.socketPair fam sock+{-# INLINE socketPair #-}++-- | Wraps 'S.sendFd'.+sendFd :: (Network :> es) => Socket -> CInt -> Eff es ()+sendFd sock = unsafeEff_ . S.sendFd sock+{-# INLINE sendFd #-}++-- | Wraps 'S.recvFd'.+recvFd :: (Network :> es) => Socket -> Eff es CInt+recvFd = unsafeEff_ . S.recvFd+{-# INLINE recvFd #-}++-- | Wraps 'S.getPeerCredential'.+getPeerCredential+  :: (Network :> es) => Socket -> Eff es (Maybe CUInt, Maybe CUInt, Maybe CUInt)+getPeerCredential = unsafeEff_ . S.getPeerCredential+{-# INLINE getPeerCredential #-}++-- | Wraps 'S.getNameInfo'.+getNameInfo+  :: (Network :> es)+  => [NameInfoFlag]+  -> Bool+  -> Bool+  -> SockAddr+  -> Eff es (Maybe HostName, Maybe ServiceName)+getNameInfo flag b1 b2 = unsafeEff_ . S.getNameInfo flag b1 b2+{-# INLINE getNameInfo #-}++-- | Wraps 'S.setCloseOnExecIfNeeded'.+setCloseOnExecIfNeeded :: (Network :> es) => CInt -> Eff es ()+setCloseOnExecIfNeeded = unsafeEff_ . S.setCloseOnExecIfNeeded+{-# INLINE setCloseOnExecIfNeeded #-}++-- | Wraps 'S.getCloseOnExec'.+getCloseOnExec :: (Network :> es) => CInt -> Eff es Bool+getCloseOnExec = unsafeEff_ . S.getCloseOnExec+{-# INLINE getCloseOnExec #-}++-- | Wraps 'S.setNonBlockIfNeeded'.+setNonBlockIfNeeded :: (Network :> es) => CInt -> Eff es ()+setNonBlockIfNeeded = unsafeEff_ . S.setNonBlockIfNeeded+{-# INLINE setNonBlockIfNeeded #-}++-- | Wraps 'S.getNonBlock'.+getNonBlock :: (Network :> es) => CInt -> Eff es Bool+getNonBlock = unsafeEff_ . S.getNonBlock+{-# INLINE getNonBlock #-}++-- | Wraps 'S.sendBuf'.+sendBuf+  :: (Network :> es) => Socket -> Ptr Word8 -> Int -> Eff es Int+sendBuf sock ptr = unsafeEff_ . S.sendBuf sock ptr+{-# INLINE sendBuf #-}++-- | Wraps 'S.recvBuf'.+recvBuf+  :: (Network :> es) => Socket -> Ptr Word8 -> Int -> Eff es Int+recvBuf sock ptr = unsafeEff_ . S.recvBuf sock ptr+{-# INLINE recvBuf #-}++-- | Wraps 'S.sendBufTo'.+sendBufTo+  :: (Network :> es) => Socket -> Ptr a -> Int -> SockAddr -> Eff es Int+sendBufTo sock ptr n = unsafeEff_ . S.sendBufTo sock ptr n+{-# INLINE sendBufTo #-}++-- | Wraps 'S.recvBufFrom'.+recvBufFrom+  :: (Network :> es) => Socket -> Ptr a -> Int -> Eff es (Int, SockAddr)+recvBufFrom sock ptr = unsafeEff_ . S.recvBufFrom sock ptr+{-# INLINE recvBufFrom #-}++-- | Wraps 'S.sendBufMsg'.+sendBufMsg+  :: (Network :> es)+  => Socket+  -> SockAddr+  -> [(Ptr Word8, Int)]+  -> [Cmsg]+  -> MsgFlag+  -> Eff es Int+sendBufMsg sock sockAddr ptrs cmsgs = unsafeEff_ . S.sendBufMsg sock sockAddr ptrs cmsgs+{-# INLINE sendBufMsg #-}++-- | Wraps 'S.recvBufMsg'.+recvBufMsg+  :: (Network :> es)+  => Socket+  -> [(Ptr Word8, Int)]+  -> Int+  -> MsgFlag+  -> Eff es (SockAddr, Int, [Cmsg], MsgFlag)+recvBufMsg sock ptrs n = unsafeEff_ . S.recvBufMsg sock ptrs n+{-# INLINE recvBufMsg #-}++-- | Wraps 'S.send'.+send :: (Network :> es) => Socket -> StrictByteString -> Eff es Int+send sock = unsafeEff_ . S.send sock+{-# INLINE send #-}++-- | Wraps 'S.sendAll'.+sendAll :: (Network :> es) => Socket -> StrictByteString -> Eff es ()+sendAll sock = unsafeEff_ . S.sendAll sock+{-# INLINE sendAll #-}++-- | Wraps 'S.sendTo'.+sendTo+  :: (Network :> es) => Socket -> StrictByteString -> SockAddr -> Eff es Int+sendTo sock bs = unsafeEff_ . S.sendTo sock bs+{-# INLINE sendTo #-}++-- | Wraps 'S.sendAllTo'.+sendAllTo+  :: (Network :> es) => Socket -> StrictByteString -> SockAddr -> Eff es ()+sendAllTo sock bs = unsafeEff_ . S.sendAllTo sock bs+{-# INLINE sendAllTo #-}++-- TODO: wrap more send functions++-- | Wraps 'S.recv'.+recv :: (Network :> es) => Socket -> Int -> Eff es StrictByteString+recv sock = unsafeEff_ . S.recv sock+{-# INLINE recv #-}++-- | Wraps 'S.recvFrom'.+recvFrom+  :: (Network :> es) => Socket -> Int -> Eff es (StrictByteString, SockAddr)+recvFrom sock = unsafeEff_ . S.recvFrom sock+{-# INLINE recvFrom #-}
+ src/Effectful/Network/Lazy.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ImportQualifiedPost #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# OPTIONS_GHC -Wno-deprecations #-}++-- | Wrapper of 'Network.Socket.Lazy.ByteString' for the 'effectful' ecosystem.+-- Please see the documentation of 'Network.Socket.Lazy.ByteString' on how to use+-- this library.+module Effectful.Network.Lazy where++import Effectful (Eff, type (:>))++import Effectful.Dispatch.Static (unsafeEff_)++import Data.ByteString.Lazy (LazyByteString)+import Network.Socket (Socket)+import Network.Socket.ByteString.Lazy qualified as S+import Prelude hiding (getContents)++import Data.Int (Int64)+import Effectful.Network (Network)++-- | Wraps 'S.send'.+send :: (Network :> es) => Socket -> LazyByteString -> Eff es Int64+send sock = unsafeEff_ . S.send sock++-- | Wraps 'S.sendAll'.+sendAll :: (Network :> es) => Socket -> LazyByteString -> Eff es ()+sendAll sock = unsafeEff_ . S.sendAll sock++#if MIN_VERSION_network(3,2,0)+-- | Wraps 'S.sendWithFds'.+sendWithFds :: (Network :> es) => Socket -> LazyByteString -> [Fd] -> Eff es ()+sendWithFds sock lbs = unsafeEff_ . S.sendWithFds sock lbs+#endif++-- | Wraps 'S.getContents'.+getContents :: (Network :> es) => Socket -> Eff es LazyByteString+getContents = unsafeEff_ . S.getContents++-- | Wraps 'S.recv'.+recv :: (Network :> es) => Socket -> Int64 -> Eff es LazyByteString+recv sock = unsafeEff_ . S.recv sock