    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE DeriveGeneric      #-}
    module Distribution.Types.Version (
        -- * Package versions
        Version,
        mkVersion,
        mkVersion',
        versionNumbers,
        nullVersion,
        alterVersion,
        version0,

        -- * Internal
        validVersion,
        versionDigitParser,
        ) where

    import Data.Bits                   (shiftL, shiftR, (.&.), (.|.))
    import Distribution.Compat.Prelude
    import Prelude ()

    import Distribution.Parsec
    import Distribution.Pretty

    import qualified Data.Version                    as Base
    import qualified Distribution.Compat.CharParsing as P
    import qualified Text.PrettyPrint                as Disp
    import qualified Text.Read                       as Read

    -- | A 'Version' represents the version of a software entity.
    --
    -- Instances of 'Eq' and 'Ord' are provided, which gives exact
    -- equality and lexicographic ordering of the version number
    -- components (i.e. 2.1 > 2.0, 1.2.3 > 1.2.2, etc.).
    --
    -- This type is opaque and distinct from the 'Base.Version' type in
    -- "Data.Version" since @Cabal-2.0@. The difference extends to the
    -- 'Binary' instance using a different (and more compact) encoding.
    --
    -- @since 2.0.0.2
    data Version = PV0 {-# UNPACK #-} !Word64
                 | PV1 !Int [Int]
                 -- NOTE: If a version fits into the packed Word64
                 -- representation (i.e. at most four version components
                 -- which all fall into the [0..0xfffe] range), then PV0
                 -- MUST be used. This is essential for the 'Eq' instance
                 -- to work.
                 deriving (Typeable Version
    Typeable Version
    -> (forall (c :: * -> *).
        (forall d b. Data d => c (d -> b) -> d -> c b)
        -> (forall g. g -> c g) -> Version -> c Version)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c Version)
    -> (Version -> Constr)
    -> (Version -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c Version))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Version))
    -> ((forall b. Data b => b -> b) -> Version -> Version)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> Version -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> Version -> r)
    -> (forall u. (forall d. Data d => d -> u) -> Version -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> Version -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> Version -> m Version)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> Version -> m Version)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> Version -> m Version)
    -> Data Version
    Version -> DataType
    Version -> Constr
    (forall b. Data b => b -> b) -> Version -> Version
    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) -> Version -> u
    forall u. (forall d. Data d => d -> u) -> Version -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Version -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Version -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Version -> m Version
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Version -> m Version
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Version
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Version -> c Version
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Version)
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Version)
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Version -> m Version
    $cgmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Version -> m Version
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Version -> m Version
    $cgmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Version -> m Version
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Version -> m Version
    $cgmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Version -> m Version
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Version -> u
    $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Version -> u
    gmapQ :: forall u. (forall d. Data d => d -> u) -> Version -> [u]
    $cgmapQ :: forall u. (forall d. Data d => d -> u) -> Version -> [u]
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Version -> r
    $cgmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> Version -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Version -> r
    $cgmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> Version -> r
    gmapT :: (forall b. Data b => b -> b) -> Version -> Version
    $cgmapT :: (forall b. Data b => b -> b) -> Version -> Version
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Version)
    $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Version)
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Version)
    $cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Version)
    dataTypeOf :: Version -> DataType
    $cdataTypeOf :: Version -> DataType
    toConstr :: Version -> Constr
    $ctoConstr :: Version -> Constr
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Version
    $cgunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Version
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Version -> c Version
    $cgfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Version -> c Version
    Data,Version -> Version -> Bool
    (Version -> Version -> Bool)
    -> (Version -> Version -> Bool) -> Eq Version
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Version -> Version -> Bool
    $c/= :: Version -> Version -> Bool
    == :: Version -> Version -> Bool
    $c== :: Version -> Version -> Bool
    Eq,(forall x. Version -> Rep Version x)
    -> (forall x. Rep Version x -> Version) -> Generic Version
    forall x. Rep Version x -> Version
    forall x. Version -> Rep Version x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cto :: forall x. Rep Version x -> Version
    $cfrom :: forall x. Version -> Rep Version x
    Generic,Typeable)

    instance Ord Version where
        compare :: Version -> Version -> Ordering
    compare (PV0 Word64
    x)    (PV0 Word64
    y)    = Word64 -> Word64 -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare Word64
    x Word64
    y
        compare (PV1 Int
    x [Int]
    xs) (PV1 Int
    y [Int]
    ys) = case Int -> Int -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare Int
    x Int
    y of
            Ordering
    EQ -> [Int] -> [Int] -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare [Int]
    xs [Int]
    ys
            Ordering
    c  -> Ordering
    c
        compare (PV0 Word64
    w)    (PV1 Int
    y [Int]
    ys) = case Int -> Int -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare Int
    x Int
    y of
            Ordering
    EQ -> [Int] -> [Int] -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare [Int
    x2,Int
    x3,Int
    x4] [Int]
    ys
            Ordering
    c  -> Ordering
    c
          where
            x :: Int
    x  = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ((Word64
    w Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    48) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
            x2 :: Int
    x2 = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ((Word64
    w Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    32) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
            x3 :: Int
    x3 = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ((Word64
    w Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    16) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
            x4 :: Int
    x4 = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral               (Word64
    w Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
        compare (PV1 Int
    x [Int]
    xs) (PV0 Word64
    w)    = case Int -> Int -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare Int
    x Int
    y of
            Ordering
    EQ -> [Int] -> [Int] -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare [Int]
    xs [Int
    y2,Int
    y3,Int
    y4]
            Ordering
    c  -> Ordering
    c
          where
            y :: Int
    y  = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ((Word64
    w Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    48) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
            y2 :: Int
    y2 = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ((Word64
    w Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    32) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
            y3 :: Int
    y3 = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ((Word64
    w Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    16) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
            y4 :: Int
    y4 = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral               (Word64
    w Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1

    instance Show Version where
        showsPrec :: Int -> Version -> ShowS
    showsPrec Int
    d Version
    v = Bool -> ShowS -> ShowS
    showParen (Int
    d Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    10)
            (ShowS -> ShowS) -> ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ String -> ShowS
    showString String
    "mkVersion "
            ShowS -> ShowS -> ShowS
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> [Int] -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    11 (Version -> [Int]
    versionNumbers Version
    v)

    instance Read Version where
        readPrec :: ReadPrec Version
    readPrec = ReadPrec Version -> ReadPrec Version
    forall a. ReadPrec a -> ReadPrec a
    Read.parens (ReadPrec Version -> ReadPrec Version)
    -> ReadPrec Version -> ReadPrec Version
    forall a b. (a -> b) -> a -> b
    $ do
            Read.Ident String
    "mkVersion" <- ReadPrec Lexeme
    Read.lexP
            [Int]
    v <- ReadPrec [Int] -> ReadPrec [Int]
    forall a. ReadPrec a -> ReadPrec a
    Read.step ReadPrec [Int]
    forall a. Read a => ReadPrec a
    Read.readPrec
            Version -> ReadPrec Version
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([Int] -> Version
    mkVersion [Int]
    v)

    instance Binary Version
    instance Structured Version

    instance NFData Version where
        rnf :: Version -> ()
    rnf (PV0 Word64
    _) = ()
        rnf (PV1 Int
    _ [Int]
    ns) = [Int] -> ()
    forall a. NFData a => a -> ()
    rnf [Int]
    ns

    instance Pretty Version where
      pretty :: Version -> Doc
    pretty Version
    ver
        = [Doc] -> Doc
    Disp.hcat (Doc -> [Doc] -> [Doc]
    Disp.punctuate (Char -> Doc
    Disp.char Char
    '.')
                                    ((Int -> Doc) -> [Int] -> [Doc]
    forall a b. (a -> b) -> [a] -> [b]
    map Int -> Doc
    Disp.int ([Int] -> [Doc]) -> [Int] -> [Doc]
    forall a b. (a -> b) -> a -> b
    $ Version -> [Int]
    versionNumbers Version
    ver))

    instance Parsec Version where
        parsec :: forall (m :: * -> *). CabalParsing m => m Version
    parsec = [Int] -> Version
    mkVersion ([Int] -> Version)
    -> (NonEmpty Int -> [Int]) -> NonEmpty Int -> Version
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> NonEmpty Int -> [Int]
    forall (t :: * -> *) a. Foldable t => t a -> [a]
    toList (NonEmpty Int -> Version) -> m (NonEmpty Int) -> m Version
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> m Int -> m Char -> m (NonEmpty Int)
    forall (m :: * -> *) a sep.
    Alternative m =>
    m a -> m sep -> m (NonEmpty a)
    P.sepByNonEmpty m Int
    forall (m :: * -> *). CabalParsing m => m Int
    versionDigitParser (Char -> m Char
    forall (m :: * -> *). CharParsing m => Char -> m Char
    P.char Char
    '.') m Version -> m () -> m Version
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* m ()
    tags
          where
            tags :: m ()
    tags = do
                [String]
    ts <- m String -> m [String]
    forall (f :: * -> *) a. Alternative f => f a -> f [a]
    many (m String -> m [String]) -> m String -> m [String]
    forall a b. (a -> b) -> a -> b
    $ Char -> m Char
    forall (m :: * -> *). CharParsing m => Char -> m Char
    P.char Char
    '-' m Char -> m String -> m String
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> m Char -> m String
    forall (f :: * -> *) a. Alternative f => f a -> f [a]
    some ((Char -> Bool) -> m Char
    forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m Char
    P.satisfy Char -> Bool
    isAlphaNum)
                case [String]
    ts of
                    []      -> () -> m ()
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()
                    (String
    _ : [String]
    _) -> PWarnType -> String -> m ()
    forall (m :: * -> *). CabalParsing m => PWarnType -> String -> m ()
    parsecWarning PWarnType
    PWTVersionTag String
    "version with tags"

    -- | An integral without leading zeroes.
    --
    -- @since 3.0
    versionDigitParser :: CabalParsing m => m Int
    versionDigitParser :: forall (m :: * -> *). CabalParsing m => m Int
    versionDigitParser = (m Int -> m [Int]
    forall (f :: * -> *) a. Alternative f => f a -> f [a]
    some m Int
    forall (m :: * -> *). CharParsing m => m Int
    d m [Int] -> ([Int] -> m Int) -> m Int
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= [Int] -> m Int
    forall (m :: * -> *). CabalParsing m => [Int] -> m Int
    toNumber) m Int -> String -> m Int
    forall (m :: * -> *) a. Parsing m => m a -> String -> m a
    P.<?> String
    "version digit (integral without leading zeroes)"
      where
        toNumber :: CabalParsing m => [Int] -> m Int
        toNumber :: forall (m :: * -> *). CabalParsing m => [Int] -> m Int
    toNumber [Int
    0]   = Int -> m Int
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    0
        toNumber (Int
    0:[Int]
    _) = String -> m Int
    forall (m :: * -> *) a. Parsing m => String -> m a
    P.unexpected String
    "Version digit with leading zero"
        toNumber [Int]
    xs
            -- 10^9 = 1000000000
            -- 2^30 = 1073741824
            --
            -- GHC Int is at least 32 bits, so 2^31-1 is the 'maxBound'.
            | [Int] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [Int]
    xs Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    9 = String -> m Int
    forall (m :: * -> *) a. Parsing m => String -> m a
    P.unexpected String
    "At most 9 numbers are allowed per version number part"
            | Bool
    otherwise     = Int -> m Int
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Int -> m Int) -> Int -> m Int
    forall a b. (a -> b) -> a -> b
    $ (Int -> Int -> Int) -> Int -> [Int] -> Int
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (\Int
    a Int
    b -> Int
    a Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    10 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    b) Int
    0 [Int]
    xs

        d :: P.CharParsing m => m Int
        d :: forall (m :: * -> *). CharParsing m => m Int
    d = Char -> Int
    f (Char -> Int) -> m Char -> m Int
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Char -> Char -> m Char
    forall (m :: * -> *). CharParsing m => Char -> Char -> m Char
    P.satisfyRange Char
    '0' Char
    '9'
        f :: Char -> Int
    f Char
    c = Char -> Int
    ord Char
    c Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Char -> Int
    ord Char
    '0'

    -- | Construct 'Version' from list of version number components.
    --
    -- For instance, @mkVersion [3,2,1]@ constructs a 'Version'
    -- representing the version @3.2.1@.
    --
    -- All version components must be non-negative. @mkVersion []@
    -- currently represents the special /null/ version; see also 'nullVersion'.
    --
    -- @since 2.0.0.2
    mkVersion :: [Int] -> Version
    -- TODO: add validity check; disallow 'mkVersion []' (we have
    -- 'nullVersion' for that)
    mkVersion :: [Int] -> Version
    mkVersion []                    = Version
    nullVersion
    mkVersion (Int
    v1:[])
      | Int -> Bool
    inWord16VerRep1 Int
    v1          = Word64 -> Version
    PV0 (Int -> Word64
    mkWord64VerRep1 Int
    v1)
      | Bool
    otherwise                   = Int -> [Int] -> Version
    PV1 Int
    v1 []
      where
        inWord16VerRep1 :: Int -> Bool
    inWord16VerRep1 Int
    x1 = Int -> Bool
    inWord16 (Int
    x1 Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. (Int
    x1Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1))
        mkWord64VerRep1 :: Int -> Word64
    mkWord64VerRep1 Int
    y1 = Int -> Int -> Int -> Int -> Word64
    mkWord64VerRep (Int
    y1Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) Int
    0 Int
    0 Int
    0

    mkVersion (Int
    v1:vs :: [Int]
    vs@(Int
    v2:[]))
      | Int -> Int -> Bool
    inWord16VerRep2 Int
    v1 Int
    v2       = Word64 -> Version
    PV0 (Int -> Int -> Word64
    mkWord64VerRep2 Int
    v1 Int
    v2)
      | Bool
    otherwise                   = Int -> [Int] -> Version
    PV1 Int
    v1 [Int]
    vs
      where
        inWord16VerRep2 :: Int -> Int -> Bool
    inWord16VerRep2 Int
    x1 Int
    x2 = Int -> Bool
    inWord16 (Int
    x1 Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. (Int
    x1Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
                                      Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. Int
    x2 Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. (Int
    x2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1))
        mkWord64VerRep2 :: Int -> Int -> Word64
    mkWord64VerRep2 Int
    y1 Int
    y2 = Int -> Int -> Int -> Int -> Word64
    mkWord64VerRep (Int
    y1Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) (Int
    y2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) Int
    0 Int
    0

    mkVersion (Int
    v1:vs :: [Int]
    vs@(Int
    v2:Int
    v3:[]))
      | Int -> Int -> Int -> Bool
    inWord16VerRep3 Int
    v1 Int
    v2 Int
    v3    = Word64 -> Version
    PV0 (Int -> Int -> Int -> Word64
    mkWord64VerRep3 Int
    v1 Int
    v2 Int
    v3)
      | Bool
    otherwise                   = Int -> [Int] -> Version
    PV1 Int
    v1 [Int]
    vs
      where
        inWord16VerRep3 :: Int -> Int -> Int -> Bool
    inWord16VerRep3 Int
    x1 Int
    x2 Int
    x3 = Int -> Bool
    inWord16 (Int
    x1 Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. (Int
    x1Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
                                         Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. Int
    x2 Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. (Int
    x2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
                                         Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. Int
    x3 Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. (Int
    x3Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1))
        mkWord64VerRep3 :: Int -> Int -> Int -> Word64
    mkWord64VerRep3 Int
    y1 Int
    y2 Int
    y3 = Int -> Int -> Int -> Int -> Word64
    mkWord64VerRep (Int
    y1Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) (Int
    y2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) (Int
    y3Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) Int
    0

    mkVersion (Int
    v1:vs :: [Int]
    vs@(Int
    v2:Int
    v3:Int
    v4:[]))
      | Int -> Int -> Int -> Int -> Bool
    inWord16VerRep4 Int
    v1 Int
    v2 Int
    v3 Int
    v4 = Word64 -> Version
    PV0 (Int -> Int -> Int -> Int -> Word64
    mkWord64VerRep4 Int
    v1 Int
    v2 Int
    v3 Int
    v4)
      | Bool
    otherwise                   = Int -> [Int] -> Version
    PV1 Int
    v1 [Int]
    vs
      where
        inWord16VerRep4 :: Int -> Int -> Int -> Int -> Bool
    inWord16VerRep4 Int
    x1 Int
    x2 Int
    x3 Int
    x4 = Int -> Bool
    inWord16 (Int
    x1 Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. (Int
    x1Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
                                            Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. Int
    x2 Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. (Int
    x2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
                                            Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. Int
    x3 Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. (Int
    x3Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
                                            Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. Int
    x4 Int -> Int -> Int
    forall a. Bits a => a -> a -> a
    .|. (Int
    x4Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1))
        mkWord64VerRep4 :: Int -> Int -> Int -> Int -> Word64
    mkWord64VerRep4 Int
    y1 Int
    y2 Int
    y3 Int
    y4 = Int -> Int -> Int -> Int -> Word64
    mkWord64VerRep (Int
    y1Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) (Int
    y2Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) (Int
    y3Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) (Int
    y4Int -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)

    mkVersion (Int
    v1:[Int]
    vs)               = Int -> [Int] -> Version
    PV1 Int
    v1 [Int]
    vs

    -- | Version 0. A lower bound of 'Version'.
    --
    -- @since 2.2
    version0 :: Version
    version0 :: Version
    version0 = [Int] -> Version
    mkVersion [Int
    0]

    {-# INLINE mkWord64VerRep #-}
    mkWord64VerRep :: Int -> Int -> Int -> Int -> Word64
    mkWord64VerRep :: Int -> Int -> Int -> Int -> Word64
    mkWord64VerRep Int
    v1 Int
    v2 Int
    v3 Int
    v4 =
          (Int -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    v1 Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    48)
      Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. (Int -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    v2 Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    32)
      Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|. (Int -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    v3 Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftL` Int
    16)
      Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .|.  Int -> Word64
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    v4

    {-# INLINE inWord16 #-}
    inWord16 :: Int -> Bool
    inWord16 :: Int -> Bool
    inWord16 Int
    x = (Int -> Word
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    x :: Word) Word -> Word -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Word
    0xffff

    -- | Variant of 'mkVersion' which converts a "Data.Version"
    -- 'Base.Version' into Cabal's 'Version' type.
    --
    -- @since 2.0.0.2
    mkVersion' :: Base.Version -> Version
    mkVersion' :: Version -> Version
    mkVersion' = [Int] -> Version
    mkVersion ([Int] -> Version) -> (Version -> [Int]) -> Version -> Version
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Version -> [Int]
    Base.versionBranch

    -- | Unpack 'Version' into list of version number components.
    --
    -- This is the inverse to 'mkVersion', so the following holds:
    --
    -- > (versionNumbers . mkVersion) vs == vs
    --
    -- @since 2.0.0.2
    versionNumbers :: Version -> [Int]
    versionNumbers :: Version -> [Int]
    versionNumbers (PV1 Int
    n [Int]
    ns) = Int
    nInt -> [Int] -> [Int]
    forall a. a -> [a] -> [a]
    :[Int]
    ns
    versionNumbers (PV0 Word64
    w)
      | Int
    v1 Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    0    = []
      | Int
    v2 Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    0    = [Int
    v1]
      | Int
    v3 Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    0    = [Int
    v1,Int
    v2]
      | Int
    v4 Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    0    = [Int
    v1,Int
    v2,Int
    v3]
      | Bool
    otherwise = [Int
    v1,Int
    v2,Int
    v3,Int
    v4]
      where
        v1 :: Int
    v1 = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ((Word64
    w Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    48) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
        v2 :: Int
    v2 = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ((Word64
    w Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    32) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
        v3 :: Int
    v3 = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ((Word64
    w Word64 -> Int -> Word64
    forall a. Bits a => a -> Int -> a
    `shiftR` Int
    16) Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1
        v4 :: Int
    v4 = Word64 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word64
    w Word64 -> Word64 -> Word64
    forall a. Bits a => a -> a -> a
    .&. Word64
    0xffff) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    1

    -- | Constant representing the special /null/ 'Version'
    --
    -- The 'nullVersion' compares (via 'Ord') as less than every proper
    -- 'Version' value.
    --
    -- @since 2.0.0.2
    nullVersion :: Version
    -- TODO: at some point, 'mkVersion' may disallow creating /null/
    -- 'Version's
    nullVersion :: Version
    nullVersion = Word64 -> Version
    PV0 Word64
    0

    -- | Apply function to list of version number components
    --
    -- > alterVersion f == mkVersion . f . versionNumbers
    --
    -- @since 2.0.0.2
    alterVersion :: ([Int] -> [Int]) -> Version -> Version
    alterVersion :: ([Int] -> [Int]) -> Version -> Version
    alterVersion [Int] -> [Int]
    f = [Int] -> Version
    mkVersion ([Int] -> Version) -> (Version -> [Int]) -> Version -> Version
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Int] -> [Int]
    f ([Int] -> [Int]) -> (Version -> [Int]) -> Version -> [Int]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Version -> [Int]
    versionNumbers

    -- internal helper
    validVersion :: Version -> Bool
    validVersion :: Version -> Bool
    validVersion Version
    v = Version
    v Version -> Version -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Version
    nullVersion Bool -> Bool -> Bool
    && (Int -> Bool) -> [Int] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all (Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >=Int
    0) (Version -> [Int]
    versionNumbers Version
    v)