{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UnboxedTuples #-}

{-| This module provides the Mac data type and functions for working
    with it.
-}
module Net.Mac
  ( -- * Convert
    mac
  , fromOctets
  , toOctets
    -- * Textual Conversion
    -- ** Text
  , encode
  , encodeWith
  , decode
  , decodeWith
  , builder
  , parser
  , parserWith
    -- ** ShortText
  , encodeShort
    -- ** UTF-8 ByteString
  , encodeUtf8
  , encodeWithUtf8
  , decodeUtf8
  , decodeWithUtf8
  , builderUtf8
  , parserUtf8
  , parserWithUtf8
    -- ** ByteString
  , decodeBytes
  , decodeOctets
    -- ** UTF-8 Bytes
  , boundedBuilderUtf8
  , decodeUtf8Bytes
  , parserUtf8Bytes
    -- ** Printing
  , print
    -- * Default Codec
  , defCodec
    -- * Types
  , Mac(..)
  , MacCodec(..)
  , MacGrouping(..)
  ) where

import Prelude hiding (print)

import Control.DeepSeq (NFData)
import Data.Aeson (FromJSON(..),ToJSON(..))
import Data.Aeson (ToJSONKey(..),FromJSONKey(..))
import Data.Aeson (ToJSONKeyFunction(..),FromJSONKeyFunction(..))
import Data.Bits ((.|.),unsafeShiftL,unsafeShiftR,(.&.))
import Data.ByteString (ByteString)
import Data.ByteString.Short.Internal (ShortByteString(SBS))
import Data.Char (ord,chr)
import Data.Data (Data)
import Data.Hashable (Hashable)
import Data.Ix (Ix)
import Data.Primitive.ByteArray (ByteArray(ByteArray))
import Data.Primitive.Types (Prim(..))
import Data.Text (Text)
import Data.Text.Short (ShortText)
import Data.Word
import Data.Word.Synthetic.Word12 (Word12)
import GHC.Enum (predError, succError)
import GHC.Exts
import GHC.Generics (Generic)
import Text.ParserCombinators.ReadPrec (prec,step)
import Text.Read (Read(..),Lexeme(Ident),lexP,parens)

import qualified Arithmetic.Nat as Nat
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Types as Aeson
import qualified Data.Attoparsec.ByteString as AB
import qualified Data.Attoparsec.ByteString as ABW
import qualified Data.Attoparsec.Text as AT
import qualified Data.Bytes.Builder.Bounded as BBB
import qualified Data.Bytes as Bytes
import qualified Data.Bytes.Parser as Parser
import qualified Data.Bytes.Parser.Latin as Latin
import qualified Data.ByteString as B
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Builder.Fixed as BFB
import qualified Data.ByteString.Unsafe as BU
import qualified Data.Text.Builder.Fixed as TFB
import qualified Data.Text.IO as TIO
import qualified Data.Text.Lazy.Builder as TBuilder
import qualified Data.Text.Short.Unsafe as TS
import qualified Data.Text as Text ()
import qualified GHC.Prim.Compat as Compat
import qualified GHC.Word.Compat as Compat

#if MIN_VERSION_aeson(2,0,0)
import qualified Data.Aeson.Key as AK
#endif

-- | A 48-bit MAC address. Do not use the data constructor for this
--   type. It is not considered part of the stable API, and it
--   allows you to construct invalid MAC addresses.
newtype Mac = Mac Word64
  deriving stock (Mac -> Mac -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Mac -> Mac -> Bool
$c/= :: Mac -> Mac -> Bool
== :: Mac -> Mac -> Bool
$c== :: Mac -> Mac -> Bool
Eq,Eq Mac
Mac -> Mac -> Bool
Mac -> Mac -> Ordering
Mac -> Mac -> Mac
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Mac -> Mac -> Mac
$cmin :: Mac -> Mac -> Mac
max :: Mac -> Mac -> Mac
$cmax :: Mac -> Mac -> Mac
>= :: Mac -> Mac -> Bool
$c>= :: Mac -> Mac -> Bool
> :: Mac -> Mac -> Bool
$c> :: Mac -> Mac -> Bool
<= :: Mac -> Mac -> Bool
$c<= :: Mac -> Mac -> Bool
< :: Mac -> Mac -> Bool
$c< :: Mac -> Mac -> Bool
compare :: Mac -> Mac -> Ordering
$ccompare :: Mac -> Mac -> Ordering
Ord,forall x. Rep Mac x -> Mac
forall x. Mac -> Rep Mac x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Mac x -> Mac
$cfrom :: forall x. Mac -> Rep Mac x
Generic,Ord Mac
(Mac, Mac) -> Int
(Mac, Mac) -> [Mac]
(Mac, Mac) -> Mac -> Bool
(Mac, Mac) -> Mac -> Int
forall a.
Ord a
-> ((a, a) -> [a])
-> ((a, a) -> a -> Int)
-> ((a, a) -> a -> Int)
-> ((a, a) -> a -> Bool)
-> ((a, a) -> Int)
-> ((a, a) -> Int)
-> Ix a
unsafeRangeSize :: (Mac, Mac) -> Int
$cunsafeRangeSize :: (Mac, Mac) -> Int
rangeSize :: (Mac, Mac) -> Int
$crangeSize :: (Mac, Mac) -> Int
inRange :: (Mac, Mac) -> Mac -> Bool
$cinRange :: (Mac, Mac) -> Mac -> Bool
unsafeIndex :: (Mac, Mac) -> Mac -> Int
$cunsafeIndex :: (Mac, Mac) -> Mac -> Int
index :: (Mac, Mac) -> Mac -> Int
$cindex :: (Mac, Mac) -> Mac -> Int
range :: (Mac, Mac) -> [Mac]
$crange :: (Mac, Mac) -> [Mac]
Ix,Typeable Mac
Mac -> DataType
Mac -> Constr
(forall b. Data b => b -> b) -> Mac -> Mac
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Mac -> u
forall u. (forall d. Data d => d -> u) -> Mac -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Mac -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Mac -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Mac -> m Mac
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Mac -> m Mac
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Mac
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Mac -> c Mac
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Mac)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Mac)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Mac -> m Mac
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Mac -> m Mac
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Mac -> m Mac
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Mac -> m Mac
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Mac -> m Mac
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Mac -> m Mac
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Mac -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Mac -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> Mac -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Mac -> [u]
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Mac -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Mac -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Mac -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Mac -> r
gmapT :: (forall b. Data b => b -> b) -> Mac -> Mac
$cgmapT :: (forall b. Data b => b -> b) -> Mac -> Mac
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Mac)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Mac)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Mac)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Mac)
dataTypeOf :: Mac -> DataType
$cdataTypeOf :: Mac -> DataType
toConstr :: Mac -> Constr
$ctoConstr :: Mac -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Mac
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Mac
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Mac -> c Mac
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Mac -> c Mac
Data)
  deriving newtype (Eq Mac
Int -> Mac -> Int
Mac -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Mac -> Int
$chash :: Mac -> Int
hashWithSalt :: Int -> Mac -> Int
$chashWithSalt :: Int -> Mac -> Int
Hashable)

instance NFData Mac


-- $setup
--
-- These are here to get doctest's property checking to work
--
-- >>> :set -XOverloadedStrings
-- >>> import Test.QuickCheck (Arbitrary(..),CoArbitrary(..),coarbitraryEnum)
-- >>> import qualified Data.Text as Text (pack)
-- >>> import qualified Data.Text.IO as T
-- >>> import qualified Data.ByteString.Char8 as BC
-- >>> import qualified Data.ByteString as B
-- >>> import qualified Data.Bytes.Text.Ascii as Ascii
-- >>> import qualified Net.Mac as Mac
-- >>> import qualified Arithmetic.Nat as Nat
-- >>> import qualified Data.Attoparsec.Text as AT
-- >>> import qualified Data.Bytes.Builder.Bounded as BBB
-- >>> import Net.Mac (Mac(Mac))
-- >>> instance Arbitrary Mac where { arbitrary = fmap (Mac . (0xFFFFFFFFFFFF .&.)) arbitrary }
-- >>> instance CoArbitrary Mac where { coarbitrary = coarbitraryEnum }

-- | Construct a 'Mac' address from a 'Word64'. Only the lower
--   48 bits are used.
mac :: Word64 -> Mac
mac :: Word64 -> Mac
mac Word64
w = Word64 -> Mac
Mac (Word64
w forall a. Bits a => a -> a -> a
.&. Word64
0xFFFFFFFFFFFF)

-- | Create a 'Mac' address from six octets.
fromOctets :: Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets :: Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets Word8
a Word8
b Word8
c Word8
d Word8
e Word8
f = Word64 -> Mac
Mac forall a b. (a -> b) -> a -> b
$ Word64 -> Word64 -> Word64 -> Word64 -> Word64 -> Word64 -> Word64
unsafeWord48FromOctets
  (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
a) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
b) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
c)
  (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
d) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
e) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
f)

-- | Convert a 'Mac' address to the six octets that make it up.
--   This function and 'fromOctets' are inverses:
--
--   prop> m == (let (a,b,c,d,e,f) = Mac.toOctets m in Mac.fromOctets a b c d e f)
toOctets :: Mac -> (Word8,Word8,Word8,Word8,Word8,Word8)
toOctets :: Mac -> (Word8, Word8, Word8, Word8, Word8, Word8)
toOctets (Mac Word64
w) =
  ( forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
40
  , forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
32
  , forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
24
  , forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
16
  , forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
8
  , forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
w
  )

-- | This function is deprecated. It will be renamed in a future release
--   since the name is misleading.
decodeBytes :: ByteString -> Maybe Mac
{-# DEPRECATED decodeBytes "Prefer decodeOctets" #-}
decodeBytes :: ByteString -> Maybe Mac
decodeBytes = ByteString -> Maybe Mac
decodeOctets

-- | Decode a 'Mac' address from a 'ByteString'. Each byte is interpreted
--   as an octet of the 'Mac' address. Consequently, 'ByteString's
--   of length 6 successfully decode, and all other 'ByteString's fail
--   to decode.
--
--   >>> Mac.decodeOctets (B.pack [0x6B,0x47,0x18,0x90,0x55,0xC3])
--   Just (mac 0x6b47189055c3)
--   >>> Mac.decodeOctets (B.replicate 6 0x3A)
--   Just (mac 0x3a3a3a3a3a3a)
--   >>> Mac.decodeOctets (B.replicate 7 0x3A)
--   Nothing
--
--   Note that the octets are interpreted in a big-endian fashion.
decodeOctets :: ByteString -> Maybe Mac
decodeOctets :: ByteString -> Maybe Mac
decodeOctets ByteString
bs = if ByteString -> Int
B.length ByteString
bs forall a. Eq a => a -> a -> Bool
== Int
6
  then forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets
    (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
0)
    (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
1)
    (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
2)
    (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
3)
    (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
4)
    (ByteString -> Int -> Word8
BU.unsafeIndex ByteString
bs Int
5)
  else forall a. Maybe a
Nothing

rightToMaybe :: Either a b -> Maybe b
rightToMaybe :: forall a b. Either a b -> Maybe b
rightToMaybe = forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. a -> b -> a
const forall a. Maybe a
Nothing) forall a. a -> Maybe a
Just

c2w :: Char -> Word8
c2w :: Char -> Word8
c2w = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Int
ord

-- | Encode a 'Mac' address using the default 'MacCodec' 'defCodec'.
--
--   >>> T.putStrLn (Mac.encode (Mac 0xA47F247AB423))
--   a4:7f:24:7a:b4:23
encode :: Mac -> Text
encode :: Mac -> Text
encode = MacCodec -> Mac -> Text
encodeWith MacCodec
defCodec

-- | Encode a 'Mac' address using the given 'MacCodec'.
--
--   >>> m = Mac 0xA47F247AB423
--   >>> T.putStrLn $ Mac.encodeWith Mac.defCodec m
--   a4:7f:24:7a:b4:23
--
--   >>> T.putStrLn $ Mac.encodeWith (Mac.MacCodec (Mac.MacGroupingTriples '-') True) m
--   A47-F24-7AB-423
encodeWith :: MacCodec -> Mac -> Text
encodeWith :: MacCodec -> Mac -> Text
encodeWith (MacCodec MacGrouping
g Bool
u) Mac
m = case MacGrouping
g of
  MacGrouping
MacGroupingNoSeparator -> case Bool
u of
    Bool
True -> forall a. Builder a -> a -> Text
TFB.run (Builder Word8 -> Builder Mac
fixedBuilderNoSeparator Builder Word8
TFB.word8HexFixedUpper) Mac
m
    Bool
False -> forall a. Builder a -> a -> Text
TFB.run (Builder Word8 -> Builder Mac
fixedBuilderNoSeparator Builder Word8
TFB.word8HexFixedLower) Mac
m
  MacGroupingPairs Char
c -> case Bool
u of
    Bool
True -> forall a. Builder a -> a -> Text
TFB.run (Builder Word8 -> Builder Pair
fixedBuilderPairs Builder Word8
TFB.word8HexFixedUpper) (Char -> Mac -> Pair
Pair Char
c Mac
m)
    Bool
False -> forall a. Builder a -> a -> Text
TFB.run (Builder Word8 -> Builder Pair
fixedBuilderPairs Builder Word8
TFB.word8HexFixedLower) (Char -> Mac -> Pair
Pair Char
c Mac
m)
    -- withCasedBuilder u $ \bw8 -> TFB.run (fixedBuilderPairs bw8) (Pair c m)
  MacGroupingTriples Char
c -> case Bool
u of
    Bool
True -> forall a. Builder a -> a -> Text
TFB.run (Builder Word12 -> Builder Pair
fixedBuilderTriples Builder Word12
TFB.word12HexFixedUpper) (Char -> Mac -> Pair
Pair Char
c Mac
m)
    Bool
False -> forall a. Builder a -> a -> Text
TFB.run (Builder Word12 -> Builder Pair
fixedBuilderTriples Builder Word12
TFB.word12HexFixedLower) (Char -> Mac -> Pair
Pair Char
c Mac
m)
  MacGroupingQuadruples Char
c -> case Bool
u of
    Bool
True -> forall a. Builder a -> a -> Text
TFB.run (Builder Word8 -> Builder Pair
fixedBuilderQuadruples Builder Word8
TFB.word8HexFixedUpper) (Char -> Mac -> Pair
Pair Char
c Mac
m)
    Bool
False -> forall a. Builder a -> a -> Text
TFB.run (Builder Word8 -> Builder Pair
fixedBuilderQuadruples Builder Word8
TFB.word8HexFixedLower) (Char -> Mac -> Pair
Pair Char
c Mac
m)

-- | Decode a 'Mac' address using the default 'MacCodec' 'defCodec'.
--
--   >>> Mac.decode (Text.pack "a4:7f:24:7a:b4:23")
--   Just (mac 0xa47f247ab423)
--
--   >>> Mac.decode (Text.pack "a47-f24-7ab-423")
--   Nothing
decode :: Text -> Maybe Mac
decode :: Text -> Maybe Mac
decode = MacCodec -> Text -> Maybe Mac
decodeWith MacCodec
defCodec

-- | Decode a 'Mac' address from 'Text' using the given 'MacCodec'.
--
-- >>> Mac.decodeWith Mac.defCodec (Text.pack "a4:7f:24:7a:b4:23")
-- Just (mac 0xa47f247ab423)
--
-- >>> Mac.decodeWith (Mac.MacCodec Mac.MacGroupingNoSeparator False) (Text.pack "a47f247ab423")
-- Just (mac 0xa47f247ab423)
decodeWith :: MacCodec -> Text -> Maybe Mac
decodeWith :: MacCodec -> Text -> Maybe Mac
decodeWith MacCodec
codec Text
t = forall a b. Either a b -> Maybe b
rightToMaybe (forall a. Parser a -> Text -> Either String a
AT.parseOnly (MacCodec -> Parser Text Mac
parserWith MacCodec
codec forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall t. Chunk t => Parser t ()
AT.endOfInput) Text
t)

-- | Encode a 'Mac' address as a 'TBuilder.Builder'.
builder :: Mac -> TBuilder.Builder
builder :: Mac -> Builder
builder = Text -> Builder
TBuilder.fromText forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mac -> Text
encode

-- | Parse a 'Mac' address using a 'AT.Parser'.
--
--   >>> AT.parseOnly Mac.parser (Text.pack "a4:7f:24:7a:b4:23")
--   Right (mac 0xa47f247ab423)
--
--   >>> AT.parseOnly Mac.parser (Text.pack "a47-f24-7ab-423")
--   Left "':': Failed reading: satisfy"
parser :: AT.Parser Mac
parser :: Parser Text Mac
parser = MacCodec -> Parser Text Mac
parserWith MacCodec
defCodec

-- | Parser a 'Mac' address using the given 'MacCodec'.
--
--   >>> p1 = Mac.parserWith Mac.defCodec
--   >>> AT.parseOnly p1 (Text.pack "a4:7f:24:7a:b4:23")
--   Right (mac 0xa47f247ab423)
--
--   >>> p2 = Mac.parserWith (Mac.MacCodec Mac.MacGroupingNoSeparator False)
--   >>> AT.parseOnly p2 (Text.pack "a47f247ab423")
--   Right (mac 0xa47f247ab423)
parserWith :: MacCodec -> AT.Parser Mac
parserWith :: MacCodec -> Parser Text Mac
parserWith (MacCodec MacGrouping
g Bool
_) = case MacGrouping
g of
  MacGroupingQuadruples Char
c -> Char -> Parser Text Mac
parserQuadruples Char
c
  MacGroupingTriples Char
c -> Char -> Parser Text Mac
parserTriples Char
c
  MacGroupingPairs Char
c -> Char -> Parser Text Mac
parserPairs Char
c
  MacGrouping
MacGroupingNoSeparator -> Parser Text Mac
parserNoSeparator

-- | The default 'MacCodec': all characters are lowercase hex, separated by colons into pairs.
--
--   >>> T.putStrLn $ Mac.encodeWith Mac.defCodec (Mac 0xa47f247ab423)
--   a4:7f:24:7a:b4:23
defCodec :: MacCodec
defCodec :: MacCodec
defCodec = MacGrouping -> Bool -> MacCodec
MacCodec (Char -> MacGrouping
MacGroupingPairs Char
':') Bool
False

parserQuadruples :: Char -> AT.Parser Mac
parserQuadruples :: Char -> Parser Text Mac
parserQuadruples Char
s = Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Word8
parseTwoHex forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Char
AT.char Char
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Char
AT.char Char
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex

parserPairs :: Char -> AT.Parser Mac
parserPairs :: Char -> Parser Text Mac
parserPairs Char
s = Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Word8
parseTwoHex forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Char
AT.char Char
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Char
AT.char Char
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Char
AT.char Char
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Char
AT.char Char
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser Char
AT.char Char
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex

parserTriples :: Char -> AT.Parser Mac
parserTriples :: Char -> Parser Text Mac
parserTriples Char
s = do
  Word8
a1 <- Parser Word8
parseOneHex
  Word8
a2 <- Parser Word8
parseOneHex
  Word8
a3 <- Parser Word8
parseOneHex
  Char
_ <- Char -> Parser Char
AT.char Char
s
  Word8
a4 <- Parser Word8
parseOneHex
  Word8
a5 <- Parser Word8
parseOneHex
  Word8
a6 <- Parser Word8
parseOneHex
  Char
_ <- Char -> Parser Char
AT.char Char
s
  Word8
a7 <- Parser Word8
parseOneHex
  Word8
a8 <- Parser Word8
parseOneHex
  Word8
a9 <- Parser Word8
parseOneHex
  Char
_ <- Char -> Parser Char
AT.char Char
s
  Word8
a10 <- Parser Word8
parseOneHex
  Word8
a11 <- Parser Word8
parseOneHex
  Word8
a12 <- Parser Word8
parseOneHex
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a1 Int
4 forall a. Num a => a -> a -> a
+ Word8
a2)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a3 Int
4 forall a. Num a => a -> a -> a
+ Word8
a4)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a5 Int
4 forall a. Num a => a -> a -> a
+ Word8
a6)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a7 Int
4 forall a. Num a => a -> a -> a
+ Word8
a8)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a9 Int
4 forall a. Num a => a -> a -> a
+ Word8
a10)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a11 Int
4 forall a. Num a => a -> a -> a
+ Word8
a12)

parserNoSeparator :: AT.Parser Mac
parserNoSeparator :: Parser Text Mac
parserNoSeparator = Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Word8
parseTwoHex
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHex

parseTwoHex :: AT.Parser Word8
parseTwoHex :: Parser Word8
parseTwoHex = do
  Word8
a <- Parser Char
AT.anyChar forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Char -> Parser Word8
parseCharHex
  Word8
b <- Parser Char
AT.anyChar forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Char -> Parser Word8
parseCharHex
  forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a Int
4 forall a. Num a => a -> a -> a
+ Word8
b)

tryParseCharHex :: AT.Parser Word8 -> Char -> AT.Parser Word8
tryParseCharHex :: Parser Word8 -> Char -> Parser Word8
tryParseCharHex Parser Word8
a Char
c
  | Word8
w forall a. Ord a => a -> a -> Bool
>= Word8
48 Bool -> Bool -> Bool
&& Word8
w forall a. Ord a => a -> a -> Bool
<= Word8
57 = forall (m :: * -> *) a. Monad m => a -> m a
return (Word8
w forall a. Num a => a -> a -> a
- Word8
48)
  | Word8
w forall a. Ord a => a -> a -> Bool
>= Word8
65 Bool -> Bool -> Bool
&& Word8
w forall a. Ord a => a -> a -> Bool
<= Word8
70 = forall (m :: * -> *) a. Monad m => a -> m a
return (Word8
w forall a. Num a => a -> a -> a
- Word8
55)
  | Word8
w forall a. Ord a => a -> a -> Bool
>= Word8
97 Bool -> Bool -> Bool
&& Word8
w forall a. Ord a => a -> a -> Bool
<= Word8
102 = forall (m :: * -> *) a. Monad m => a -> m a
return (Word8
w forall a. Num a => a -> a -> a
- Word8
87)
  | Bool
otherwise = Parser Word8
a
  where w :: Word8
w = Char -> Word8
c2w Char
c

parseOneHex :: AT.Parser Word8
parseOneHex :: Parser Word8
parseOneHex = Parser Char
AT.anyChar forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Char -> Parser Word8
parseCharHex

parseCharHex :: Char -> AT.Parser Word8
parseCharHex :: Char -> Parser Word8
parseCharHex = Parser Word8 -> Char -> Parser Word8
tryParseCharHex (forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalid hexadecimal character")

data Pair = Pair
  { Pair -> Char
pairSep :: {-# UNPACK #-} !Char
  , Pair -> Mac
pairMac :: {-# UNPACK #-} !Mac
  }

fixedBuilderTriples :: TFB.Builder Word12 -> TFB.Builder Pair
fixedBuilderTriples :: Builder Word12 -> Builder Pair
fixedBuilderTriples Builder Word12
tripBuilder =
     forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word12
word12At Int
36 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word12
tripBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder Pair -> Char
pairSep Builder Char
TFB.charBmp
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word12
word12At Int
24 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word12
tripBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder Pair -> Char
pairSep Builder Char
TFB.charBmp
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word12
word12At Int
12 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word12
tripBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder Pair -> Char
pairSep Builder Char
TFB.charBmp
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word12
word12At Int
0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word12
tripBuilder
{-# INLINE fixedBuilderTriples #-}

fixedBuilderNoSeparator :: TFB.Builder Word8 -> TFB.Builder Mac
fixedBuilderNoSeparator :: Builder Word8 -> Builder Mac
fixedBuilderNoSeparator Builder Word8
hexBuilder =
     forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
40) Builder Word8
hexBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
32) Builder Word8
hexBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
24) Builder Word8
hexBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
16) Builder Word8
hexBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
8) Builder Word8
hexBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
0) Builder Word8
hexBuilder
{-# INLINE fixedBuilderNoSeparator #-}

fixedBuilderQuadruples :: TFB.Builder Word8 -> TFB.Builder Pair
fixedBuilderQuadruples :: Builder Word8 -> Builder Pair
fixedBuilderQuadruples Builder Word8
pairBuilder =
     forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
40 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
32 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder Pair -> Char
pairSep Builder Char
TFB.charBmp
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
24 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
16 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder Pair -> Char
pairSep Builder Char
TFB.charBmp
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
8 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
{-# INLINE fixedBuilderQuadruples #-}

fixedBuilderPairs :: TFB.Builder Word8 -> TFB.Builder Pair
fixedBuilderPairs :: Builder Word8 -> Builder Pair
fixedBuilderPairs Builder Word8
pairBuilder =
     forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
40 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder Pair -> Char
pairSep Builder Char
TFB.charBmp
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
32 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder Pair -> Char
pairSep Builder Char
TFB.charBmp
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
24 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder Pair -> Char
pairSep Builder Char
TFB.charBmp
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
16 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder Pair -> Char
pairSep Builder Char
TFB.charBmp
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
8 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder Pair -> Char
pairSep Builder Char
TFB.charBmp
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
TFB.contramapBuilder (Int -> Mac -> Word8
word8At Int
0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Pair -> Mac
pairMac) Builder Word8
pairBuilder
{-# INLINE fixedBuilderPairs #-}

word8At :: Int -> Mac -> Word8
word8At :: Int -> Mac -> Word8
word8At Int
i (Mac Word64
w) = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
i)
{-# INLINE word8At #-}

word12At :: Int -> Mac -> Word12
word12At :: Int -> Mac -> Word12
word12At Int
i (Mac Word64
w) = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
i)
{-# INLINE word12At #-}

-- | Encode a 'Mac' address using the default 'MacCodec' 'defCodec'.
--
--   >>> BC.putStrLn (Mac.encodeUtf8 (Mac.mac 0x64255A0F2C47))
--   64:25:5a:0f:2c:47
encodeUtf8 :: Mac -> ByteString
encodeUtf8 :: Mac -> ByteString
encodeUtf8 = MacCodec -> Mac -> ByteString
encodeWithUtf8 MacCodec
defCodec

-- | Lenient decoding of MAC address that accepts lowercase, uppercase,
--   and any kind of separator.
--
--   >>> Mac.decodeUtf8 "A2:DE:AD:BE:EF:67"
--   Just (mac 0xa2deadbeef67)
--   >>> Mac.decodeUtf8 "13-a2-fe-a4-17-96"
--   Just (mac 0x13a2fea41796)
--   >>> Mac.decodeUtf8 "0A42.47BA.67C2"
--   Just (mac 0x0a4247ba67c2)
decodeUtf8 :: ByteString -> Maybe Mac
decodeUtf8 :: ByteString -> Maybe Mac
decodeUtf8 = ByteString -> Maybe Mac
decodeLenientUtf8

-- | Decode a 'ByteString' as a 'Mac' address using the given 'MacCodec'.
--
--   >>> Mac.decodeWithUtf8 Mac.defCodec (BC.pack "64:25:5a:0f:2c:47")
--   Just (mac 0x64255a0f2c47)
--
--   >>> Mac.decodeWithUtf8 (Mac.MacCodec Mac.MacGroupingNoSeparator False) (BC.pack "64255a0f2c47")
--   Just (mac 0x64255a0f2c47)
decodeWithUtf8 :: MacCodec -> ByteString -> Maybe Mac
decodeWithUtf8 :: MacCodec -> ByteString -> Maybe Mac
decodeWithUtf8 MacCodec
codec ByteString
bs = forall a b. Either a b -> Maybe b
rightToMaybe (forall a. Parser a -> ByteString -> Either String a
AB.parseOnly (MacCodec -> Parser ByteString Mac
parserWithUtf8 MacCodec
codec forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall t. Chunk t => Parser t ()
AB.endOfInput) ByteString
bs)

decodeLenientUtf8 :: ByteString -> Maybe Mac
decodeLenientUtf8 :: ByteString -> Maybe Mac
decodeLenientUtf8 ByteString
bs = forall a b. Either a b -> Maybe b
rightToMaybe (forall a. Parser a -> ByteString -> Either String a
AB.parseOnly (Parser ByteString Mac
parserLenientUtf8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall t. Chunk t => Parser t ()
AB.endOfInput) ByteString
bs)

-- | Encode a 'Mac' address as colon-separated hexadecimal octets,
--   preferring lowercase for alphabetical characters.
encodeShort :: Mac -> ShortText
encodeShort :: Mac -> ShortText
encodeShort !Mac
m = case forall (n :: Nat). Nat n -> Builder n -> ByteArray
BBB.run forall (n :: Nat). KnownNat n => Nat n
Nat.constant (Mac -> Builder 17
boundedBuilderUtf8 Mac
m) of
  ByteArray ByteArray#
x -> ShortByteString -> ShortText
TS.fromShortByteStringUnsafe (ByteArray# -> ShortByteString
SBS ByteArray#
x)

-- | Encode a 'Mac' address as colon-separated hexadecimal octets,
--   preferring lowercase for alphabetical characters.
--
--   >>> BBB.run Nat.constant $ Mac.boundedBuilderUtf8 $ Mac.mac 0xDEADBEEF1609
--   [0x64, 0x65, 0x3a, 0x61, 0x64, 0x3a, 0x62, 0x65, 0x3a, 0x65, 0x66, 0x3a, 0x31, 0x36, 0x3a, 0x30, 0x39]
boundedBuilderUtf8 :: Mac -> BBB.Builder 17
boundedBuilderUtf8 :: Mac -> Builder 17
boundedBuilderUtf8 !Mac
w =
  Word8 -> Builder 2
BBB.word8PaddedLowerHex Word8
w0
  forall (m :: Nat) (n :: Nat).
Builder m -> Builder n -> Builder (m + n)
`BBB.append`
  Char -> Builder 1
BBB.ascii Char
':'
  forall (m :: Nat) (n :: Nat).
Builder m -> Builder n -> Builder (m + n)
`BBB.append`
  Word8 -> Builder 2
BBB.word8PaddedLowerHex Word8
w1
  forall (m :: Nat) (n :: Nat).
Builder m -> Builder n -> Builder (m + n)
`BBB.append`
  Char -> Builder 1
BBB.ascii Char
':'
  forall (m :: Nat) (n :: Nat).
Builder m -> Builder n -> Builder (m + n)
`BBB.append`
  Word8 -> Builder 2
BBB.word8PaddedLowerHex Word8
w2
  forall (m :: Nat) (n :: Nat).
Builder m -> Builder n -> Builder (m + n)
`BBB.append`
  Char -> Builder 1
BBB.ascii Char
':'
  forall (m :: Nat) (n :: Nat).
Builder m -> Builder n -> Builder (m + n)
`BBB.append`
  Word8 -> Builder 2
BBB.word8PaddedLowerHex Word8
w3
  forall (m :: Nat) (n :: Nat).
Builder m -> Builder n -> Builder (m + n)
`BBB.append`
  Char -> Builder 1
BBB.ascii Char
':'
  forall (m :: Nat) (n :: Nat).
Builder m -> Builder n -> Builder (m + n)
`BBB.append`
  Word8 -> Builder 2
BBB.word8PaddedLowerHex Word8
w4
  forall (m :: Nat) (n :: Nat).
Builder m -> Builder n -> Builder (m + n)
`BBB.append`
  Char -> Builder 1
BBB.ascii Char
':'
  forall (m :: Nat) (n :: Nat).
Builder m -> Builder n -> Builder (m + n)
`BBB.append`
  Word8 -> Builder 2
BBB.word8PaddedLowerHex Word8
w5
  where
  (Word8
w0,Word8
w1,Word8
w2,Word8
w3,Word8
w4,Word8
w5) = Mac -> (Word8, Word8, Word8, Word8, Word8, Word8)
toOctets Mac
w

-- | Lenient decoding of MAC address. This
--   is case insensitive and allows either @:@ or @-@ as the separator.
--   It also allows leading zeroes to be missing.
--
--   >>> Mac.decodeUtf8Bytes (Ascii.fromString "A2:DE:AD:BE:EF:67")
--   Just (mac 0xa2deadbeef67)
--   >>> Mac.decodeUtf8Bytes (Ascii.fromString "13-a2-FE-A4-17-96")
--   Just (mac 0x13a2fea41796)
decodeUtf8Bytes :: Bytes.Bytes -> Maybe Mac
decodeUtf8Bytes :: Bytes -> Maybe Mac
decodeUtf8Bytes = forall e a. (forall s. Parser e s a) -> Bytes -> Maybe a
Parser.parseBytesMaybe (forall e s. e -> Parser e s Mac
parserUtf8Bytes ())

-- | Leniently parse UTF-8-encoded 'Bytes' as a 'Mac' address. This
--   is case insensitive and allows either @:@ or @-@ as the separator.
--   It also allows leading zeroes to be missing.
--
--   >>> Parser.parseBytes (Mac.parserUtf8Bytes ()) (Ascii.fromString "de:ad:BE:EF:1:23")
--   Success (Slice {offset = 16, length = 0, value = mac 0xdeadbeef0123})
parserUtf8Bytes :: e -> Parser.Parser e s Mac
parserUtf8Bytes :: forall e s. e -> Parser e s Mac
parserUtf8Bytes e
e = do
  Word8
w1 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e
  forall e s. e -> Parser e s Char
Latin.any e
e forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Char
':' -> do
      Word8
w2 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s. e -> Char -> Parser e s ()
Latin.char e
e Char
':'
      Word8
w3 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s. e -> Char -> Parser e s ()
Latin.char e
e Char
':'
      Word8
w4 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s. e -> Char -> Parser e s ()
Latin.char e
e Char
':'
      Word8
w5 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s. e -> Char -> Parser e s ()
Latin.char e
e Char
':'
      Word8
w6 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e
      forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets Word8
w1 Word8
w2 Word8
w3 Word8
w4 Word8
w5 Word8
w6)
    Char
'-' -> do
      Word8
w2 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s. e -> Char -> Parser e s ()
Latin.char e
e Char
'-'
      Word8
w3 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s. e -> Char -> Parser e s ()
Latin.char e
e Char
'-'
      Word8
w4 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s. e -> Char -> Parser e s ()
Latin.char e
e Char
'-'
      Word8
w5 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s. e -> Char -> Parser e s ()
Latin.char e
e Char
'-'
      Word8
w6 <- forall e s. e -> Parser e s Word8
Latin.hexWord8 e
e
      forall (f :: * -> *) a. Applicative f => a -> f a
pure (Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets Word8
w1 Word8
w2 Word8
w3 Word8
w4 Word8
w5 Word8
w6)
    Char
_ -> forall e s a. e -> Parser e s a
Parser.fail e
e

-- | Make a bytestring builder from a 'Mac' address
--   using a colon as the separator.
builderUtf8 :: Mac -> BB.Builder
builderUtf8 :: Mac -> Builder
builderUtf8 = ByteString -> Builder
BB.byteString forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mac -> ByteString
encodeUtf8

-- | Lenient parser for a 'Mac' address using any character
--   as the separator and accepting any digit grouping
--   (i.e. @FA:43:B2:C0:0F:99@ or @A065.647B.87FA@).
parserUtf8 :: AB.Parser Mac
parserUtf8 :: Parser ByteString Mac
parserUtf8 = Parser ByteString Mac
parserLenientUtf8

-- | Parser for a 'Mac' address using the provided settings.
parserWithUtf8 :: MacCodec -> AB.Parser Mac
parserWithUtf8 :: MacCodec -> Parser ByteString Mac
parserWithUtf8 (MacCodec MacGrouping
g Bool
_) = case MacGrouping
g of
  MacGroupingPairs Char
s -> Word8 -> Parser ByteString Mac
parserPairsUtf8 (Char -> Word8
c2w Char
s)
  MacGroupingTriples Char
s -> Word8 -> Parser ByteString Mac
parserTriplesUtf8 (Char -> Word8
c2w Char
s)
  MacGroupingQuadruples Char
s -> Word8 -> Parser ByteString Mac
parserQuadruplesUtf8 (Char -> Word8
c2w Char
s)
  MacGrouping
MacGroupingNoSeparator -> Parser ByteString Mac
parserNoSeparatorUtf8

parserLenientUtf8 :: AB.Parser Mac
parserLenientUtf8 :: Parser ByteString Mac
parserLenientUtf8 = do
  Word8
a1 <- Parser Word8
parseOneHexUtf8
  Word8
a2 <- Parser Word8
parseOneHexLenientUtf8
  Word8
a3 <- Parser Word8
parseOneHexLenientUtf8
  Word8
a4 <- Parser Word8
parseOneHexLenientUtf8
  Word8
a5 <- Parser Word8
parseOneHexLenientUtf8
  Word8
a6 <- Parser Word8
parseOneHexLenientUtf8
  Word8
a7 <- Parser Word8
parseOneHexLenientUtf8
  Word8
a8 <- Parser Word8
parseOneHexLenientUtf8
  Word8
a9 <- Parser Word8
parseOneHexLenientUtf8
  Word8
a10 <- Parser Word8
parseOneHexLenientUtf8
  Word8
a11 <- Parser Word8
parseOneHexLenientUtf8
  Word8
a12 <- Parser Word8
parseOneHexLenientUtf8
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a1 Int
4 forall a. Num a => a -> a -> a
+ Word8
a2)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a3 Int
4 forall a. Num a => a -> a -> a
+ Word8
a4)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a5 Int
4 forall a. Num a => a -> a -> a
+ Word8
a6)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a7 Int
4 forall a. Num a => a -> a -> a
+ Word8
a8)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a9 Int
4 forall a. Num a => a -> a -> a
+ Word8
a10)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a11 Int
4 forall a. Num a => a -> a -> a
+ Word8
a12)


parserNoSeparatorUtf8 :: AB.Parser Mac
parserNoSeparatorUtf8 :: Parser ByteString Mac
parserNoSeparatorUtf8 = Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Word8
parseTwoHexUtf8
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8

parserPairsUtf8 :: Word8 -> AB.Parser Mac
parserPairsUtf8 :: Word8 -> Parser ByteString Mac
parserPairsUtf8 Word8
s = Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Word8
parseTwoHexUtf8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Word8 -> Parser Word8
ABW.word8 Word8
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Word8 -> Parser Word8
ABW.word8 Word8
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Word8 -> Parser Word8
ABW.word8 Word8
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Word8 -> Parser Word8
ABW.word8 Word8
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Word8 -> Parser Word8
ABW.word8 Word8
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8

parserTriplesUtf8 :: Word8 -> AB.Parser Mac
parserTriplesUtf8 :: Word8 -> Parser ByteString Mac
parserTriplesUtf8 Word8
s = do
  Word8
a1 <- Parser Word8
parseOneHexUtf8
  Word8
a2 <- Parser Word8
parseOneHexUtf8
  Word8
a3 <- Parser Word8
parseOneHexUtf8
  Word8
_ <- Word8 -> Parser Word8
ABW.word8 Word8
s
  Word8
a4 <- Parser Word8
parseOneHexUtf8
  Word8
a5 <- Parser Word8
parseOneHexUtf8
  Word8
a6 <- Parser Word8
parseOneHexUtf8
  Word8
_ <- Word8 -> Parser Word8
ABW.word8 Word8
s
  Word8
a7 <- Parser Word8
parseOneHexUtf8
  Word8
a8 <- Parser Word8
parseOneHexUtf8
  Word8
a9 <- Parser Word8
parseOneHexUtf8
  Word8
_ <- Word8 -> Parser Word8
ABW.word8 Word8
s
  Word8
a10 <- Parser Word8
parseOneHexUtf8
  Word8
a11 <- Parser Word8
parseOneHexUtf8
  Word8
a12 <- Parser Word8
parseOneHexUtf8
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a1 Int
4 forall a. Num a => a -> a -> a
+ Word8
a2)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a3 Int
4 forall a. Num a => a -> a -> a
+ Word8
a4)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a5 Int
4 forall a. Num a => a -> a -> a
+ Word8
a6)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a7 Int
4 forall a. Num a => a -> a -> a
+ Word8
a8)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a9 Int
4 forall a. Num a => a -> a -> a
+ Word8
a10)
    (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a11 Int
4 forall a. Num a => a -> a -> a
+ Word8
a12)

parserQuadruplesUtf8 :: Word8 -> AB.Parser Mac
parserQuadruplesUtf8 :: Word8 -> Parser ByteString Mac
parserQuadruplesUtf8 Word8
s  = Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Mac
fromOctets
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Word8
parseTwoHexUtf8 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Word8 -> Parser Word8
ABW.word8 Word8
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Word8 -> Parser Word8
ABW.word8 Word8
s
  forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8 forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Word8
parseTwoHexUtf8

parseOneHexUtf8 :: AB.Parser Word8
parseOneHexUtf8 :: Parser Word8
parseOneHexUtf8 = Parser Word8
ABW.anyWord8 forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Word8 -> Parser Word8
parseWord8Hex

-- | Parse a single hexidecimal character. This will skip
--   at most one character to do this.
parseOneHexLenientUtf8 :: AB.Parser Word8
parseOneHexLenientUtf8 :: Parser Word8
parseOneHexLenientUtf8 = do
  Word8
a <- Parser Word8
ABW.anyWord8
  forall a b c. (a -> b -> c) -> b -> a -> c
flip Parser Word8 -> Word8 -> Parser Word8
tryParseWord8Hex Word8
a forall a b. (a -> b) -> a -> b
$ do
    Word8
b <- Parser Word8
ABW.anyWord8
    Parser Word8 -> Word8 -> Parser Word8
tryParseWord8Hex (forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalid hexadecimal character") Word8
b

parseTwoHexUtf8 :: AB.Parser Word8
parseTwoHexUtf8 :: Parser Word8
parseTwoHexUtf8 = do
  Word8
a <- Parser Word8
ABW.anyWord8 forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Word8 -> Parser Word8
parseWord8Hex
  Word8
b <- Parser Word8
ABW.anyWord8 forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Word8 -> Parser Word8
parseWord8Hex
  forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. Bits a => a -> Int -> a
unsafeShiftL Word8
a Int
4 forall a. Num a => a -> a -> a
+ Word8
b)

-- | Kind of a confusing type signature. The Word8 that stands
--   alone represented an ascii-encoded value. The others actually
--   describes the numbers that would be decoded from this value.
tryParseWord8Hex :: AB.Parser Word8 -> Word8 -> AB.Parser Word8
tryParseWord8Hex :: Parser Word8 -> Word8 -> Parser Word8
tryParseWord8Hex Parser Word8
a Word8
w
  | Word8
w forall a. Ord a => a -> a -> Bool
>= Word8
48 Bool -> Bool -> Bool
&& Word8
w forall a. Ord a => a -> a -> Bool
<= Word8
57 = forall (m :: * -> *) a. Monad m => a -> m a
return (Word8
w forall a. Num a => a -> a -> a
- Word8
48)
  | Word8
w forall a. Ord a => a -> a -> Bool
>= Word8
65 Bool -> Bool -> Bool
&& Word8
w forall a. Ord a => a -> a -> Bool
<= Word8
70 = forall (m :: * -> *) a. Monad m => a -> m a
return (Word8
w forall a. Num a => a -> a -> a
- Word8
55)
  | Word8
w forall a. Ord a => a -> a -> Bool
>= Word8
97 Bool -> Bool -> Bool
&& Word8
w forall a. Ord a => a -> a -> Bool
<= Word8
102 = forall (m :: * -> *) a. Monad m => a -> m a
return (Word8
w forall a. Num a => a -> a -> a
- Word8
87)
  | Bool
otherwise = Parser Word8
a

parseWord8Hex :: Word8 -> AB.Parser Word8
parseWord8Hex :: Word8 -> Parser Word8
parseWord8Hex = Parser Word8 -> Word8 -> Parser Word8
tryParseWord8Hex (forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalid hexadecimal character")

-- | Encode a 'Mac' address as a 'ByteString' using the given 'MacCodec'.
--
--   >>> m = Mac 0xA47F247AB423
--   >>> BC.putStrLn $ Mac.encodeWithUtf8 Mac.defCodec m
--   a4:7f:24:7a:b4:23
--
--   >>> BC.putStrLn $ Mac.encodeWithUtf8 (Mac.MacCodec (Mac.MacGroupingTriples '-') True) m
--   A47-F24-7AB-423
encodeWithUtf8 :: MacCodec -> Mac -> ByteString
encodeWithUtf8 :: MacCodec -> Mac -> ByteString
encodeWithUtf8 (MacCodec MacGrouping
g Bool
u) Mac
m = case MacGrouping
g of
  MacGrouping
MacGroupingNoSeparator -> case Bool
u of
    Bool
True -> forall a. Builder a -> a -> ByteString
BFB.run (Builder Word8 -> Builder Mac
fixedBuilderNoSeparatorUtf8 Builder Word8
BFB.word8HexFixedUpper) Mac
m
    Bool
False -> forall a. Builder a -> a -> ByteString
BFB.run (Builder Word8 -> Builder Mac
fixedBuilderNoSeparatorUtf8 Builder Word8
BFB.word8HexFixedLower) Mac
m
  MacGroupingPairs Char
c -> case Bool
u of
    Bool
True -> forall a. Builder a -> a -> ByteString
BFB.run (Builder Word8 -> Builder PairUtf8
fixedBuilderPairsUtf8 Builder Word8
BFB.word8HexFixedUpper) (Word8 -> Mac -> PairUtf8
PairUtf8 (Char -> Word8
c2w Char
c) Mac
m)
    Bool
False -> forall a. Builder a -> a -> ByteString
BFB.run (Builder Word8 -> Builder PairUtf8
fixedBuilderPairsUtf8 Builder Word8
BFB.word8HexFixedLower) (Word8 -> Mac -> PairUtf8
PairUtf8 (Char -> Word8
c2w Char
c) Mac
m)
    -- withCasedBuilder u $ \bw8 -> BFB.run (fixedBuilderPairs bw8) (Pair c m)
  MacGroupingTriples Char
c -> case Bool
u of
    Bool
True -> forall a. Builder a -> a -> ByteString
BFB.run (Builder Word12 -> Builder PairUtf8
fixedBuilderTriplesUtf8 Builder Word12
BFB.word12HexFixedUpper) (Word8 -> Mac -> PairUtf8
PairUtf8 (Char -> Word8
c2w Char
c) Mac
m)
    Bool
False -> forall a. Builder a -> a -> ByteString
BFB.run (Builder Word12 -> Builder PairUtf8
fixedBuilderTriplesUtf8 Builder Word12
BFB.word12HexFixedLower) (Word8 -> Mac -> PairUtf8
PairUtf8 (Char -> Word8
c2w Char
c) Mac
m)
  MacGroupingQuadruples Char
c -> case Bool
u of
    Bool
True -> forall a. Builder a -> a -> ByteString
BFB.run (Builder Word8 -> Builder PairUtf8
fixedBuilderQuadruplesUtf8 Builder Word8
BFB.word8HexFixedUpper) (Word8 -> Mac -> PairUtf8
PairUtf8 (Char -> Word8
c2w Char
c) Mac
m)
    Bool
False -> forall a. Builder a -> a -> ByteString
BFB.run (Builder Word8 -> Builder PairUtf8
fixedBuilderQuadruplesUtf8 Builder Word8
BFB.word8HexFixedLower) (Word8 -> Mac -> PairUtf8
PairUtf8 (Char -> Word8
c2w Char
c) Mac
m)

data PairUtf8 = PairUtf8
  { PairUtf8 -> Word8
pairSepUtf8 :: {-# UNPACK #-} !Word8
  , PairUtf8 -> Mac
pairMacUtf8 :: {-# UNPACK #-} !Mac
  }

fixedBuilderTriplesUtf8 :: BFB.Builder Word12 -> BFB.Builder PairUtf8
fixedBuilderTriplesUtf8 :: Builder Word12 -> Builder PairUtf8
fixedBuilderTriplesUtf8 Builder Word12
tripBuilder =
     forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word12
word12AtUtf8 Int
36 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word12
tripBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder PairUtf8 -> Word8
pairSepUtf8 Builder Word8
BFB.word8
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word12
word12AtUtf8 Int
24 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word12
tripBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder PairUtf8 -> Word8
pairSepUtf8 Builder Word8
BFB.word8
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word12
word12AtUtf8 Int
12 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word12
tripBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder PairUtf8 -> Word8
pairSepUtf8 Builder Word8
BFB.word8
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word12
word12AtUtf8 Int
0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word12
tripBuilder
{-# INLINE fixedBuilderTriplesUtf8 #-}

fixedBuilderQuadruplesUtf8 :: BFB.Builder Word8 -> BFB.Builder PairUtf8
fixedBuilderQuadruplesUtf8 :: Builder Word8 -> Builder PairUtf8
fixedBuilderQuadruplesUtf8 Builder Word8
pairBuilder =
     forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
40 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
32 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder PairUtf8 -> Word8
pairSepUtf8 Builder Word8
BFB.word8
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
24 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
16 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder PairUtf8 -> Word8
pairSepUtf8 Builder Word8
BFB.word8
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
8 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
{-# INLINE fixedBuilderQuadruplesUtf8 #-}

fixedBuilderPairsUtf8 :: BFB.Builder Word8 -> BFB.Builder PairUtf8
fixedBuilderPairsUtf8 :: Builder Word8 -> Builder PairUtf8
fixedBuilderPairsUtf8 Builder Word8
pairBuilder =
     forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
40 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder PairUtf8 -> Word8
pairSepUtf8 Builder Word8
BFB.word8
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
32 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder PairUtf8 -> Word8
pairSepUtf8 Builder Word8
BFB.word8
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
24 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder PairUtf8 -> Word8
pairSepUtf8 Builder Word8
BFB.word8
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
16 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder PairUtf8 -> Word8
pairSepUtf8 Builder Word8
BFB.word8
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
8 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder PairUtf8 -> Word8
pairSepUtf8 Builder Word8
BFB.word8
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. PairUtf8 -> Mac
pairMacUtf8) Builder Word8
pairBuilder
{-# INLINE fixedBuilderPairsUtf8 #-}

fixedBuilderNoSeparatorUtf8 :: BFB.Builder Word8 -> BFB.Builder Mac
fixedBuilderNoSeparatorUtf8 :: Builder Word8 -> Builder Mac
fixedBuilderNoSeparatorUtf8 Builder Word8
hexBuilder =
     forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
40) Builder Word8
hexBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
32) Builder Word8
hexBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
24) Builder Word8
hexBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
16) Builder Word8
hexBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
8) Builder Word8
hexBuilder
  forall a. Semigroup a => a -> a -> a
<> forall b a. (b -> a) -> Builder a -> Builder b
BFB.contramapBuilder (Int -> Mac -> Word8
word8AtUtf8 Int
0) Builder Word8
hexBuilder
{-# INLINE fixedBuilderNoSeparatorUtf8 #-}

word8AtUtf8 :: Int -> Mac -> Word8
word8AtUtf8 :: Int -> Mac -> Word8
word8AtUtf8 Int
i (Mac Word64
w) = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
i)
{-# INLINE word8AtUtf8 #-}

word12AtUtf8 :: Int -> Mac -> Word12
word12AtUtf8 :: Int -> Mac -> Word12
word12AtUtf8 Int
i (Mac Word64
w) = forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
i)
{-# INLINE word12AtUtf8 #-}

-- | This only preserves the lower 6 bytes of the 8-byte word that backs a mac address.
-- It runs slower than it would if it used a full 8-byte word, but it consumes less
-- space. When storing millions of mac addresses, this is a good trade to make. When
-- storing a small number of mac address, it might be preferable to make a primitive
-- array of 'Word64' instead and use the mac address data constructor to coerce between
-- the two.
instance Prim Mac where
  sizeOf# :: Mac -> Int#
sizeOf# Mac
_ = Int#
6#
  alignment# :: Mac -> Int#
alignment# Mac
_ = Int#
2#
  indexByteArray# :: ByteArray# -> Int# -> Mac
indexByteArray# ByteArray#
arr Int#
i0 = Word# -> Word# -> Word# -> Mac
macFromWord16#
    (ByteArray# -> Int# -> Word#
Compat.indexWord16Array# ByteArray#
arr Int#
i)
    (ByteArray# -> Int# -> Word#
Compat.indexWord16Array# ByteArray#
arr (Int#
i Int# -> Int# -> Int#
+# Int#
1#))
    (ByteArray# -> Int# -> Word#
Compat.indexWord16Array# ByteArray#
arr (Int#
i Int# -> Int# -> Int#
+# Int#
2#))
    where !i :: Int#
i = Int#
3# Int# -> Int# -> Int#
*# Int#
i0
  readByteArray# :: forall s.
MutableByteArray# s -> Int# -> State# s -> (# State# s, Mac #)
readByteArray# MutableByteArray# s
arr Int#
i0 State# s
s0 = case forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
Compat.readWord16Array# MutableByteArray# s
arr Int#
i State# s
s0 of
    (# State# s
s1, Word#
a #) -> case forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
Compat.readWord16Array# MutableByteArray# s
arr (Int#
i Int# -> Int# -> Int#
+# Int#
1#) State# s
s1 of
      (# State# s
s2, Word#
b #) -> case forall d.
MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
Compat.readWord16Array# MutableByteArray# s
arr (Int#
i Int# -> Int# -> Int#
+# Int#
2#) State# s
s2 of
        (# State# s
s3, Word#
c #) -> (# State# s
s3, Word# -> Word# -> Word# -> Mac
macFromWord16# Word#
a Word#
b Word#
c #)
    where !i :: Int#
i = Int#
3# Int# -> Int# -> Int#
*# Int#
i0
  writeByteArray# :: forall s.
MutableByteArray# s -> Int# -> Mac -> State# s -> State# s
writeByteArray# MutableByteArray# s
arr Int#
i0 Mac
m State# s
s0 = case forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
Compat.writeWord16Array# MutableByteArray# s
arr Int#
i (Mac -> Word#
macToWord16A# Mac
m) State# s
s0 of
    State# s
s1 -> case forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
Compat.writeWord16Array# MutableByteArray# s
arr (Int#
i Int# -> Int# -> Int#
+# Int#
1#) (Mac -> Word#
macToWord16B# Mac
m) State# s
s1 of
      State# s
s2 -> forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
Compat.writeWord16Array# MutableByteArray# s
arr (Int#
i Int# -> Int# -> Int#
+# Int#
2#) (Mac -> Word#
macToWord16C# Mac
m) State# s
s2
    where !i :: Int#
i = Int#
3# Int# -> Int# -> Int#
*# Int#
i0
  indexOffAddr# :: Addr# -> Int# -> Mac
indexOffAddr# Addr#
arr Int#
i0 = Word# -> Word# -> Word# -> Mac
macFromWord16#
    (Addr# -> Int# -> Word#
Compat.indexWord16OffAddr# Addr#
arr Int#
i)
    (Addr# -> Int# -> Word#
Compat.indexWord16OffAddr# Addr#
arr (Int#
i Int# -> Int# -> Int#
+# Int#
1#))
    (Addr# -> Int# -> Word#
Compat.indexWord16OffAddr# Addr#
arr (Int#
i Int# -> Int# -> Int#
+# Int#
2#))
    where !i :: Int#
i = Int#
3# Int# -> Int# -> Int#
*# Int#
i0
  readOffAddr# :: forall s. Addr# -> Int# -> State# s -> (# State# s, Mac #)
readOffAddr# Addr#
arr Int#
i0 State# s
s0 = case forall d. Addr# -> Int# -> State# d -> (# State# d, Word# #)
Compat.readWord16OffAddr# Addr#
arr Int#
i State# s
s0 of
    (# State# s
s1, Word#
a #) -> case forall d. Addr# -> Int# -> State# d -> (# State# d, Word# #)
Compat.readWord16OffAddr# Addr#
arr (Int#
i Int# -> Int# -> Int#
+# Int#
1#) State# s
s1 of
      (# State# s
s2, Word#
b #) -> case forall d. Addr# -> Int# -> State# d -> (# State# d, Word# #)
Compat.readWord16OffAddr# Addr#
arr (Int#
i Int# -> Int# -> Int#
+# Int#
2#) State# s
s2 of
        (# State# s
s3, Word#
c #) -> (# State# s
s3, Word# -> Word# -> Word# -> Mac
macFromWord16# Word#
a Word#
b Word#
c #)
    where !i :: Int#
i = Int#
3# Int# -> Int# -> Int#
*# Int#
i0
  writeOffAddr# :: forall s. Addr# -> Int# -> Mac -> State# s -> State# s
writeOffAddr# Addr#
arr Int#
i0 Mac
m State# s
s0 = case forall d. Addr# -> Int# -> Word# -> State# d -> State# d
Compat.writeWord16OffAddr# Addr#
arr Int#
i (Mac -> Word#
macToWord16A# Mac
m) State# s
s0 of
    State# s
s1 -> case forall d. Addr# -> Int# -> Word# -> State# d -> State# d
Compat.writeWord16OffAddr# Addr#
arr (Int#
i Int# -> Int# -> Int#
+# Int#
1#) (Mac -> Word#
macToWord16B# Mac
m) State# s
s1 of
      State# s
s2 -> forall d. Addr# -> Int# -> Word# -> State# d -> State# d
Compat.writeWord16OffAddr# Addr#
arr (Int#
i Int# -> Int# -> Int#
+# Int#
2#) (Mac -> Word#
macToWord16C# Mac
m) State# s
s2
    where !i :: Int#
i = Int#
3# Int# -> Int# -> Int#
*# Int#
i0
  setByteArray# :: forall s.
MutableByteArray# s -> Int# -> Int# -> Mac -> State# s -> State# s
setByteArray# MutableByteArray# s
arr# Int#
i# Int#
len# Mac
ident = Int# -> State# s -> State# s
go Int#
0#
    where
      go :: Int# -> State# s -> State# s
go Int#
ix# State# s
s0 = if Int# -> Bool
isTrue# (Int#
ix# Int# -> Int# -> Int#
<# Int#
len#)
        then case forall a s.
Prim a =>
MutableByteArray# s -> Int# -> a -> State# s -> State# s
writeByteArray# MutableByteArray# s
arr# (Int#
i# Int# -> Int# -> Int#
+# Int#
ix#) Mac
ident State# s
s0 of
          State# s
s1 -> Int# -> State# s -> State# s
go (Int#
ix# Int# -> Int# -> Int#
+# Int#
1#) State# s
s1
        else State# s
s0
  setOffAddr# :: forall s. Addr# -> Int# -> Int# -> Mac -> State# s -> State# s
setOffAddr# Addr#
addr# Int#
i# Int#
len# Mac
ident = Int# -> State# s -> State# s
go Int#
0#
    where
      go :: Int# -> State# s -> State# s
go Int#
ix# State# s
s0 = if Int# -> Bool
isTrue# (Int#
ix# Int# -> Int# -> Int#
<# Int#
len#)
        then case forall a s. Prim a => Addr# -> Int# -> a -> State# s -> State# s
writeOffAddr# Addr#
addr# (Int#
i# Int# -> Int# -> Int#
+# Int#
ix#) Mac
ident State# s
s0 of
          State# s
s1 -> Int# -> State# s -> State# s
go (Int#
ix# Int# -> Int# -> Int#
+# Int#
1#) State# s
s1
        else State# s
s0

macToWord16A# :: Mac -> Word#
{-# inline macToWord16A# #-}
macToWord16A# :: Mac -> Word#
macToWord16A# (Mac Word64
w) = case Word64 -> Word16
word64ToWord16 (forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
32) of
  Compat.W16# Word#
x -> Word#
x

macToWord16B# :: Mac -> Word#
{-# inline macToWord16B# #-}
macToWord16B# :: Mac -> Word#
macToWord16B# (Mac Word64
w) = case Word64 -> Word16
word64ToWord16 (forall a. Bits a => a -> Int -> a
unsafeShiftR Word64
w Int
16) of
  Compat.W16# Word#
x -> Word#
x

macToWord16C# :: Mac -> Word#
{-# inline macToWord16C# #-}
macToWord16C# :: Mac -> Word#
macToWord16C# (Mac Word64
w) = case Word64 -> Word16
word64ToWord16 Word64
w of
  Compat.W16# Word#
x -> Word#
x

macFromWord16# :: Word# -> Word# -> Word# -> Mac
macFromWord16# :: Word# -> Word# -> Word# -> Mac
macFromWord16# Word#
a Word#
b Word#
c = Word64 -> Mac
Mac
    forall a b. (a -> b) -> a -> b
$ (forall a. Bits a => a -> Int -> a
unsafeShiftL (Word16 -> Word64
word16ToWord64 (Word# -> Word16
Compat.W16# Word#
a)) Int
32)
  forall a. Bits a => a -> a -> a
.|. (forall a. Bits a => a -> Int -> a
unsafeShiftL (Word16 -> Word64
word16ToWord64 (Word# -> Word16
Compat.W16# Word#
b)) Int
16)
  forall a. Bits a => a -> a -> a
.|. (Word16 -> Word64
word16ToWord64 (Word# -> Word16
Compat.W16# Word#
c))

word16ToWord64 :: Word16 -> Word64
word16ToWord64 :: Word16 -> Word64
word16ToWord64 = forall a b. (Integral a, Num b) => a -> b
fromIntegral

word64ToWord16 :: Word64 -> Word16
word64ToWord16 :: Word64 -> Word16
word64ToWord16 = forall a b. (Integral a, Num b) => a -> b
fromIntegral

-- What this instance does is to display the
-- inner contents in hexadecimal and pad them out to
-- 6 bytes in case it begins with several zeroes.
-- It also uses the smart constructor instead
-- of the actual constructor
instance Show Mac where
  showsPrec :: Int -> Mac -> ShowS
showsPrec Int
p (Mac Word64
addr) = Bool -> ShowS -> ShowS
showParen (Int
p forall a. Ord a => a -> a -> Bool
> Int
10)
    forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
"mac "
    forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word64 -> ShowS
showHexWord48 Word64
addr

instance Read Mac where
  readPrec :: ReadPrec Mac
readPrec = forall a. ReadPrec a -> ReadPrec a
parens forall a b. (a -> b) -> a -> b
$ forall a. Int -> ReadPrec a -> ReadPrec a
prec Int
10 forall a b. (a -> b) -> a -> b
$ do
    Ident String
"mac" <- ReadPrec Lexeme
lexP
    Word64
w <- forall a. ReadPrec a -> ReadPrec a
step forall a. Read a => ReadPrec a
readPrec
    forall (m :: * -> *) a. Monad m => a -> m a
return (Word64 -> Mac
mac Word64
w)

instance Bounded Mac where
  minBound :: Mac
minBound = Word64 -> Mac
Mac Word64
0
  maxBound :: Mac
maxBound = Word64 -> Mac
Mac Word64
0xFFFFFFFFFFFF

instance Enum Mac where
  succ :: Mac -> Mac
succ m :: Mac
m@(Mac Word64
x)
    | Mac
m forall a. Eq a => a -> a -> Bool
== forall a. Bounded a => a
maxBound = forall a. String -> a
succError String
"Mac"
    | Bool
otherwise = Word64 -> Mac
Mac (Word64
x forall a. Num a => a -> a -> a
+ Word64
1)
  pred :: Mac -> Mac
pred m :: Mac
m@(Mac Word64
x)
    | Mac
m forall a. Eq a => a -> a -> Bool
== forall a. Bounded a => a
minBound = forall a. String -> a
predError String
"Mac"
    | Bool
otherwise = Word64 -> Mac
Mac (Word64
x forall a. Num a => a -> a -> a
- Word64
1)
  toEnum :: Int -> Mac
toEnum Int
i = Word64 -> Mac
Mac (forall a. Enum a => Int -> a
toEnum Int
i)
  fromEnum :: Mac -> Int
fromEnum (Mac Word64
x) = forall a. Enum a => a -> Int
fromEnum Word64
x

-- | Print a 'Mac' address using the textual encoding.
print :: Mac -> IO ()
print :: Mac -> IO ()
print = Text -> IO ()
TIO.putStrLn forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mac -> Text
encode

showHexWord48 :: Word64 -> ShowS
showHexWord48 :: Word64 -> ShowS
showHexWord48 Word64
w = String -> ShowS
showString String
"0x" forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
go Int
11
  where
  go :: Int -> ShowS
  go :: Int -> ShowS
go !Int
ix = if Int
ix forall a. Ord a => a -> a -> Bool
>= Int
0
    then Char -> ShowS
showChar (Word -> Char
nibbleToHex ((forall a. Bits a => a -> Int -> a
unsafeShiftR (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
w) (Int
ix forall a. Num a => a -> a -> a
* Int
4)) forall a. Bits a => a -> a -> a
.&. Word
0xF)) forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
go (Int
ix forall a. Num a => a -> a -> a
- Int
1)
    else forall a. a -> a
id

nibbleToHex :: Word -> Char
nibbleToHex :: Word -> Char
nibbleToHex Word
w
  | Word
w forall a. Ord a => a -> a -> Bool
< Word
10 = Int -> Char
chr (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word
w forall a. Num a => a -> a -> a
+ Word
48))
  | Bool
otherwise = Int -> Char
chr (forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word
w forall a. Num a => a -> a -> a
+ Word
87))

-- | A 'MacCodec' allows users to control the encoding/decoding
--   of their 'Mac' addresses.
data MacCodec = MacCodec
  { MacCodec -> MacGrouping
macCodecGrouping :: !MacGrouping
  , MacCodec -> Bool
macCodecUpperCase :: !Bool
  } deriving (MacCodec -> MacCodec -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MacCodec -> MacCodec -> Bool
$c/= :: MacCodec -> MacCodec -> Bool
== :: MacCodec -> MacCodec -> Bool
$c== :: MacCodec -> MacCodec -> Bool
Eq,Eq MacCodec
MacCodec -> MacCodec -> Bool
MacCodec -> MacCodec -> Ordering
MacCodec -> MacCodec -> MacCodec
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MacCodec -> MacCodec -> MacCodec
$cmin :: MacCodec -> MacCodec -> MacCodec
max :: MacCodec -> MacCodec -> MacCodec
$cmax :: MacCodec -> MacCodec -> MacCodec
>= :: MacCodec -> MacCodec -> Bool
$c>= :: MacCodec -> MacCodec -> Bool
> :: MacCodec -> MacCodec -> Bool
$c> :: MacCodec -> MacCodec -> Bool
<= :: MacCodec -> MacCodec -> Bool
$c<= :: MacCodec -> MacCodec -> Bool
< :: MacCodec -> MacCodec -> Bool
$c< :: MacCodec -> MacCodec -> Bool
compare :: MacCodec -> MacCodec -> Ordering
$ccompare :: MacCodec -> MacCodec -> Ordering
Ord,Int -> MacCodec -> ShowS
[MacCodec] -> ShowS
MacCodec -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MacCodec] -> ShowS
$cshowList :: [MacCodec] -> ShowS
show :: MacCodec -> String
$cshow :: MacCodec -> String
showsPrec :: Int -> MacCodec -> ShowS
$cshowsPrec :: Int -> MacCodec -> ShowS
Show,ReadPrec [MacCodec]
ReadPrec MacCodec
Int -> ReadS MacCodec
ReadS [MacCodec]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [MacCodec]
$creadListPrec :: ReadPrec [MacCodec]
readPrec :: ReadPrec MacCodec
$creadPrec :: ReadPrec MacCodec
readList :: ReadS [MacCodec]
$creadList :: ReadS [MacCodec]
readsPrec :: Int -> ReadS MacCodec
$creadsPrec :: Int -> ReadS MacCodec
Read,forall x. Rep MacCodec x -> MacCodec
forall x. MacCodec -> Rep MacCodec x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MacCodec x -> MacCodec
$cfrom :: forall x. MacCodec -> Rep MacCodec x
Generic,Typeable MacCodec
MacCodec -> DataType
MacCodec -> Constr
(forall b. Data b => b -> b) -> MacCodec -> MacCodec
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> MacCodec -> u
forall u. (forall d. Data d => d -> u) -> MacCodec -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> MacCodec -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> MacCodec -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> MacCodec -> m MacCodec
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> MacCodec -> m MacCodec
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c MacCodec
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> MacCodec -> c MacCodec
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c MacCodec)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c MacCodec)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> MacCodec -> m MacCodec
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> MacCodec -> m MacCodec
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> MacCodec -> m MacCodec
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> MacCodec -> m MacCodec
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> MacCodec -> m MacCodec
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> MacCodec -> m MacCodec
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> MacCodec -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> MacCodec -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> MacCodec -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> MacCodec -> [u]
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> MacCodec -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> MacCodec -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> MacCodec -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> MacCodec -> r
gmapT :: (forall b. Data b => b -> b) -> MacCodec -> MacCodec
$cgmapT :: (forall b. Data b => b -> b) -> MacCodec -> MacCodec
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c MacCodec)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c MacCodec)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c MacCodec)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c MacCodec)
dataTypeOf :: MacCodec -> DataType
$cdataTypeOf :: MacCodec -> DataType
toConstr :: MacCodec -> Constr
$ctoConstr :: MacCodec -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c MacCodec
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c MacCodec
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> MacCodec -> c MacCodec
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> MacCodec -> c MacCodec
Data)

-- | The format expected by the mac address parser. The 'Word8' taken
--   by some of these constructors is the ascii value of the character
--   to be used as the separator. This is typically a colon, a hyphen, or
--   a space character. All decoding functions are case insensitive.
data MacGrouping
  = MacGroupingPairs !Char -- ^ Two-character groups, @FA:2B:40:09:8C:11@
  | MacGroupingTriples !Char -- ^ Three-character groups, @24B-F0A-025-829@
  | MacGroupingQuadruples !Char -- ^ Four-character groups, @A220.0745.CAC7@
  | MacGroupingNoSeparator -- ^ No separator, @24AF4B5B0780@
  deriving (MacGrouping -> MacGrouping -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MacGrouping -> MacGrouping -> Bool
$c/= :: MacGrouping -> MacGrouping -> Bool
== :: MacGrouping -> MacGrouping -> Bool
$c== :: MacGrouping -> MacGrouping -> Bool
Eq,Eq MacGrouping
MacGrouping -> MacGrouping -> Bool
MacGrouping -> MacGrouping -> Ordering
MacGrouping -> MacGrouping -> MacGrouping
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MacGrouping -> MacGrouping -> MacGrouping
$cmin :: MacGrouping -> MacGrouping -> MacGrouping
max :: MacGrouping -> MacGrouping -> MacGrouping
$cmax :: MacGrouping -> MacGrouping -> MacGrouping
>= :: MacGrouping -> MacGrouping -> Bool
$c>= :: MacGrouping -> MacGrouping -> Bool
> :: MacGrouping -> MacGrouping -> Bool
$c> :: MacGrouping -> MacGrouping -> Bool
<= :: MacGrouping -> MacGrouping -> Bool
$c<= :: MacGrouping -> MacGrouping -> Bool
< :: MacGrouping -> MacGrouping -> Bool
$c< :: MacGrouping -> MacGrouping -> Bool
compare :: MacGrouping -> MacGrouping -> Ordering
$ccompare :: MacGrouping -> MacGrouping -> Ordering
Ord,Int -> MacGrouping -> ShowS
[MacGrouping] -> ShowS
MacGrouping -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MacGrouping] -> ShowS
$cshowList :: [MacGrouping] -> ShowS
show :: MacGrouping -> String
$cshow :: MacGrouping -> String
showsPrec :: Int -> MacGrouping -> ShowS
$cshowsPrec :: Int -> MacGrouping -> ShowS
Show,ReadPrec [MacGrouping]
ReadPrec MacGrouping
Int -> ReadS MacGrouping
ReadS [MacGrouping]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [MacGrouping]
$creadListPrec :: ReadPrec [MacGrouping]
readPrec :: ReadPrec MacGrouping
$creadPrec :: ReadPrec MacGrouping
readList :: ReadS [MacGrouping]
$creadList :: ReadS [MacGrouping]
readsPrec :: Int -> ReadS MacGrouping
$creadsPrec :: Int -> ReadS MacGrouping
Read,forall x. Rep MacGrouping x -> MacGrouping
forall x. MacGrouping -> Rep MacGrouping x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep MacGrouping x -> MacGrouping
$cfrom :: forall x. MacGrouping -> Rep MacGrouping x
Generic,Typeable MacGrouping
MacGrouping -> DataType
MacGrouping -> Constr
(forall b. Data b => b -> b) -> MacGrouping -> MacGrouping
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> MacGrouping -> u
forall u. (forall d. Data d => d -> u) -> MacGrouping -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> MacGrouping -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> MacGrouping -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> MacGrouping -> m MacGrouping
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> MacGrouping -> m MacGrouping
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c MacGrouping
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> MacGrouping -> c MacGrouping
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c MacGrouping)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c MacGrouping)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> MacGrouping -> m MacGrouping
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> MacGrouping -> m MacGrouping
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> MacGrouping -> m MacGrouping
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> MacGrouping -> m MacGrouping
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> MacGrouping -> m MacGrouping
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> MacGrouping -> m MacGrouping
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> MacGrouping -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> MacGrouping -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> MacGrouping -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> MacGrouping -> [u]
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> MacGrouping -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> MacGrouping -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> MacGrouping -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> MacGrouping -> r
gmapT :: (forall b. Data b => b -> b) -> MacGrouping -> MacGrouping
$cgmapT :: (forall b. Data b => b -> b) -> MacGrouping -> MacGrouping
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c MacGrouping)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c MacGrouping)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c MacGrouping)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c MacGrouping)
dataTypeOf :: MacGrouping -> DataType
$cdataTypeOf :: MacGrouping -> DataType
toConstr :: MacGrouping -> Constr
$ctoConstr :: MacGrouping -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c MacGrouping
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c MacGrouping
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> MacGrouping -> c MacGrouping
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> MacGrouping -> c MacGrouping
Data)

instance ToJSON Mac where
  toJSON :: Mac -> Value
toJSON = Text -> Value
Aeson.String forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mac -> Text
encode

instance ToJSONKey Mac where
  toJSONKey :: ToJSONKeyFunction Mac
toJSONKey = forall a. (a -> Key) -> (a -> Encoding' Key) -> ToJSONKeyFunction a
ToJSONKeyText
    (Text -> Key
keyFromText forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mac -> Text
encode)
    (\Mac
m -> forall a. Builder -> Encoding' a
Aeson.unsafeToEncoding forall a b. (a -> b) -> a -> b
$ Char -> Builder
BB.char7 Char
'"' forall a. Semigroup a => a -> a -> a
<> Mac -> Builder
builderUtf8 Mac
m forall a. Semigroup a => a -> a -> a
<> Char -> Builder
BB.char7 Char
'"')
    where
#if MIN_VERSION_aeson(2,0,0)
      keyFromText :: Text -> Key
keyFromText = Text -> Key
AK.fromText
#else
      keyFromText = id
#endif

instance FromJSONKey Mac where
  fromJSONKey :: FromJSONKeyFunction Mac
fromJSONKey = forall a. (Text -> Parser a) -> FromJSONKeyFunction a
FromJSONKeyTextParser forall a b. (a -> b) -> a -> b
$ \Text
t -> case Text -> Maybe Mac
decode Text
t of
    Maybe Mac
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalid mac address"
    Just Mac
addr -> forall (m :: * -> *) a. Monad m => a -> m a
return Mac
addr

instance FromJSON Mac where
  parseJSON :: Value -> Parser Mac
parseJSON = forall a. Parser a -> Value -> Parser a
attoparsecParseJSON Parser Text Mac
parser

attoparsecParseJSON :: AT.Parser a -> Aeson.Value -> Aeson.Parser a
attoparsecParseJSON :: forall a. Parser a -> Value -> Parser a
attoparsecParseJSON Parser a
p Value
v =
  case Value
v of
    Aeson.String Text
t ->
      case forall a. Parser a -> Text -> Either String a
AT.parseOnly Parser a
p Text
t of
        Left String
err  -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
err
        Right a
res -> forall (m :: * -> *) a. Monad m => a -> m a
return a
res
    Value
_ -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"expected a String"

-- Unchecked invariant: each of these Word64s must be smaller
-- than 256.
unsafeWord48FromOctets :: Word64 -> Word64 -> Word64 -> Word64 -> Word64 -> Word64 -> Word64
unsafeWord48FromOctets :: Word64 -> Word64 -> Word64 -> Word64 -> Word64 -> Word64 -> Word64
unsafeWord48FromOctets Word64
a Word64
b Word64
c Word64
d Word64
e Word64
f =
    forall a b. (Integral a, Num b) => a -> b
fromIntegral
  forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> Int -> a
unsafeShiftL Word64
a Int
40
  forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
unsafeShiftL Word64
b Int
32
  forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
unsafeShiftL Word64
c Int
24
  forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
unsafeShiftL Word64
d Int
16
  forall a. Bits a => a -> a -> a
.|. forall a. Bits a => a -> Int -> a
unsafeShiftL Word64
e Int
8
  forall a. Bits a => a -> a -> a
.|. Word64
f