-- | This module defines types and functions for working with versions as
-- defined by [Semantic Versioning](http://semver.org/spec/v2.0.0.html). It
-- also provides types and functions for working with version constraints as
-- described by [npm](https://github.com/npm/npm/blob/d081cc6/doc/misc/semver.md#ranges).
module Salve
  ( -- | This module doesn't export anything that conflicts with the "Prelude", so
    -- you can import it unqualified.
    --
    -- >>> import Salve
    --
    -- This module provides lenses for modifying versions. If you want to modify
    -- versions, consider importing a lens library like
    -- [microlens](https://www.stackage.org/lts-9.3/package/microlens-0.4.8.1).
    --
    -- The 'Version' data type is the core of this module. Use 'parseVersion' to
    -- make versions and 'renderVersion' to convert them into strings.
    --
    -- >>> renderVersion <$> parseVersion "1.2.3"
    -- Just "1.2.3"
    --
    -- The 'Constraint' data type allows you to specify version constraints. Use
    -- 'parseConstraint' to make constraints and 'renderConstraint' to convert them
    -- into strings.
    --
    -- >>> renderConstraint <$> parseConstraint ">1.2.0"
    -- Just ">1.2.0"
    --
    -- Use 'satisfiesConstraint' to see if a version satisfiesConstraint a
    -- constraint.
    --
    -- >>> satisfiesConstraint <$> parseConstraint ">1.2.0" <*> parseVersion "1.2.3"
    -- Just True

    -- * Cheat sheet

    -- | If you're coming from Cabal, you might not be familiar with npm's version
    -- range syntax. This table shows you how npm version ranges map to Cabal's
    -- version constraints.
    --
    -- > Salve           | Cabal              | Notes
    -- > -----           | -----              | -----
    -- > <1.2.3          | <1.2.3             | -
    -- > <=1.2.3         | <=1.2.3            | -
    -- > =1.2.3          | ==1.2.3            | equals sign is optional
    -- > >=1.2.3         | >=1.2.3            | -
    -- > >1.2.3          | >1.2.3             | -
    -- > 1.2.3 || >1.2.3 | ==1.2.3 || >1.2.3  | lower precedence than and
    -- > >=1.2.3 <2.0.0  | >=1.2.3 && <2.0.0  | higher precedence than or
    -- > 1.2.3 - 2.3.4   | >=1.2.3 && <=2.3.4 | inclusive ranges
    -- > 1.2.x           | ==1.2.*            | can use X or * instead of x
    -- > 1.x.x           | ==1.*              | -
    -- > x.x.x           | ==*                | same as -any
    -- > ~1.2.3          | ^>=1.2.3           | same as >=1.2.3 && <1.3.0
    -- > ^1.2.3          | >=1.2.3 && <2      | -
    -- > ^0.2.3          | >=0.2.3 && <0.3    | -
    -- > ^0.0.3          | >=0.0.3 && <0.0.4  | -

    -- * Rationale

    -- ** The PVP

    -- | Haskell's
    -- [Package Versioning Policy](https://github.com/haskell/pvp/blob/176bb14/pvp-specification.md)
    -- (PVP) defines three things:
    --
    -- 1.  A spec for versioning your package, which includes how version numbers
    --     look and how to encode breaking changes.
    -- 2.  A spec for constraining the versions of your dependencies, which
    --     incldues how version ranges look.
    -- 3.  A prescription for how to constrain the versions of your dependencies,
    --     which includes how the ranges of your dependencies should be.
    --
    -- By comparison, Semantic Versioning only deals with the first thing. npm's
    -- version ranges only deal with the second thing. This module deals with the
    -- first and second things but leaves the third up to you.
    --
    -- Looking at the first point, why might you want to use SemVer instead of the
    -- PVP? The PVP has many problems, as described by the
    -- [Problematic versioning policy](http://taylor.fausak.me/2016/12/28/problematic-versioning-policy/)
    -- blog post. In short, the PVP is too flexible and it's unique to Haskell,
    -- which causes unnecessary friction with developers from other languages.
    --
    -- Moving on to the second point, why should we use npm's version ranges
    -- instead of the PVP's? This is a less clear cut. The two syntaxes are broadly
    -- compatible. Really the only gains here are compatibility with a widely-used
    -- syntax and convenient shorthand for common constraints (like hyphens
    -- @1.2.3 - 2.3.4@, tildes @~1.2.3@, and carets @^1.2.3@).

    -- ** Other modules

    -- | There are already a few modules that provide version numbers. Why do we
    -- need another one? Let's take a look at the options.
    --
    -- -   [Data.Version](https://www.stackage.org/haddock/lts-9.3/base-4.9.1.0/Data-Version.html)
    --     from the @base@ package:
    --
    --     -   Exposes constructors, which allows creating versions that cannot be
    --         parsed.
    --     -   Allows any number of components, from zero to inifinity.
    --     -   Deprecated tags on versions.
    --     -   Does not support build metadata on versions.
    --     -   Does not support constraints.
    --
    -- -   [Distribution.Version](https://www.stackage.org/haddock/lts-9.3/Cabal-1.24.2.0/Distribution-Version.html)
    --     from the @Cabal@ package:
    --
    --     -   Has the same problems as Data.Version because it re-uses that
    --         version type.
    --     -   Depends on the @array@, @binary@, @bytestring@, @containers@,
    --         @deepseq@, @directory@, @filepath@, @pretty@, @process@, @time@, and
    --         @unix@ packages.
    --
    -- -   [Data.SemVer](https://www.stackage.org/haddock/lts-9.3/semver-0.3.3.1/Data-SemVer.html)
    --     from the @semver@ package:
    --
    --     -   Depends on the @attoparsec@, @deepseq@, and @text@ packages.
    --     -   Does not support version constraints.
    --
    -- -   [Data.SemVer](https://hackage.haskell.org/package/semver-range-0.2.2/docs/Data-SemVer.html)
    --     from the @semver-range@ package:
    --
    --     -   Depends on the @classy-prelude@, @parsec@, @text@, and
    --         @unordered-containers@ packages.
    --     -   Module name collides with the @semver@ package.
    --     -   Supports constraints, but does not provide a way to render them.
    --
    -- -   [Data.Versions](https://www.stackage.org/haddock/lts-9.3/versions-3.1.1/Data-Versions.html)
    --     from the @versions@ package:
    --
    --     -   Depends on the @deepseq@, @hashable@, @megaparsec@, and @text@
    --         packages.
    --     -   Intentially allows weird versions.
    --     -   Does not support constraints.
    --
    -- By comparison, this module:
    --
    -- -   Does not expose constructors. Any version you create can be rendered and
    --     parsed without issue.
    -- -   Requires exactly three components. You won't have to wonder if version
    --     @1.2.0@ is greater than @1.2@.
    -- -   Allows pre-release identifiers on versions. Go ahead and release version
    --     @1.0.0-alpha@ for early adopters.
    -- -   Allows build metadata on versions. Show when a release was made with
    --     versions like @1.0.0+2001-02-03@.
    -- -   Supports version constraints. Just like versions, rendering and parsing
    --     constraints is no problem.
    -- -   Only depends on the @base@ package. You can use all the functionality
    --     without installing any other packages.
    -- -   Has a unique module name. You won't have to use the @PackageImports@
    --     extension simply to deal with version numbers.

    -- * Types
    Salve.Version,
    Salve.PreRelease,
    Salve.Build,
    Salve.Constraint,

    -- * Constructors
    Salve.makeVersion,
    Salve.initialVersion,

    -- * Parsing
    Salve.parseVersion,
    Salve.parsePreRelease,
    Salve.parseBuild,
    Salve.parseConstraint,

    -- ** Unsafe

    -- | These functions can be used to unsafely parse strings. Instead of
    -- returning 'Nothing', they raise an exception. Only use these if you are sure
    -- the string can be successfully parsed!
    Salve.unsafeParseVersion,
    Salve.unsafeParsePreRelease,
    Salve.unsafeParseBuild,
    Salve.unsafeParseConstraint,

    -- * Rendering
    Salve.renderVersion,
    Salve.renderPreRelease,
    Salve.renderBuild,
    Salve.renderConstraint,

    -- * Predicates
    Salve.isUnstable,
    Salve.isStable,

    -- * Conversions
    Salve.fromBaseVersion,
    Salve.toBaseVersion,

    -- * Helpers
    Salve.bumpMajor,
    Salve.bumpMinor,
    Salve.bumpPatch,
    Salve.satisfiesConstraint,

    -- * Lenses

    -- | These lenses can be used to access and modify specific parts of a
    -- 'Version'.
    --
    -- Don't be scared by these type signatures. They are provided in full to avoid
    -- the @RankNTypes@ language extension. The type signature
    -- @'Functor' f => (a -> f a) -> 'Version' -> f 'Version'@ is the same as
    -- @Lens' 'Version' a@, which you may already be familiar with.
    Salve.majorLens,
    Salve.minorLens,
    Salve.patchLens,
    Salve.preReleasesLens,
    Salve.buildsLens,

    -- * Examples

    -- | These examples are provided to showcase functionality and explain weird
    -- behavior. If something isn't clear, please open a pull request adding an
    -- example!

    -- ** Versions

    -- | Leading zeros are not allowed.
    --
    -- >>> parseVersion "01.0.0"
    -- Nothing
    -- >>> parseVersion "0.01.0"
    -- Nothing
    -- >>> parseVersion "0.0.01"
    -- Nothing
    --
    -- Negative numbers are not allowed.
    --
    -- >>> parseVersion "-1.0.0"
    -- Nothing
    -- >>> parseVersion "0.-1.0"
    -- Nothing
    -- >>> parseVersion "0.0.-1"
    -- Nothing
    --
    -- Non-digits are not allowed.
    --
    -- >>> parseVersion "a.0.0"
    -- Nothing
    -- >>> parseVersion "0.a.0"
    -- Nothing
    -- >>> parseVersion "0.0.a"
    -- Nothing
    --
    -- Partial version numbers are not allowed.
    --
    -- >>> parseVersion "0.0"
    -- Nothing
    --
    -- Extra version numbers are not allowed.
    --
    -- >>> parseVersion "0.0.0.0"
    -- Nothing
    --
    -- Spaces are allowed
    --
    -- >>> parseVersion " 0.0.0"
    -- Just (Version {versionMajor = 0, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = []})
    -- >>> parseVersion "0.0.0 "
    -- Just (Version {versionMajor = 0, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = []})
    --
    -- Interior spaces are not allowed.
    --
    -- >>> parseVersion "0 .0.0"
    -- Nothing
    -- >>> parseVersion "0. 0.0"
    -- Nothing
    --
    -- Each version component cannot be larger than a 64-bit unsigned integer.
    --
    -- >>> parseVersion "18446744073709551615.0.0"
    -- Just (Version {versionMajor = 18446744073709551615, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = []})
    -- >>> parseVersion "18446744073709551616.0.0"
    -- Nothing
    --
    -- Numeric pre-releases tags cannot be larger than a 64-bit unsigned integer.
    --
    -- >>> parseVersion "0.0.0-18446744073709551615"
    -- Just (Version {versionMajor = 0, versionMinor = 0, versionPatch = 0, versionPreReleases = [PreReleaseNumeric 18446744073709551615], versionBuilds = []})
    -- >>> parseVersion "0.0.0-18446744073709551616"
    -- Nothing
    --
    -- Build metadata is not numeric so it does not have any limit.
    --
    -- >>> parseVersion "0.0.0+18446744073709551615"
    -- Just (Version {versionMajor = 0, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = [Build "18446744073709551615"]})
    -- >>> parseVersion "0.0.0+18446744073709551616"
    -- Just (Version {versionMajor = 0, versionMinor = 0, versionPatch = 0, versionPreReleases = [], versionBuilds = [Build "18446744073709551616"]})

    -- ** Constraints

    -- | Partial version numbers are not allowed.
    --
    -- >>> parseConstraint "1.2"
    -- Nothing
    --
    -- Wildcards (also known as "x-ranges") are allowed. The exact character used
    -- for the wildcard is not round-tripped.
    --
    -- >>> renderConstraint <$> parseConstraint "1.2.x"
    -- Just "1.2.x"
    -- >>> renderConstraint <$> parseConstraint "1.2.X"
    -- Just "1.2.x"
    -- >>> renderConstraint <$> parseConstraint "1.2.*"
    -- Just "1.2.x"
    --
    -- An optional equals sign can be included with wildcard constraints.
    --
    -- >>> renderConstraint <$> parseConstraint "=1.2.x"
    -- Just "1.2.x"
    --
    -- Wildcards can be combined with other constraints.
    --
    -- >>> renderConstraint <$> parseConstraint "1.2.x 2.3.4"
    -- Just "1.2.x 2.3.4"
    -- >>> renderConstraint <$> parseConstraint "1.2.x || 2.3.4"
    -- Just "1.2.x || 2.3.4"
    --
    -- Wildcards are allowed at any position.
    --
    -- >>> renderConstraint <$> parseConstraint "1.2.x"
    -- Just "1.2.x"
    -- >>> renderConstraint <$> parseConstraint "1.x.x"
    -- Just "1.x.x"
    -- >>> renderConstraint <$> parseConstraint "x.x.x"
    -- Just "x.x.x"
    --
    -- Non-wildcards cannot come after wildcards.
    --
    -- >>> parseConstraint "1.x.3"
    -- Nothing
    -- >>> parseConstraint "x.2.3"
    -- Nothing
    -- >>> parseConstraint "x.x.3"
    -- Nothing
    -- >>> parseConstraint "x.2.x"
    -- Nothing
    --
    -- Wildcards cannot be used with other operators.
    --
    -- >>> parseConstraint "<1.2.x"
    -- Nothing
    -- >>> parseConstraint "<=1.2.x"
    -- Nothing
    -- >>> parseConstraint ">=1.2.x"
    -- Nothing
    -- >>> parseConstraint ">1.2.x"
    -- Nothing
    -- >>> parseConstraint "~1.2.x"
    -- Nothing
    -- >>> parseConstraint "^1.2.x"
    -- Nothing
    -- >>> parseConstraint "1.2.x - 2.3.4"
    -- Nothing
    -- >>> parseConstraint "1.2.3 - 2.3.x"
    -- Nothing
    --
    -- Spaces are allowed in most places. Extra spaces are not round-tripped.
    --
    -- >>> renderConstraint <$> parseConstraint " 1.2.3 "
    -- Just "1.2.3"
    -- >>> renderConstraint <$> parseConstraint "> 1.2.3"
    -- Just ">1.2.3"
    -- >>> renderConstraint <$> parseConstraint "1.2.3  -  2.3.4"
    -- Just "1.2.3 - 2.3.4"
    -- >>> renderConstraint <$> parseConstraint "1.2.3  2.3.4"
    -- Just "1.2.3 2.3.4"
    -- >>> renderConstraint <$> parseConstraint "1.2.3  ||  2.3.4"
    -- Just "1.2.3 || 2.3.4"
    --
    -- Parentheses are not allowed. Note that combining two constraints with a
    -- space (and) has higher precedence than combining them with pipes (or). In
    -- other words, @"a b || c"@ parses as @"(a b) || c"@, not @"a (b || c)"@.
    --
    -- >>> parseConstraint "(1.2.3)"
    -- Nothing
    -- >>> parseConstraint "(1.2.3 || >1.2.3) <1.3.0"
    -- Nothing
    -- >>> parseConstraint "(>1.2.3 <1.3.0) || 1.2.3"
    -- Nothing
    --
    -- Most constraints can be round-tripped through parsing and rendering.
    --
    -- >>> renderConstraint <$> parseConstraint "<1.2.3"
    -- Just "<1.2.3"
    -- >>> renderConstraint <$> parseConstraint "<=1.2.3"
    -- Just "<=1.2.3"
    -- >>> renderConstraint <$> parseConstraint "1.2.3"
    -- Just "1.2.3"
    -- >>> renderConstraint <$> parseConstraint ">=1.2.3"
    -- Just ">=1.2.3"
    -- >>> renderConstraint <$> parseConstraint ">1.2.3"
    -- Just ">1.2.3"
    -- >>> renderConstraint <$> parseConstraint "1.2.3 - 2.3.4"
    -- Just "1.2.3 - 2.3.4"
    -- >>> renderConstraint <$> parseConstraint "~1.2.3"
    -- Just "~1.2.3"
    -- >>> renderConstraint <$> parseConstraint "^1.2.3"
    -- Just "^1.2.3"
    -- >>> renderConstraint <$> parseConstraint ">1.2.3 <2.0.0"
    -- Just ">1.2.3 <2.0.0"
    -- >>> renderConstraint <$> parseConstraint "1.2.3 || >1.2.3"
    -- Just "1.2.3 || >1.2.3"
    --
    -- Explicit equal signs do not get round-tripped.
    --
    -- >>> renderConstraint <$> parseConstraint "=1.2.3"
    -- Just "1.2.3"
    --
    -- Pre-releases and builds are allowed on any constraints except wildcards.
    --
    -- >>> renderConstraint <$> parseConstraint "1.2.3-p+b"
    -- Just "1.2.3-p+b"
    -- >>> renderConstraint <$> parseConstraint ">1.2.3-p+b"
    -- Just ">1.2.3-p+b"
    -- >>> renderConstraint <$> parseConstraint "1.2.3-p+b - 2.3.4-p+b"
    -- Just "1.2.3-p+b - 2.3.4-p+b"
    -- >>> renderConstraint <$> parseConstraint "~1.2.3-p+b"
    -- Just "~1.2.3-p+b"
    -- >>> renderConstraint <$> parseConstraint "^1.2.3-p+b"
    -- Just "^1.2.3-p+b"
    --
    -- >>> parseConstraint "1.2.x-p+b"
    -- Nothing
    --
    -- These examples show every type of constraint in a single expression.
    --
    -- >>> renderConstraint <$> parseConstraint "<1.2.0 <=1.2.1 =1.2.2 >=1.2.3 >1.2.4 1.2.5 1.2.6 - 1.2.7 ~1.2.8 ^1.2.9 1.2.x"
    -- Just "<1.2.0 <=1.2.1 1.2.2 >=1.2.3 >1.2.4 1.2.5 1.2.6 - 1.2.7 ~1.2.8 ^1.2.9 1.2.x"
    -- >>> renderConstraint <$> parseConstraint "<1.2.0 <=1.2.1 || =1.2.2 >=1.2.3 || >1.2.4 1.2.5 || 1.2.6 - 1.2.7 ~1.2.8 || ^1.2.9 1.2.x"
    -- Just "<1.2.0 <=1.2.1 || 1.2.2 >=1.2.3 || >1.2.4 1.2.5 || 1.2.6 - 1.2.7 ~1.2.8 || ^1.2.9 1.2.x"
    -- >>> renderConstraint <$> parseConstraint "<1.2.0 || <=1.2.1 =1.2.2 || >=1.2.3 >1.2.4 || 1.2.5 1.2.6 - 1.2.7 || ~1.2.8 ^1.2.9 || 1.2.x"
    -- Just "<1.2.0 || <=1.2.1 1.2.2 || >=1.2.3 >1.2.4 || 1.2.5 1.2.6 - 1.2.7 || ~1.2.8 ^1.2.9 || 1.2.x"
    -- >>> renderConstraint <$> parseConstraint "<1.2.0 || <=1.2.1 || =1.2.2 || >=1.2.3 || >1.2.4 || 1.2.5 || 1.2.6 - 1.2.7 || ~1.2.8 || ^1.2.9 || 1.2.x"
    -- Just "<1.2.0 || <=1.2.1 || 1.2.2 || >=1.2.3 || >1.2.4 || 1.2.5 || 1.2.6 - 1.2.7 || ~1.2.8 || ^1.2.9 || 1.2.x"

    -- ** Satisfying constraints

    -- | Although in general you should use 'satisfiesConstraint', 'parseVersion',
    -- and 'parseConstraint', doing that here makes it hard to tell what the
    -- examples are doing. An operator makes things clearer.
    --
    -- >>> satisfiesConstraint <$> parseConstraint "=1.2.3" <*> parseVersion "1.2.3"
    -- Just True
    -- >>> let version ? constraint = satisfiesConstraint (unsafeParseConstraint constraint) (unsafeParseVersion version)
    -- >>> "1.2.3" ? "=1.2.3"
    -- True
    --
    -- -   Less than:
    --
    --     >>> "1.2.2" ? "<1.2.3"
    --     True
    --     >>> "1.2.3" ? "<1.2.3"
    --     False
    --     >>> "1.2.4" ? "<1.2.3"
    --     False
    --     >>> "1.2.3-pre" ? "<1.2.3"
    --     True
    --
    -- -   Less than or equal to:
    --
    --     >>> "1.2.2" ? "<=1.2.3"
    --     True
    --     >>> "1.2.3" ? "<=1.2.3"
    --     True
    --     >>> "1.2.4" ? "<=1.2.3"
    --     False
    --
    -- -   Equal to:
    --
    --     >>> "1.2.2" ? "=1.2.3"
    --     False
    --     >>> "1.2.3" ? "=1.2.3"
    --     True
    --     >>> "1.2.4" ? "=1.2.3"
    --     False
    --     >>> "1.2.3-pre" ? "=1.2.3"
    --     False
    --     >>> "1.2.3+build" ? "=1.2.3"
    --     True
    --
    -- -   Greater than or equal to:
    --
    --     >>> "1.2.2" ? ">=1.2.3"
    --     False
    --     >>> "1.2.3" ? ">=1.2.3"
    --     True
    --     >>> "1.2.4" ? ">=1.2.3"
    --     True
    --
    -- -   Greater than:
    --
    --     >>> "1.2.2" ? ">1.2.3"
    --     False
    --     >>> "1.2.3" ? ">1.2.3"
    --     False
    --     >>> "1.2.4" ? ">1.2.3"
    --     True
    --     >>> "1.2.4-pre" ? ">1.2.3"
    --     True
    --
    --     >>> "1.2.4" ? ">1.2.3-pre"
    --     True
    --
    -- -   And:
    --
    --     >>> "1.2.3" ? ">1.2.3 <1.2.5"
    --     False
    --     >>> "1.2.4" ? ">1.2.3 <1.2.5"
    --     True
    --     >>> "1.2.5" ? ">1.2.3 <1.2.5"
    --     False
    --
    -- -   Or:
    --
    --     >>> "1.2.2" ? "1.2.3 || 1.2.4"
    --     False
    --     >>> "1.2.3" ? "1.2.3 || 1.2.4"
    --     True
    --     >>> "1.2.4" ? "1.2.3 || 1.2.4"
    --     True
    --     >>> "1.2.5" ? "1.2.3 || 1.2.4"
    --     False
    --
    -- -   And & or:
    --
    --     >>> "1.2.2" ? "1.2.2 || >1.2.3 <1.3.0"
    --     True
    --     >>> "1.2.3" ? "1.2.2 || >1.2.3 <1.3.0"
    --     False
    --     >>> "1.2.4" ? "1.2.2 || >1.2.3 <1.3.0"
    --     True
    --     >>> "1.3.0" ? "1.2.2 || >1.2.3 <1.3.0"
    --     False
    --
    -- -   Hyphen:
    --
    --     >>> "1.2.2" ? "1.2.3 - 1.2.4"
    --     False
    --     >>> "1.2.3" ? "1.2.3 - 1.2.4"
    --     True
    --     >>> "1.2.4" ? "1.2.3 - 1.2.4"
    --     True
    --     >>> "1.2.5" ? "1.2.3 - 1.2.4"
    --     False
    --
    -- -   Tilde:
    --
    --     >>> "1.2.2" ? "~1.2.3"
    --     False
    --     >>> "1.2.3" ? "~1.2.3"
    --     True
    --     >>> "1.2.4" ? "~1.2.3"
    --     True
    --     >>> "1.3.0" ? "~1.2.3"
    --     False
    --
    -- -   Caret:
    --
    --     >>> "1.2.2" ? "^1.2.3"
    --     False
    --     >>> "1.2.3" ? "^1.2.3"
    --     True
    --     >>> "1.2.4" ? "^1.2.3"
    --     True
    --     >>> "1.3.0" ? "^1.2.3"
    --     True
    --     >>> "2.0.0" ? "^1.2.3"
    --     False
    --
    --     >>> "0.2.2" ? "^0.2.3"
    --     False
    --     >>> "0.2.3" ? "^0.2.3"
    --     True
    --     >>> "0.2.4" ? "^0.2.3"
    --     True
    --     >>> "0.3.0" ? "^0.2.3"
    --     False
    --
    --     >>> "0.0.2" ? "^0.0.3"
    --     False
    --     >>> "0.0.3" ? "^0.0.3"
    --     True
    --     >>> "0.0.4" ? "^0.0.3"
    --     False
    --
    -- -   Wildcard:
    --
    --     >>> "1.1.0" ? "1.2.x"
    --     False
    --     >>> "1.2.3" ? "1.2.x"
    --     True
    --     >>> "1.3.0" ? "1.2.x"
    --     False
    --
    --     >>> "0.1.0" ? "1.x.x"
    --     False
    --     >>> "1.0.0" ? "1.x.x"
    --     True
    --     >>> "1.2.3" ? "1.x.x"
    --     True
    --     >>> "2.0.0" ? "1.x.x"
    --     False
    --
    --     >>> "0.0.0" ? "x.x.x"
    --     True
    --     >>> "1.2.3" ? "x.x.x"
    --     True
    --     >>> "2.0.0" ? "x.x.x"
    --     True
  )
where

import qualified Salve.Internal as Salve

-- $setup
-- >>> import Control.Applicative
-- >>> import Salve