{-| A MAC address datatype, representing the six bytes of a MAC address, also
    known as an OID, IAB or \"...Vendor Address, Vendor ID, NIC Address,
    Ethernet Address and others.\", see
    <http://standards.ieee.org/faqs/OUI.html#q4>
 -}

module Data.MAC where

import Numeric
import Data.Word
import Data.List
import Data.Bits
import Foreign.Ptr
import Foreign.Storable
import Data.Binary
import Data.Binary.Put
import Data.Binary.Get
import Text.Printf
import Text.Read
import qualified Text.Read.Lex as Rex
import qualified Text.ParserCombinators.ReadPrec as Rex
import qualified Text.ParserCombinators.ReadP as Rex


data MAC                     =  MAC
  {-# UNPACK #-} !Word8
  {-# UNPACK #-} !Word8
  {-# UNPACK #-} !Word8
  {-# UNPACK #-} !Word8
  {-# UNPACK #-} !Word8
  {-# UNPACK #-} !Word8
 deriving (MAC -> MAC -> Bool
(MAC -> MAC -> Bool) -> (MAC -> MAC -> Bool) -> Eq MAC
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
Eq MAC
-> (MAC -> MAC -> Ordering)
-> (MAC -> MAC -> Bool)
-> (MAC -> MAC -> Bool)
-> (MAC -> MAC -> Bool)
-> (MAC -> MAC -> Bool)
-> (MAC -> MAC -> MAC)
-> (MAC -> MAC -> MAC)
-> Ord 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
$cp1Ord :: Eq MAC
Ord, MAC
MAC -> MAC -> Bounded MAC
forall a. a -> a -> Bounded a
maxBound :: MAC
$cmaxBound :: MAC
minBound :: MAC
$cminBound :: MAC
Bounded)
instance Show MAC where
  show :: MAC -> String
show (MAC Word8
a Word8
b Word8
c Word8
d Word8
e Word8
f)
    = String
-> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> String
forall r. PrintfType r => String -> r
printf String
"%02x:%02x:%02x:%02x:%02x:%02x" Word8
a Word8
b Word8
c Word8
d Word8
e Word8
f
instance Read MAC where
  readPrec :: ReadPrec MAC
readPrec                   =  ReadP MAC -> ReadPrec MAC
forall a. ReadP a -> ReadPrec a
Rex.lift (ReadP MAC -> ReadPrec MAC) -> ReadP MAC -> ReadPrec MAC
forall a b. (a -> b) -> a -> b
$ do
    Word8
a                       <-  ReadP Word8
forall a. (Eq a, Num a) => ReadP a
Rex.readHexP
    [Word8
b, Word8
c, Word8
d, Word8
e, Word8
f]         <-  ReadP Word8 -> ReadP [Word8]
forall a. ReadP a -> ReadP [a]
Rex.many (ReadP Word8 -> ReadP [Word8]) -> ReadP Word8 -> ReadP [Word8]
forall a b. (a -> b) -> a -> b
$ Char -> ReadP Char
Rex.char Char
':' ReadP Char -> ReadP Word8 -> ReadP Word8
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ReadP Word8
forall a. (Eq a, Num a) => ReadP a
Rex.readHexP
    MAC -> ReadP MAC
forall (m :: * -> *) a. Monad m => a -> m a
return (MAC -> ReadP MAC) -> MAC -> ReadP MAC
forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> MAC
MAC Word8
a Word8
b Word8
c Word8
d Word8
e Word8
f
instance Binary MAC where
 -- Thanks to aslatter@gmail.com for this instance.
  put :: MAC -> Put
put (MAC Word8
a Word8
b Word8
c Word8
d Word8
e Word8
f)      =  do
    Word8 -> Put
putWord8 Word8
a
    Word8 -> Put
putWord8 Word8
b
    Word8 -> Put
putWord8 Word8
c
    Word8 -> Put
putWord8 Word8
d
    Word8 -> Put
putWord8 Word8
e
    Word8 -> Put
putWord8 Word8
f
  get :: Get MAC
get                        =  do
    Word8
a                       <-  Get Word8
getWord8
    Word8
b                       <-  Get Word8
getWord8
    Word8
c                       <-  Get Word8
getWord8
    Word8
d                       <-  Get Word8
getWord8
    Word8
e                       <-  Get Word8
getWord8
    Word8
f                       <-  Get Word8
getWord8
    MAC -> Get MAC
forall (m :: * -> *) a. Monad m => a -> m a
return (MAC -> Get MAC) -> MAC -> Get MAC
forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> MAC
MAC Word8
a Word8
b Word8
c Word8
d Word8
e Word8
f
instance Storable MAC where
 -- Thanks to aslatter@gmail.com for this instance.
  sizeOf :: MAC -> Int
sizeOf MAC
_                   =  Int
6
  alignment :: MAC -> Int
alignment MAC
_                =  Int
1
  peek :: Ptr MAC -> IO MAC
peek Ptr MAC
p                     =  do
    Word8
a                       <-  Ptr Word8 -> IO Word8
forall a. Storable a => Ptr a -> IO a
peek (Ptr Word8 -> IO Word8) -> Ptr Word8 -> IO Word8
forall a b. (a -> b) -> a -> b
$ Ptr MAC -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr MAC
p
    Word8
b                       <-  Ptr MAC -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr MAC
p Int
1
    Word8
c                       <-  Ptr MAC -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr MAC
p Int
2
    Word8
d                       <-  Ptr MAC -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr MAC
p Int
3
    Word8
e                       <-  Ptr MAC -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr MAC
p Int
4
    Word8
f                       <-  Ptr MAC -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr MAC
p Int
5
    MAC -> IO MAC
forall (m :: * -> *) a. Monad m => a -> m a
return (MAC -> IO MAC) -> MAC -> IO MAC
forall a b. (a -> b) -> a -> b
$ Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> MAC
MAC Word8
a Word8
b Word8
c Word8
d Word8
e Word8
f
  poke :: Ptr MAC -> MAC -> IO ()
poke Ptr MAC
p (MAC Word8
a Word8
b Word8
c Word8
d Word8
e Word8
f)   =  do
    Ptr Word8 -> Word8 -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr MAC -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr MAC
p) Word8
a
    Ptr MAC -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr MAC
p Int
1 Word8
b
    Ptr MAC -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr MAC
p Int
2 Word8
c
    Ptr MAC -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr MAC
p Int
3 Word8
d
    Ptr MAC -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr MAC
p Int
4 Word8
e
    Ptr MAC -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
pokeByteOff Ptr MAC
p Int
5 Word8
f