Skip to content

Commit 991ae2b

Browse files
committed
Add hexFixedWord16#, release 0.3.12.0
1 parent a1262cd commit 991ae2b

File tree

4 files changed

+31
-7
lines changed

4 files changed

+31
-7
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Revision history for bytesmith
22

3+
## 0.3.20.0 -- 2025-07-11
4+
5+
* Add `hexFixedWord16#`
6+
* Drop support for base < 4.18, clean up CPP
7+
* Add more levity-monomorphized variants of bind, pure, and fail
8+
39
## 0.3.11.1 -- 2024-02-28
410

511
* Update package metadata.

bytesmith.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cabal-version: 3.0
22
name: bytesmith
3-
version: 0.3.11.1
3+
version: 0.3.12.0
44
synopsis: Nonresumable byte parser
55
description:
66
Parse bytes as fast as possible. This is a nonresumable parser

src/Data/Bytes/Parser.hs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ module Data.Bytes.Parser
106106
-- get used in your original source code, GHC will not introduce them.
107107
, bindFromCharToLifted
108108
, bindFromCharToByteArrayIntInt
109+
, bindFromWordToByteArrayIntInt
109110
, bindFromLiftedToIntPair
110111
, bindFromLiftedToInt
111112
, bindFromIntToIntPair
@@ -524,15 +525,15 @@ peekRemaining = uneffectful $ \b@(Bytes _ off len) ->
524525
-- | Skip while the predicate is matched. This is always inlined.
525526
skipWhile :: (Word8 -> Bool) -> Parser e s ()
526527
{-# INLINE skipWhile #-}
527-
skipWhile f = go
528+
skipWhile f = goSkipWhile
528529
where
529-
go =
530+
goSkipWhile =
530531
isEndOfInput >>= \case
531532
True -> pure ()
532533
False -> do
533534
w <- anyUnsafe
534535
if f w
535-
then go
536+
then goSkipWhile
536537
else unconsume 1
537538

538539
{- | The parser @satisfy p@ succeeds for any byte for which the
@@ -697,6 +698,17 @@ bindFromCharToLifted (Parser f) g =
697698
runParser (g y) (# arr, b, c #) s1
698699
)
699700

701+
bindFromWordToByteArrayIntInt :: Parser s e Word# -> (Word# -> Parser s e (# ByteArray#, Int#, Int# #)) -> Parser s e (# ByteArray#, Int#, Int# #)
702+
{-# INLINE bindFromWordToByteArrayIntInt #-}
703+
bindFromWordToByteArrayIntInt (Parser f) g =
704+
Parser
705+
( \x@(# arr, _, _ #) s0 -> case f x s0 of
706+
(# s1, r0 #) -> case r0 of
707+
(# e | #) -> (# s1, (# e | #) #)
708+
(# | (# y, b, c #) #) ->
709+
runParser (g y) (# arr, b, c #) s1
710+
)
711+
700712
bindFromCharToByteArrayIntInt :: Parser s e Char# -> (Char# -> Parser s e (# ByteArray#, Int#, Int# #)) -> Parser s e (# ByteArray#, Int#, Int# #)
701713
{-# INLINE bindFromCharToByteArrayIntInt #-}
702714
bindFromCharToByteArrayIntInt (Parser f) g =

src/Data/Bytes/Parser/Latin.hs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ module Data.Bytes.Parser.Latin
9999
-- *** Fixed Length
100100
, hexFixedWord8
101101
, hexFixedWord16
102+
, hexFixedWord16#
102103
, hexFixedWord32
103104
, hexFixedWord64
104105
, hexFixedWord128
@@ -1285,6 +1286,11 @@ hexFixedWord16 e = Parser
12851286
a), b, c #) #) #)
12861287
)
12871288

1289+
-- | Variant of hexFixedWord16 that returns an unboxed result. The result is
1290+
-- a machine-sized word instead of a 16-bit word, but this function guarantees
1291+
-- that only the low 16 bits may be non-zero. This is helpful because the
1292+
-- result needs to be constructed as a machine-sized word. GHC's primitives
1293+
-- for working with 16-bit words lower to most ISAs poorly.
12881294
hexFixedWord16# :: e -> Parser e s Word#
12891295
{-# noinline hexFixedWord16# #-}
12901296
hexFixedWord16# e = uneffectfulWord# $ \chunk -> if length chunk >= 4
@@ -1295,9 +1301,9 @@ hexFixedWord16# e = uneffectfulWord# $ \chunk -> if length chunk >= 4
12951301
!w3@(W# n3) = oneHex $ PM.indexByteArray (array chunk) (offset chunk + 3)
12961302
in if | w0 .|. w1 .|. w2 .|. w3 /= maxBound ->
12971303
(# |
1298-
(# (n0 `Exts.timesWord#` 4096##) `Exts.plusWord#`
1299-
(n1 `Exts.timesWord#` 256##) `Exts.plusWord#`
1300-
(n2 `Exts.timesWord#` 16##) `Exts.plusWord#`
1304+
(# (n0 `Exts.shiftL#` 12#) `Exts.plusWord#`
1305+
(n1 `Exts.shiftL#` 8#) `Exts.plusWord#`
1306+
(n2 `Exts.shiftL#` 4#) `Exts.plusWord#`
13011307
n3
13021308
, unI (offset chunk) +# 4#
13031309
, unI (length chunk) -# 4# #) #)

0 commit comments

Comments
 (0)