From a06585840d8716706690705b6685e8c1ffefb5f4 Mon Sep 17 00:00:00 2001 From: Adithya Kumar Date: Tue, 9 Sep 2025 02:37:09 +0530 Subject: [PATCH 1/7] Fetch dependencies from hackage --- cabal.project.Werror | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cabal.project.Werror b/cabal.project.Werror index 0559699..d4610aa 100644 --- a/cabal.project.Werror +++ b/cabal.project.Werror @@ -3,13 +3,13 @@ packages: streamly-text.cabal package streamly-text ghc-options: -Werror -source-repository-package - type: git - location: https://github.com/composewell/streamly.git - tag: master +-- source-repository-package +-- type: git +-- location: https://github.com/composewell/streamly.git +-- tag: master -source-repository-package - type: git - location: https://github.com/composewell/streamly.git - tag: master - subdir: core +-- source-repository-package +-- type: git +-- location: https://github.com/composewell/streamly.git +-- tag: master +-- subdir: core From 0a6eae5ee015350afbfaef6dc560a775823e9631 Mon Sep 17 00:00:00 2001 From: Adithya Kumar Date: Tue, 9 Sep 2025 02:38:24 +0530 Subject: [PATCH 2/7] Update the CI --- .github/workflows/packcheck.yml | 253 ++++++++++++-------------------- 1 file changed, 92 insertions(+), 161 deletions(-) diff --git a/.github/workflows/packcheck.yml b/.github/workflows/packcheck.yml index 922ac74..268beb2 100644 --- a/.github/workflows/packcheck.yml +++ b/.github/workflows/packcheck.yml @@ -1,4 +1,4 @@ -# packcheck-0.5.1 +# packcheck-0.7.0 # You can use any of the options supported by packcheck as environment # variables here. See https://github.com/composewell/packcheck for all # options and their explanation. @@ -23,219 +23,150 @@ on: jobs: build: name: ${{ matrix.name }} - env: # ------------------------------------------------------------------------ # Common options # ------------------------------------------------------------------------ # GHC_OPTIONS: "-Werror" + GHCUP_VERSION: 0.1.20.0 + DOCSPEC_URL: https://github.com/phadej/cabal-extras/releases/download/cabal-docspec-0.0.0.20210111/cabal-docspec-0.0.0.20210111.xz + DOCSPEC_OPTIONS: "--timeout 60" CABAL_REINIT_CONFIG: y LC_ALL: C.UTF-8 - # ------------------------------------------------------------------------ - # What to build - # ------------------------------------------------------------------------ - # DISABLE_TEST: "y" - # DISABLE_BENCH: "y" - # DISABLE_DOCS: "y" - # DISABLE_SDIST_BUILD: "y" - # DISABLE_SDIST_GIT_CHECK: "y" - # DISABLE_DIST_CHECKS: "y" - - # ------------------------------------------------------------------------ - # stack options - # ------------------------------------------------------------------------ - # Note requiring a specific version of stack using STACKVER may fail due to - # github API limit while checking and upgrading/downgrading to the specific - # version. - #STACKVER: "1.6.5" - #STACK_UPGRADE: "y" - #RESOLVER: ${{ matrix.resolver }} + STACK_UPGRADE: "y" - # ------------------------------------------------------------------------ - # cabal options - # ------------------------------------------------------------------------ CABAL_CHECK_RELAX: y - CABAL_HACKAGE_MIRROR: "hackage.haskell.org:http://hackage.fpcomplete.com" - # CABAL_PROJECT: "cabal.project.user" - DISABLE_SDIST_BUILD: "n" - - # ------------------------------------------------------------------------ - # Where to find the required tools - # ------------------------------------------------------------------------ - PATH: /opt/ghc/bin:/sbin:/usr/sbin:/bin:/usr/bin - #TOOLS_DIR: /opt + CABAL_HACKAGE_MIRROR: hackage.haskell.org:http://hackage.fpcomplete.com - # ------------------------------------------------------------------------ - # Location of packcheck.sh (the shell script invoked to perform CI tests ). - # ------------------------------------------------------------------------ - # You can either commit the packcheck.sh script at this path in your repo or - # you can use it by specifying the PACKCHECK_REPO_URL option below in which - # case it will be automatically copied from the packcheck repo to this path - # during CI tests. In any case it is finally invoked from this path. PACKCHECK: "./packcheck.sh" - # If you have not committed packcheck.sh in your repo at PACKCHECK - # then it is automatically pulled from this URL. PACKCHECK_GITHUB_URL: "https://raw.githubusercontent.com/composewell/packcheck" - PACKCHECK_GITHUB_COMMIT: "ccc55fd4b895e842ca6e2d8ac63aa4acc1c3209a" + PACKCHECK_GITHUB_COMMIT: "7c4e1ab7a59b5ed6e92cfd0da67460a6116be4ac" - # ------------------------------------------------------------------------ - # Final build variables - # ------------------------------------------------------------------------ - PACKCHECK_COMMAND: ${{ matrix.command }} ${{ matrix.pack_options }} + BUILD: ${{ matrix.build }} + GHCVER: ${{ matrix.ghc_version }} + #RESOLVER: ${{ matrix.resolver }} + CABAL_BUILD_OPTIONS: ${{ matrix.cabal_build_options }} + CABAL_PROJECT: ${{ matrix.cabal_project }} + DISABLE_DOCS: ${{ matrix.disable_docs }} + #DISABLE_SDIST_BUILD: ${{ matrix.disable_sdist_build }} + #DISABLE_SDIST_BUILD: "y" + HLINT_VERSION: 3.6.1 + HLINT_OPTIONS: ${{ matrix.hlint_options }} + HLINT_TARGETS: ${{ matrix.hlint_targets }} runs-on: ${{ matrix.runner }} - continue-on-error: ${{ matrix.ignore_error }} strategy: fail-fast: false matrix: - include: - - - name: 9.10.1+streamly-core-master + - name: 9.10.1-Werror ghc_version: 9.10.1 - command: cabal-v2 + build: cabal runner: ubuntu-latest - cabal-version: 3.8.1.0 - ignore_error: false - pack_options: >- - CABAL_PROJECT=cabal.project.Werror + cabal-version: 3.10.2.0 + cabal_project: cabal.project.Werror - - name: 9.8.1+streamly-core-0.2.2+text-2.1.1 + - name: 9.8.1-Werror ghc_version: 9.8.1 - command: cabal-v2 + build: cabal runner: ubuntu-latest - cabal-version: 3.8.1.0 - pack_options: >- - CABAL_BUILD_OPTIONS=" - --constraint='streamly-core==0.2.2' - --constraint='text==2.1.1' - " - ignore_error: false - - - name: 9.6.2+streamly-core-0.2.2+text-2.1 - ghc_version: 9.6.2 - command: cabal-v2 + cabal-version: 3.10.2.0 + cabal_project: cabal.project.Werror + + - name: hlint + build: hlint + hlint_options: "lint" + hlint_targets: "src" runner: ubuntu-latest - cabal-version: 3.8.1.0 - ignore_error: true - pack_options: >- - CABAL_BUILD_OPTIONS=" - --constraint='streamly-core==0.2.2' - --constraint='text==2.1' - " - - - name: 9.4.4+streamly-core-0.2.1+text-2.0.2 - ghc_version: 9.4.4 - command: cabal-v2 + cabal-version: 3.2 + cabal_project: cabal.project.Werror + + - name: 9.6.3-macos + runner: macos-latest + ghc_version: 9.6.3 + build: cabal + cabal-version: 3.10.1.0 + cabal_project: cabal.project.Werror + + - name: 9.4.4 runner: ubuntu-latest + ghc_version: 9.4.4 + build: cabal cabal-version: 3.8.1.0 - ignore_error: false - pack_options: >- - CABAL_BUILD_OPTIONS=" - --constraint='streamly-core==0.2.1' - --constraint='text==2.0.2' - " - - - name: 9.2.7+streamly-core-0.2.1+text-2.0.1 - ghc_version: 9.2.7 - command: cabal-v2 + cabal_project: cabal.project.Werror + + - name: 9.4.4 runner: ubuntu-latest - cabal-version: 3.6.2.0 - ignore_error: false - pack_options: >- - CABAL_BUILD_OPTIONS=" - --constraint='streamly-core==0.2.1' - --constraint='text==2.0.1' - " - - - name: 9.0.1+streamly-core-0.2.0+text-2.0 - ghc_version: 9.0.1 - command: cabal-v2 + ghc_version: 9.4.4 + build: cabal + cabal-version: 3.8.1.0 + cabal_project: cabal.project.Werror + + - name: 9.2.7 runner: ubuntu-latest - cabal-version: 3.2 - ignore_error: false - pack_options: >- - CABAL_BUILD_OPTIONS=" - --constraint='streamly-core==0.2.0' - --constraint='text==2.0' - " + ghc_version: 9.2.7 + build: cabal + cabal-version: 3.6 + cabal_project: cabal.project.Werror - name: 8.10.7 - ghc_version: 8.10.7 - command: cabal-v2 runner: ubuntu-latest - cabal-version: 3.2 - ignore_error: false - - - name: 8.10.7+macOS ghc_version: 8.10.7 - command: cabal-v2 - runner: macos-latest - cabal_version: 3.4 - ignore_error: false + build: cabal + cabal-version: 3.2 + cabal_project: cabal.project.Werror + disable_docs: y - name: 8.8.4 - ghc_version: 8.8.4 - command: cabal-v2 runner: ubuntu-latest + ghc_version: 8.8.4 + build: cabal cabal-version: 3.2 - ignore_error: false + cabal_project: cabal.project.Werror + disable_docs: y - name: 8.6.5 - ghc_version: 8.6.5 - command: cabal-v2 runner: ubuntu-latest + ghc_version: 8.6.5 + build: cabal cabal-version: 3.2 - ignore_error: false - - - name: hlint - ghc_version: 8.8.4 - command: cabal-v2 - runner: ubuntu-latest - pack_options: >- - HLINT_OPTIONS="lint" - HLINT_TARGETS="src" - cabal-version: 3.2 - ignore_error: false + cabal_project: cabal.project.Werror + disable_docs: y steps: - uses: actions/checkout@v2 - - uses: haskell/actions/setup@v1 - with: - ghc-version: ${{ matrix.ghc_version }} - - - uses: actions/cache@v2 - name: Cache common directories + - uses: actions/cache@v4 + name: Restore cache with: path: | - ~/.cabal - ~/.ghc ~/.local + ~/.cabal ~/.stack - key: ${{ matrix.ghc_version }}-${{ matrix.runner }} - - - name: Run installer - if: ${{ matrix.installer != '' }} - run: ${{ matrix.installer }} - - - name: Setup stack - if: ${{ matrix.command == 'stack' }} - run: | - # required for packcheck - sudo apt-get install -y curl - # required for outbound https for stack and for stack setup - sudo apt-get install -y netbase xz-utils make + .stack-work + key: ${{ runner.os }}-${{ matrix.name }} - name: Download packcheck run: | - # Get packcheck if needed - CURL=$(which curl) - PACKCHECK_URL=${PACKCHECK_GITHUB_URL}/${PACKCHECK_GITHUB_COMMIT}/packcheck.sh - if test ! -e "$PACKCHECK"; then $CURL -sL -o "$PACKCHECK" $PACKCHECK_URL; fi; - chmod +x $PACKCHECK + # If a custom stack-yaml is specified, replace the default with that + #if test -e "$STACK_YAML"; then rm -f stack.yaml && ln -sv $STACK_YAML stack.yaml; else true; fi + #unset STACK_YAML + + if test ! -e "$PACKCHECK" + then + if test -z "$PACKCHECK_GITHUB_COMMIT" + then + die "PACKCHECK_GITHUB_COMMIT is not specified." + fi + PACKCHECK_URL=${PACKCHECK_GITHUB_URL}/${PACKCHECK_GITHUB_COMMIT}/packcheck.sh + curl --fail -sL -o "$PACKCHECK" $PACKCHECK_URL || exit 1 + chmod +x $PACKCHECK + elif test ! -x "$PACKCHECK" + then + chmod +x $PACKCHECK + fi - name: Run packcheck run: | - bash -c "$PACKCHECK $PACKCHECK_COMMAND" + bash -c "$PACKCHECK $BUILD" From 01d97476061d2568a44f693b6bc6532e3632ee8a Mon Sep 17 00:00:00 2001 From: Adithya Kumar Date: Tue, 9 Sep 2025 17:41:00 +0530 Subject: [PATCH 3/7] Rename External -> Compat --- src/Streamly/{External => Compat}/Text.hs | 2 +- src/Streamly/{External => Compat}/Text/Lazy.hs | 4 ++-- streamly-text.cabal | 4 ++-- test/Main.hs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) rename src/Streamly/{External => Compat}/Text.hs (98%) rename src/Streamly/{External => Compat}/Text/Lazy.hs (97%) diff --git a/src/Streamly/External/Text.hs b/src/Streamly/Compat/Text.hs similarity index 98% rename from src/Streamly/External/Text.hs rename to src/Streamly/Compat/Text.hs index 610a783..d5197ff 100644 --- a/src/Streamly/External/Text.hs +++ b/src/Streamly/Compat/Text.hs @@ -3,7 +3,7 @@ {-# LANGUAGE MagicHash #-} {-# LANGUAGE BangPatterns #-} -module Streamly.External.Text +module Streamly.Compat.Text ( toArray , unsafeFromArray diff --git a/src/Streamly/External/Text/Lazy.hs b/src/Streamly/Compat/Text/Lazy.hs similarity index 97% rename from src/Streamly/External/Text/Lazy.hs rename to src/Streamly/Compat/Text/Lazy.hs index 6053c31..d2d3284 100644 --- a/src/Streamly/External/Text/Lazy.hs +++ b/src/Streamly/Compat/Text/Lazy.hs @@ -1,6 +1,6 @@ {-# LANGUAGE CPP #-} -module Streamly.External.Text.Lazy +module Streamly.Compat.Text.Lazy ( chunkReader , reader @@ -20,7 +20,7 @@ import Data.Text.Internal.Lazy (Text(..), chunk) import Streamly.Internal.Data.Stream (Step(..)) import Streamly.Internal.Data.Unfold (Unfold(..)) -import qualified Streamly.External.Text as Strict +import qualified Streamly.Compat.Text as Strict import qualified Streamly.Data.Array as Array import qualified Streamly.Data.Unfold as Unfold import qualified Streamly.Data.Stream as Stream diff --git a/streamly-text.cabal b/streamly-text.cabal index 99d4fbb..d62806a 100644 --- a/streamly-text.cabal +++ b/streamly-text.cabal @@ -26,8 +26,8 @@ common compile-options library import: compile-options - exposed-modules: Streamly.External.Text - , Streamly.External.Text.Lazy + exposed-modules: Streamly.Compat.Text + , Streamly.Compat.Text.Lazy build-depends: base >=4.7 && <5 , streamly-core >=0.2.0 && <0.3.1 , text >=2.0 && <2.1.2 diff --git a/test/Main.hs b/test/Main.hs index 472f2c5..6e98b84 100644 --- a/test/Main.hs +++ b/test/Main.hs @@ -15,8 +15,8 @@ import qualified Streamly.Internal.Data.Array as Array (castUnsafe) import qualified Data.Text as BS import qualified Data.Text.Lazy as BSL import qualified Streamly.FileSystem.File as File -import qualified Streamly.External.Text as Strict -import qualified Streamly.External.Text.Lazy as Lazy +import qualified Streamly.Compat.Text as Strict +import qualified Streamly.Compat.Text.Lazy as Lazy import qualified Streamly.Data.Stream as Stream pipeline :: From 94159deefc7a7d3efbc38a8e7a48f743c3170455 Mon Sep 17 00:00:00 2001 From: Adithya Kumar Date: Tue, 9 Sep 2025 17:47:13 +0530 Subject: [PATCH 4/7] Update documentation --- README.md | 5 ++--- src/Streamly/Compat/Text.hs | 11 +++++++---- src/Streamly/Compat/Text/Lazy.hs | 8 ++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index fcca492..f4e8985 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,8 @@ Library for streamly and text interoperation. This library is to enable interoperation of streamly with existing code that uses `Text`. -The package provides APIs to interconvert between strict `Text` and -streamly `Array Word16` and between lazy `Text` and stream of `Array -Word16`. +The package provides APIs to interconvert between strict `Text` and streamly +`Array Word8` and between lazy `Text` and stream of `Array Word8`. The interconversion in the case of strict `Text` and streamly `Array Word8` has no overhead. diff --git a/src/Streamly/Compat/Text.hs b/src/Streamly/Compat/Text.hs index d5197ff..d913ced 100644 --- a/src/Streamly/Compat/Text.hs +++ b/src/Streamly/Compat/Text.hs @@ -58,10 +58,13 @@ toArray (Text (TArr.ByteArray _) _ len) toArray (Text (TArr.ByteArray barr#) off8 len8) = Array (MutByteArray (unsafeCoerce# barr#)) off8 (off8 + len8) --- | Treat an an array of 'Word8' as 'Text'. This function is unsafe and the --- onus is on the caller to check the sanity of 'Array' 'Word8'. This function --- unwraps the 'Array' and wraps it with 'Text' constructors and hence the --- operation is performed in constant time. +-- | Treat an an array of 'Word8' as 'Text'. +-- +-- This function is unsafe: the caller must ensure that the 'Array' 'Word8' is a +-- valid UTF-8 encoding. +-- +-- This function unwraps the 'Array' and wraps it with 'Text' constructors and +-- hence the operation is performed in constant time. {-# INLINE unsafeFromArray #-} unsafeFromArray :: Array Word8 -> Text unsafeFromArray Array {..} diff --git a/src/Streamly/Compat/Text/Lazy.hs b/src/Streamly/Compat/Text/Lazy.hs index d2d3284..cf4995f 100644 --- a/src/Streamly/Compat/Text/Lazy.hs +++ b/src/Streamly/Compat/Text/Lazy.hs @@ -55,8 +55,8 @@ toChunks = Stream.unfold chunkReader -- | Convert a serial stream of 'Array' 'Word8' to a lazy 'Text'. -- --- This function is unsafe and the onus is on the caller to check the sanity of --- the stream of 'Array' 'Word8'. +-- This function is unsafe: the caller must ensure that each 'Array' 'Word8' +-- element in the stream is a valid UTF-8 encoding. -- -- IMPORTANT NOTE: This function is lazy only for lazy monads -- (e.g. Identity). For strict monads (e.g. /IO/) it consumes the entire input @@ -65,8 +65,8 @@ toChunks = Stream.unfold chunkReader -- -- For strict monads like /IO/ you could create a newtype wrapper to make the -- monad bind operation lazy and lift the stream to that type using hoist, then --- you can use this function to generate the bytestring lazily. For example you --- can wrap the /IO/ type to make the bind lazy like this: +-- you can use this function to generate the text lazily. For example you can +-- wrap the /IO/ type to make the bind lazy like this: -- -- @ -- newtype LazyIO a = LazyIO { runLazy :: IO a } deriving (Functor, Applicative) From 35372d0032865bd6e583ee34135b50a15d5b3822 Mon Sep 17 00:00:00 2001 From: Adithya Kumar Date: Tue, 9 Sep 2025 21:46:51 +0530 Subject: [PATCH 5/7] Unexport unsafeCreateOf --- src/Streamly/Compat/Text.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Streamly/Compat/Text.hs b/src/Streamly/Compat/Text.hs index d913ced..7ddca95 100644 --- a/src/Streamly/Compat/Text.hs +++ b/src/Streamly/Compat/Text.hs @@ -9,7 +9,7 @@ module Streamly.Compat.Text , reader - , unsafeCreateOf + -- , unsafeCreateOf , unsafeCreate ) where @@ -83,9 +83,9 @@ reader :: Monad m => Unfold m Text Word8 reader = lmap toArray Array.reader -- | Fold a stream of Word8 to a 'Text' of given size in bytes. -{-# INLINE unsafeCreateOf #-} -unsafeCreateOf :: MonadIO m => Int -> Fold m Word8 Text -unsafeCreateOf i = unsafeFromArray <$> CREATE_OF i +{-# INLINE _unsafeCreateOf #-} +_unsafeCreateOf :: MonadIO m => Int -> Fold m Word8 Text +_unsafeCreateOf i = unsafeFromArray <$> CREATE_OF i -- | Fold a stream of Word8 to a 'Text' of appropriate size. {-# INLINE unsafeCreate #-} From 1fa19461458d89603e5903733b3428c7dcffe925 Mon Sep 17 00:00:00 2001 From: Adithya Kumar Date: Tue, 9 Sep 2025 21:50:57 +0530 Subject: [PATCH 6/7] Relax build strictness in lower GHCs --- .github/workflows/packcheck.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/packcheck.yml b/.github/workflows/packcheck.yml index 268beb2..e338309 100644 --- a/.github/workflows/packcheck.yml +++ b/.github/workflows/packcheck.yml @@ -123,7 +123,6 @@ jobs: ghc_version: 8.8.4 build: cabal cabal-version: 3.2 - cabal_project: cabal.project.Werror disable_docs: y - name: 8.6.5 @@ -131,7 +130,6 @@ jobs: ghc_version: 8.6.5 build: cabal cabal-version: 3.2 - cabal_project: cabal.project.Werror disable_docs: y steps: From 503b97d7b8016b2ca96e72fd603a1296e8863fa2 Mon Sep 17 00:00:00 2001 From: Adithya Kumar Date: Wed, 10 Sep 2025 00:24:01 +0530 Subject: [PATCH 7/7] Update the test suite to use the latest APIs --- test/Main.hs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/Main.hs b/test/Main.hs index 6e98b84..c70a66c 100644 --- a/test/Main.hs +++ b/test/Main.hs @@ -10,11 +10,12 @@ import Test.QuickCheck.Instances.Text () import System.IO (hClose) import Data.Functor.Identity (Identity(..)) -import qualified Streamly.Internal.Data.Array as Array (castUnsafe) +import qualified Streamly.Internal.Data.Array as Array (unsafeCast) import qualified Data.Text as BS import qualified Data.Text.Lazy as BSL -import qualified Streamly.FileSystem.File as File +import qualified Streamly.FileSystem.FileIO as File +import qualified Streamly.FileSystem.Path as Path import qualified Streamly.Compat.Text as Strict import qualified Streamly.Compat.Text.Lazy as Lazy import qualified Streamly.Data.Stream as Stream @@ -55,11 +56,12 @@ writeRead :: Int -> IO () writeRead n = do str <- sequence $ replicate n (randomIO :: IO Char) let txt = BSL.pack str - withSystemTempFile "temp" $ \fp hdl -> do + withSystemTempFile "temp" $ \fp0 hdl -> do + fp <- Path.fromString fp0 hClose hdl - let strm = fmap Array.castUnsafe $ Lazy.toChunks txt + let strm = fmap Array.unsafeCast $ Lazy.toChunks txt Stream.fold (File.writeChunks fp) strm - let strm1 = fmap Array.castUnsafe $ File.readChunks fp + let strm1 = fmap Array.unsafeCast $ File.readChunks fp txt1 <- Lazy.unsafeFromChunksIO strm1 txt1 `shouldBe` txt