packages feed

streamly-core 0.2.2 → 0.2.3

raw patch · 16 files changed

+174/−106 lines, 16 filesdep ~basedep ~ghc-primdep ~template-haskell

Dependency ranges changed: base, ghc-prim, template-haskell

Files

Changelog.md view
@@ -1,5 +1,10 @@ # Changelog +## 0.2.3 (Feb 2025)++* Fix breakOn/lines in the Array module.+* Support GHC 9.12+ ## 0.2.2 (Jan 2024)  * Add fixities `infixr 5` for `cons` and `consM` functions.
configure view
@@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles.-# Generated by GNU Autoconf 2.71 for streamly-core 0.2.2.+# Generated by GNU Autoconf 2.71 for streamly-core 0.2.3. # # Report bugs to <streamly@composewell.com>. #@@ -610,8 +610,8 @@ # Identity of this package. PACKAGE_NAME='streamly-core' PACKAGE_TARNAME='streamly-core'-PACKAGE_VERSION='0.2.2'-PACKAGE_STRING='streamly-core 0.2.2'+PACKAGE_VERSION='0.2.3'+PACKAGE_STRING='streamly-core 0.2.3' PACKAGE_BUGREPORT='streamly@composewell.com' PACKAGE_URL='https://streamly.composewell.com' @@ -1256,7 +1256,7 @@   # Omit some internal or obsolete options to make the list less imposing.   # This message is too long to be a string in the A/UX 3.1 sh.   cat <<_ACEOF-\`configure' configures streamly-core 0.2.2 to adapt to many kinds of systems.+\`configure' configures streamly-core 0.2.3 to adapt to many kinds of systems.  Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1318,7 +1318,7 @@  if test -n "$ac_init_help"; then   case $ac_init_help in-     short | recursive ) echo "Configuration of streamly-core 0.2.2:";;+     short | recursive ) echo "Configuration of streamly-core 0.2.3:";;    esac   cat <<\_ACEOF @@ -1404,7 +1404,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then   cat <<\_ACEOF-streamly-core configure 0.2.2+streamly-core configure 0.2.3 generated by GNU Autoconf 2.71  Copyright (C) 2021 Free Software Foundation, Inc.@@ -1622,7 +1622,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by streamly-core $as_me 0.2.2, which was+It was created by streamly-core $as_me 0.2.3, which was generated by GNU Autoconf 2.71.  Invocation command line was    $ $0$ac_configure_args_raw@@ -3832,7 +3832,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log="-This file was extended by streamly-core $as_me 0.2.2, which was+This file was extended by streamly-core $as_me 0.2.3, which was generated by GNU Autoconf 2.71.  Invocation command line was    CONFIG_FILES    = $CONFIG_FILES@@ -3888,7 +3888,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\-streamly-core config.status 0.2.2+streamly-core config.status 0.2.3 configured by $0, generated by GNU Autoconf 2.71,   with options \\"\$ac_cs_config\\" 
configure.ac view
@@ -3,7 +3,7 @@ # See https://www.gnu.org/software/autoconf/manual/autoconf.html for help on # the macros used in this file. -AC_INIT([streamly-core], [0.2.2], [streamly@composewell.com], [streamly-core], [https://streamly.composewell.com])+AC_INIT([streamly-core], [0.2.3], [streamly@composewell.com], [streamly-core], [https://streamly.composewell.com])  # To suppress "WARNING: unrecognized options: --with-compiler" AC_ARG_WITH([compiler], [GHC])
+ docs/ApiChangelogs/0.2.2-0.2.3.txt view
@@ -0,0 +1,28 @@+---------------------------------+API Annotations+---------------------------------++[A] : Added+[R] : Removed+[C] : Changed+[O] : Old definition+[N] : New definition+[D] : Deprecated++---------------------------------+API diff+---------------------------------++++---------------------------------+Internal API diff+---------------------------------++[C] Streamly.Internal.Data.MutByteArray+    [D] unsafePinnedAsPtr :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b+[C] Streamly.Internal.Data.MutArray+    [D] unsafePinnedAsPtr :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b+    [D] memcpy :: Ptr Word8 -> Ptr Word8 -> Int -> IO ()+    [D] memcmp :: Ptr Word8 -> Ptr Word8 -> Int -> IO Bool+    [D] c_memchr :: Ptr Word8 -> Word8 -> CSize -> IO (Ptr Word8)
docs/Changelog.md view
@@ -1,5 +1,10 @@ # Changelog +## 0.2.3 (Feb 2025)++* Fix breakOn/lines in the Array module.+* Support GHC 9.12+ ## 0.2.2 (Jan 2024)  * Add fixities `infixr 5` for `cons` and `consM` functions.
src/Streamly/Internal/Data/Array/Type.hs view
@@ -247,7 +247,10 @@ -- {-# INLINE unsafePinnedAsPtr #-} unsafePinnedAsPtr :: MonadIO m => Array a -> (Ptr a -> m b) -> m b-unsafePinnedAsPtr arr = MA.unsafePinnedAsPtr (unsafeThaw arr)+unsafePinnedAsPtr arr f = do+    let marr = unsafeThaw arr+    pinned <- liftIO $ MA.pin marr+    MA.unsafeAsPtr pinned f  {-# DEPRECATED asPtrUnsafe "Please use unsafePinnedAsPtr instead." #-} {-# INLINE asPtrUnsafe #-}
+ src/Streamly/Internal/Data/MutArray/Lib.c view
@@ -0,0 +1,15 @@+#include <string.h>++// Find the char "c" starting from "dst+off" and up to "len" chars from+// it, returns the index of the character found, considering dst + off+// as the base pointer. If index is greater than or equal to len the+// char is not found.+size_t memchr_index(const void *dst, size_t off, int c, size_t len) {+    void *p = memchr ((char *)dst + off, c, len);++    if (p) {+        return (size_t) (p - dst - off);+    } else {+        return len;+    }+}
src/Streamly/Internal/Data/MutArray/Type.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UnliftedFFITypes #-} -- | -- Module      : Streamly.Internal.Data.MutArray.Type -- Copyright   : (c) 2020 Composewell Technologies@@ -313,8 +314,9 @@ import Data.Functor.Identity (Identity(..)) import Data.Proxy (Proxy(..)) import Data.Word (Word8)-import Foreign.C.Types (CSize(..), CInt(..))-import Foreign.Ptr (plusPtr, minusPtr, nullPtr)+import Foreign.C.Types (CSize(..))+import Foreign.Ptr (plusPtr)+import Foreign.C.Types (CInt(..)) import Streamly.Internal.Data.MutByteArray.Type     ( MutByteArray(..)     , PinnedState(..)@@ -329,7 +331,7 @@     , copyMutableByteArray#     ) import GHC.Base (noinline)-import GHC.Exts (unsafeCoerce#, Addr#)+import GHC.Exts (unsafeCoerce#, Addr#, MutableByteArray#, RealWorld) import GHC.Ptr (Ptr(..))  import Streamly.Internal.Data.Fold.Type (Fold(..))@@ -362,17 +364,14 @@ -------------------------------------------------------------------------------  -- NOTE: Have to be "ccall unsafe" so that we can pass unpinned memory to these-foreign import ccall unsafe "string.h memcpy" c_memcpy-    :: Ptr Word8 -> Ptr Word8 -> CSize -> IO (Ptr Word8)--foreign import ccall unsafe "string.h memchr" c_memchr-    :: Ptr Word8 -> Word8 -> CSize -> IO (Ptr Word8)+foreign import ccall unsafe "string.h memcpy" c_memcpy_pinned_src+    :: MutableByteArray# RealWorld -> Ptr Word8 -> CSize -> IO (Ptr Word8) -foreign import ccall unsafe "string.h memcmp" c_memcmp-    :: Ptr Word8 -> Ptr Word8 -> CSize -> IO CInt+foreign import ccall unsafe "memchr_index" c_memchr_index+    :: MutableByteArray# RealWorld -> CSize -> Word8 -> CSize -> IO CSize -foreign import ccall unsafe "string.h strlen" c_strlen-    :: Ptr Word8 -> IO CSize+foreign import ccall unsafe "string.h strlen" c_strlen_pinned+    :: Addr# -> IO CSize  -- | Given an 'Unboxed' type (unused first arg) and a number of bytes, return -- how many elements of that type will completely fit in those bytes.@@ -381,18 +380,6 @@ bytesToElemCount :: forall a. Unbox a => a -> Int -> Int bytesToElemCount _ n = n `div` SIZE_OF(a) --- XXX we are converting Int to CSize-memcpy :: Ptr Word8 -> Ptr Word8 -> Int -> IO ()-memcpy dst src len = void (c_memcpy dst src (fromIntegral len))---- XXX we are converting Int to CSize--- return True if the memory locations have identical contents-{-# INLINE memcmp #-}-memcmp :: Ptr Word8 -> Ptr Word8 -> Int -> IO Bool-memcmp p1 p2 len = do-    r <- c_memcmp p1 p2 (fromIntegral len)-    return $ r == 0- ------------------------------------------------------------------------------- -- MutArray Data Type -------------------------------------------------------------------------------@@ -2439,10 +2426,10 @@     -- memcpy is better than stream copy when the size is known.     -- XXX We can implement a stream copy in a similar way by streaming Word64     -- first and then remaining Word8.-    arr <- new len-    _ <- unsafeAsPtr arr-            (\ptr -> liftIO $ c_memcpy ptr addr (fromIntegral len))-    return (arr {arrEnd = len})+    (arr :: MutArray Word8) <- emptyOf len+    let mbarr = getMutableByteArray# (arrContents arr)+    _ <- liftIO $ c_memcpy_pinned_src mbarr addr (fromIntegral len)+    pure (arr { arrEnd = len })  {-# INLINABLE fromByteStr# #-} fromByteStr# :: MonadIO m => Addr# -> m (MutArray Word8)@@ -2453,11 +2440,8 @@     -- version. https://github.com/bminor/glibc/blob/master/string/strlen.c     -- XXX We can possibly use a stream of Word64 to do the same.     -- fromByteStr# addr = fromPureStream (D.fromByteStr# addr)-    len <- liftIO $ c_strlen (Ptr addr)-    let lenInt = fromIntegral len-    arr <- new lenInt-    _ <- unsafeAsPtr arr (\ptr -> liftIO $ c_memcpy ptr (Ptr addr) len)-    return (arr {arrEnd = lenInt})+    len <- liftIO $ c_strlen_pinned addr+    fromPtrN (fromIntegral len) (Ptr addr)  ------------------------------------------------------------------------------- -- convert a stream of arrays to a single array by reallocating and copying@@ -2744,24 +2728,26 @@ {-# INLINE breakOn #-} breakOn :: MonadIO m     => Word8 -> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))-breakOn sep arr@MutArray{..} = unsafeAsPtr arr $ \p -> liftIO $ do+breakOn sep arr@MutArray{..} = liftIO $ do     -- XXX We do not need memchr here, we can use a Haskell equivalent.     -- Need efficient stream based primitives that work on Word64.-    loc <- c_memchr p sep (fromIntegral $ byteLength arr)-    let sepIndex = loc `minusPtr` p+    let marr = getMutableByteArray# arrContents+        len = fromIntegral (arrEnd - arrStart)+    sepIndex <- c_memchr_index marr (fromIntegral arrStart) sep len+    let intIndex = fromIntegral sepIndex     return $-        if loc == nullPtr+        if sepIndex >= len         then (arr, Nothing)         else             ( MutArray                 { arrContents = arrContents                 , arrStart = arrStart-                , arrEnd = arrStart + sepIndex -- exclude the separator-                , arrBound = arrStart + sepIndex+                , arrEnd = arrStart + intIndex -- exclude the separator+                , arrBound = arrStart + intIndex                 }             , Just $ MutArray                     { arrContents = arrContents-                    , arrStart = arrStart + (sepIndex + 1)+                    , arrStart = arrStart + (intIndex + 1)                     , arrEnd = arrEnd                     , arrBound = arrBound                     }@@ -2859,33 +2845,31 @@ -- available e.g. a null terminated C string. However, we can create another -- flavor of the API e.g. asPtrN. --- | Use a @MutArray a@ as @Ptr a@. This is useful when we want to pass an--- array as a pointer to some operating system call or to a "safe" FFI call.------ If the array is not pinned it is copied to pinned memory before passing it--- to the monadic action.------ /Performance Notes:/ Forces a copy if the array is not pinned. It is advised--- that the programmer keeps this in mind and creates a pinned array--- opportunistically before this operation occurs, to avoid the cost of a copy--- if possible.------ /Unsafe/ because of direct pointer operations. The user must ensure that--- they are writing within the legal bounds of the array.------ /Pre-release/---+-- | NOTE: this is deprecated because it can lead to accidental problems if the+-- user tries to use it to mutate the array because it does not return the new+-- array after pinning.+{-# DEPRECATED unsafePinnedAsPtr "Pin the array and then use unsafeAsPtr." #-} {-# INLINE unsafePinnedAsPtr #-} unsafePinnedAsPtr :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b-unsafePinnedAsPtr arr f =-    Unboxed.unsafePinnedAsPtr-        (arrContents arr) (\ptr -> f (ptr `plusPtr` arrStart arr))+unsafePinnedAsPtr arr f = do+    arr1 <- liftIO $ Unboxed.pin (arrContents arr)+    Unboxed.unsafeAsPtr arr1 (\ptr -> f (ptr `plusPtr` arrStart arr)) -{-# DEPRECATED asPtrUnsafe "Please use unsafePinnedAsPtr instead." #-}+{-# DEPRECATED asPtrUnsafe "Pin the array and then use unsafeAsPtr." #-} {-# INLINE asPtrUnsafe #-} asPtrUnsafe :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b asPtrUnsafe = unsafePinnedAsPtr +-- | @unsafeAsPtr arr f@, f is a function used as @f ptr len@ where @ptr@ is a+-- pointer to the beginning of array and @len@ is the length of the array.+--+-- /Unsafe/ WARNING:+--+-- 1. The array must be pinned, otherwise it will lead to memory corruption.+-- 2. The user must not use the pointer beyond the supplied length.+--+-- /Pre-release/+-- {-# INLINE unsafeAsPtr #-} unsafeAsPtr :: MonadIO m => MutArray a -> (Ptr a -> m b) -> m b unsafeAsPtr arr f =@@ -3316,3 +3300,28 @@                         go x (i - 1)                     _ -> putIndexUnsafe (i + 1) arr x             else putIndexUnsafe (i + 1) arr x++--------------------------------------------------------------------------------+-- Deprecated Foreign APIs+--------------------------------------------------------------------------------++foreign import ccall unsafe "string.h memcpy" c_memcpy+    :: Ptr Word8 -> Ptr Word8 -> CSize -> IO (Ptr Word8)++{-# DEPRECATED c_memchr "c_memchr is now deprecated." #-}+foreign import ccall unsafe "string.h memchr" c_memchr+    :: Ptr Word8 -> Word8 -> CSize -> IO (Ptr Word8)++foreign import ccall unsafe "string.h memcmp" c_memcmp+    :: Ptr Word8 -> Ptr Word8 -> CSize -> IO CInt++{-# DEPRECATED memcpy "Use copyMutableByteArray# instead." #-}+memcpy :: Ptr Word8 -> Ptr Word8 -> Int -> IO ()+memcpy dst src len = void (c_memcpy dst src (fromIntegral len))++{-# DEPRECATED memcmp "Use byteCmp instead." #-}+{-# INLINE memcmp #-}+memcmp :: Ptr Word8 -> Ptr Word8 -> Int -> IO Bool+memcmp p1 p2 len = do+    r <- c_memcmp p1 p2 (fromIntegral len)+    return $ r == 0
src/Streamly/Internal/Data/MutByteArray/Type.hs view
@@ -12,7 +12,6 @@     (     -- ** MutByteArray       MutByteArray(..)-    , MutableByteArray     , getMutableByteArray# -- XXX getMutByteArray#      -- ** Pinning@@ -38,13 +37,14 @@     , unsafeAsPtr      -- ** Deprecated+    , MutableByteArray     , asPtrUnsafe     , nil     ) where  import Control.Monad.IO.Class (MonadIO(..))-#ifdef DEBUG import Control.Monad (when)+#ifdef DEBUG import Debug.Trace (trace) #endif import GHC.Base (IO(..))@@ -102,31 +102,15 @@ -- guarantees that unsafe calls will be performed in the calling thread. Making -- it safe to pass heap-allocated objects to unsafe functions. --- | Use a @MutByteArray@ as @Ptr a@. This is useful when we want to pass--- an array as a pointer to some operating system call or to a "safe" FFI call.------ If the array is not pinned it is copied to pinned memory before passing it--- to the monadic action.------ /Performance Notes:/ Forces a copy if the array is not pinned. It is advised--- that the programmer keeps this in mind and creates a pinned array--- opportunistically before this operation occurs, to avoid the cost of a copy--- if possible.------ /Unsafe/ because of direct pointer operations. The user must ensure that--- they are writing within the legal bounds of the array.------ /Pre-release/---+-- | NOTE: this is deprecated because it can lead to accidental problems if the+-- user tries to use it to mutate the array because it does not return the new+-- array after pinning.+{-# DEPRECATED unsafePinnedAsPtr "Pin the array and then use unsafeAsPtr." #-} {-# INLINE unsafePinnedAsPtr #-} unsafePinnedAsPtr :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b unsafePinnedAsPtr arr f = do-  contents <- liftIO $ pin arr-  let !ptr = Ptr (byteArrayContents#-                     (unsafeCoerce# (getMutableByteArray# contents)))-  r <- f ptr-  liftIO $ touch contents-  return r+    arr1 <- liftIO $ pin arr+    unsafeAsPtr arr1 f  {-# DEPRECATED asPtrUnsafe "Please use unsafePinnedAsPtr instead." #-} {-# INLINE asPtrUnsafe #-}@@ -137,11 +121,15 @@ {-# INLINE unsafeAsPtr #-} unsafeAsPtr :: MonadIO m => MutByteArray -> (Ptr a -> m b) -> m b unsafeAsPtr arr f = do-  let !ptr = Ptr (byteArrayContents#+    when (not (isPinned arr))+        $ error "unsafeAsPtr requires the array to be pinned"+    let !ptr = Ptr (byteArrayContents#                      (unsafeCoerce# (getMutableByteArray# arr)))-  r <- f ptr-  liftIO $ touch arr-  return r+    r <- f ptr+    -- While f is using the bare pointer, the MutByteArray may be garbage+    -- collected by the GC, tell the GC that we are still using it.+    liftIO $ touch arr+    return r  -------------------------------------------------------------------------------- -- Creation
src/Streamly/Internal/Data/Serialize/TH.hs view
@@ -28,6 +28,7 @@  import Data.List (foldl') import Data.Word (Word16, Word32, Word64, Word8)+import Data.Foldable (length)  import Language.Haskell.TH import Language.Haskell.TH.Syntax@@ -44,6 +45,7 @@ import Streamly.Internal.Data.Serialize.TH.Bottom import Streamly.Internal.Data.Serialize.TH.Common import Streamly.Internal.Data.Serialize.TH.RecHeader+import Prelude hiding (Foldable(..))  -------------------------------------------------------------------------------- -- Domain specific helpers
src/Streamly/Internal/Data/Serialize/TH/Bottom.hs view
@@ -57,6 +57,7 @@ import Data.Maybe (isJust) import Data.Char (chr, ord) import Data.List (foldl')+import Data.Foldable (length) import Data.Word (Word16, Word32, Word64, Word8) import Data.Bits (Bits, (.|.), shiftL, zeroBits, xor) import Streamly.Internal.System.IO (unsafeInlineIO)@@ -69,6 +70,7 @@ import qualified Streamly.Internal.Data.Unbox as Unbox  import Streamly.Internal.Data.Unbox.TH (DataCon(..))+import Prelude hiding (Foldable(..))  -------------------------------------------------------------------------------- -- Config
src/Streamly/Internal/Data/Serialize/TH/RecHeader.hs view
@@ -22,6 +22,7 @@  import Control.Monad (void) import Data.List (foldl')+import Data.Foldable (length, sum) import Data.Word (Word32, Word8) import Data.Maybe (fromJust) import Language.Haskell.TH@@ -34,6 +35,7 @@  import Streamly.Internal.Data.Serialize.TH.Bottom import Streamly.Internal.Data.Serialize.TH.Common+import Prelude hiding (Foldable(..))  -------------------------------------------------------------------------------- -- Notes@@ -353,7 +355,7 @@                      ([], dataOff)                      keys              $(varP finalRec) <--                 $(foldl+                 $(foldl'                        (\acc i ->                             [|$(acc) <*>                               $(deserializeFieldExpr i)|])
src/Streamly/Internal/Data/Serialize/Type.hs view
@@ -31,6 +31,7 @@ import qualified Streamly.Internal.Data.MutArray as MutArray  import GHC.Exts+import Prelude hiding (Foldable(..))  -------------------------------------------------------------------------------- -- Developer Note
src/Streamly/Internal/Data/Unbox.hs view
@@ -54,7 +54,9 @@ import GHC.Real (Ratio(..)) import GHC.Stable (StablePtr(..)) import GHC.Word (Word16(..), Word32(..), Word64(..), Word8(..))-#if MIN_VERSION_base(4,15,0)+#if MIN_VERSION_base(4,21,0)+import GHC.IO.SubSystem (IoSubSystem (..))+#elif MIN_VERSION_base(4,15,0) import GHC.RTS.Flags (IoSubSystem(..)) #endif import Streamly.Internal.Data.Builder (Builder (..))
src/Streamly/Internal/FileSystem/Handle.hs view
@@ -179,7 +179,8 @@ getChunk size h = liftIO $ do     arr :: MArray.MutArray Word8 <- MArray.pinnedEmptyOf size     -- ptr <- mallocPlainForeignPtrAlignedBytes size (alignment (undefined :: Word8))-    MArray.unsafePinnedAsPtr arr $ \p -> do+    -- Since the array is pinned (pinnedEmptyOf) we can safely use unsafeAsPtr+    MArray.unsafeAsPtr arr $ \p -> do         n <- hGetBufSome h p size         -- XXX shrink only if the diff is significant         return $
streamly-core.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.2 name:               streamly-core-version:            0.2.2+version:            0.2.3 synopsis:           Streaming, parsers, arrays, serialization and more description:   For upgrading to streamly-0.9.0+ please read the@@ -69,6 +69,8 @@                    , GHC==9.4.7                    , GHC==9.6.3                    , GHC==9.8.1+                   , GHC==9.10.1+                   , GHC==9.12.1 author:              Composewell Technologies maintainer:          streamly@composewell.com copyright:           2017 Composewell Technologies@@ -117,6 +119,7 @@     docs/ApiChangelogs/0.1.0.txt     docs/ApiChangelogs/0.1.0-0.2.0.txt     docs/ApiChangelogs/0.2.0-0.2.2.txt+    docs/ApiChangelogs/0.2.2-0.2.3.txt  source-repository head     type: git@@ -294,6 +297,8 @@         , src/Streamly/Internal/Data/Array         , src/Streamly/Internal/Data/Stream +    c-sources: src/Streamly/Internal/Data/MutArray/Lib.c+     if os(windows)       c-sources:     src/Streamly/Internal/Data/Time/Clock/Windows.c @@ -499,15 +504,15 @@                     -- packages depending on the "ghc" package (packages                     -- depending on doctest is a common example) can                     -- depend on streamly.-                       ghc-prim          >= 0.5.3 && < 0.12+                       ghc-prim          >= 0.5.3 && < 0.14                      , fusion-plugin-types >= 0.1 && < 0.2-                     , base              >= 4.12  && < 4.20+                     , base              >= 4.12  && < 4.22                      , exceptions        >= 0.8.0 && < 0.11                      , transformers      >= 0.5.5 && < 0.7                      , filepath          >= 1.4.2 && < 1.6                      -- streamly-unicode-core-                     , template-haskell  >= 2.14  && < 2.22+                     , template-haskell  >= 2.14  && < 2.24                       -- streamly-filesystem-core                      , directory         >= 1.3.3 && < 1.4