{-# LANGUAGE OverloadedStrings #-} 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)