-- | -- Stability : Ultra-Violence -- Portability : I'm too young to die -- Instances for dealing with the usual data. {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, OverloadedStrings, OverlappingInstances, ViewPatterns #-} module Network.NineP.File.Instances ( Convertible , ReadRef , WriteRef ) where import Control.Concurrent.Chan import Control.Monad import Control.Exception import Data.ByteString.Lazy.Char8 (ByteString) import qualified Data.ByteString.Lazy.Char8 as B import Data.Char import Data.Convertible.Base import Data.Convertible.Instances import Data.StateRef import Data.Typeable import Network.NineP.File -- How do I avoid writing that? trim xs = dropSpaceTail "" $ dropWhile isSpace xs dropSpaceTail maybeStuff "" = "" dropSpaceTail maybeStuff (x:xs) | isSpace x = dropSpaceTail (x:maybeStuff) xs | null maybeStuff = x : dropSpaceTail "" xs | otherwise = reverse maybeStuff ++ x : dropSpaceTail "" xs -- | @'read'@ in @'Maybe'@. safeRead :: (Read a) => String -> Maybe a safeRead (reads -> [(v,"")]) = Just v safeRead _ = Nothing instance Convertible ByteString ByteString where safeConvert = Right . id instance Convertible () ByteString where safeConvert x = convError "impossible to read that" x instance Convertible ByteString () where safeConvert _ = Right () instance Convertible ByteString Bool where safeConvert s | l == "1" = Right True | l == "true" = Right True | l == "0" = Right False | l == "false" = Right False | otherwise = convError "doesn't look like a boolean value" l where l = trim $ B.unpack s instance Convertible Bool ByteString where safeConvert True = Right "true" safeConvert False = Right "false" instance (Show a, Num a) => Convertible a ByteString where safeConvert = Right . B.pack . show instance (Read a, Num a, Typeable a) => Convertible ByteString a where safeConvert s = maybe (convError "doesn't look like an integral value" l) id $ liftM Right =<< safeRead l where l = trim $ B.unpack s -- TODO sane error instance ReadRef () m ByteString where readReference = throw $ Underflow instance Monad m => WriteRef () m ByteString where writeReference _ = return $ return () instance MonadIO m => ReadRef (Chan a) m a where readReference = liftIO . readChan instance MonadIO m => WriteRef (Chan a) m a where writeReference r = liftIO . writeChan r