    {-# LINE 1 "Data/Text/ICU/Enumerator.hsc" #-}
    {-# LANGUAGE EmptyDataDecls, BangPatterns, ForeignFunctionInterface, RecordWildCards #-}
    -- |
    -- Module      : Data.Text.ICU.Calendar
    -- Copyright   : (c) 2021 Torsten Kemps-Benedix
    --
    -- License     : BSD-style
    -- Maintainer  : bos@serpentine.com
    -- Stability   : experimental
    -- Portability : GHC
    --
    -- Calendar functions implemented as bindings to
    -- the International Components for Unicode (ICU) libraries.

    module Data.Text.ICU.Enumerator
        (next, toList, createEnumerator, Enumerator, UEnumerator,
        ) where

    import Data.Int (Int32)
    import Data.Text (Text)
    import Data.Text.ICU.Error.Internal (UErrorCode, handleError)
    import Data.Text.ICU.Internal (UChar, newICUPtr, fromUCharPtr)
    import Foreign.ForeignPtr (withForeignPtr, ForeignPtr)
    import Foreign.Marshal.Alloc (alloca)
    import Foreign.Ptr (FunPtr, Ptr, nullPtr)
    import Foreign.Storable (peek)
    import Prelude hiding (last)

    data UEnumerator

    newtype Enumerator = Enumerator {Enumerator -> ForeignPtr UEnumerator
    enumeratorToForeignPtr :: ForeignPtr UEnumerator}

    createEnumerator :: IO (Ptr UEnumerator) -> IO Enumerator
    createEnumerator :: IO (Ptr UEnumerator) -> IO Enumerator
    createEnumerator = (ForeignPtr UEnumerator -> Enumerator)
    -> FinalizerPtr UEnumerator
    -> IO (Ptr UEnumerator)
    -> IO Enumerator
    forall a i.
    (ForeignPtr a -> i) -> FinalizerPtr a -> IO (Ptr a) -> IO i
    newICUPtr ForeignPtr UEnumerator -> Enumerator
    Enumerator FinalizerPtr UEnumerator
    uenum_close

    next :: Enumerator -> IO (Maybe Text)
    next :: Enumerator -> IO (Maybe Text)
    next Enumerator
    enum = ForeignPtr UEnumerator
    -> (Ptr UEnumerator -> IO (Maybe Text)) -> IO (Maybe Text)
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr (Enumerator -> ForeignPtr UEnumerator
    enumeratorToForeignPtr Enumerator
    enum) ((Ptr UEnumerator -> IO (Maybe Text)) -> IO (Maybe Text))
    -> (Ptr UEnumerator -> IO (Maybe Text)) -> IO (Maybe Text)
    forall a b. (a -> b) -> a -> b
    $ \Ptr UEnumerator
    enumPtr ->
      (Ptr Int32 -> IO (Maybe Text)) -> IO (Maybe Text)
    forall a b. Storable a => (Ptr a -> IO b) -> IO b
    alloca ((Ptr Int32 -> IO (Maybe Text)) -> IO (Maybe Text))
    -> (Ptr Int32 -> IO (Maybe Text)) -> IO (Maybe Text)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Int32
    lenPtr -> do
        textPtr <- (Ptr UErrorCode -> IO (Ptr UChar)) -> IO (Ptr UChar)
    forall a. (Ptr UErrorCode -> IO a) -> IO a
    handleError ((Ptr UErrorCode -> IO (Ptr UChar)) -> IO (Ptr UChar))
    -> (Ptr UErrorCode -> IO (Ptr UChar)) -> IO (Ptr UChar)
    forall a b. (a -> b) -> a -> b
    $ Ptr UEnumerator -> Ptr Int32 -> Ptr UErrorCode -> IO (Ptr UChar)
    uenum_unext Ptr UEnumerator
    enumPtr Ptr Int32
    lenPtr
        if textPtr == nullPtr
          then pure Nothing
          else do
              n <- peek lenPtr
              t <- fromUCharPtr textPtr (fromIntegral n)
              pure $ Just t

    toList :: Enumerator -> IO [Text]
    toList :: Enumerator -> IO [Text]
    toList Enumerator
    enum = [Text] -> [Text]
    forall a. [a] -> [a]
    reverse ([Text] -> [Text]) -> IO [Text] -> IO [Text]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> [Text] -> IO [Text]
    go []
      where
        go :: [Text] -> IO [Text]
    go [Text]
    l = do
          mx <- Enumerator -> IO (Maybe Text)
    next Enumerator
    enum
          case mx of
            Maybe Text
    Nothing -> [Text] -> IO [Text]
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure [Text]
    l
            Just Text
    x -> [Text] -> IO [Text]
    go (Text
    xText -> [Text] -> [Text]
    forall a. a -> [a] -> [a]
    :[Text]
    l)

    foreign import ccall unsafe "hs_text_icu.h &__hs_uenum_close" uenum_close
        :: FunPtr (Ptr UEnumerator -> IO ())
    foreign import ccall unsafe "hs_text_icu.h __hs_uenum_unext" uenum_unext
        :: Ptr UEnumerator -> Ptr Int32 -> Ptr UErrorCode
        -> IO (Ptr UChar)