module Sound.MIDI.Parser.ByteString
(T(..), run, runIncomplete,
PossiblyIncomplete, UserMessage, ) where
import qualified Data.ByteString.Lazy as B
import qualified Data.Binary.Get as Binary
import Data.Binary.Get (Get, runGet, )
import Control.Monad.Trans.Class (lift, )
import Control.Monad (liftM, ap, )
import Control.Applicative (Applicative, pure, (<*>), )
import qualified Sound.MIDI.Parser.Report as Report
import qualified Sound.MIDI.Parser.Class as Parser
import Sound.MIDI.Parser.Class (UserMessage, PossiblyIncomplete, )
import qualified Sound.MIDI.Parser.Exception as Exception
import qualified Sound.MIDI.Parser.Warning as Warning
import Data.Int (Int64)
import qualified Numeric.NonNegative.Wrapper as NonNeg
import Prelude hiding (replicate, until, )
newtype T a = Cons {forall a. T a -> T Get a
decons :: Warning.T Get a}
run :: Parser.Fragile T a -> B.ByteString -> Report.T a
run :: forall a. Fragile T a -> ByteString -> T a
run Fragile T a
parser ByteString
input =
forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Get a -> ByteString -> a
runGet ByteString
input forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
Monad m =>
T m (Exceptional UserMessage a) -> m (T a)
Warning.run forall a b. (a -> b) -> a -> b
$ forall a. T a -> T Get a
decons forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
Monad m =>
T m a -> m (Exceptional UserMessage a)
Exception.run forall a b. (a -> b) -> a -> b
$
(do a
a <- Fragile T a
parser
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall a b. (a -> b) -> a -> b
$
forall (parser :: * -> *). EndCheck parser => parser Bool
Parser.isEnd forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Bool
end ->
forall (parser :: * -> *).
C parser =>
Bool -> UserMessage -> parser ()
Parser.warnIf (Bool -> Bool
not Bool
end) UserMessage
"unparsed data left over"
forall (m :: * -> *) a. Monad m => a -> m a
return a
a)
runIncomplete ::
Parser.Partial (Parser.Fragile T) a -> B.ByteString -> Report.T a
runIncomplete :: forall a.
Partial (ExceptionalT UserMessage T) a -> ByteString -> T a
runIncomplete Partial (ExceptionalT UserMessage T) a
parser ByteString
input =
forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Fragile T a -> ByteString -> T a
run ByteString
input forall a b. (a -> b) -> a -> b
$
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (parser :: * -> *) a.
C parser =>
PossiblyIncomplete a -> parser a
Parser.warnIncomplete forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Partial (ExceptionalT UserMessage T) a
parser
fromGet :: Get a -> T a
fromGet :: forall a. Get a -> T a
fromGet Get a
p =
forall a. T Get a -> T a
Cons forall a b. (a -> b) -> a -> b
$ forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift Get a
p
instance Functor T where
fmap :: forall a b. (a -> b) -> T a -> T b
fmap = forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM
instance Applicative T where
pure :: forall a. a -> T a
pure = forall (m :: * -> *) a. Monad m => a -> m a
return
<*> :: forall a b. T (a -> b) -> T a -> T b
(<*>) = forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Monad T where
return :: forall a. a -> T a
return = forall a. T Get a -> T a
Cons forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => a -> m a
return
T a
x >>= :: forall a b. T a -> (a -> T b) -> T b
>>= a -> T b
y = forall a. T Get a -> T a
Cons forall a b. (a -> b) -> a -> b
$ forall a. T a -> T Get a
decons forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> T b
y forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a. T a -> T Get a
decons T a
x
instance Parser.EndCheck T where
isEnd :: T Bool
isEnd = forall a. Get a -> T a
fromGet Get Bool
Binary.isEmpty
instance Parser.C T where
getByte :: Fragile T Word8
getByte =
do Bool
end <- forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall a b. (a -> b) -> a -> b
$ forall a. Get a -> T a
fromGet Get Bool
Binary.isEmpty
if Bool
end
then forall (m :: * -> *) a. Monad m => UserMessage -> T m a
Parser.giveUp UserMessage
"unexpected end of ByteString"
else forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall a b. (a -> b) -> a -> b
$ forall a. Get a -> T a
fromGet Get Word8
Binary.getWord8
skip :: Integer -> ExceptionalT UserMessage T ()
skip Integer
n =
let toSize :: p -> a
toSize p
x =
let y :: a
y = if p
x forall a. Ord a => a -> a -> Bool
> forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bounded a => a
maxBound forall a. a -> a -> a
`asTypeOf` a
y)
then forall a. HasCallStack => UserMessage -> a
error UserMessage
"skip: number too big"
else forall a b. (Integral a, Num b) => a -> b
fromIntegral p
x
in a
y
in forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift forall a b. (a -> b) -> a -> b
$ forall a. Get a -> T a
fromGet forall a b. (a -> b) -> a -> b
$ Int64 -> Get ()
skip forall a b. (a -> b) -> a -> b
$ forall {a} {p}. (Bounded a, Integral a, Integral p) => p -> a
toSize forall a b. (a -> b) -> a -> b
$ forall a. T a -> a
NonNeg.toNumber Integer
n
warn :: UserMessage -> T ()
warn = forall a. T Get a -> T a
Cons forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *). Monad m => UserMessage -> T m ()
Warning.warn
skip :: Int64 -> Get ()
skip :: Int64 -> Get ()
skip Int64
n = Int64 -> Get ByteString
Binary.getLazyByteString Int64
n forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return ()