{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
module Distribution.Types.Version
( Version
, mkVersion
, mkVersion'
, versionNumbers
, nullVersion
, alterVersion
, version0
, 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
data Version
= PV0 {-# UNPACK #-} !Word64
| PV1 !Int [Int]
deriving (Data, Eq, Generic)
instance Ord Version where
compare (PV0 x) (PV0 y) = compare x y
compare (PV1 x xs) (PV1 y ys) = case compare x y of
EQ -> compare xs ys
c -> c
compare (PV0 w) (PV1 y ys) = case compare x y of
EQ -> compare [x2, x3, x4] ys
c -> c
where
x = fromIntegral ((w `shiftR` 48) .&. 0xffff) - 1
x2 = fromIntegral ((w `shiftR` 32) .&. 0xffff) - 1
x3 = fromIntegral ((w `shiftR` 16) .&. 0xffff) - 1
x4 = fromIntegral (w .&. 0xffff) - 1
compare (PV1 x xs) (PV0 w) = case compare x y of
EQ -> compare xs [y2, y3, y4]
c -> c
where
y = fromIntegral ((w `shiftR` 48) .&. 0xffff) - 1
y2 = fromIntegral ((w `shiftR` 32) .&. 0xffff) - 1
y3 = fromIntegral ((w `shiftR` 16) .&. 0xffff) - 1
y4 = fromIntegral (w .&. 0xffff) - 1
instance Show Version where
showsPrec d v =
showParen (d > 10) $
showString "mkVersion "
. showsPrec 11 (versionNumbers v)
instance Read Version where
readPrec = Read.parens $ do
Read.Ident "mkVersion" <- Read.lexP
v <- Read.step Read.readPrec
return (mkVersion v)
instance Binary Version
instance Structured Version
instance NFData Version where
rnf (PV0 _) = ()
rnf (PV1 _ ns) = rnf ns
instance Pretty Version where
pretty ver =
Disp.hcat
( Disp.punctuate
(Disp.char '.')
(map Disp.int $ versionNumbers ver)
)
instance Parsec Version where
parsec = mkVersion <$> toList <$> P.sepByNonEmpty versionDigitParser (P.char '.') <* tags
where
tags = do
ts <- many $ P.char '-' *> some (P.satisfy isAlphaNum)
case ts of
[] -> pure ()
(_ : _) -> parsecWarning PWTVersionTag "version with tags"
versionDigitParser :: CabalParsing m => m Int
versionDigitParser = (some d >>= toNumber) P.<?> "version digit (integral without leading zeroes)"
where
toNumber :: CabalParsing m => [Int] -> m Int
toNumber [0] = return 0
toNumber (0 : _) = P.unexpected "Version digit with leading zero"
toNumber xs