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 (Eq, Show) instance Json.FromJSON a => Json.FromJSON (List a) where parseJSON = fmap fromList . Json.parseJSON instance Json.ToJSON a => Json.ToJSON (List a) where toJSON = Json.toJSON . toList schema :: Schema.Schema -> Schema.Schema schema = Schema.array fromList :: [a] -> List a fromList = List empty :: List a empty = fromList [] toList :: List a -> [a] toList (List x) = x bytePut :: (a -> BytePut.BytePut) -> List a -> BytePut.BytePut bytePut f x = let v = toList x in (U32.bytePut . U32.fromWord32 . fromIntegral $ length v) <> foldMap f v byteGet :: ByteGet.ByteGet a -> ByteGet.ByteGet (List a) byteGet f = ByteGet.label "List" $ do size <- ByteGet.label "size" U32.byteGet generateM (fromIntegral $ U32.toWord32 size) $ \i -> ByteGet.label ("element (" <> show i <> ")") f generateM :: Monad m => Int -> (Int -> m a) -> m (List a) generateM n f = fmap fromList $ mapM f [0 .. n - 1] replicateM :: Monad m => Int -> m a -> m (List a) replicateM n = fmap fromList . Monad.replicateM n untilM :: Monad m => m (Maybe a) -> m (List a) untilM f = untilMWith f 0 [] untilMWith :: Monad m => m (Maybe a) -> Int -> [(Int, a)] -> m (List a) untilMWith f i xs = do m <- f case m of Nothing -> pure . fromList . reverse $ fmap snd xs Just x -> untilMWith f (i + 1) ((i, x) : xs)