-
Notifications
You must be signed in to change notification settings - Fork 10
Turns the standard AST JNumber
into a safe constructor
#30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
9e32346
bc14b53
0dbd2f0
32b180f
d4efef2
178a34d
1baab54
cc1643b
d75e458
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,15 +50,15 @@ final case class JString(value: String) extends JValue { | |
} | ||
|
||
object JNumber { | ||
def apply(value: Int): JNumber = JNumber(value.toString) | ||
def apply(value: Int): JNumber = new JNumber(value.toString) | ||
|
||
def apply(value: Integer): JNumber = JNumber(value.toString) | ||
def apply(value: Integer): JNumber = new JNumber(value.toString) | ||
|
||
def apply(value: Long): JNumber = JNumber(value.toString) | ||
def apply(value: Long): JNumber = new JNumber(value.toString) | ||
|
||
def apply(value: BigInt): JNumber = JNumber(value.toString()) | ||
def apply(value: BigInt): JNumber = new JNumber(value.toString()) | ||
|
||
def apply(value: BigDecimal): JNumber = JNumber(value.toString()) | ||
def apply(value: BigDecimal): JNumber = new JNumber(value.toString()) | ||
|
||
/** | ||
* @param value | ||
|
@@ -67,7 +67,7 @@ object JNumber { | |
def apply(value: Double): JValue = value match { | ||
case n if n.isNaN => JNull | ||
case n if n.isInfinity => JNull | ||
case _ => JNumber(value.toString) | ||
case _ => new JNumber(value.toString) | ||
} | ||
|
||
/** | ||
|
@@ -77,22 +77,26 @@ object JNumber { | |
def apply(value: Float): JValue = value match { | ||
case n if java.lang.Float.isNaN(n) => JNull | ||
case n if n.isInfinity => JNull | ||
case _ => JNumber(value.toString) | ||
case _ => new JNumber(value.toString) | ||
} | ||
|
||
def fromString(value: String): Option[JNumber] = | ||
if (value.matches(jNumberRegex)) | ||
Some(new JNumber(value)) | ||
else | ||
None | ||
|
||
def unapply(arg: JNumber): Option[String] = Some(arg.underlying) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be improved via something like this, i.e. it could be done in a way that avoids the allocation here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will have a look at this tomorrow There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From an end-user standpoint I'm not a fan of having a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
|
||
} | ||
|
||
/** Represents a JSON number value. If you are passing in a | ||
* NaN or Infinity as a [[scala.Double]], [[JNumber]] will | ||
* NaN or Infinity as a [[scala.Double]] or [[scala.Float]], [[JNumber]] will | ||
* return a [[JNull]]. | ||
* | ||
* @author Matthew de Detrich | ||
* @throws scala.NumberFormatException - If the value is not a valid JSON Number | ||
*/ | ||
final case class JNumber(value: String) extends JValue { | ||
|
||
if (!value.matches(jNumberRegex)) { | ||
throw new NumberFormatException(value) | ||
} | ||
final class JNumber private[ast] (val underlying: String) extends JValue { | ||
@inline def value: String = underlying | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO, with the constructor parameter being a public field, this construct is now completely superfluous. |
||
|
||
/** | ||
* Javascript specification for numbers specify a [[scala.Double]], so this is the default export method to `Javascript` | ||
|
@@ -101,22 +105,40 @@ final case class JNumber(value: String) extends JValue { | |
*/ | ||
def this(value: Double) = this(value.toString) | ||
|
||
override def toUnsafe: unsafe.JValue = unsafe.JNumber(value) | ||
override def toUnsafe: unsafe.JValue = unsafe.JNumber(underlying) | ||
|
||
override def toJsAny: js.Any = value.toDouble match { | ||
override def toJsAny: js.Any = underlying.toDouble match { | ||
case n if n.isNaN => null | ||
case n if n.isInfinity => null | ||
case n => n | ||
} | ||
|
||
override def equals(obj: Any) = | ||
override def equals(obj: Any): Boolean = | ||
obj match { | ||
case jNumber: JNumber => numericStringEquals(value, jNumber.value) | ||
case jNumber: JNumber => | ||
numericStringEquals(underlying, jNumber.underlying) | ||
case _ => false | ||
} | ||
|
||
override def hashCode: Int = | ||
numericStringHashcode(value) | ||
numericStringHashcode(underlying) | ||
|
||
override def productElement(n: Int): Any = | ||
if (n == 0) | ||
underlying | ||
else | ||
throw new IndexOutOfBoundsException(n.toString) | ||
|
||
override def productArity: Int = 1 | ||
|
||
override def canEqual(obj: Any): Boolean = { | ||
obj match { | ||
case _: JNumber => true | ||
case _ => false | ||
} | ||
} | ||
|
||
override def toString: String = s"JNumber($underlying)" | ||
} | ||
|
||
/** Represents a JSON Boolean value, which can either be a | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With Scala 2.10 out of the way we should be able to simply name this method
apply
as well, like all the others...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am thinking of leaving in the
fromString
method for all versions and aliasing it toapply
for Scala 2.10.x and Scala 2.11.x, that way for a codebase that needs to targets all Scala versions you can usefromString
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am thinking of leaving in the
fromString
method for all versions and aliasing it toapply
for Scala 2.10.x and Scala 2.11.x, that way for a codebase that needs to targets all Scala versions you can usefromString