@@ -30,6 +30,8 @@ module Streamly.Internal.Memory.Array.Types
30 , spliceWithDoubling
30 , spliceWithDoubling
31 , spliceTwo
31 , spliceTwo
33 , fromList
35 , fromList
34 , fromListN
36 , fromListN
35 , fromStreamDN
37 , fromStreamDN
@@ -355,18 +357,74 @@ shrinkToFit arr@Array{..} = do
355 then realloc used arr
357 then realloc used arr
356 else return arr
358 else return arr
358−-- XXX when converting an array of Word8 from a literal string we can simply
360+-- See also: https://gitlab.haskell.org/ghc/ghc/issues/5218 (Add
359−-- refer to the literal string. Is it possible to write rules such that
361+-- unpackCStringLen# to create Strings from string literals)
360−-- fromList Word8 can be rewritten so that GHC does not first convert the
361−-- literal to [Char] and then we convert it back to an Array Word8?
363−-- Note that the address must be a read-only address (meant to be used for
363+-- TBD: We can also add template haskell quasiquotes to specify arrays of other
364−-- read-only string literals) because we are sharing it, any modification to
364+-- literal types. TH will encode them into a string literal and we read that as
365−-- the original address would change our array. That's why this function is
365+-- an array of the required type. With template Haskell we can provide a safe
366−-- unsafe.
366+-- version of fromString#.
367−{-# INLINE _fromCStringAddrUnsafe #-}
367+--
368+-- | Create an @Array Word8@ of the given length from a machine address
369+-- 'Addr#'. This API is unsafe for the following reasons:
371+-- 1. The address must point to pinned memory or foreign memory.
372+-- 2. The address must be legally accessible upto the given length.
373+-- 3. To guarantee that the array is immutable, the contents of the address
374+-- must be guaranteed to not change.
376+-- A common use case for this API is to create an array from a static unboxed
377+-- string literal. GHC string literals are of type 'Addr#', and must contain
378+-- characters that can be encoded in a byte i.e. characters or literal bytes in
379+-- the range from 0-255.
381+-- >>> fromAddr# 5 "hello world!"#
382+-- > [104,101,108,108,111]
384+-- >>> fromAddr# 3 "\255\NUL\255"#
387+-- /See also: 'fromString#'/
391+-- /Time complexity: O(1)/
393+{-# INLINE fromAddr# #-}
368−_fromCStringAddrUnsafe :: Addr# -> IO (Array Word8)
394+fromAddr# :: Int -> Addr# -> IO (Array Word8)
369−_fromCStringAddrUnsafe addr# = do
395+fromAddr# n addr# = do
396+ ptr <- newForeignPtr_ (castPtr $ Ptr addr#)
397+ let p = unsafeForeignPtrToPtr ptr
398+ let end = p `plusPtr` n
405+-- | Like 'fromAddr#' but determines the length of the array upto and excluding
406+-- the first @0@ byte. The address must be legally accessible up to the first
409+-- A common use case for this API is to create an array from an unboxed string
410+-- literal. Unboxed string literals are guaranteed to be terminated by a NUL
413+-- >>> fromString# "hello world!"#
414+-- > [104,101,108,108,111,32,119,111,114,108,100,33]
416+-- >>> fromString# "\255\NUL\255"#
419+-- /See also: 'fromAddr#', 'fromString'/
423+-- /Time complexity: O(n) (computes the length of the string)/
425+{-# INLINE fromString# #-}
426+fromString# :: Addr# -> IO (Array Word8)
427+fromString# addr# = do
370 ptr <- newForeignPtr_ (castPtr cstr)
428 ptr <- newForeignPtr_ (castPtr cstr)
371 len <- c_strlen cstr
429 len <- c_strlen cstr
372 let n = fromIntegral len
430 let n = fromIntegral len