Network-NineP-0.0.2: Network/NineP/Internal/State.hs
{-# LANGUAGE TemplateHaskell #-}
module Network.NineP.Internal.State
( Nine
, NineVersion(..)
, readVersion
, Config(..)
, emptyState
, msize
, protoVersion
, lookup
, insert
, delete
, iounit
) where
import Control.Concurrent.MState
import Control.Monad.Reader
import Control.Monad.State.Class
import Data.List (isPrefixOf)
import Data.Map (Map)
import qualified Data.Map as M
import Data.Word
import Prelude hiding (lookup)
import Network.NineP.Error
import Network.NineP.Internal.File
data NineVersion = VerUnknown | Ver9P2000
instance Show NineVersion where
show VerUnknown = "unknown"
show Ver9P2000 = "9P2000"
readVersion :: String -> NineVersion
readVersion s = if isPrefixOf "9P2000" s then Ver9P2000 else VerUnknown
-- |Server configuration.
data Config = Config {
-- |The @/@ directory of the hosted filesystem
root :: NineFile,
-- |The listening address. The syntax is taken from @Plan 9@ operating system and has the form @unix!/path/to/socket@ for unix socket files, and @tcp!hostname!port@ for tcp sockets.
addr :: String
}
data NineState = NineState {
fidMap :: Map Word32 NineFile,
msize :: Word32,
protoVersion :: NineVersion
}
emptyState = NineState
(M.empty :: Map Word32 NineFile)
0
VerUnknown
type Nine x = ErrorT NineError (MState NineState (ReaderT Config IO)) x
lookup :: Word32 -> Nine NineFile
lookup fid = do
m <- (return . fidMap) =<< get
case M.lookup fid m of
Nothing -> throwError $ ENoFid fid
Just f -> return f
insert :: Word32 -> NineFile -> Nine ()
insert fid f = do
m <- (return . fidMap) =<< get
lift $ modifyM_ (\s -> s { fidMap = M.insert fid f $ fidMap s })
delete :: Word32 -> Nine ()
delete fid = do
lift $ modifyM_ (\s -> s { fidMap = M.delete fid $ fidMap s })
iounit :: Nine Word32
iounit = do
ms <- (return . msize) =<< get
-- 23 is the biggest size of a message (write), but libixp uses 24, so we do too to stay safe
return $ ms - 24