module Saturn.Unstable.Type.RangeSpec where

import qualified Data.Maybe as Maybe
import qualified Data.Text.Lazy.Builder as Builder
import qualified Data.Word as Word
import qualified Saturn.Unstable.Extra.Tuple as Tuple
import qualified Saturn.Unstable.Type.Number as Number
import qualified Saturn.Unstable.Type.NumberSpec as NumberSpec
import qualified Saturn.Unstable.Type.Range as Range
import qualified Test.Hspec as Hspec
import qualified Test.QuickCheck as QuickCheck
import qualified Text.Parsec as Parsec

spec :: Hspec.Spec
spec :: Spec
spec = forall a. HasCallStack => String -> SpecWith a -> SpecWith a
Hspec.describe String
"Saturn.Unstable.Type.Range" forall a b. (a -> b) -> a -> b
$ do
  forall a.
(HasCallStack, Example a) =>
String -> a -> SpecWith (Arg a)
Hspec.it String
"round trips"
    forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a prop.
(Show a, Testable prop) =>
Gen a -> (a -> [a]) -> (a -> prop) -> Property
QuickCheck.forAllShrink Gen Range
arbitrary Range -> [Range]
shrink
    forall a b. (a -> b) -> a -> b
$ \Range
x -> do
      forall s t a.
Stream s Identity t =>
Parsec s () a -> String -> s -> Either ParseError a
Parsec.parse forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Range
Range.parsec String
"" (Builder -> Text
Builder.toLazyText forall a b. (a -> b) -> a -> b
$ Range -> Builder
Range.toBuilder Range
x)
        forall a. (HasCallStack, Show a, Eq a) => a -> a -> Expectation
`Hspec.shouldBe` forall a b. b -> Either a b
Right Range
x

arbitrary :: QuickCheck.Gen Range.Range
arbitrary :: Gen Range
arbitrary =
  forall a b. Gen a -> (a -> Maybe b) -> Gen b
QuickCheck.suchThatMap
    (forall (f :: * -> * -> *) a b.
Arbitrary2 f =>
Gen a -> Gen b -> Gen (f a b)
QuickCheck.liftArbitrary2 Gen Number
NumberSpec.arbitrary Gen Number
NumberSpec.arbitrary)
    (Number, Number) -> Maybe Range
Range.fromTuple

shrink :: Range.Range -> [Range.Range]
shrink :: Range -> [Range]
shrink =
  forall a b. (a -> Maybe b) -> [a] -> [b]
Maybe.mapMaybe (Number, Number) -> Maybe Range
Range.fromTuple
    forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> * -> *) a b.
Arbitrary2 f =>
(a -> [a]) -> (b -> [b]) -> f a b -> [f a b]
QuickCheck.liftShrink2 Number -> [Number]
NumberSpec.shrink Number -> [Number]
NumberSpec.shrink
    forall b c a. (b -> c) -> (a -> b) -> a -> c
. Range -> (Number, Number)
Range.toTuple

new :: (MonadFail m) => (Word.Word8, Word.Word8) -> m Range.Range
new :: forall (m :: * -> *). MonadFail m => (Word8, Word8) -> m Range
new (Word8, Word8)
tuple =
  forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"invalid Range: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> String
show (Word8, Word8)
tuple) forall (f :: * -> *) a. Applicative f => a -> f a
pure
    forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Number, Number) -> Maybe Range
Range.fromTuple
    forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> (a, a) -> (b, b)
Tuple.mapBoth Word8 -> Number
Number.fromWord8 (Word8, Word8)
tuple