Code Snippets

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/env stack
{- stack
   --resolver lts-12.0
   --install-ghc
   script
   --
   --ghc-options -Werror
   --ghc-options -Wall
-}

--------------------------------------------------------------------------------

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE Safe              #-}

--------------------------------------------------------------------------------

module Main (main) where

--------------------------------------------------------------------------------

import           Data.Bits
    ( Bits
    , shiftL
    , shiftR
    )
import qualified Data.ByteString.Lazy.Char8 as L8
import           Data.Word
    ( Word16
    , Word32
    , Word64
    , Word8
    )

--------------------------------------------------------------------------------

(.<.)
  :: Bits a
  => a
  -> Int
  -> a
(.>.)
  :: Bits a
  => a
  -> Int
  -> a

cons
  :: Char
  -> L8.ByteString
  -> L8.ByteString

toBase
  :: Int
  -> (Integer -> Integer)
  -> Integer
  -> L8.ByteString
toBit
  :: Integer
  -> L8.ByteString
toHex'
  :: Bool
  -> Integer
  -> L8.ByteString
toHex
  :: Integer
  -> L8.ByteString
toHexLow
  :: Integer
  -> L8.ByteString

main
  :: IO ()

--------------------------------------------------------------------------------

(.<.) x y = x `shiftL` y
(.>.) x y = x `shiftR` y

-- O(1) cons is analogous to '(:)' for lists.
cons = L8.cons

toBase base f =
  aux ""
  where
    aux acc 0 = acc
    aux acc n =
      aux (cons r acc) c
      where
        c = n .>. base
        r = toEnum . fromIntegral $ f (n - c * 1 .<. base)

toBit =
  toBase 1 {- 2^1 = 002 -} (+ 48)

toHex' cap =
  toBase 4 {- 2^4 = 016 -} aux
  where
    aux x
      | x < 0x0A  = 48 + x
      | x < 0x10  = cc + x
      | otherwise = error "Shouldn't be possible to reach (toHex')"
    cc = if cap then 55 else 87

toHex =
  toHex' True

toHexLow =
  toHex' False


toByte =
  toBase 8 {- 2^8 = 256 -} id

--------------------------------------------------------------------------------

main =
  do
    L8.putStrLn "-- Word08 as bits:"
    L8.putStrLn $ toBit  $ fromIntegral $ w08
    L8.putStrLn "-- Word08 as hex:"
    L8.putStrLn $ toHex  $ fromIntegral $ w08
    L8.putStrLn "-- Word08 as bytes:"
    L8.putStrLn $ toByte $ fromIntegral $ w08
    L8.putStrLn $ ""

    L8.putStrLn "-- Word16 as bits:"
    L8.putStrLn $ toBit  $ fromIntegral $ w16
    L8.putStrLn "-- Word16 as hex:"
    L8.putStrLn $ toHex  $ fromIntegral $ w16
    L8.putStrLn "-- Word16 as bytes:"
    L8.putStrLn $ toByte $ fromIntegral $ w16
    L8.putStrLn $ ""

    L8.putStrLn "-- Word32 as bits:"
    L8.putStrLn $ toBit  $ fromIntegral $ w32
    L8.putStrLn "-- Word32 as hex:"
    L8.putStrLn $ toHex  $ fromIntegral $ w32
    L8.putStrLn "-- Word32 as bytes:"
    L8.putStrLn $ toByte $ fromIntegral $ w32
    L8.putStrLn $ ""

    L8.putStrLn "-- Word64 as bits:"
    L8.putStrLn $ toBit  $ fromIntegral $ w64
    L8.putStrLn "-- Word64 as hex:"
    L8.putStrLn $ toHex  $ fromIntegral $ w64
    L8.putStrLn "-- Word64 as bytes:"
    L8.putStrLn $ toByte $ fromIntegral $ w64
    L8.putStrLn $ ""

    L8.putStrLn "-- Integer as bits:"
    L8.putStrLn $ toBit  $                int
    L8.putStrLn "-- Integer as hex:"
    L8.putStrLn $ toHex  $                int
    L8.putStrLn "-- Integer as bytes:"
    L8.putStrLn $ toByte $ fromIntegral $ int
  where
    w08 = 0xFF                :: Word8   -- 1 .<. 08 - 1
    w16 = 0xFFFF              :: Word16  -- 1 .<. 16 - 1
    w32 = 0xFFFFFFFF          :: Word32  -- 1 .<. 32 - 1
    w64 = 0xFFFFFFFFFFFFFFFF  :: Word64  -- 1 .<. 64 - 1
    int = 0x10000000000000000 :: Integer -- 1 .<. 64

Output:

user@personal:~/.../bitwise$ ./Main.hs
-- Word08 as bits:
11111111
-- Word08 as hex:
FF
-- Word08 as bytes:
\255

-- Word16 as bits:
1111111111111111
-- Word16 as hex:
FFFF
-- Word16 as bytes:
\255\255

-- Word32 as bits:
11111111111111111111111111111111
-- Word32 as hex:
FFFFFFFF
-- Word32 as bytes:
\255\255\255\255

-- Word64 as bits:
1111111111111111111111111111111111111111111111111111111111111111
-- Word64 as hex:
FFFFFFFFFFFFFFFF
-- Word64 as bytes:
\255\255\255\255\255\255\255\255

-- Integer as bits:
10000000000000000000000000000000000000000000000000000000000000000
-- Integer as hex:
10000000000000000
-- Word08 as bytes:
\SOH\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL