Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions core/src/Streamly/Data/Array.hs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ module Streamly.Data.Array
)
where

#include "inline.hs"

import Streamly.Internal.Data.Array
import Streamly.Internal.Data.MutByteArray (Unbox(..), Serialize(..))

Expand Down
92 changes: 92 additions & 0 deletions core/src/Streamly/Data/RingArray.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
{-# LANGUAGE CPP #-}
-- |
-- Module : Streamly.Data.RingArray
-- Copyright : (c) 2025 Composewell Technologies
--
-- License : BSD3
-- Maintainer : streamly@composewell.com
-- Stability : released
-- Portability : GHC
--
-- This module provides APIs to create and use unboxed, mutable ring arrays of
-- fixed size. Ring arrays are useful to keep a circular buffer or a sliding
-- window of elements.
--
-- RingArrays are of fixed size but there is a way to expand the size of the
-- ring, you can copy the ring to a MutArray, expand the MutArray and the cast
-- it back to RingArray.
--
-- This module is designed to be imported qualified:
--
-- >>> import qualified Streamly.Data.RingArray as Ring
--
-- Please refer to "Streamly.Internal.Data.RingArray" for functions that have
-- not yet been released.
--

module Streamly.Data.RingArray
( RingArray

-- * Construction
, createOfLast
, castMutArray -- XXX this is unsafeFreeze in Array module
, castMutArrayWith
-- , unsafeCastMutArray
-- , unsafeCastMutArrayWith

-- * Moving the Head
, moveForward
, moveReverse
-- , moveBy

-- * In-place Mutation
, insert
, replace
, replace_
, putIndex
, modifyIndex

-- * Random Access
, getIndex
, unsafeGetIndex
, unsafeGetHead

-- * Conversion
, toList
, toMutArray

-- * Streams
, read
, readRev

-- * Unfolds
, reader
, readerRev

-- * Size
, length
, byteLength

-- * Casting
, cast
-- , unsafeCast
, asBytes
, asMutArray
-- , asMutArray_

-- * Folds
-- , foldlM'
, fold

-- * Stream of Rings
, ringsOf
, scanRingsOf

-- * Fast Byte Comparisons
, eqArray
, eqArrayN

) where

import Streamly.Internal.Data.RingArray
import Prelude hiding (read, length)
33 changes: 23 additions & 10 deletions core/src/Streamly/Internal/Data/RingArray.hs
Original file line number Diff line number Diff line change
Expand Up @@ -285,16 +285,22 @@ unsafeCastMutArray = unsafeCastMutArrayWith 0
-- field in the ring. For copying we can have another API though.

-- XXX castMutArray is called unsafeFreeze in the Array module. Make the naming
-- consistent? Also we can use castMutArrayWith to specify the index and use
-- the default index 0.
-- consistent?

-- | @castMutArray arr index@ casts a mutable array to a ring array having
-- the ring head at @index@ position in the array.
-- | @castMutArrayWith index arr@ casts a mutable array to a ring array, and
-- positions the ring head at the given @index@ in the array.
--
-- A MutArray can be a slice which means its memory starts from some offset in
-- the underlying MutableByteArray, and not from 0 offset. RingArray always
-- uses the memory from offset zero in the MutableByteArray, therefore, it
-- refuses to cast if it finds the array does not start from offset zero i.e.
-- if the array was created from some slicing operation over another array. In
-- such cases it returns 'Nothing'.
--
-- To create a RingArray from a sliced MutArray use 'createOfLast', or clone
-- the MutArray and then cast it.
--
-- This operation throws an error if the index is not within the array bounds.
-- It returns Nothing if the array cannot be cast into ring because the array
-- is a slice. In that case clone the array and cast it or stream the array and
-- use 'createOfLast' to create a ring.
--
{-# INLINE castMutArrayWith #-}
castMutArrayWith :: forall a. Unbox a => Int -> MutArray a -> Maybe (RingArray a)
Expand All @@ -306,8 +312,10 @@ castMutArrayWith i arr
| otherwise = Nothing

-- | Cast a MutArray to a ring sharing the same memory without copying. The
-- ring head is at index 0 of the array. Cast fails with Nothing if the array
-- is a slice.
-- ring head is positioned at index 0 of the array. The size of the ring is
-- equal to the MutArray length.
--
-- See 'castMutArrayWith' for failure scenarios.
--
-- >>> castMutArray = RingArray.castMutArrayWith 0
--
Expand Down Expand Up @@ -667,7 +675,8 @@ eqArrayN RingArray{..} Array.Array{..} nBytes
{-# INLINE eqArray #-}
eqArray :: RingArray a -> Array a -> IO Bool
eqArray RingArray{..} Array.Array{..}
| arrEnd - arrStart < ringSize = error "eqArrayN: array is shorter than ring"
| arrEnd - arrStart < ringSize =
error "eqArrayN: array is shorter than ring"
| otherwise = do
part1 <-
MutByteArray.unsafeByteCmp
Expand Down Expand Up @@ -832,6 +841,10 @@ asMutArray rb =
, ringHead rb
)

-- | Like 'asMutArray' but does not return the ring head.
--
-- >>> asMutArray_ = fst . RingArray.asMutArray
--
{-# INLINE asMutArray_ #-}
asMutArray_ :: RingArray a -> MutArray a
asMutArray_ rb =
Expand Down
9 changes: 4 additions & 5 deletions core/streamly-core.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,6 @@ library

-- Pre-release modules
-- , Streamly.Data.Pipe
-- , Streamly.Data.RingArray
-- , Streamly.Data.RingArray.Generic
-- , Streamly.Data.IORef
-- , Streamly.Data.List
Expand All @@ -466,18 +465,18 @@ library
-- , Streamly.Data.Either.Strict

-- streamly-core released modules in alphabetic order
-- NOTE: these must be added to streamly.cabal as well
, Streamly.Console.Stdio
, Streamly.Control.Exception
, Streamly.Data.MutByteArray
, Streamly.Data.Array
, Streamly.Data.Array.Generic
, Streamly.Data.Fold
, Streamly.Data.MutArray
, Streamly.Data.MutArray.Generic
, Streamly.Data.Fold
, Streamly.Data.Scanl
, Streamly.Data.MutByteArray
, Streamly.Data.Parser
, Streamly.Data.ParserK
, Streamly.Data.RingArray
, Streamly.Data.Scanl
, Streamly.Data.Stream
, Streamly.Data.StreamK
, Streamly.Data.Unfold
Expand Down
Loading