module Bio.SeqLoc.LocRepr
( LocRepr(..), reprStr
, unreprMaybe, unreprEither, unreprErr
)
where
import Control.Applicative
import qualified Data.ByteString as BSW
import qualified Data.ByteString.Char8 as BS
import qualified Data.Attoparsec.Char8 as AP (isDigit_w8)
import qualified Data.Attoparsec.Zepto as ZP
import Bio.Core.Sequence
import Bio.Core.Strand
class LocRepr l where
repr :: l -> BS.ByteString
unrepr :: ZP.Parser l
reprStr :: (LocRepr l) => l -> String
reprStr = BS.unpack . repr
unreprMaybe :: (LocRepr l) => BS.ByteString -> Maybe l
unreprMaybe = either (const Nothing) Just . ZP.parse unrepr
unreprEither :: (LocRepr l) => BS.ByteString -> Either String l
unreprEither = ZP.parse unrepr
unreprErr :: (LocRepr l) => BS.ByteString -> l
unreprErr = either error id . ZP.parse unrepr
instance LocRepr Strand where
repr Plus = BS.pack "(+)"
repr Minus = BS.pack "(-)"
unrepr = (ZP.string "(+)" *> return Plus) <|>
(ZP.string "(-)" *> return Minus)
instance LocRepr Offset where
repr = BS.pack . show . unOff
unrepr = (negate <$> (ZP.string "-" *> decimal)) <|> (ZP.string "+" *> decimal) <|> decimal
where decimal = Offset . BSW.foldl' step 0 <$> ZP.takeWhile AP.isDigit_w8
step a w = a * 10 + fromIntegral (w 48)