diff --git a/src/Data/BigInt/Argonaut.js b/src/Data/BigInt/Argonaut.js index 1a137e5..a99f3f2 100644 --- a/src/Data/BigInt/Argonaut.js +++ b/src/Data/BigInt/Argonaut.js @@ -17,7 +17,7 @@ exports.restoreJson = function (original) { } exports.decodeBigInt = function (fail, succ, json) { - if (typeof json === "number" || typeof json === "bigint") { + if (Number.isInteger(json) || typeof json === "bigint") { return succ(bigInt(json)); } else { return fail; @@ -25,5 +25,12 @@ exports.decodeBigInt = function (fail, succ, json) { } exports.encodeBigInt = function (a) { - return bigInt(a); + if (JSON.stringify !== JSONbig.stringify) { + console.warn( + "Tried to encode BitInt without patching JSON.stringify. Wrap your app in Data.BigInt.Argonaut.withJsonPatch." + ); + return a.toJSNumber(); + } else { + return a.value; + } } diff --git a/test/Data/BigInt/Argonaut/Spec.purs b/test/Data/BigInt/Argonaut/Spec.purs new file mode 100644 index 0000000..5aa6ece --- /dev/null +++ b/test/Data/BigInt/Argonaut/Spec.purs @@ -0,0 +1,54 @@ +module Data.BigInt.Argonaut.Spec + ( bigIntSpec + ) where + +import Prologue + +import Data.Argonaut.Decode (JsonDecodeError) +import Data.Argonaut.Extra (encodeStringifyJson, parseDecodeJson) +import Data.BigInt as BI +import Data.BigInt.Argonaut (BigInt, fromInt, withJsonPatch) +import Data.Newtype (unwrap) +import Data.String (codePointFromChar, dropWhile, null) +import Data.String.Gen (genDigitString) +import Test.QuickCheck (class Arbitrary, (===)) +import Test.QuickCheck.Gen (suchThat) +import Test.Spec (Spec, around_, describe, it) +import Test.Spec.Assertions (shouldNotEqual) +import Test.Spec.QuickCheck (quickCheck) + +newtype DigitString = DigitString String + +instance arbitraryDigitString :: Arbitrary DigitString where + arbitrary = + map DigitString + $ flip suchThat (not null) + $ map (dropWhile (eq (codePointFromChar '0'))) + $ genDigitString + +bigIntSpec :: Spec Unit +bigIntSpec = + describe "Data.BigInt.Argonaut" do + around_ withJsonPatch $ it "obeys the roundtrip law under withJsonPatch" do + quickCheck \(DigitString s) -> + let + decoded :: Either JsonDecodeError BigInt + decoded = parseDecodeJson s + in + encodeStringifyJson <$> decoded === Right s + it "does not always obey the roundtrip law when not under withJsonPatch" do + let + s = "23457890122347890123478901234123409871234" + + decoded :: Either JsonDecodeError BigInt + decoded = parseDecodeJson s + (encodeStringifyJson <$> decoded) `shouldNotEqual` Right s + around_ withJsonPatch $ it "decodes a valid BigInt" do + quickCheck \(DigitString s) -> + let + decoded :: Either JsonDecodeError BigInt + decoded = parseDecodeJson s + in + (unwrap <<< add (fromInt 10)) + <$> decoded === (add (BI.fromInt 10) <<< unwrap) + <$> decoded diff --git a/test/Main.purs b/test/Main.purs index 4cf7cb5..b64cb90 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -3,7 +3,7 @@ module Test.Main where import Prologue import Data.Array.Extra.Spec (arrayExtraSpec) -import Data.BigInt.Argonaut (withJsonPatch) +import Data.BigInt.Argonaut.Spec (bigIntSpec) import Data.Cursor.Spec (cursorSpec) import Data.Foldable.Extra.Spec (foldableExtraSpec) import Data.String.Extra.Spec (stringExtraSpec) @@ -16,10 +16,10 @@ import Test.Spec.Runner (runSpec) main :: Effect Unit main = launchAff_ do - withJsonPatch do - runSpec [ consoleReporter ] do - cursorSpec - arrayExtraSpec - foldableExtraSpec - stringExtraSpec - assocMapSpec + runSpec [ consoleReporter ] do + cursorSpec + arrayExtraSpec + foldableExtraSpec + stringExtraSpec + assocMapSpec + bigIntSpec