module Rattletrap.Type.List where

import qualified Control.Monad as Monad
import qualified Rattletrap.ByteGet as ByteGet
import qualified Rattletrap.BytePut as BytePut
import qualified Rattletrap.Schema as Schema
import qualified Rattletrap.Type.U32 as U32
import qualified Rattletrap.Utility.Json as Json

newtype List a
  = List [a]
  deriving (List a -> List a -> Bool
forall a. Eq a => List a -> List a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: List a -> List a -> Bool
$c/= :: forall a. Eq a => List a -> List a -> Bool
== :: List a -> List a -> Bool
$c== :: forall a. Eq a => List a -> List a -> Bool
Eq, Int -> List a -> ShowS
forall a. Show a => Int -> List a -> ShowS
forall a. Show a => [List a] -> ShowS
forall a. Show a => List a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [List a] -> ShowS
$cshowList :: forall a. Show a => [List a] -> ShowS
show :: List a -> String
$cshow :: forall a. Show a => List a -> String
showsPrec :: Int -> List a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> List a -> ShowS
Show)

instance (Json.FromJSON a) => Json.FromJSON (List a) where
  parseJSON :: Value -> Parser (List a)
parseJSON = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. [a] -> List a
fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. FromJSON a => Value -> Parser a
Json.parseJSON

instance (Json.ToJSON a) => Json.ToJSON (List a) where
  toJSON :: List a -> Value
toJSON = forall a. ToJSON a => a -> Value
Json.toJSON forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. List a -> [a]
toList

schema :: Schema.Schema -> Schema.Schema
schema :: Schema -> Schema
schema = Schema -> Schema
Schema.array

fromList :: [a] -> List a
fromList :: forall a. [a] -> List a
fromList = forall a. [a] -> List a
List

empty :: List a
empty :: forall a. List a
empty = forall a. [a] -> List a
fromList []

toList :: List a -> [a]
toList :: forall a. List a -> [a]
toList (List [a]
x) = [a]
x

bytePut :: (a -> BytePut.BytePut) -> List a -> BytePut.BytePut
bytePut :: forall a. (a -> BytePut) -> List a -> BytePut
bytePut a -> BytePut
f List a
x =
  let v :: [a]
v = forall a. List a -> [a]
toList List a
x
   in (U32 -> BytePut
U32.bytePut forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word32 -> U32
U32.fromWord32 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
v) forall a. Semigroup a => a -> a -> a
<> forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> BytePut
f [a]
v

byteGet :: ByteGet.ByteGet a -> ByteGet.ByteGet (List a)
byteGet :: forall a. ByteGet a -> ByteGet (List a)
byteGet ByteGet a
f = forall a. String -> ByteGet a -> ByteGet a
ByteGet.label String
"List" forall a b. (a -> b) -> a -> b
$ do
  U32
size <- forall a. String -> ByteGet a -> ByteGet a
ByteGet.label String
"size" ByteGet U32
U32.byteGet
  forall (m :: * -> *) a.
Monad m =>
Int -> (Int -> m a) -> m (List a)
generateM (forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ U32 -> Word32
U32.toWord32 U32
size) forall a b. (a -> b) -> a -> b
$
    \Int
i -> forall a. String -> ByteGet a -> ByteGet a
ByteGet.label (String
"element (" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show Int
i forall a. Semigroup a => a -> a -> a
<> String
")") ByteGet a
f

generateM :: (Monad m) => Int -> (Int -> m a) -> m (List a)
generateM :: forall (m :: * -> *) a.
Monad m =>
Int -> (Int -> m a) -> m (List a)
generateM Int
n Int -> m a
f = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. [a] -> List a
fromList forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Int -> m a
f [Int
0 .. Int
n forall a. Num a => a -> a -> a
- Int
1]

replicateM :: (Monad m) => Int -> m a -> m (List a)
replicateM :: forall (m :: * -> *) a. Monad m => Int -> m a -> m (List a)
replicateM Int
n = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. [a] -> List a
fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
Monad.replicateM Int
n

untilM :: (Monad m) => m (Maybe a) -> m (List a)
untilM :: forall (m :: * -> *) a. Monad m => m (Maybe a) -> m (List a)
untilM m (Maybe a)
f = forall (m :: * -> *) a.
Monad m =>
m (Maybe a) -> Int -> [(Int, a)] -> m (List a)
untilMWith m (Maybe a)
f Int
0 []

untilMWith :: (Monad m) => m (Maybe a) -> Int -> [(Int, a)] -> m (List a)
untilMWith :: forall (m :: * -> *) a.
Monad m =>
m (Maybe a) -> Int -> [(Int, a)] -> m (List a)
untilMWith m (Maybe a)
f Int
i [(Int, a)]
xs = do
  Maybe a
m <- m (Maybe a)
f
  case Maybe a
m of
    Maybe a
Nothing -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> List a
fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
reverse forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> b
snd [(Int, a)]
xs
    Just a
x -> forall (m :: * -> *) a.
Monad m =>
m (Maybe a) -> Int -> [(Int, a)] -> m (List a)
untilMWith m (Maybe a)
f (Int
i forall a. Num a => a -> a -> a
+ Int
1) ((Int
i, a
x) forall a. a -> [a] -> [a]
: [(Int, a)]
xs)