{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE RecordWildCards       #-}

module Network.IPv6DB.Types where

import           Data.Aeson    as A
import qualified Data.Text     as T
import qualified Data.Vector   as V
import           Text.IPv6Addr

newtype Addresses = Addresses [IPv6Addr]

instance FromJSON Addresses where
  parseJSON :: Value -> Parser Addresses
parseJSON (Array Array
v) = do
    let rslts :: [Result IPv6Addr]
rslts = forall a. FromJSON a => Value -> Result a
fromJSON forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Vector a -> [a]
V.toList Array
v
    if forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all forall a. Result a -> Bool
isSuccess [Result IPv6Addr]
rslts
      then forall (f :: * -> *) a. Applicative f => a -> f a
pure ([IPv6Addr] -> Addresses
Addresses forall a b. (a -> b) -> a -> b
$ forall a. Result a -> a
fromSuccess forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Result IPv6Addr]
rslts)
      else forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Bad JSON Array Of IPv6 Addresses"
  parseJSON Value
_         = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"JSON Array Expected"

data Entry =
  Entry
    { Entry -> Text
list    :: !T.Text
    , Entry -> IPv6Addr
address :: IPv6Addr
    } deriving (Entry -> Entry -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Entry -> Entry -> Bool
$c/= :: Entry -> Entry -> Bool
== :: Entry -> Entry -> Bool
$c== :: Entry -> Entry -> Bool
Eq, Int -> Entry -> ShowS
[Entry] -> ShowS
Entry -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Entry] -> ShowS
$cshowList :: [Entry] -> ShowS
show :: Entry -> String
$cshow :: Entry -> String
showsPrec :: Int -> Entry -> ShowS
$cshowsPrec :: Int -> Entry -> ShowS
Show)

instance FromJSON Entry where
  parseJSON :: Value -> Parser Entry
parseJSON (Object Object
o) = do
    Text
list    <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"list"
    IPv6Addr
address <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"address"
    forall (f :: * -> *) a. Applicative f => a -> f a
pure Entry{Text
IPv6Addr
address :: IPv6Addr
list :: Text
$sel:address:Entry :: IPv6Addr
$sel:list:Entry :: Text
..}
  parseJSON Value
_          = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"JSON Object Expected"

newtype Entries = Entries [Entry]

instance FromJSON Entries where
  parseJSON :: Value -> Parser Entries
parseJSON (Array Array
v) = do
    let ents :: [Result Entry]
ents = forall a. FromJSON a => Value -> Result a
fromJSON forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Vector a -> [a]
V.toList Array
v
    if forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all forall a. Result a -> Bool
isSuccess [Result Entry]
ents
      then forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Entry] -> Entries
Entries forall a b. (a -> b) -> a -> b
$ forall a. Result a -> a
fromSuccess forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Result Entry]
ents)
      else forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Malformed JSON Array"
  parseJSON Value
_         = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"JSON Array Expected"

newtype Source = Source Value deriving (Source -> Source -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Source -> Source -> Bool
$c/= :: Source -> Source -> Bool
== :: Source -> Source -> Bool
$c== :: Source -> Source -> Bool
Eq, Int -> Source -> ShowS
[Source] -> ShowS
Source -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Source] -> ShowS
$cshowList :: [Source] -> ShowS
show :: Source -> String
$cshow :: Source -> String
showsPrec :: Int -> Source -> ShowS
$cshowsPrec :: Int -> Source -> ShowS
Show)

instance ToJSON Source where
  toJSON :: Source -> Value
toJSON (Source Value
v) = Value
v

instance FromJSON Source where
  parseJSON :: Value -> Parser Source
parseJSON Value
v = forall (f :: * -> *) a. Applicative f => a -> f a
pure (Value -> Source
Source Value
v)

data Resource
  = Resource
      { Resource -> Text
list    :: !T.Text
      , Resource -> IPv6Addr
address :: !IPv6Addr
      , Resource -> Maybe Integer
ttl     :: !(Maybe Integer)
      , Resource -> Source
source  :: !Source
      }
  | ResourceError
      { list    :: !T.Text
      , address :: !IPv6Addr
      , Resource -> Text
error   :: !T.Text
      }
  deriving (Resource -> Resource -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Resource -> Resource -> Bool
$c/= :: Resource -> Resource -> Bool
== :: Resource -> Resource -> Bool
$c== :: Resource -> Resource -> Bool
Eq, Int -> Resource -> ShowS
[Resource] -> ShowS
Resource -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Resource] -> ShowS
$cshowList :: [Resource] -> ShowS
show :: Resource -> String
$cshow :: Resource -> String
showsPrec :: Int -> Resource -> ShowS
$cshowsPrec :: Int -> Resource -> ShowS
Show)

instance ToJSON Resource where
  toJSON :: Resource -> Value
toJSON Resource{Maybe Integer
Text
IPv6Addr
Source
source :: Source
ttl :: Maybe Integer
address :: IPv6Addr
list :: Text
$sel:source:Resource :: Resource -> Source
$sel:ttl:Resource :: Resource -> Maybe Integer
$sel:address:Resource :: Resource -> IPv6Addr
$sel:list:Resource :: Resource -> Text
..} =
    [Pair] -> Value
object
      [ Key
"list"    forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Text
list
      , Key
"address" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= IPv6Addr
address
      , Key
"ttl"     forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Maybe Integer
ttl
      , Key
"source"  forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Source
source
      ]
  toJSON ResourceError{$sel:error:Resource :: Resource -> Text
error=Text
err, Text
IPv6Addr
address :: IPv6Addr
list :: Text
$sel:address:Resource :: Resource -> IPv6Addr
$sel:list:Resource :: Resource -> Text
..} =
    [Pair] -> Value
object
      [ Key
"list"    forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Text
list
      , Key
"address" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= IPv6Addr
address
      , Key
"error"   forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Text
err
      ]

instance FromJSON Resource where
  parseJSON :: Value -> Parser Resource
parseJSON =
    forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"resource" forall a b. (a -> b) -> a -> b
$
      \Object
o -> do
        Text
list    <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"list"
        IPv6Addr
address <- do
          Text
ma <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"address"
          case Text -> Maybe IPv6Addr
maybeIPv6Addr Text
ma of
            Just IPv6Addr
a  -> forall (f :: * -> *) a. Applicative f => a -> f a
pure IPv6Addr
a
            Maybe IPv6Addr
Nothing -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Not an IPv6 Address"
        Maybe Integer
ttl     <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"ttl"
        Source
source  <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"source"
        forall (m :: * -> *) a. Monad m => a -> m a
return Resource{Maybe Integer
Text
IPv6Addr
Source
source :: Source
ttl :: Maybe Integer
address :: IPv6Addr
list :: Text
$sel:source:Resource :: Source
$sel:ttl:Resource :: Maybe Integer
$sel:address:Resource :: IPv6Addr
$sel:list:Resource :: Text
..}

newtype Resources = Resources [Resource] deriving (Resources -> Resources -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Resources -> Resources -> Bool
$c/= :: Resources -> Resources -> Bool
== :: Resources -> Resources -> Bool
$c== :: Resources -> Resources -> Bool
Eq, Int -> Resources -> ShowS
[Resources] -> ShowS
Resources -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Resources] -> ShowS
$cshowList :: [Resources] -> ShowS
show :: Resources -> String
$cshow :: Resources -> String
showsPrec :: Int -> Resources -> ShowS
$cshowsPrec :: Int -> Resources -> ShowS
Show)

instance ToJSON Resources where
  toJSON :: Resources -> Value
toJSON (Resources [Resource]
rs) =
    [Pair] -> Value
object [ (Key
"resources", Array -> Value
Array (forall a. [a] -> Vector a
V.fromList forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Value
toJSON forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Resource]
rs)) ]

instance FromJSON Resources where
  parseJSON :: Value -> Parser Resources
parseJSON (Array Array
v) = do
    let rsrcs :: [Result Resource]
rsrcs = forall a. FromJSON a => Value -> Result a
fromJSON forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Vector a -> [a]
V.toList Array
v
    if forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all forall a. Result a -> Bool
isSuccess [Result Resource]
rsrcs
      then forall (f :: * -> *) a. Applicative f => a -> f a
pure ([Resource] -> Resources
Resources forall a b. (a -> b) -> a -> b
$ forall a. Result a -> a
fromSuccess forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Result Resource]
rsrcs)
      else forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Malformed JSON Array Of Resources"
  parseJSON Value
_         = forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"JSON Array Expected"

isSuccess :: Result a -> Bool
isSuccess :: forall a. Result a -> Bool
isSuccess (A.Success a
_) = Bool
True
isSuccess (A.Error String
_)   = Bool
False

fromSuccess :: Result a -> a
fromSuccess :: forall a. Result a -> a
fromSuccess (A.Success a
e) = a
e
fromSuccess (A.Error String
_)   = forall a. HasCallStack => String -> a
Prelude.error String
"Success value only"