-- |
-- General utilities for immutable vectors.
module OpcXmlDaClient.Base.Vector where

import Data.Vector.Generic
import qualified Data.Vector.Generic.Mutable as M
import qualified OpcXmlDaClient.Base.MVector as M
import OpcXmlDaClient.Base.Prelude hiding (Vector)

-- |
-- >>> fromReverseListN 3 [1,2,3] :: Data.Vector.Vector Int
-- [3,2,1]
{-# INLINE fromReverseListN #-}
fromReverseListN :: Vector v a => Int -> [a] -> v a
fromReverseListN :: Int -> [a] -> v a
fromReverseListN Int
size [a]
list =
  Int -> (forall s. Mutable v s a -> ST s ()) -> v a
forall (v :: * -> *) a.
Vector v a =>
Int -> (forall s. Mutable v s a -> ST s ()) -> v a
initialized Int
size ((forall s. Mutable v s a -> ST s ()) -> v a)
-> (forall s. Mutable v s a -> ST s ()) -> v a
forall a b. (a -> b) -> a -> b
$ \Mutable v s a
mv -> Mutable v s a -> Int -> [a] -> ST s ()
forall (v :: * -> * -> *) a s.
MVector v a =>
v s a -> Int -> [a] -> ST s ()
M.writeListInReverseOrderStartingFrom Mutable v s a
mv (Int -> Int
forall a. Enum a => a -> a
pred Int
size) [a]
list

{-# INLINE initialized #-}
initialized :: Vector v a => Int -> (forall s. Mutable v s a -> ST s ()) -> v a
initialized :: Int -> (forall s. Mutable v s a -> ST s ()) -> v a
initialized Int
size forall s. Mutable v s a -> ST s ()
initialize = (forall s. ST s (v a)) -> v a
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (v a)) -> v a) -> (forall s. ST s (v a)) -> v a
forall a b. (a -> b) -> a -> b
$ do
  Mutable v s a
mv <- Int -> ST s (Mutable v (PrimState (ST s)) a)
forall (m :: * -> *) (v :: * -> * -> *) a.
(PrimMonad m, MVector v a) =>
Int -> m (v (PrimState m) a)
M.unsafeNew Int
size
  Mutable v s a -> ST s ()
forall s. Mutable v s a -> ST s ()
initialize Mutable v s a
mv
  Mutable v (PrimState (ST s)) a -> ST s (v a)
forall (m :: * -> *) (v :: * -> *) a.
(PrimMonad m, Vector v a) =>
Mutable v (PrimState m) a -> m (v a)
unsafeFreeze Mutable v s a
Mutable v (PrimState (ST s)) a
mv

-- |
-- Efficiently build a vector with the @many@ pattern.
many :: (MonadPlus m, Vector v a) => m a -> m (v a)
many :: m a -> m (v a)
many m a
produce =
  (Int -> m a) -> m (v a)
forall (m :: * -> *) (v :: * -> *) a.
(MonadPlus m, Vector v a) =>
(Int -> m a) -> m (v a)
manyWithIndex (m a -> Int -> m a
forall a b. a -> b -> a
const m a
produce)

manyWithIndex :: (MonadPlus m, Vector v a) => (Int -> m a) -> m (v a)
manyWithIndex :: (Int -> m a) -> m (v a)
manyWithIndex Int -> m a
produce =
  [a] -> Int -> m (v a)
build [] Int
0
  where
    build :: [a] -> Int -> m (v a)
build [a]
list !Int
size =
      m (v a)
step m (v a) -> m (v a) -> m (v a)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m (v a)
finish
      where
        step :: m (v a)
step =
          Int -> m a
produce Int
size m a -> (a -> m (v a)) -> m (v a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
a -> [a] -> Int -> m (v a)
build (a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
list) (Int -> Int
forall a. Enum a => a -> a
succ Int
size)
        finish :: m (v a)
finish =
          v a -> m (v a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int -> [a] -> v a
forall (v :: * -> *) a. Vector v a => Int -> [a] -> v a
fromReverseListN Int
size [a]
list)

manyWithIndexTerminating :: (MonadPlus m, Vector v a) => (Int -> m (Either e a)) -> m (Either e (v a))
manyWithIndexTerminating :: (Int -> m (Either e a)) -> m (Either e (v a))
manyWithIndexTerminating Int -> m (Either e a)
produce =
  [a] -> Int -> m (Either e (v a))
build [] Int
0
  where
    build :: [a] -> Int -> m (Either e (v a))
build [a]
list !Int
size =
      m (Either e (v a))
step m (Either e (v a)) -> m (Either e (v a)) -> m (Either e (v a))
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m (Either e (v a))
finish
      where
        step :: m (Either e (v a))
step =
          Int -> m (Either e a)
produce Int
size m (Either e a)
-> (Either e a -> m (Either e (v a))) -> m (Either e (v a))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
            Right a
a -> [a] -> Int -> m (Either e (v a))
build (a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
list) (Int -> Int
forall a. Enum a => a -> a
succ Int
size)
            Left e
a -> Either e (v a) -> m (Either e (v a))
forall (m :: * -> *) a. Monad m => a -> m a
return (e -> Either e (v a)
forall a b. a -> Either a b
Left e
a)
        finish :: m (Either e (v a))
finish =
          Either e (v a) -> m (Either e (v a))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (v a -> Either e (v a)
forall a b. b -> Either a b
Right (Int -> [a] -> v a
forall (v :: * -> *) a. Vector v a => Int -> [a] -> v a
fromReverseListN Int
size [a]
list))