module Net.Mac.ByteString.Char8
( encode
, decode
, builder
, parser
, parserWith
) where
import Net.Types (Mac(..),MacEncoding(..),MacDecoding(..))
import Net.Mac (fromOctets)
import Data.ByteString (ByteString)
import Data.Attoparsec.ByteString.Char8 (Parser)
import Data.ByteString.Lazy.Builder (Builder)
import Net.Internal (rightToMaybe)
import Data.Text.Encoding (encodeUtf8, decodeUtf8')
import Data.Word (Word8)
import Data.Bits (unsafeShiftL)
import Control.Monad
import qualified Data.ByteString.Builder as Builder
import qualified Data.Attoparsec.ByteString as ABW
import qualified Data.Attoparsec.ByteString.Char8 as AB
import qualified Net.Mac.Text as MacText
encode :: Mac -> ByteString
encode = encodeUtf8 . MacText.encode
decode :: ByteString -> Maybe Mac
decode = MacText.decode <=< rightToMaybe . decodeUtf8'
builder :: Mac -> Builder
builder = Builder.byteString . encode
parser :: Parser Mac
parser = parserWith defDecoding
parserWith :: MacDecoding -> Parser Mac
parserWith (MacDecoding separator) = fromOctets
<$> parseTwoHex
<* parseSeparator
<*> parseTwoHex
<* parseSeparator
<*> parseTwoHex
<* parseSeparator
<*> parseTwoHex
<* parseSeparator
<*> parseTwoHex
<* parseSeparator
<*> parseTwoHex
where
parseSeparator = case separator of
Just c -> ABW.word8 c
Nothing -> return 60
parseTwoHex :: Parser Word8
parseTwoHex = do
a <- ABW.anyWord8 >>= parseWord8Hex
b <- ABW.anyWord8 >>= parseWord8Hex
return (unsafeShiftL a 4 + b)
parseWord8Hex :: Word8 -> Parser Word8
parseWord8Hex w
| w >= 48 && w <= 57 = return (w 48)
| w >= 65 && w <= 70 = return (w 55)
| w >= 97 && w <= 102 = return (w 87)
| otherwise = fail "invalid hexadecimal character"
defDecoding :: MacDecoding
defDecoding = MacDecoding (Just 58)