@@ -508,7 +508,15 @@ compareText (Text arrA offA lenA) (Text arrB offB lenB) =
508508-- copying a new array. Performs replacement on
509509-- invalid scalar values.
510510cons :: Char -> Text -> Text
511- cons c = unstream . S. cons (safe c) . stream
511+ cons c (Text srcArr srcOff srcLen) = runST $ do
512+ let ch = safe c
513+ chLen = utf8Length ch
514+ totalLen = chLen + srcLen
515+ marr <- A. new totalLen
516+ _ <- unsafeWrite marr 0 ch
517+ A. copyI srcLen marr chLen srcArr srcOff
518+ arr <- A. unsafeFreeze marr
519+ pure $ Text arr 0 totalLen
512520{-# INLINE [1] cons #-}
513521
514522infixr 5 `cons`
@@ -517,13 +525,23 @@ infixr 5 `cons`
517525-- entire array in the process.
518526-- Performs replacement on invalid scalar values.
519527snoc :: Text -> Char -> Text
520- snoc t c = unstream (S. snoc (stream t) (safe c))
528+ snoc (Text srcArr srcOff srcLen) c = runST $ do
529+ let ch = safe c
530+ chLen = utf8Length ch
531+ totalLen = srcLen + chLen
532+ marr <- A. new totalLen
533+ A. copyI srcLen marr 0 srcArr srcOff
534+ _ <- unsafeWrite marr srcLen ch
535+ arr <- A. unsafeFreeze marr
536+ pure $ Text arr 0 totalLen
521537{-# INLINE snoc #-}
522538
523539-- | /O(1)/ Returns the first character of a 'Text', which must be
524540-- non-empty. This is a partial function, consider using 'uncons' instead.
525541head :: HasCallStack => Text -> Char
526- head t = S. head (stream t)
542+ head t
543+ | null t = emptyError " head"
544+ | otherwise = let Iter c _ = iter t 0 in c
527545{-# INLINE head #-}
528546
529547-- | /O(1)/ Returns the first character and rest of a 'Text', or
@@ -615,7 +633,8 @@ infixl 5 :>
615633
616634-- | /O(1)/ Tests whether a 'Text' contains exactly one character.
617635isSingleton :: Text -> Bool
618- isSingleton = S. isSingleton . stream
636+ isSingleton (Text arr off len) =
637+ len == utf8LengthByLeader (A. unsafeIndex arr off)
619638{-# INLINE isSingleton #-}
620639
621640-- | /O(n)/ Returns the number of characters in a 'Text'.
@@ -1975,18 +1994,21 @@ unwords = intercalate (singleton ' ')
19751994-- | /O(n)/ The 'isPrefixOf' function takes two 'Text's and returns
19761995-- 'True' if and only if the first is a prefix of the second.
19771996isPrefixOf :: Text -> Text -> Bool
1978- isPrefixOf a@ (Text _ _ alen) b@ (Text _ _ blen) =
1979- alen <= blen && S. isPrefixOf (stream a) (stream b)
1997+ isPrefixOf a@ (Text _aArr _aOff aLen) b@ (Text bArr bOff bLen) =
1998+ d >= 0 && a == b'
1999+ where d = bLen - aLen
2000+ b' | d == 0 = b
2001+ | otherwise = Text bArr bOff aLen
19802002{-# INLINE [1] isPrefixOf #-}
19812003
19822004-- | /O(n)/ The 'isSuffixOf' function takes two 'Text's and returns
19832005-- 'True' if and only if the first is a suffix of the second.
19842006isSuffixOf :: Text -> Text -> Bool
1985- isSuffixOf a@ (Text _aarr _aoff alen ) b@ (Text barr boff blen ) =
2007+ isSuffixOf a@ (Text _aArr _aOff aLen ) b@ (Text bArr bOff bLen ) =
19862008 d >= 0 && a == b'
1987- where d = blen - alen
2009+ where d = bLen - aLen
19882010 b' | d == 0 = b
1989- | otherwise = Text barr (boff + d) alen
2011+ | otherwise = Text bArr (bOff + d) aLen
19902012{-# INLINE isSuffixOf #-}
19912013
19922014-- | /O(n+m)/ The 'isInfixOf' function takes two 'Text's and returns
0 commit comments