    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE DeriveGeneric #-}

    module Distribution.Types.PkgconfigVersionRange
      ( PkgconfigVersionRange (..)
      , anyPkgconfigVersion
      , isAnyPkgconfigVersion
      , withinPkgconfigVersionRange

        -- * Internal
      , versionToPkgconfigVersion
      , versionRangeToPkgconfigVersionRange
      ) where

    import Distribution.Compat.Prelude
    import Prelude ()

    import Distribution.CabalSpecVersion
    import Distribution.Parsec
    import Distribution.Pretty
    import Distribution.Types.PkgconfigVersion
    import Distribution.Types.Version
    import Distribution.Types.VersionInterval
    import Distribution.Types.VersionRange

    import qualified Data.ByteString.Char8 as BS8
    import qualified Distribution.Compat.CharParsing as P
    import qualified Text.PrettyPrint as PP

    -- | @since 3.0
    data PkgconfigVersionRange
      = PcAnyVersion
      | PcThisVersion PkgconfigVersion -- = version
      | PcLaterVersion PkgconfigVersion -- > version  (NB. not >=)
      | PcEarlierVersion PkgconfigVersion -- < version
      | PcOrLaterVersion PkgconfigVersion -- >= version
      | PcOrEarlierVersion PkgconfigVersion -- =< version
      | PcUnionVersionRanges PkgconfigVersionRange PkgconfigVersionRange
      | PcIntersectVersionRanges PkgconfigVersionRange PkgconfigVersionRange
      deriving ((forall x. PkgconfigVersionRange -> Rep PkgconfigVersionRange x)
    -> (forall x. Rep PkgconfigVersionRange x -> PkgconfigVersionRange)
    -> Generic PkgconfigVersionRange
    forall x. Rep PkgconfigVersionRange x -> PkgconfigVersionRange
    forall x. PkgconfigVersionRange -> Rep PkgconfigVersionRange x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. PkgconfigVersionRange -> Rep PkgconfigVersionRange x
    from :: forall x. PkgconfigVersionRange -> Rep PkgconfigVersionRange x
    $cto :: forall x. Rep PkgconfigVersionRange x -> PkgconfigVersionRange
    to :: forall x. Rep PkgconfigVersionRange x -> PkgconfigVersionRange
    Generic, ReadPrec [PkgconfigVersionRange]
    ReadPrec PkgconfigVersionRange
    Int -> ReadS PkgconfigVersionRange
    ReadS [PkgconfigVersionRange]
    (Int -> ReadS PkgconfigVersionRange)
    -> ReadS [PkgconfigVersionRange]
    -> ReadPrec PkgconfigVersionRange
    -> ReadPrec [PkgconfigVersionRange]
    -> Read PkgconfigVersionRange
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS PkgconfigVersionRange
    readsPrec :: Int -> ReadS PkgconfigVersionRange
    $creadList :: ReadS [PkgconfigVersionRange]
    readList :: ReadS [PkgconfigVersionRange]
    $creadPrec :: ReadPrec PkgconfigVersionRange
    readPrec :: ReadPrec PkgconfigVersionRange
    $creadListPrec :: ReadPrec [PkgconfigVersionRange]
    readListPrec :: ReadPrec [PkgconfigVersionRange]
    Read, Int -> PkgconfigVersionRange -> ShowS
    [PkgconfigVersionRange] -> ShowS
    PkgconfigVersionRange -> String
    (Int -> PkgconfigVersionRange -> ShowS)
    -> (PkgconfigVersionRange -> String)
    -> ([PkgconfigVersionRange] -> ShowS)
    -> Show PkgconfigVersionRange
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> PkgconfigVersionRange -> ShowS
    showsPrec :: Int -> PkgconfigVersionRange -> ShowS
    $cshow :: PkgconfigVersionRange -> String
    show :: PkgconfigVersionRange -> String
    $cshowList :: [PkgconfigVersionRange] -> ShowS
    showList :: [PkgconfigVersionRange] -> ShowS
    Show, PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    (PkgconfigVersionRange -> PkgconfigVersionRange -> Bool)
    -> (PkgconfigVersionRange -> PkgconfigVersionRange -> Bool)
    -> Eq PkgconfigVersionRange
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    == :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    $c/= :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    /= :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    Eq, Eq PkgconfigVersionRange
    Eq PkgconfigVersionRange =>
    (PkgconfigVersionRange -> PkgconfigVersionRange -> Ordering)
    -> (PkgconfigVersionRange -> PkgconfigVersionRange -> Bool)
    -> (PkgconfigVersionRange -> PkgconfigVersionRange -> Bool)
    -> (PkgconfigVersionRange -> PkgconfigVersionRange -> Bool)
    -> (PkgconfigVersionRange -> PkgconfigVersionRange -> Bool)
    -> (PkgconfigVersionRange
        -> PkgconfigVersionRange -> PkgconfigVersionRange)
    -> (PkgconfigVersionRange
        -> PkgconfigVersionRange -> PkgconfigVersionRange)
    -> Ord PkgconfigVersionRange
    PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    PkgconfigVersionRange -> PkgconfigVersionRange -> Ordering
    PkgconfigVersionRange
    -> PkgconfigVersionRange -> PkgconfigVersionRange
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: PkgconfigVersionRange -> PkgconfigVersionRange -> Ordering
    compare :: PkgconfigVersionRange -> PkgconfigVersionRange -> Ordering
    $c< :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    < :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    $c<= :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    <= :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    $c> :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    > :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    $c>= :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    >= :: PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    $cmax :: PkgconfigVersionRange
    -> PkgconfigVersionRange -> PkgconfigVersionRange
    max :: PkgconfigVersionRange
    -> PkgconfigVersionRange -> PkgconfigVersionRange
    $cmin :: PkgconfigVersionRange
    -> PkgconfigVersionRange -> PkgconfigVersionRange
    min :: PkgconfigVersionRange
    -> PkgconfigVersionRange -> PkgconfigVersionRange
    Ord, Typeable, Typeable PkgconfigVersionRange
    Typeable PkgconfigVersionRange =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g)
     -> PkgconfigVersionRange
     -> c PkgconfigVersionRange)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c PkgconfigVersionRange)
    -> (PkgconfigVersionRange -> Constr)
    -> (PkgconfigVersionRange -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c PkgconfigVersionRange))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e))
        -> Maybe (c PkgconfigVersionRange))
    -> ((forall b. Data b => b -> b)
        -> PkgconfigVersionRange -> PkgconfigVersionRange)
    -> (forall r r'.
        (r -> r' -> r)
        -> r
        -> (forall d. Data d => d -> r')
        -> PkgconfigVersionRange
        -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r
        -> (forall d. Data d => d -> r')
        -> PkgconfigVersionRange
        -> r)
    -> (forall u.
        (forall d. Data d => d -> u) -> PkgconfigVersionRange -> [u])
    -> (forall u.
        Int -> (forall d. Data d => d -> u) -> PkgconfigVersionRange -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d)
        -> PkgconfigVersionRange -> m PkgconfigVersionRange)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d)
        -> PkgconfigVersionRange -> m PkgconfigVersionRange)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d)
        -> PkgconfigVersionRange -> m PkgconfigVersionRange)
    -> Data PkgconfigVersionRange
    PkgconfigVersionRange -> Constr
    PkgconfigVersionRange -> DataType
    (forall b. Data b => b -> b)
    -> PkgconfigVersionRange -> PkgconfigVersionRange
    forall a.
    Typeable a =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u.
    Int -> (forall d. Data d => d -> u) -> PkgconfigVersionRange -> u
    forall u.
    (forall d. Data d => d -> u) -> PkgconfigVersionRange -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PkgconfigVersionRange -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PkgconfigVersionRange -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> PkgconfigVersionRange -> m PkgconfigVersionRange
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> PkgconfigVersionRange -> m PkgconfigVersionRange
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PkgconfigVersionRange
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g)
    -> PkgconfigVersionRange
    -> c PkgconfigVersionRange
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PkgconfigVersionRange)
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c PkgconfigVersionRange)
    $cgfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g)
    -> PkgconfigVersionRange
    -> c PkgconfigVersionRange
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g)
    -> PkgconfigVersionRange
    -> c PkgconfigVersionRange
    $cgunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PkgconfigVersionRange
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PkgconfigVersionRange
    $ctoConstr :: PkgconfigVersionRange -> Constr
    toConstr :: PkgconfigVersionRange -> Constr
    $cdataTypeOf :: PkgconfigVersionRange -> DataType
    dataTypeOf :: PkgconfigVersionRange -> DataType
    $cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PkgconfigVersionRange)
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PkgconfigVersionRange)
    $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c PkgconfigVersionRange)
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c PkgconfigVersionRange)
    $cgmapT :: (forall b. Data b => b -> b)
    -> PkgconfigVersionRange -> PkgconfigVersionRange
    gmapT :: (forall b. Data b => b -> b)
    -> PkgconfigVersionRange -> PkgconfigVersionRange
    $cgmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PkgconfigVersionRange -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PkgconfigVersionRange -> r
    $cgmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PkgconfigVersionRange -> r
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PkgconfigVersionRange -> r
    $cgmapQ :: forall u.
    (forall d. Data d => d -> u) -> PkgconfigVersionRange -> [u]
    gmapQ :: forall u.
    (forall d. Data d => d -> u) -> PkgconfigVersionRange -> [u]
    $cgmapQi :: forall u.
    Int -> (forall d. Data d => d -> u) -> PkgconfigVersionRange -> u
    gmapQi :: forall u.
    Int -> (forall d. Data d => d -> u) -> PkgconfigVersionRange -> u
    $cgmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> PkgconfigVersionRange -> m PkgconfigVersionRange
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d)
    -> PkgconfigVersionRange -> m PkgconfigVersionRange
    $cgmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> PkgconfigVersionRange -> m PkgconfigVersionRange
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> PkgconfigVersionRange -> m PkgconfigVersionRange
    $cgmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> PkgconfigVersionRange -> m PkgconfigVersionRange
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d)
    -> PkgconfigVersionRange -> m PkgconfigVersionRange
    Data)

    instance Binary PkgconfigVersionRange
    instance Structured PkgconfigVersionRange
    instance NFData PkgconfigVersionRange where rnf :: PkgconfigVersionRange -> ()
    rnf = PkgconfigVersionRange -> ()
    forall a. (Generic a, GNFData (Rep a)) => a -> ()
    genericRnf

    instance Pretty PkgconfigVersionRange where
      pretty :: PkgconfigVersionRange -> Doc
    pretty = Int -> PkgconfigVersionRange -> Doc
    pp Int
    0
        where
          pp :: Int -> PkgconfigVersionRange -> PP.Doc
          pp :: Int -> PkgconfigVersionRange -> Doc
    pp Int
    _ PkgconfigVersionRange
    PcAnyVersion = String -> Doc
    PP.text String
    "-any"
          pp Int
    _ (PcThisVersion PkgconfigVersion
    v) = String -> Doc
    PP.text String
    "==" Doc -> Doc -> Doc
    <<>> PkgconfigVersion -> Doc
    forall a. Pretty a => a -> Doc
    pretty PkgconfigVersion
    v
          pp Int
    _ (PcLaterVersion PkgconfigVersion
    v) = String -> Doc
    PP.text String
    ">" Doc -> Doc -> Doc
    <<>> PkgconfigVersion -> Doc
    forall a. Pretty a => a -> Doc
    pretty PkgconfigVersion
    v
          pp Int
    _ (PcEarlierVersion PkgconfigVersion
    v) = String -> Doc
    PP.text String
    "<" Doc -> Doc -> Doc
    <<>> PkgconfigVersion -> Doc
    forall a. Pretty a => a -> Doc
    pretty PkgconfigVersion
    v
          pp Int
    _ (PcOrLaterVersion PkgconfigVersion
    v) = String -> Doc
    PP.text String
    ">=" Doc -> Doc -> Doc
    <<>> PkgconfigVersion -> Doc
    forall a. Pretty a => a -> Doc
    pretty PkgconfigVersion
    v
          pp Int
    _ (PcOrEarlierVersion PkgconfigVersion
    v) = String -> Doc
    PP.text String
    "<=" Doc -> Doc -> Doc
    <<>> PkgconfigVersion -> Doc
    forall a. Pretty a => a -> Doc
    pretty PkgconfigVersion
    v
          pp Int
    d (PcUnionVersionRanges PkgconfigVersionRange
    v PkgconfigVersionRange
    u) =
            Bool -> Doc -> Doc
    parens (Int
    d Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    1) (Doc -> Doc) -> Doc -> Doc
    forall a b. (a -> b) -> a -> b
    $
              Int -> PkgconfigVersionRange -> Doc
    pp Int
    1 PkgconfigVersionRange
    v Doc -> Doc -> Doc
    PP.<+> String -> Doc
    PP.text String
    "||" Doc -> Doc -> Doc
    PP.<+> Int -> PkgconfigVersionRange -> Doc
    pp Int
    0 PkgconfigVersionRange
    u
          pp Int
    d (PcIntersectVersionRanges PkgconfigVersionRange
    v PkgconfigVersionRange
    u) =
            Bool -> Doc -> Doc
    parens (Int
    d Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    2) (Doc -> Doc) -> Doc -> Doc
    forall a b. (a -> b) -> a -> b
    $
              Int -> PkgconfigVersionRange -> Doc
    pp Int
    2 PkgconfigVersionRange
    v Doc -> Doc -> Doc
    PP.<+> String -> Doc
    PP.text String
    "&&" Doc -> Doc -> Doc
    PP.<+> Int -> PkgconfigVersionRange -> Doc
    pp Int
    1 PkgconfigVersionRange
    u

          parens :: Bool -> Doc -> Doc
    parens Bool
    True = Doc -> Doc
    PP.parens
          parens Bool
    False = Doc -> Doc
    forall a. a -> a
    id

    instance Parsec PkgconfigVersionRange where
      -- note: the wildcard is used in some places, e.g
      -- http://hackage.haskell.org/package/bindings-libzip-0.10.1/bindings-libzip.cabal
      --
      -- however, in the presence of alphanumerics etc. lax version parser,
      -- wildcard is ill-specified

      parsec :: forall (m :: * -> *). CabalParsing m => m PkgconfigVersionRange
    parsec = do
        csv <- m CabalSpecVersion
    forall (m :: * -> *). CabalParsing m => m CabalSpecVersion
    askCabalSpecVersion
        if csv >= CabalSpecV3_0
          then pkgconfigParser
          else versionRangeToPkgconfigVersionRange <$> versionRangeParser P.integral csv

    -- "modern" parser of @pkg-config@ package versions.
    pkgconfigParser :: CabalParsing m => m PkgconfigVersionRange
    pkgconfigParser :: forall (m :: * -> *). CabalParsing m => m PkgconfigVersionRange
    pkgconfigParser = m ()
    forall (m :: * -> *). CharParsing m => m ()
    P.spaces m () -> m PkgconfigVersionRange -> m PkgconfigVersionRange
    forall a b. m a -> m b -> m b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> m PkgconfigVersionRange
    expr
      where
        -- every parser here eats trailing space
        expr :: m PkgconfigVersionRange
    expr = do
          ts <- m PkgconfigVersionRange
    term m PkgconfigVersionRange
    -> m () -> m (NonEmpty PkgconfigVersionRange)
    forall (m :: * -> *) a sep.
    Alternative m =>
    m a -> m sep -> m (NonEmpty a)
    `P.sepByNonEmpty` (String -> m String
    forall (m :: * -> *). CharParsing m => String -> m String
    P.string String
    "||" m String -> m () -> m ()
    forall a b. m a -> m b -> m b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> m ()
    forall (m :: * -> *). CharParsing m => m ()
    P.spaces)
          return $ foldr1 PcUnionVersionRanges ts

        term :: m PkgconfigVersionRange
    term = do
          fs <- m PkgconfigVersionRange
    factor m PkgconfigVersionRange
    -> m () -> m (NonEmpty PkgconfigVersionRange)
    forall (m :: * -> *) a sep.
    Alternative m =>
    m a -> m sep -> m (NonEmpty a)
    `P.sepByNonEmpty` (String -> m String
    forall (m :: * -> *). CharParsing m => String -> m String
    P.string String
    "&&" m String -> m () -> m ()
    forall a b. m a -> m b -> m b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> m ()
    forall (m :: * -> *). CharParsing m => m ()
    P.spaces)
          return $ foldr1 PcIntersectVersionRanges fs

        factor :: m PkgconfigVersionRange
    factor = m PkgconfigVersionRange -> m PkgconfigVersionRange
    forall {a}. m a -> m a
    parens m PkgconfigVersionRange
    expr m PkgconfigVersionRange
    -> m PkgconfigVersionRange -> m PkgconfigVersionRange
    forall a. m a -> m a -> m a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    <|> m PkgconfigVersionRange
    prim

        prim :: m PkgconfigVersionRange
    prim = do
          op <- (Char -> Bool) -> m String
    forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m String
    P.munch1 Char -> Bool
    isOpChar m String -> String -> m String
    forall a. m a -> String -> m a
    forall (m :: * -> *) a. Parsing m => m a -> String -> m a
    P.<?> String
    "operator"
          case op of
            String
    "-" -> PkgconfigVersionRange
    anyPkgconfigVersion PkgconfigVersionRange -> m () -> m PkgconfigVersionRange
    forall a b. a -> m b -> m a
    forall (f :: * -> *) a b. Functor f => a -> f b -> f a
    <$ (String -> m String
    forall (m :: * -> *). CharParsing m => String -> m String
    P.string String
    "any" m String -> m () -> m ()
    forall a b. m a -> m b -> m b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> m ()
    forall (m :: * -> *). CharParsing m => m ()
    P.spaces)
            String
    "==" -> (PkgconfigVersion -> PkgconfigVersionRange)
    -> m PkgconfigVersionRange
    forall {m :: * -> *} {t} {b}.
    (Parsec t, CabalParsing m) =>
    (t -> b) -> m b
    afterOp PkgconfigVersion -> PkgconfigVersionRange
    PcThisVersion
            String
    ">" -> (PkgconfigVersion -> PkgconfigVersionRange)
    -> m PkgconfigVersionRange
    forall {m :: * -> *} {t} {b}.
    (Parsec t, CabalParsing m) =>
    (t -> b) -> m b
    afterOp PkgconfigVersion -> PkgconfigVersionRange
    PcLaterVersion
            String
    "<" -> (PkgconfigVersion -> PkgconfigVersionRange)
    -> m PkgconfigVersionRange
    forall {m :: * -> *} {t} {b}.
    (Parsec t, CabalParsing m) =>
    (t -> b) -> m b
    afterOp PkgconfigVersion -> PkgconfigVersionRange
    PcEarlierVersion
            String
    ">=" -> (PkgconfigVersion -> PkgconfigVersionRange)
    -> m PkgconfigVersionRange
    forall {m :: * -> *} {t} {b}.
    (Parsec t, CabalParsing m) =>
    (t -> b) -> m b
    afterOp PkgconfigVersion -> PkgconfigVersionRange
    PcOrLaterVersion
            String
    "<=" -> (PkgconfigVersion -> PkgconfigVersionRange)
    -> m PkgconfigVersionRange
    forall {m :: * -> *} {t} {b}.
    (Parsec t, CabalParsing m) =>
    (t -> b) -> m b
    afterOp PkgconfigVersion -> PkgconfigVersionRange
    PcOrEarlierVersion
            String
    _ -> String -> m PkgconfigVersionRange
    forall a. String -> m a
    forall (m :: * -> *) a. Parsing m => String -> m a
    P.unexpected (String -> m PkgconfigVersionRange)
    -> String -> m PkgconfigVersionRange
    forall a b. (a -> b) -> a -> b
    $ String
    "Unknown version operator " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ShowS
    forall a. Show a => a -> String
    show String
    op

        -- https://gitlab.haskell.org/ghc/ghc/issues/17752
        isOpChar :: Char -> Bool
    isOpChar Char
    '<' = Bool
    True
        isOpChar Char
    '=' = Bool
    True
        isOpChar Char
    '>' = Bool
    True
        isOpChar Char
    '^' = Bool
    True
        isOpChar Char
    '-' = Bool
    True
        isOpChar Char
    _ = Bool
    False

        afterOp :: (t -> b) -> m b
    afterOp t -> b
    f = do
          m ()
    forall (m :: * -> *). CharParsing m => m ()
    P.spaces
          v <- m t
    forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
    forall (m :: * -> *). CabalParsing m => m t
    parsec
          P.spaces
          return (f v)

        parens :: m a -> m a
    parens =
          m () -> m () -> m a -> m a
    forall (m :: * -> *) bra ket a.
    Applicative m =>
    m bra -> m ket -> m a -> m a
    P.between
            ((Char -> m Char
    forall (m :: * -> *). CharParsing m => Char -> m Char
    P.char Char
    '(' m Char -> String -> m Char
    forall a. m a -> String -> m a
    forall (m :: * -> *) a. Parsing m => m a -> String -> m a
    P.<?> String
    "opening paren") m Char -> m () -> m ()
    forall a b. m a -> m b -> m b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> m ()
    forall (m :: * -> *). CharParsing m => m ()
    P.spaces)
            (Char -> m Char
    forall (m :: * -> *). CharParsing m => Char -> m Char
    P.char Char
    ')' m Char -> m () -> m ()
    forall a b. m a -> m b -> m b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> m ()
    forall (m :: * -> *). CharParsing m => m ()
    P.spaces)

    anyPkgconfigVersion :: PkgconfigVersionRange
    anyPkgconfigVersion :: PkgconfigVersionRange
    anyPkgconfigVersion = PkgconfigVersionRange
    PcAnyVersion

    -- | TODO: this is not precise, but used only to prettify output.
    isAnyPkgconfigVersion :: PkgconfigVersionRange -> Bool
    isAnyPkgconfigVersion :: PkgconfigVersionRange -> Bool
    isAnyPkgconfigVersion = (PkgconfigVersionRange -> PkgconfigVersionRange -> Bool
    forall a. Eq a => a -> a -> Bool
    == PkgconfigVersionRange
    PcAnyVersion)

    withinPkgconfigVersionRange :: PkgconfigVersion -> PkgconfigVersionRange -> Bool
    withinPkgconfigVersionRange :: PkgconfigVersion -> PkgconfigVersionRange -> Bool
    withinPkgconfigVersionRange PkgconfigVersion
    v = PkgconfigVersionRange -> Bool
    go
      where
        go :: PkgconfigVersionRange -> Bool
    go PkgconfigVersionRange
    PcAnyVersion = Bool
    True
        go (PcThisVersion PkgconfigVersion
    u) = PkgconfigVersion
    v PkgconfigVersion -> PkgconfigVersion -> Bool
    forall a. Eq a => a -> a -> Bool
    == PkgconfigVersion
    u
        go (PcLaterVersion PkgconfigVersion
    u) = PkgconfigVersion
    v PkgconfigVersion -> PkgconfigVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    > PkgconfigVersion
    u
        go (PcEarlierVersion PkgconfigVersion
    u) = PkgconfigVersion
    v PkgconfigVersion -> PkgconfigVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    < PkgconfigVersion
    u
        go (PcOrLaterVersion PkgconfigVersion
    u) = PkgconfigVersion
    v PkgconfigVersion -> PkgconfigVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    >= PkgconfigVersion
    u
        go (PcOrEarlierVersion PkgconfigVersion
    u) = PkgconfigVersion
    v PkgconfigVersion -> PkgconfigVersion -> Bool
    forall a. Ord a => a -> a -> Bool
    <= PkgconfigVersion
    u
        go (PcUnionVersionRanges PkgconfigVersionRange
    a PkgconfigVersionRange
    b) = PkgconfigVersionRange -> Bool
    go PkgconfigVersionRange
    a Bool -> Bool -> Bool
    || PkgconfigVersionRange -> Bool
    go PkgconfigVersionRange
    b
        go (PcIntersectVersionRanges PkgconfigVersionRange
    a PkgconfigVersionRange
    b) = PkgconfigVersionRange -> Bool
    go PkgconfigVersionRange
    a Bool -> Bool -> Bool
    && PkgconfigVersionRange -> Bool
    go PkgconfigVersionRange
    b

    -------------------------------------------------------------------------------
    -- Conversion
    -------------------------------------------------------------------------------

    versionToPkgconfigVersion :: Version -> PkgconfigVersion
    versionToPkgconfigVersion :: Version -> PkgconfigVersion
    versionToPkgconfigVersion = ByteString -> PkgconfigVersion
    PkgconfigVersion (ByteString -> PkgconfigVersion)
    -> (Version -> ByteString) -> Version -> PkgconfigVersion
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> ByteString
    BS8.pack (String -> ByteString)
    -> (Version -> String) -> Version -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Version -> String
    forall a. Pretty a => a -> String
    prettyShow

    versionRangeToPkgconfigVersionRange :: VersionRange -> PkgconfigVersionRange
    versionRangeToPkgconfigVersionRange :: VersionRange -> PkgconfigVersionRange
    versionRangeToPkgconfigVersionRange VersionRange
    vr
      | VersionRange -> Bool
    isAnyVersion VersionRange
    vr =
          PkgconfigVersionRange
    PcAnyVersion
      | Bool
    otherwise =
          case VersionRange -> [VersionInterval]
    asVersionIntervals VersionRange
    vr of
            [] -> PkgconfigVersion -> PkgconfigVersionRange
    PcEarlierVersion (ByteString -> PkgconfigVersion
    PkgconfigVersion (String -> ByteString
    BS8.pack String
    "0"))
            (VersionInterval
    i : [VersionInterval]
    is) -> (PkgconfigVersionRange -> VersionInterval -> PkgconfigVersionRange)
    -> PkgconfigVersionRange
    -> [VersionInterval]
    -> PkgconfigVersionRange
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl (\PkgconfigVersionRange
    r VersionInterval
    j -> PkgconfigVersionRange
    -> PkgconfigVersionRange -> PkgconfigVersionRange
    PcUnionVersionRanges PkgconfigVersionRange
    r (VersionInterval -> PkgconfigVersionRange
    conv VersionInterval
    j)) (VersionInterval -> PkgconfigVersionRange
    conv VersionInterval
    i) [VersionInterval]
    is
      where
        conv :: VersionInterval -> PkgconfigVersionRange
    conv (VersionInterval (LowerBound Version
    v Bound
    b) UpperBound
    NoUpperBound) = Version -> Bound -> PkgconfigVersionRange
    convL Version
    v Bound
    b
        conv (VersionInterval (LowerBound Version
    v Bound
    b) (UpperBound Version
    u Bound
    c)) = PkgconfigVersionRange
    -> PkgconfigVersionRange -> PkgconfigVersionRange
    PcIntersectVersionRanges (Version -> Bound -> PkgconfigVersionRange
    convL Version
    v Bound
    b) (Version -> Bound -> PkgconfigVersionRange
    convU Version
    u Bound
    c)

        convL :: Version -> Bound -> PkgconfigVersionRange
    convL Version
    v Bound
    ExclusiveBound = PkgconfigVersion -> PkgconfigVersionRange
    PcLaterVersion (Version -> PkgconfigVersion
    versionToPkgconfigVersion Version
    v)
        convL Version
    v Bound
    InclusiveBound = PkgconfigVersion -> PkgconfigVersionRange
    PcOrLaterVersion (Version -> PkgconfigVersion
    versionToPkgconfigVersion Version
    v)

        convU :: Version -> Bound -> PkgconfigVersionRange
    convU Version
    v Bound
    ExclusiveBound = PkgconfigVersion -> PkgconfigVersionRange
    PcEarlierVersion (Version -> PkgconfigVersion
    versionToPkgconfigVersion Version
    v)
        convU Version
    v Bound
    InclusiveBound = PkgconfigVersion -> PkgconfigVersionRange
    PcOrEarlierVersion (Version -> PkgconfigVersion
    versionToPkgconfigVersion Version
    v)