module Net.DNSBase.Resolver.Internal.Parser
( getDefaultNameservers
) where
import Control.Monad.Trans (lift)
import Data.Char (isSpace)
import Data.List (dropWhileEnd, stripPrefix, uncons)
import Data.Maybe (catMaybes)
import System.IO.Error (catchIOError)
import Net.DNSBase.Resolver.Internal.Types
getDefaultNameservers :: FilePath -> DNSIO [NameserverSpec]
getDefaultNameservers :: FilePath -> DNSIO [NameserverSpec]
getDefaultNameservers FilePath
fp = IO [NameserverSpec] -> DNSIO [NameserverSpec]
forall (m :: * -> *) a. Monad m => m a -> ExceptT DNSError m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (IO [NameserverSpec] -> DNSIO [NameserverSpec])
-> IO [NameserverSpec] -> DNSIO [NameserverSpec]
forall a b. (a -> b) -> a -> b
$ IO [NameserverSpec]
parseFile IO [NameserverSpec]
-> (IOError -> IO [NameserverSpec]) -> IO [NameserverSpec]
forall a. IO a -> (IOError -> IO a) -> IO a
`catchIOError` (IO [NameserverSpec] -> IOError -> IO [NameserverSpec]
forall a b. a -> b -> a
const (IO [NameserverSpec] -> IOError -> IO [NameserverSpec])
-> IO [NameserverSpec] -> IOError -> IO [NameserverSpec]
forall a b. (a -> b) -> a -> b
$ [NameserverSpec] -> IO [NameserverSpec]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return [])
where
parseFile :: IO [NameserverSpec]
parseFile :: IO [NameserverSpec]
parseFile = [Maybe NameserverSpec] -> [NameserverSpec]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe NameserverSpec] -> [NameserverSpec])
-> (FilePath -> [Maybe NameserverSpec])
-> FilePath
-> [NameserverSpec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> Maybe NameserverSpec)
-> [FilePath] -> [Maybe NameserverSpec]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> Maybe NameserverSpec
parseLine ([FilePath] -> [Maybe NameserverSpec])
-> (FilePath -> [FilePath]) -> FilePath -> [Maybe NameserverSpec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> [FilePath]
lines (FilePath -> [NameserverSpec])
-> IO FilePath -> IO [NameserverSpec]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FilePath -> IO FilePath
readFile FilePath
fp
parseLine :: String -> Maybe NameserverSpec
parseLine :: FilePath -> Maybe NameserverSpec
parseLine (FilePath -> FilePath -> Maybe FilePath
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix FilePath
"nameserver" -> Just FilePath
rest)
| Just (Char
h, FilePath
t) <- FilePath -> Maybe (Char, FilePath)
forall a. [a] -> Maybe (a, [a])
uncons FilePath
rest
, Char -> Bool
isSpace Char
h
, FilePath
name <- (Char -> Bool) -> FilePath -> FilePath
forall a. (a -> Bool) -> [a] -> [a]
dropWhileEnd Char -> Bool
isSpace (FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> FilePath -> FilePath
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace FilePath
t
, Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null FilePath
name
= NameserverSpec -> Maybe NameserverSpec
forall a. a -> Maybe a
Just (NameserverSpec -> Maybe NameserverSpec)
-> NameserverSpec -> Maybe NameserverSpec
forall a b. (a -> b) -> a -> b
$ FilePath -> Maybe PortNumber -> NameserverSpec
NameserverSpec FilePath
name Maybe PortNumber
forall a. Maybe a
Nothing
parseLine FilePath
_ = Maybe NameserverSpec
forall a. Maybe a
Nothing