ip 0.8.5 → 0.8.6
raw patch · 5 files changed
+107/−43 lines, 5 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
+ Net.Mac.ByteString.Char8: parserWith :: MacDecoding -> Parser Mac
+ Net.Mac.Text: decodeEitherWith :: MacDecoding -> Text -> Either String Mac
+ Net.Mac.Text: decodeWith :: MacDecoding -> Text -> Maybe Mac
+ Net.Mac.Text: parserWith :: MacDecoding -> Parser Mac
+ Net.Types: MacDecoding :: Maybe Word8 -> MacDecoding
+ Net.Types: [macDecodingSeparator] :: MacDecoding -> Maybe Word8
+ Net.Types: instance GHC.Generics.Constructor Net.Types.C1_0IPv4
+ Net.Types: instance GHC.Generics.Constructor Net.Types.C1_0IPv4Range
+ Net.Types: instance GHC.Generics.Constructor Net.Types.C1_0Mac
+ Net.Types: instance GHC.Generics.Constructor Net.Types.C1_0MacEncoding
+ Net.Types: instance GHC.Generics.Datatype Net.Types.D1IPv4
+ Net.Types: instance GHC.Generics.Datatype Net.Types.D1IPv4Range
+ Net.Types: instance GHC.Generics.Datatype Net.Types.D1Mac
+ Net.Types: instance GHC.Generics.Datatype Net.Types.D1MacEncoding
+ Net.Types: instance GHC.Generics.Selector Net.Types.S1_0_0IPv4
+ Net.Types: instance GHC.Generics.Selector Net.Types.S1_0_0IPv4Range
+ Net.Types: instance GHC.Generics.Selector Net.Types.S1_0_0Mac
+ Net.Types: instance GHC.Generics.Selector Net.Types.S1_0_0MacEncoding
+ Net.Types: instance GHC.Generics.Selector Net.Types.S1_0_1IPv4Range
+ Net.Types: instance GHC.Generics.Selector Net.Types.S1_0_1Mac
+ Net.Types: instance GHC.Generics.Selector Net.Types.S1_0_1MacEncoding
+ Net.Types: newtype MacDecoding
- Net.Internal: macFromText :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Maybe a
+ Net.Internal: macFromText :: Maybe Char -> (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Maybe a
- Net.Internal: macFromText' :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Either String a
+ Net.Internal: macFromText' :: Maybe Char -> (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Either String a
- Net.Internal: macTextParser :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Parser a
+ Net.Internal: macTextParser :: Maybe Char -> (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Parser a
Files
- ip.cabal +4/−3
- src/Net/Internal.hs +18/−14
- src/Net/Mac/ByteString/Char8.hs +50/−20
- src/Net/Mac/Text.hs +29/−5
- src/Net/Types.hs +6/−1
ip.cabal view
@@ -1,5 +1,5 @@ name: ip-version: 0.8.5+version: 0.8.6 synopsis: Library for IP and MAC addresses homepage: https://github.com/andrewthad/haskell-ip#readme license: BSD3@@ -20,8 +20,8 @@ typeclasses of its own. Neither does it prefix functions with the name of the type that they work on. Instead, functions of the same name are exported by several different modules, and it is expected that end users- disambiguate by imported these modules qualified. For example,- `Data.IPv4.Text` and `Data.IPv4.ByteString.Char8` have nearly identical+ disambiguate by importing these modules qualified. For example,+ `Data.IPv4.ByteString.Char8` and `Data.IPv4.Text` have nearly identical export lists. . The only module intended to be imported unqualified is `Net.Types`. The@@ -32,6 +32,7 @@ . * `yesod-ip`: Provides orphan instances needed to work with yesod and persistent. Also, provides a `yesod-form` helper.+ . * `impure-containers`: Provides a trie that can be used for looking up which subnet an IP address belongs in.
src/Net/Internal.hs view
@@ -236,11 +236,11 @@ -- | Given the size of the mask, return the -- total number of ips in the subnet. This--- only works for IPv4 addresses because --- an IPv6 subnet can have up to 2^128 +-- only works for IPv4 addresses because+-- an IPv6 subnet can have up to 2^128 -- addresses. countAddrs :: Word8 -> Word64-countAddrs w = +countAddrs w = let amountToShift = if w > 32 then 0 else 32 - fromIntegral w@@ -285,20 +285,23 @@ -- r1,r2,r3,r4,r5,r6 :: Word32 -- r1 = fromOctets' 0 0 0 0 -macTextParser :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> AT.Parser a-macTextParser f = f+macTextParser :: Maybe Char -> (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> AT.Parser a+macTextParser separator f = f <$> (AT.hexadecimal >>= limitSize)- <* AT.char ':'+ <* parseSeparator <*> (AT.hexadecimal >>= limitSize)- <* AT.char ':'+ <* parseSeparator <*> (AT.hexadecimal >>= limitSize)- <* AT.char ':'+ <* parseSeparator <*> (AT.hexadecimal >>= limitSize)- <* AT.char ':'+ <* parseSeparator <*> (AT.hexadecimal >>= limitSize)- <* AT.char ':'+ <* parseSeparator <*> (AT.hexadecimal >>= limitSize) where+ parseSeparator = case separator of+ Just c -> AT.char c+ Nothing -> return 'x' -- character is unused limitSize i = if i > 255 then fail "All octets in a mac address must be between 00 and FF"@@ -322,12 +325,13 @@ <> TBuilder.hexadecimal (255 .&. b) where colon = TBuilder.singleton ':' -macFromText :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Maybe a-macFromText f = rightToMaybe . macFromText' f+macFromText :: Maybe Char -> (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Maybe a+macFromText separator f = rightToMaybe . macFromText' separator f {-# INLINE macFromText #-} -macFromText' :: (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Either String a-macFromText' f = AT.parseOnly (macTextParser f <* AT.endOfInput)+macFromText' :: Maybe Char -> (Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> a) -> Text -> Either String a+macFromText' separator f =+ AT.parseOnly (macTextParser separator f <* AT.endOfInput) {-# INLINE macFromText' #-} twoDigits :: ByteString
src/Net/Mac/ByteString/Char8.hs view
@@ -3,47 +3,77 @@ , decode , builder , parser+ , parserWith ) where -import Net.Types (Mac(..))-import Net.Mac (fromOctetsNoCast)+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 bad implementation that should be rewritten+-- | This is a mediocre implementation that should+-- be rewritten. encode :: Mac -> ByteString encode = encodeUtf8 . MacText.encode --- | This is a bad implementation that should be rewritten+-- | 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 = fromOctetsNoCast- <$> (AB.hexadecimal >>= limitSize)- <* AB.char ':'- <*> (AB.hexadecimal >>= limitSize)- <* AB.char ':'- <*> (AB.hexadecimal >>= limitSize)- <* AB.char ':'- <*> (AB.hexadecimal >>= limitSize)- <* AB.char ':'- <*> (AB.hexadecimal >>= limitSize)- <* AB.char ':'- <*> (AB.hexadecimal >>= limitSize)+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- limitSize i =- if i > 255- then fail "All octets in a mac address must be between 00 and FF"- else return i+ 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)
src/Net/Mac/Text.hs view
@@ -1,15 +1,20 @@ module Net.Mac.Text ( encode+ , encodeWith , decode+ , decodeWith , decodeEither+ , decodeEitherWith , builder , parser- , encodeWith+ , parserWith ) where -import Net.Types (Mac(..),MacEncoding(..))+import Net.Types (Mac(..),MacEncoding(..),MacDecoding(..)) import Net.Mac (fromOctetsNoCast) import Data.Text (Text)+import Data.Word (Word8)+import Data.Char (chr) import qualified Net.Internal as Internal import qualified Data.Attoparsec.Text as AT import qualified Data.Text.Lazy.Builder as TBuilder@@ -17,19 +22,38 @@ encode :: Mac -> Text encode (Mac a b) = Internal.macToTextPreAllocated 58 False a b +decodeEitherWith :: MacDecoding -> Text -> Either String Mac+decodeEitherWith (MacDecoding separator) =+ Internal.macFromText' (fmap w8ToChar separator) fromOctetsNoCast+ decodeEither :: Text -> Either String Mac-decodeEither = Internal.macFromText' fromOctetsNoCast+decodeEither = decodeEitherWith defDecoding decode :: Text -> Maybe Mac-decode = Internal.rightToMaybe . decodeEither+decode = decodeWith defDecoding +decodeWith :: MacDecoding -> Text -> Maybe Mac+decodeWith d = Internal.rightToMaybe . decodeEitherWith d++-- decodeWith ::+ builder :: Mac -> TBuilder.Builder builder (Mac a b) = Internal.macToTextBuilder a b parser :: AT.Parser Mac-parser = Internal.macTextParser fromOctetsNoCast+parser = parserWith defDecoding +parserWith :: MacDecoding -> AT.Parser Mac+parserWith (MacDecoding separator) =+ Internal.macTextParser (fmap w8ToChar separator) fromOctetsNoCast+ encodeWith :: MacEncoding -> Mac -> Text encodeWith (MacEncoding separator isUpperCase) (Mac a b) = Internal.macToTextPreAllocated separator isUpperCase a b++defDecoding :: MacDecoding+defDecoding = MacDecoding (Just 58)++w8ToChar :: Word8 -> Char+w8ToChar = chr . fromIntegral
src/Net/Types.hs view
@@ -12,6 +12,7 @@ , IPv4Range(..) , Mac(..) , MacEncoding(..)+ , MacDecoding(..) ) where import qualified Net.Internal as Internal@@ -61,6 +62,10 @@ , macEncodingUpperCase :: {-# UNPACK #-} !Bool } deriving (Eq,Ord,Show,Read,Generic) +newtype MacDecoding = MacDecoding+ { macDecodingSeparator :: Maybe Word8+ }+ instance Hashable Mac instance ToJSON Mac where@@ -68,7 +73,7 @@ instance FromJSON Mac where parseJSON = Internal.attoparsecParseJSON- (Internal.macTextParser macFromOctets' <* AT.endOfInput)+ (Internal.macTextParser (Just ':') macFromOctets' <* AT.endOfInput) macFromOctets' :: Word16 -> Word16 -> Word32 -> Word32 -> Word32 -> Word32 -> Mac macFromOctets' a b c d e f = Mac