-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add readers and writers instances for cats non-empty collections (#284)
* Add readers and writers instances for cats non-empty collections * fix problem with SortedSet * up version to 0.28.4 * renamed module name to tethys-cats
- Loading branch information
1 parent
0fc4b10
commit 6d72556
Showing
8 changed files
with
219 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
modules/cats/src/main/scala-2.12/tethys/cats/NonEmptySetReader.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package tethys.cats | ||
|
||
import cats.data.NonEmptySet | ||
import tethys.JsonReader | ||
import tethys.readers.{FieldName, ReaderError} | ||
import tethys.readers.tokens.TokenIterator | ||
|
||
import scala.collection.immutable.{Seq, SortedSet} | ||
|
||
trait NonEmptySetReader { | ||
|
||
implicit def readerForNes[T: JsonReader: Ordering] | ||
: JsonReader[NonEmptySet[T]] = | ||
new JsonReader[NonEmptySet[T]] { | ||
override def read( | ||
it: TokenIterator | ||
)(implicit fieldName: FieldName): NonEmptySet[T] = | ||
NonEmptySet.fromSet(SortedSet(JsonReader[Seq[T]].read(it): _*)) match { | ||
case Some(value) => value | ||
case None => | ||
ReaderError.wrongJson( | ||
s"Seq is empty and can't be converted to NonEmptySet" | ||
) | ||
} | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
modules/cats/src/main/scala-2.13+/tethys/cats/NonEmptySetReader.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package tethys.cats | ||
|
||
import cats.data.NonEmptySet | ||
import tethys.JsonReader | ||
import tethys.readers.{FieldName, ReaderError} | ||
import tethys.readers.tokens.TokenIterator | ||
|
||
import scala.collection.immutable.SortedSet | ||
|
||
trait NonEmptySetReader { | ||
|
||
implicit def readerForNes[T: JsonReader: Ordering] | ||
: JsonReader[NonEmptySet[T]] = | ||
new JsonReader[NonEmptySet[T]] { | ||
override def read( | ||
it: TokenIterator | ||
)(implicit fieldName: FieldName): NonEmptySet[T] = | ||
NonEmptySet.fromSet(SortedSet.from(JsonReader[Seq[T]].read(it))) match { | ||
case Some(value) => value | ||
case None => | ||
ReaderError.wrongJson( | ||
s"Seq is empty and can't be converted to NonEmptySet" | ||
) | ||
} | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
modules/cats/src/main/scala-3/tethys.cats/NonEmptySetReader.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package tethys.cats | ||
|
||
import cats.data.NonEmptySet | ||
import tethys.JsonReader | ||
import tethys.readers.{FieldName, ReaderError} | ||
import tethys.readers.tokens.TokenIterator | ||
|
||
import scala.collection.immutable.SortedSet | ||
|
||
trait NonEmptySetReader { | ||
|
||
implicit def readerForNes[T: JsonReader: Ordering] | ||
: JsonReader[NonEmptySet[T]] = | ||
new JsonReader[NonEmptySet[T]] { | ||
override def read( | ||
it: TokenIterator | ||
)(implicit fieldName: FieldName): NonEmptySet[T] = | ||
NonEmptySet.fromSet(SortedSet.from(JsonReader[Seq[T]].read(it))) match { | ||
case Some(value) => value | ||
case None => | ||
ReaderError.wrongJson( | ||
s"Seq is empty and can't be converted to NonEmptySet" | ||
) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package tethys.cats | ||
|
||
import tethys.cats.readers.CatsReaders | ||
import tethys.cats.writers.CatsWriters | ||
|
||
object instances extends CatsReaders with CatsWriters with NonEmptySetReader |
56 changes: 56 additions & 0 deletions
56
modules/cats/src/main/scala/tethys/cats/readers/CatsReaders.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package tethys.cats.readers | ||
|
||
import cats.data._ | ||
import tethys.readers.tokens.TokenIterator | ||
import tethys.readers.{FieldName, ReaderError} | ||
import tethys.JsonReader | ||
import tethys.JsonReader.iterableReader | ||
|
||
trait CatsReaders { | ||
|
||
implicit def readerForNel[T: JsonReader]: JsonReader[NonEmptyList[T]] = | ||
new JsonReader[NonEmptyList[T]] { | ||
override def read( | ||
it: TokenIterator | ||
)(implicit fieldName: FieldName): NonEmptyList[T] = | ||
NonEmptyList.fromList(JsonReader[List[T]].read(it)) match { | ||
case Some(value) => value | ||
case None => | ||
ReaderError.wrongJson( | ||
s"List is empty and can't be converted to NonEmptyList" | ||
) | ||
} | ||
} | ||
|
||
implicit def readerForNev[T: JsonReader]: JsonReader[NonEmptyVector[T]] = | ||
new JsonReader[NonEmptyVector[T]] { | ||
override def read( | ||
it: TokenIterator | ||
)(implicit fieldName: FieldName): NonEmptyVector[T] = | ||
NonEmptyVector.fromVector(JsonReader[Vector[T]].read(it)) match { | ||
case Some(value) => value | ||
case None => | ||
ReaderError.wrongJson( | ||
s"Vector is empty and can't be converted to NonEmptyVector" | ||
) | ||
} | ||
} | ||
|
||
implicit def readerForChain[T: JsonReader]: JsonReader[Chain[T]] = | ||
JsonReader[Seq[T]].map(Chain.fromIterableOnce) | ||
|
||
implicit def readerForNec[T: JsonReader]: JsonReader[NonEmptyChain[T]] = | ||
new JsonReader[NonEmptyChain[T]] { | ||
override def read( | ||
it: TokenIterator | ||
)(implicit fieldName: FieldName): NonEmptyChain[T] = | ||
NonEmptyChain.fromChain(JsonReader[Chain[T]].read(it)) match { | ||
case Some(value) => value | ||
case None => | ||
ReaderError.wrongJson( | ||
s"Chain is empty and can't be converted to NonEmptyChain" | ||
) | ||
} | ||
} | ||
|
||
} |
21 changes: 21 additions & 0 deletions
21
modules/cats/src/main/scala/tethys/cats/writers/CatsWriters.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package tethys.cats.writers | ||
|
||
import cats.data._ | ||
import tethys.JsonWriter | ||
|
||
trait CatsWriters { | ||
implicit def writerForNev[T: JsonWriter]: JsonWriter[NonEmptyVector[T]] = | ||
JsonWriter[Vector[T]].contramap(_.toVector) | ||
|
||
implicit def writerForNel[T: JsonWriter]: JsonWriter[NonEmptyList[T]] = | ||
JsonWriter[List[T]].contramap(_.toList) | ||
|
||
implicit def writerForNes[T: JsonWriter]: JsonWriter[NonEmptySet[T]] = | ||
JsonWriter[Set[T]].contramap(_.toSortedSet) | ||
|
||
implicit def writerForChain[T: JsonWriter]: JsonWriter[Chain[T]] = | ||
JsonWriter[List[T]].contramap(_.toList) | ||
|
||
implicit def writerForNec[T: JsonWriter]: JsonWriter[NonEmptyChain[T]] = | ||
JsonWriter[Chain[T]].contramap(_.toChain) | ||
} |
44 changes: 44 additions & 0 deletions
44
modules/cats/src/test/scala/tethys/cats/CatsSupportTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package tethys.cats | ||
|
||
import cats.data._ | ||
import org.scalatest.flatspec.AnyFlatSpec | ||
import org.scalatest.matchers.should.Matchers | ||
import tethys.commons.TokenNode._ | ||
import instances._ | ||
import tethys.readers.ReaderError | ||
import tethys.writers.tokens.SimpleTokenWriter._ | ||
|
||
class CatsSupportTests extends AnyFlatSpec with Matchers { | ||
val nev: NonEmptyVector[String] = NonEmptyVector.of("a", "b") | ||
val nel: NonEmptyList[Int] = NonEmptyList.of(1, 2) | ||
val nes: NonEmptySet[Int] = NonEmptySet.of(1, 2, 3, 4) | ||
val chain: Chain[Int] = Chain.fromIterableOnce(Seq(1, 2, 3)) | ||
val nec: NonEmptyChain[String] = NonEmptyChain.of("a", "b", "c") | ||
|
||
behavior of "CatsWriters" | ||
it should "write non-empty" in { | ||
nev.asTokenList shouldBe arr("a", "b") | ||
nel.asTokenList shouldBe arr(1, 2) | ||
nes.asTokenList shouldBe arr(1, 2, 3, 4) | ||
chain.asTokenList shouldBe arr(1, 2, 3) | ||
nec.asTokenList shouldBe arr("a", "b", "c") | ||
} | ||
|
||
behavior of "CatsReaders" | ||
it should "read non-empty" in { | ||
nev shouldBe arr("a", "b").tokensAs[NonEmptyVector[String]] | ||
assertThrows[ReaderError](Nil.tokensAs[NonEmptyVector[String]]) | ||
|
||
nel shouldBe arr(1, 2).tokensAs[NonEmptyList[Int]] | ||
assertThrows[ReaderError](Nil.tokensAs[NonEmptyList[Int]]) | ||
|
||
nes shouldBe arr(1, 2, 3, 4).tokensAs[NonEmptySet[Int]] | ||
nes shouldBe arr(4, 4, 1, 3, 3, 2).tokensAs[NonEmptySet[Int]] | ||
assertThrows[ReaderError](Nil.tokensAs[NonEmptySet[Int]]) | ||
|
||
chain shouldBe arr(1, 2, 3).tokensAs[Chain[Int]] | ||
|
||
nec shouldBe arr("a", "b", "c").tokensAs[NonEmptyChain[String]] | ||
assertThrows[ReaderError](Nil.tokensAs[NonEmptyChain[String]]) | ||
} | ||
} |