From 4280a3b06dbcc6c9be5d619e2a67b35c46dafeec Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Thu, 6 Apr 2023 13:04:10 +0800 Subject: [PATCH] Add readwriters for SortedMap and LinkedHashMap (#479) There are a lot more `scala.collection.*Maps` out there, but these are the ones I need regularly --- implicits/src/upickle/implicits/Readers.scala | 38 ++++++++++++- implicits/src/upickle/implicits/Writers.scala | 23 +++++++- upickle/test/src/upickle/StructTests.scala | 57 +++++++++++++++++++ 3 files changed, 112 insertions(+), 6 deletions(-) diff --git a/implicits/src/upickle/implicits/Readers.scala b/implicits/src/upickle/implicits/Readers.scala index a184d3379..f15c890a8 100644 --- a/implicits/src/upickle/implicits/Readers.scala +++ b/implicits/src/upickle/implicits/Readers.scala @@ -257,17 +257,17 @@ trait Readers extends upickle.core.Types } } - implicit def MapReader1[K, V](implicit k: Reader[K], v: Reader[V]): Reader[collection.Map[K, V]] = { + implicit def MapReader1[K: Reader, V: Reader]: Reader[collection.Map[K, V]] = { MapReader0[collection.Map, K, V](_.toMap) } - implicit def MapReader2[K, V](implicit k: Reader[K], v: Reader[V]): Reader[collection.immutable.Map[K, V]] = { + implicit def MapReader2[K: Reader, V: Reader]: Reader[collection.immutable.Map[K, V]] = { MapReader0[collection.immutable.Map, K, V]{seq => val b = collection.immutable.Map.newBuilder[K, V] seq.foreach(b += _) b.result() } } - implicit def MapReader3[K, V](implicit k: Reader[K], v: Reader[V]): Reader[collection.mutable.Map[K, V]] = { + implicit def MapReader3[K: Reader, V: Reader]: Reader[collection.mutable.Map[K, V]] = { MapReader0[collection.mutable.Map, K, V]{seq => val b = collection.mutable.Map.newBuilder[K, V] seq.foreach(b += _) @@ -275,6 +275,38 @@ trait Readers extends upickle.core.Types } } + implicit def MapReader4[K: Reader, V: Reader]: Reader[collection.mutable.LinkedHashMap[K, V]] = { + MapReader0[collection.mutable.LinkedHashMap, K, V]{seq => + val b = collection.mutable.LinkedHashMap.newBuilder[K, V] + seq.foreach(b += _) + b.result() + } + } + + implicit def SortedMapReader[K: Reader: Ordering, V: Reader]: Reader[collection.mutable.SortedMap[K, V]] = { + MapReader0[collection.mutable.SortedMap, K, V]{seq => + val b = collection.mutable.SortedMap.newBuilder[K, V] + seq.foreach(b += _) + b.result() + } + } + + implicit def MapReader6[K: Reader: Ordering, V: Reader]: Reader[collection.immutable.SortedMap[K, V]] = { + MapReader0[collection.immutable.SortedMap, K, V]{seq => + val b = collection.immutable.SortedMap.newBuilder[K, V] + seq.foreach(b += _) + b.result() + } + } + + implicit def MapReader7[K: Reader: Ordering, V: Reader]: Reader[collection.SortedMap[K, V]] = { + MapReader0[collection.SortedMap, K, V]{seq => + val b = collection.SortedMap.newBuilder[K, V] + seq.foreach(b += _) + b.result() + } + } + implicit def OptionReader[T: Reader]: Reader[Option[T]] = new SimpleReader[Option[T]] { override def expectedMsg = "expected sequence" override def visitArray(length: Int, index: Int) = new ArrVisitor[Any, Option[T]] { diff --git a/implicits/src/upickle/implicits/Writers.scala b/implicits/src/upickle/implicits/Writers.scala index 67f1948d4..01a94b02b 100644 --- a/implicits/src/upickle/implicits/Writers.scala +++ b/implicits/src/upickle/implicits/Writers.scala @@ -141,18 +141,35 @@ trait Writers extends upickle.core.Types } } - implicit def MapWriter1[K, V](implicit kw: Writer[K], vw: Writer[V]): Writer[collection.Map[K, V]] = { + implicit def MapWriter1[K: Writer, V: Writer]: Writer[collection.Map[K, V]] = { MapWriter0[collection.Map, K, V] } - implicit def MapWriter2[K, V](implicit kw: Writer[K], vw: Writer[V]): Writer[collection.immutable.Map[K, V]] = { + implicit def MapWriter2[K: Writer, V: Writer]: Writer[collection.immutable.Map[K, V]] = { MapWriter0[collection.immutable.Map, K, V] } - implicit def MapWriter3[K, V](implicit kw: Writer[K], vw: Writer[V]): Writer[collection.mutable.Map[K, V]] = { + implicit def MapWriter3[K: Writer, V: Writer]: Writer[collection.mutable.Map[K, V]] = { MapWriter0[collection.mutable.Map, K, V] } + implicit def MapWriter4[K: Writer, V: Writer]: Writer[collection.mutable.LinkedHashMap[K, V]] = { + MapWriter0[collection.mutable.LinkedHashMap, K, V] + } + + implicit def MapWriter5[K: Writer, V: Writer]: Writer[collection.mutable.SortedMap[K, V]] = { + MapWriter0[collection.mutable.SortedMap, K, V] + } + + implicit def MapWriter6[K: Writer, V: Writer]: Writer[collection.immutable.SortedMap[K, V]] = { + MapWriter0[collection.immutable.SortedMap, K, V] + } + + + implicit def MapWriter7[K: Writer, V: Writer]: Writer[collection.SortedMap[K, V]] = { + MapWriter0[collection.SortedMap, K, V] + } + implicit val DurationWriter: Writer[Duration] = new SimpleMapKeyWriter[Duration]{ override def writeString(v: Duration) = v match{ case Duration.Inf => "inf" diff --git a/upickle/test/src/upickle/StructTests.scala b/upickle/test/src/upickle/StructTests.scala index 3c349def0..24e7e4d26 100644 --- a/upickle/test/src/upickle/StructTests.scala +++ b/upickle/test/src/upickle/StructTests.scala @@ -384,6 +384,63 @@ object StructTests extends TestSuite { upack.Arr(upack.Arr(upack.Str("abc"), upack.Str("def"))) ) } + + test("variants"){ + test("LinkedHashMap") - rw( + scala.collection.mutable.LinkedHashMap("Hello" -> List(1), "World" -> List(1, 2, 3)), + """{"Hello":[1],"World":[1,2,3]}""", + """[["Hello",[1]],["World",[1,2,3]]]""", + upack.Obj( + upack.Str("Hello") -> upack.Arr(upack.Int32(1)), + upack.Str("World") -> upack.Arr(upack.Int32(1), upack.Int32(2), upack.Int32(3)) + ), + upack.Arr( + upack.Arr(upack.Str("Hello"), upack.Arr(upack.Int32(1))), + upack.Arr(upack.Str("World"), upack.Arr(upack.Int32(1), upack.Int32(2), upack.Int32(3))) + ) + ) + test("SortedMap"){ + test("immutable") - rw( + scala.collection.immutable.SortedMap("Hello" -> List(1), "World" -> List(1, 2, 3)), + """{"Hello":[1],"World":[1,2,3]}""", + """[["Hello",[1]],["World",[1,2,3]]]""", + upack.Obj( + upack.Str("Hello") -> upack.Arr(upack.Int32(1)), + upack.Str("World") -> upack.Arr(upack.Int32(1), upack.Int32(2), upack.Int32(3)) + ), + upack.Arr( + upack.Arr(upack.Str("Hello"), upack.Arr(upack.Int32(1))), + upack.Arr(upack.Str("World"), upack.Arr(upack.Int32(1), upack.Int32(2), upack.Int32(3))) + ) + ) + test("mutable") - rw( + scala.collection.mutable.SortedMap("Hello" -> List(1), "World" -> List(1, 2, 3)), + """{"Hello":[1],"World":[1,2,3]}""", + """[["Hello",[1]],["World",[1,2,3]]]""", + upack.Obj( + upack.Str("Hello") -> upack.Arr(upack.Int32(1)), + upack.Str("World") -> upack.Arr(upack.Int32(1), upack.Int32(2), upack.Int32(3)) + ), + upack.Arr( + upack.Arr(upack.Str("Hello"), upack.Arr(upack.Int32(1))), + upack.Arr(upack.Str("World"), upack.Arr(upack.Int32(1), upack.Int32(2), upack.Int32(3))) + ) + ) + test("collection") - rw( + scala.collection.SortedMap("Hello" -> List(1), "World" -> List(1, 2, 3)), + """{"Hello":[1],"World":[1,2,3]}""", + """[["Hello",[1]],["World",[1,2,3]]]""", + upack.Obj( + upack.Str("Hello") -> upack.Arr(upack.Int32(1)), + upack.Str("World") -> upack.Arr(upack.Int32(1), upack.Int32(2), upack.Int32(3)) + ), + upack.Arr( + upack.Arr(upack.Str("Hello"), upack.Arr(upack.Int32(1))), + upack.Arr(upack.Str("World"), upack.Arr(upack.Int32(1), upack.Int32(2), upack.Int32(3))) + ) + ) + } + } } test("option"){