Skip to content
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

More efficient encoding of UUIDs #1295

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 49 additions & 2 deletions zio-json/js/src/main/scala/zio/json/internal/SafeNumbers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package zio.json.internal

import java.util.UUID

/**
* Total, fast, number parsing.
*
Expand Down Expand Up @@ -75,13 +77,19 @@ object SafeNumbers {
def toString(x: Double): String = {
val out = new FastStringWrite(24)
write(x, out)
out.toString
out.buffer.toString
}

def toString(x: Float): String = {
val out = new FastStringWrite(16)
write(x, out)
out.toString
out.buffer.toString
}

def toString(x: UUID): String = {
val out = writes.get
write(x, out)
out.buffer.toString
}

// Based on the amazing work of Raffaello Giulietti
Expand Down Expand Up @@ -303,6 +311,26 @@ object SafeNumbers {
}
}

def write(x: UUID, out: Write): Unit = {
val ds = lowerCaseHexDigits
val msb = x.getMostSignificantBits
val lsb = x.getLeastSignificantBits
val msb1 = (msb >> 32).toInt
out.write(ds(msb1 >>> 24), ds(msb1 >> 16 & 0xff), ds(msb1 >> 8 & 0xff), ds(msb1 & 0xff))
out.write('-')
val msb2 = msb.toInt
out.write(ds(msb2 >>> 24), ds(msb2 >> 16 & 0xff))
out.write('-')
out.write(ds(msb2 >> 8 & 0xff), ds(msb2 & 0xff))
out.write('-')
val lsb1 = (lsb >>> 32).toInt
out.write(ds(lsb1 >>> 24), ds(lsb1 >> 16 & 0xff))
out.write('-')
out.write(ds(lsb1 >> 8 & 0xff), ds(lsb1 & 0xff))
val lsb2 = lsb.toInt
out.write(ds(lsb2 >>> 24), ds(lsb2 >> 16 & 0xff), ds(lsb2 >> 8 & 0xff), ds(lsb2 & 0xff))
}

private[json] def writeNano(x: Int, out: Write): Unit = {
out.write('.')
var coeff = 100000000
Expand Down Expand Up @@ -549,6 +577,25 @@ object SafeNumbers {
else 10
}

private final val lowerCaseHexDigits: Array[Short] = Array(
12336, 12592, 12848, 13104, 13360, 13616, 13872, 14128, 14384, 14640, 24880, 25136, 25392, 25648, 25904, 26160,
12337, 12593, 12849, 13105, 13361, 13617, 13873, 14129, 14385, 14641, 24881, 25137, 25393, 25649, 25905, 26161,
12338, 12594, 12850, 13106, 13362, 13618, 13874, 14130, 14386, 14642, 24882, 25138, 25394, 25650, 25906, 26162,
12339, 12595, 12851, 13107, 13363, 13619, 13875, 14131, 14387, 14643, 24883, 25139, 25395, 25651, 25907, 26163,
12340, 12596, 12852, 13108, 13364, 13620, 13876, 14132, 14388, 14644, 24884, 25140, 25396, 25652, 25908, 26164,
12341, 12597, 12853, 13109, 13365, 13621, 13877, 14133, 14389, 14645, 24885, 25141, 25397, 25653, 25909, 26165,
12342, 12598, 12854, 13110, 13366, 13622, 13878, 14134, 14390, 14646, 24886, 25142, 25398, 25654, 25910, 26166,
12343, 12599, 12855, 13111, 13367, 13623, 13879, 14135, 14391, 14647, 24887, 25143, 25399, 25655, 25911, 26167,
12344, 12600, 12856, 13112, 13368, 13624, 13880, 14136, 14392, 14648, 24888, 25144, 25400, 25656, 25912, 26168,
12345, 12601, 12857, 13113, 13369, 13625, 13881, 14137, 14393, 14649, 24889, 25145, 25401, 25657, 25913, 26169,
12385, 12641, 12897, 13153, 13409, 13665, 13921, 14177, 14433, 14689, 24929, 25185, 25441, 25697, 25953, 26209,
12386, 12642, 12898, 13154, 13410, 13666, 13922, 14178, 14434, 14690, 24930, 25186, 25442, 25698, 25954, 26210,
12387, 12643, 12899, 13155, 13411, 13667, 13923, 14179, 14435, 14691, 24931, 25187, 25443, 25699, 25955, 26211,
12388, 12644, 12900, 13156, 13412, 13668, 13924, 14180, 14436, 14692, 24932, 25188, 25444, 25700, 25956, 26212,
12389, 12645, 12901, 13157, 13413, 13669, 13925, 14181, 14437, 14693, 24933, 25189, 25445, 25701, 25957, 26213,
12390, 12646, 12902, 13158, 13414, 13670, 13926, 14182, 14438, 14694, 24934, 25190, 25446, 25702, 25958, 26214
)

private[this] val gs: Array[Long] = Array(
5696189077778435540L, 6557778377634271669L, 9113902524445496865L, 1269073367360058862L, 7291122019556397492L,
1015258693888047090L, 5832897615645117993L, 6346230177223303157L, 4666318092516094394L, 8766332956520552849L,
Expand Down
51 changes: 49 additions & 2 deletions zio-json/jvm/src/main/scala/zio/json/internal/SafeNumbers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package zio.json.internal

import java.util.UUID

/**
* Total, fast, number parsing.
*
Expand Down Expand Up @@ -75,13 +77,19 @@ object SafeNumbers {
def toString(x: Double): String = {
val out = new FastStringWrite(24)
write(x, out)
out.toString
out.buffer.toString
}

def toString(x: Float): String = {
val out = new FastStringWrite(16)
write(x, out)
out.toString
out.buffer.toString
}

def toString(x: UUID): String = {
val out = writes.get
write(x, out)
out.buffer.toString
}

// Based on the amazing work of Raffaello Giulietti
Expand Down Expand Up @@ -294,6 +302,26 @@ object SafeNumbers {
}
}

def write(x: UUID, out: Write): Unit = {
val ds = lowerCaseHexDigits
val msb = x.getMostSignificantBits
val lsb = x.getLeastSignificantBits
val msb1 = (msb >> 32).toInt
out.write(ds(msb1 >>> 24), ds(msb1 >> 16 & 0xff), ds(msb1 >> 8 & 0xff), ds(msb1 & 0xff))
out.write('-')
val msb2 = msb.toInt
out.write(ds(msb2 >>> 24), ds(msb2 >> 16 & 0xff))
out.write('-')
out.write(ds(msb2 >> 8 & 0xff), ds(msb2 & 0xff))
out.write('-')
val lsb1 = (lsb >>> 32).toInt
out.write(ds(lsb1 >>> 24), ds(lsb1 >> 16 & 0xff))
out.write('-')
out.write(ds(lsb1 >> 8 & 0xff), ds(lsb1 & 0xff))
val lsb2 = lsb.toInt
out.write(ds(lsb2 >>> 24), ds(lsb2 >> 16 & 0xff), ds(lsb2 >> 8 & 0xff), ds(lsb2 & 0xff))
}

private[json] def writeNano(x: Int, out: Write): Unit = {
out.write('.')
var coeff = 100000000
Expand Down Expand Up @@ -482,6 +510,25 @@ object SafeNumbers {
576460752303423478L, 576460752303423478L, 576460752303423478L, 576460752303423478L, 576460752303423478L
)

private final val lowerCaseHexDigits: Array[Short] = Array(
12336, 12592, 12848, 13104, 13360, 13616, 13872, 14128, 14384, 14640, 24880, 25136, 25392, 25648, 25904, 26160,
12337, 12593, 12849, 13105, 13361, 13617, 13873, 14129, 14385, 14641, 24881, 25137, 25393, 25649, 25905, 26161,
12338, 12594, 12850, 13106, 13362, 13618, 13874, 14130, 14386, 14642, 24882, 25138, 25394, 25650, 25906, 26162,
12339, 12595, 12851, 13107, 13363, 13619, 13875, 14131, 14387, 14643, 24883, 25139, 25395, 25651, 25907, 26163,
12340, 12596, 12852, 13108, 13364, 13620, 13876, 14132, 14388, 14644, 24884, 25140, 25396, 25652, 25908, 26164,
12341, 12597, 12853, 13109, 13365, 13621, 13877, 14133, 14389, 14645, 24885, 25141, 25397, 25653, 25909, 26165,
12342, 12598, 12854, 13110, 13366, 13622, 13878, 14134, 14390, 14646, 24886, 25142, 25398, 25654, 25910, 26166,
12343, 12599, 12855, 13111, 13367, 13623, 13879, 14135, 14391, 14647, 24887, 25143, 25399, 25655, 25911, 26167,
12344, 12600, 12856, 13112, 13368, 13624, 13880, 14136, 14392, 14648, 24888, 25144, 25400, 25656, 25912, 26168,
12345, 12601, 12857, 13113, 13369, 13625, 13881, 14137, 14393, 14649, 24889, 25145, 25401, 25657, 25913, 26169,
12385, 12641, 12897, 13153, 13409, 13665, 13921, 14177, 14433, 14689, 24929, 25185, 25441, 25697, 25953, 26209,
12386, 12642, 12898, 13154, 13410, 13666, 13922, 14178, 14434, 14690, 24930, 25186, 25442, 25698, 25954, 26210,
12387, 12643, 12899, 13155, 13411, 13667, 13923, 14179, 14435, 14691, 24931, 25187, 25443, 25699, 25955, 26211,
12388, 12644, 12900, 13156, 13412, 13668, 13924, 14180, 14436, 14692, 24932, 25188, 25444, 25700, 25956, 26212,
12389, 12645, 12901, 13157, 13413, 13669, 13925, 14181, 14437, 14693, 24933, 25189, 25445, 25701, 25957, 26213,
12390, 12646, 12902, 13158, 13414, 13670, 13926, 14182, 14438, 14694, 24934, 25190, 25446, 25702, 25958, 26214
)

private[this] val gs: Array[Long] = Array(
5696189077778435540L, 6557778377634271669L, 9113902524445496865L, 1269073367360058862L, 7291122019556397492L,
1015258693888047090L, 5832897615645117993L, 6346230177223303157L, 4666318092516094394L, 8766332956520552849L,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package zio.json.internal

import java.util.UUID

/**
* Total, fast, number parsing.
*
Expand Down Expand Up @@ -75,13 +77,19 @@ object SafeNumbers {
def toString(x: Double): String = {
val out = new FastStringWrite(24)
write(x, out)
out.toString
out.buffer.toString
}

def toString(x: Float): String = {
val out = new FastStringWrite(16)
write(x, out)
out.toString
out.buffer.toString
}

def toString(x: UUID): String = {
val out = writes.get
write(x, out)
out.buffer.toString
}

// Based on the amazing work of Raffaello Giulietti
Expand Down Expand Up @@ -294,6 +302,26 @@ object SafeNumbers {
}
}

def write(x: UUID, out: Write): Unit = {
val ds = lowerCaseHexDigits
val msb = x.getMostSignificantBits
val lsb = x.getLeastSignificantBits
val msb1 = (msb >> 32).toInt
out.write(ds(msb1 >>> 24), ds(msb1 >> 16 & 0xff), ds(msb1 >> 8 & 0xff), ds(msb1 & 0xff))
out.write('-')
val msb2 = msb.toInt
out.write(ds(msb2 >>> 24), ds(msb2 >> 16 & 0xff))
out.write('-')
out.write(ds(msb2 >> 8 & 0xff), ds(msb2 & 0xff))
out.write('-')
val lsb1 = (lsb >>> 32).toInt
out.write(ds(lsb1 >>> 24), ds(lsb1 >> 16 & 0xff))
out.write('-')
out.write(ds(lsb1 >> 8 & 0xff), ds(lsb1 & 0xff))
val lsb2 = lsb.toInt
out.write(ds(lsb2 >>> 24), ds(lsb2 >> 16 & 0xff), ds(lsb2 >> 8 & 0xff), ds(lsb2 & 0xff))
}

private[json] def writeNano(x: Int, out: Write): Unit = {
out.write('.')
var coeff = 100000000
Expand Down Expand Up @@ -482,6 +510,25 @@ object SafeNumbers {
576460752303423478L, 576460752303423478L, 576460752303423478L, 576460752303423478L, 576460752303423478L
)

private final val lowerCaseHexDigits: Array[Short] = Array(
12336, 12592, 12848, 13104, 13360, 13616, 13872, 14128, 14384, 14640, 24880, 25136, 25392, 25648, 25904, 26160,
12337, 12593, 12849, 13105, 13361, 13617, 13873, 14129, 14385, 14641, 24881, 25137, 25393, 25649, 25905, 26161,
12338, 12594, 12850, 13106, 13362, 13618, 13874, 14130, 14386, 14642, 24882, 25138, 25394, 25650, 25906, 26162,
12339, 12595, 12851, 13107, 13363, 13619, 13875, 14131, 14387, 14643, 24883, 25139, 25395, 25651, 25907, 26163,
12340, 12596, 12852, 13108, 13364, 13620, 13876, 14132, 14388, 14644, 24884, 25140, 25396, 25652, 25908, 26164,
12341, 12597, 12853, 13109, 13365, 13621, 13877, 14133, 14389, 14645, 24885, 25141, 25397, 25653, 25909, 26165,
12342, 12598, 12854, 13110, 13366, 13622, 13878, 14134, 14390, 14646, 24886, 25142, 25398, 25654, 25910, 26166,
12343, 12599, 12855, 13111, 13367, 13623, 13879, 14135, 14391, 14647, 24887, 25143, 25399, 25655, 25911, 26167,
12344, 12600, 12856, 13112, 13368, 13624, 13880, 14136, 14392, 14648, 24888, 25144, 25400, 25656, 25912, 26168,
12345, 12601, 12857, 13113, 13369, 13625, 13881, 14137, 14393, 14649, 24889, 25145, 25401, 25657, 25913, 26169,
12385, 12641, 12897, 13153, 13409, 13665, 13921, 14177, 14433, 14689, 24929, 25185, 25441, 25697, 25953, 26209,
12386, 12642, 12898, 13154, 13410, 13666, 13922, 14178, 14434, 14690, 24930, 25186, 25442, 25698, 25954, 26210,
12387, 12643, 12899, 13155, 13411, 13667, 13923, 14179, 14435, 14691, 24931, 25187, 25443, 25699, 25955, 26211,
12388, 12644, 12900, 13156, 13412, 13668, 13924, 14180, 14436, 14692, 24932, 25188, 25444, 25700, 25956, 26212,
12389, 12645, 12901, 13157, 13413, 13669, 13925, 14181, 14437, 14693, 24933, 25189, 25445, 25701, 25957, 26213,
12390, 12646, 12902, 13158, 13414, 13670, 13926, 14182, 14438, 14694, 24934, 25190, 25446, 25702, 25958, 26214
)

private[this] val gs: Array[Long] = Array(
5696189077778435540L, 6557778377634271669L, 9113902524445496865L, 1269073367360058862L, 7291122019556397492L,
1015258693888047090L, 5832897615645117993L, 6346230177223303157L, 4666318092516094394L, 8766332956520552849L,
Expand Down
15 changes: 12 additions & 3 deletions zio-json/shared/src/main/scala/zio/json/JsonEncoder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -723,12 +723,12 @@ private[json] trait EncoderLowPriority3 extends EncoderLowPriority4 {
implicit val zoneId: JsonEncoder[ZoneId] = new JsonEncoder[ZoneId] {
def unsafeEncode(a: ZoneId, indent: Option[Int], out: Write): Unit = {
out.write('"')
serializers.write(a, out)
out.write(a.getId)
out.write('"')
}

override final def toJsonAST(a: ZoneId): Either[String, Json] =
new Right(new Json.Str(serializers.toString(a)))
new Right(new Json.Str(a.getId))
}

implicit val zoneOffset: JsonEncoder[ZoneOffset] = new JsonEncoder[ZoneOffset] {
Expand All @@ -742,7 +742,16 @@ private[json] trait EncoderLowPriority3 extends EncoderLowPriority4 {
new Right(new Json.Str(serializers.toString(a)))
}

implicit val uuid: JsonEncoder[UUID] = stringify(_.toString)
implicit val uuid: JsonEncoder[UUID] = new JsonEncoder[UUID] {
def unsafeEncode(a: UUID, indent: Option[Int], out: Write): Unit = {
out.write('"')
SafeNumbers.write(a, out)
out.write('"')
}

override final def toJsonAST(a: UUID): Either[String, Json] =
new Right(new Json.Str(SafeNumbers.toString(a)))
}

implicit val currency: JsonEncoder[java.util.Currency] = stringify(_.toString)
}
Expand Down