bech32

Fast Haskell bech32, bech32m encoding/decoding (docs.ppad.tech/bech32).
git clone git://git.ppad.tech/bech32.git
Log | Files | Refs | README | LICENSE

Internal.hs (2676B)


      1 {-# OPTIONS_HADDOCK hide, prune #-}
      2 {-# LANGUAGE OverloadedStrings #-}
      3 
      4 -- |
      5 -- Module: Data.ByteString.Base32.Internal
      6 -- Copyright: (c) 2024 Jared Tobin
      7 -- License: MIT
      8 -- Maintainer: Jared Tobin <jared@ppad.tech>
      9 --
     10 -- Static rodata tables for the bech32 base32 charset, shared by
     11 -- 'Data.ByteString.Base32' and 'Data.ByteString.Bech32.Internal'.
     12 
     13 module Data.ByteString.Base32.Internal (
     14     enc_tab
     15   , dec_tab
     16   ) where
     17 
     18 import qualified Data.ByteString as BS
     19 
     20 -- 32-byte encoding table: the bech32 character set.  Maps a 5-bit
     21 -- value (0..31) to its bech32 character.  ASCII-only with no embedded
     22 -- NUL, so the bytestring 'IsString' rule rewrites the literal to
     23 -- 'unsafePackAddress' and the bytes live in static rodata.
     24 enc_tab :: BS.ByteString
     25 enc_tab = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
     26 {-# NOINLINE enc_tab #-}
     27 
     28 -- 256-byte reverse table.  Index by an ASCII byte to obtain its
     29 -- 5-bit value (biased into bit 5); valid bech32 chars map to
     30 -- 0x20..0x3f, every other byte maps to 0x40.
     31 --
     32 -- The encoding is chosen so the literal is strictly ASCII and
     33 -- contains no embedded NUL, which is what the bytestring 'IsString'
     34 -- rule needs to rewrite it into 'unsafePackAddress' (cf. 'enc_tab')
     35 -- - the bytes end up in static rodata, with no CAF allocation.
     36 --
     37 -- The 0x40 sentinel is distinguished by bit 6; no value 0x20..0x3f
     38 -- carries that bit, so callers OR-fold every lookup into an
     39 -- accumulator and test 'acc .&. 0x40 == 0' once at the end.  The
     40 -- 5-bit value is extracted as 'b .&. 0x1f'.
     41 dec_tab :: BS.ByteString
     42 dec_tab =
     43   "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     44   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     45   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     46   \\x2f\x40\x2a\x31\x35\x34\x3a\x3e\x27\x25\x40\x40\x40\x40\x40\x40\
     47   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     48   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     49   \\x40\x3d\x40\x38\x2d\x39\x29\x28\x37\x40\x32\x36\x3f\x3b\x33\x40\
     50   \\x21\x20\x23\x30\x2b\x3c\x2c\x2e\x26\x24\x22\x40\x40\x40\x40\x40\
     51   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     52   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     53   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     54   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     55   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     56   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     57   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\
     58   \\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
     59 {-# NOINLINE dec_tab #-}