{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE LambdaCase #-}

module Data.SemanticVersion.BuildIdentifier where

import Control.Applicative
import Control.Lens
import Data.Digit
import Data.List.NonEmpty
import Data.SemanticVersion.AlphanumericIdentifier
import Text.Parser.Char
import Text.Parser.Combinators

-- $setup
-- >>> import Text.Parsec(parse)
-- >>> import Data.Either(isLeft)

-- <build identifier> ::= <alphanumeric identifier>
--                      | <digits>
data BuildIdentifier =
  BuildIdentifierAlphanumeric AlphanumericIdentifier
  | BuildIdentifierDigits (NonEmpty DecDigit)
  deriving (BuildIdentifier -> BuildIdentifier -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: BuildIdentifier -> BuildIdentifier -> Bool
$c/= :: BuildIdentifier -> BuildIdentifier -> Bool
== :: BuildIdentifier -> BuildIdentifier -> Bool
$c== :: BuildIdentifier -> BuildIdentifier -> Bool
Eq, Int -> BuildIdentifier -> ShowS
[BuildIdentifier] -> ShowS
BuildIdentifier -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [BuildIdentifier] -> ShowS
$cshowList :: [BuildIdentifier] -> ShowS
show :: BuildIdentifier -> String
$cshow :: BuildIdentifier -> String
showsPrec :: Int -> BuildIdentifier -> ShowS
$cshowsPrec :: Int -> BuildIdentifier -> ShowS
Show)

class HasBuildIdentifier a where
  buildIdentifier ::
    Lens' a BuildIdentifier

instance HasBuildIdentifier BuildIdentifier where
  buildIdentifier :: Lens' BuildIdentifier BuildIdentifier
buildIdentifier =
    forall a. a -> a
id

class AsBuildIdentifier a where
  _BuildIdentifier ::
    Prism' a BuildIdentifier
  _BuildIdentifierDigits ::
    Prism' a (NonEmpty DecDigit)
  _BuildIdentifierDigits =
    forall a. AsBuildIdentifier a => Prism' a BuildIdentifier
_BuildIdentifier forall b c a. (b -> c) -> (a -> b) -> a -> c
.
    forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
      NonEmpty DecDigit -> BuildIdentifier
BuildIdentifierDigits
      (\case
        BuildIdentifierDigits NonEmpty DecDigit
a ->
          forall a. a -> Maybe a
Just NonEmpty DecDigit
a
        BuildIdentifier
_ ->
          forall a. Maybe a
Nothing)

instance AsBuildIdentifier BuildIdentifier where
  _BuildIdentifier :: Prism' BuildIdentifier BuildIdentifier
_BuildIdentifier =
    forall a. a -> a
id

instance AsAlphanumericIdentifier BuildIdentifier where
  _AlphanumericIdentifier :: Prism' BuildIdentifier AlphanumericIdentifier
_AlphanumericIdentifier =
    forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
      AlphanumericIdentifier -> BuildIdentifier
BuildIdentifierAlphanumeric
      (\case
        BuildIdentifierAlphanumeric AlphanumericIdentifier
a ->
          forall a. a -> Maybe a
Just AlphanumericIdentifier
a
        BuildIdentifier
_ ->
          forall a. Maybe a
Nothing)

-- |
--
-- >>> parse (parseBuildIdentifier <* eof) "parseBuildIdentifier" "A"
-- Right (BuildIdentifierAlphanumeric (AlphanumericIdentifierNonDigit (NonDigitLetter (AlphaUpper Upper_A))))
--
-- >>> isLeft (parse parseBuildIdentifier "parseBuildIdentifier" "")
-- True
--
-- >>> parse (parseBuildIdentifier <* eof) "parseBuildIdentifier" "Abc-123--XYZ"
-- Right (BuildIdentifierAlphanumeric (AlphanumericIdentifierNonDigits (NonDigitLetter (AlphaUpper Upper_A)) (IdentifierCharacters (IdentifierCharacterNonDigit (NonDigitLetter (AlphaLower Lower_b)) :| [IdentifierCharacterNonDigit (NonDigitLetter (AlphaLower Lower_c)),IdentifierCharacterNonDigit NonDigitHyphen,IdentifierCharacterDigit DecDigit1,IdentifierCharacterDigit DecDigit2,IdentifierCharacterDigit DecDigit3,IdentifierCharacterNonDigit NonDigitHyphen,IdentifierCharacterNonDigit NonDigitHyphen,IdentifierCharacterNonDigit (NonDigitLetter (AlphaUpper Upper_X)),IdentifierCharacterNonDigit (NonDigitLetter (AlphaUpper Upper_Y)),IdentifierCharacterNonDigit (NonDigitLetter (AlphaUpper Upper_Z))]))))
--
-- >>> isLeft (parse parseBuildIdentifier "parseBuildIdentifier" "+")
-- True
--
-- >>> parse parseBuildIdentifier "parseBuildIdentifier" "0"
-- Right (BuildIdentifierDigits (DecDigit0 :| []))
--
-- >>> parse parseBuildIdentifier "parseBuildIdentifier" "0+"
-- Right (BuildIdentifierDigits (DecDigit0 :| []))
--
-- >>> parse (parseBuildIdentifier <* eof) "parseBuildIdentifier" "0a"
-- Right (BuildIdentifierAlphanumeric (AlphanumericIdentifierCharacters (IdentifierCharacters (IdentifierCharacterDigit DecDigit0 :| [])) (NonDigitLetter (AlphaLower Lower_a))))
--
-- >>> parse parseBuildIdentifier "parseBuildIdentifier" "-"
-- Right (BuildIdentifierAlphanumeric (AlphanumericIdentifierNonDigit NonDigitHyphen))
--
-- >>> parse parseBuildIdentifier "parseBuildIdentifier" "Abc-123--XYZ+"
-- Right (BuildIdentifierAlphanumeric (AlphanumericIdentifierNonDigits (NonDigitLetter (AlphaUpper Upper_A)) (IdentifierCharacters (IdentifierCharacterNonDigit (NonDigitLetter (AlphaLower Lower_b)) :| [IdentifierCharacterNonDigit (NonDigitLetter (AlphaLower Lower_c)),IdentifierCharacterNonDigit NonDigitHyphen,IdentifierCharacterDigit DecDigit1,IdentifierCharacterDigit DecDigit2,IdentifierCharacterDigit DecDigit3,IdentifierCharacterNonDigit NonDigitHyphen,IdentifierCharacterNonDigit NonDigitHyphen,IdentifierCharacterNonDigit (NonDigitLetter (AlphaUpper Upper_X)),IdentifierCharacterNonDigit (NonDigitLetter (AlphaUpper Upper_Y)),IdentifierCharacterNonDigit (NonDigitLetter (AlphaUpper Upper_Z))]))))
--
-- >>> parse parseBuildIdentifier "parseBuildIdentifier" "0901010"
-- Right (BuildIdentifierDigits (DecDigit0 :| [DecDigit9,DecDigit0,DecDigit1,DecDigit0,DecDigit1,DecDigit0]))
--
-- >>> parse parseBuildIdentifier "parseBuildIdentifier" "90109010"
-- Right (BuildIdentifierDigits (DecDigit9 :| [DecDigit0,DecDigit1,DecDigit0,DecDigit9,DecDigit0,DecDigit1,DecDigit0]))
parseBuildIdentifier ::
  CharParsing p =>
  p BuildIdentifier
parseBuildIdentifier :: forall (p :: * -> *). CharParsing p => p BuildIdentifier
parseBuildIdentifier =
  forall (m :: * -> *) a. Parsing m => m a -> m a
try (AlphanumericIdentifier -> BuildIdentifier
BuildIdentifierAlphanumeric forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (p :: * -> *). CharParsing p => p AlphanumericIdentifier
parseAlphanumericIdentifier) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  NonEmpty DecDigit -> BuildIdentifier
BuildIdentifierDigits forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a. Alternative f => f a -> f (NonEmpty a)
some1 forall d (p :: * -> *). (Decimal d, CharParsing p) => p d
parseDecimal