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 -- | This is a mediocre implementation that should -- be rewritten. encode :: Mac -> ByteString encode = encodeUtf8 . MacText.encode -- | This is a mediocre implementation that should -- be rewritten. decode :: ByteString -> Maybe Mac decode = MacText.decode <=< rightToMaybe . decodeUtf8' -- | Make a bytestring builder from a 'Mac' address -- using a colon as the separator. builder :: Mac -> Builder builder = Builder.byteString . encode -- | Parser for a 'Mac' address using with a colon as the -- separator (i.e. @FA:43:B2:C0:0F:99@). parser :: Parser Mac parser = parserWith defDecoding -- | Parser for a 'Mac' address using to the provided -- settings. 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 -- character is unused parseTwoHex :: Parser Word8 parseTwoHex = do a <- ABW.anyWord8 >>= parseWord8Hex b <- ABW.anyWord8 >>= parseWord8Hex return (unsafeShiftL a 1 + 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)