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

Allow modifying encoded maps and objects #254

Merged
merged 2 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions src/main/scala/scynamo/ScynamoEncoder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import shapeless.tag.@@
import software.amazon.awssdk.services.dynamodb.model.AttributeValue

import java.time.Instant
import java.util.{Collections, UUID}
import java.util.UUID
import scala.collection.compat._
import scala.collection.immutable.Seq
import scala.concurrent.duration.{Duration, FiniteDuration}
Expand Down Expand Up @@ -197,7 +197,7 @@ object ObjectScynamoEncoder extends SemiautoDerivationEncoder {
}
}

NonEmptyChain.fromChain(allErrors).toLeft(Collections.unmodifiableMap(attrValues))
NonEmptyChain.fromChain(allErrors).toLeft(attrValues)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package scynamo.generic
import scynamo.ObjectScynamoEncoder
import shapeless.{LabelledGeneric, Lazy}

import java.util.Collections

trait GenericScynamoEncoder[A] extends ObjectScynamoEncoder[A]

object GenericScynamoEncoder extends GenericScynamoEncoderInstances
Expand All @@ -14,5 +12,5 @@ trait GenericScynamoEncoderInstances {
gen: LabelledGeneric.Aux[F, G],
sg: Lazy[ShapelessScynamoEncoder[F, G]]
): GenericScynamoEncoder[F] =
value => sg.value.encodeMap(gen.to(value)).map(Collections.unmodifiableMap(_))
value => sg.value.encodeMap(gen.to(value))
}
45 changes: 41 additions & 4 deletions src/test/scala/scynamo/ScynamoEncoderTest.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package scynamo

import cats.data.EitherNec
import cats.syntax.either._
import cats.syntax.all._
import org.scalatest.Inside
import scynamo.ScynamoEncoderTest.{Foo, Foo2, Snake}
import scynamo.syntax.all._
import scynamo.ScynamoEncoderTest._
import scynamo.StackFrame.{Attr, Case, Index, MapKey}
import scynamo.wrapper.{ScynamoBinarySet, ScynamoNumberSet, ScynamoStringSet}
import software.amazon.awssdk.core.SdkBytes
import software.amazon.awssdk.services.dynamodb.model.AttributeValue
import scala.jdk.CollectionConverters._

class ScynamoEncoderTest extends UnitTest {
"ScynamoEncoder" should {
Expand Down Expand Up @@ -138,14 +140,49 @@ class ScynamoEncoderTest extends UnitTest {
.encodeMap(Snake(1, Some(Snake(2, None))))
.map(attrs => Option(attrs.get("tail").m.get("tail"))) should ===(Right(None))
}

"allow modifying encoded maps" in {
val prices = Typed("price", Map("milk" -> 1.29, "hummus" -> 0.99))
prices.encodedMap.map(_.asScala) shouldBe Right(
Map(
"type" -> AttributeValue.builder.s("price").build(),
"milk" -> AttributeValue.builder.n("1.29").build(),
"hummus" -> AttributeValue.builder.n("0.99").build()
)
)
}

"allow modifying encoded objects" in {
val prices = Typed("snake", Snake(42, None))
prices.encodedMap.map(_.asScala) shouldBe Right(
Map(
"type" -> AttributeValue.builder.s("snake").build(),
"head" -> AttributeValue.builder.n("42").build()
)
)
}
}
}

object ScynamoEncoderTest {
case class Typed[A](tpe: String, value: A)
object Typed {
implicit def encoder[A: ObjectScynamoEncoder]: ObjectScynamoEncoder[Typed[A]] =
ObjectScynamoEncoder.instance { case Typed(tpe, value) =>
for {
encodedType <- tpe.encoded
encodedValue <- value.encodedMap
} yield {
encodedValue.put("type", encodedType)
encodedValue
}
}
}

case class Snake[A](head: A, tail: Option[Snake[A]])
object Snake {
implicit def codec[A: ScynamoCodec]: ObjectScynamoCodec[Snake[A]] =
scynamo.generic.semiauto.deriveScynamoCodec[Snake[A]]
implicit def codec[A: ScynamoEncoder]: ObjectScynamoEncoder[Snake[A]] =
scynamo.generic.semiauto.deriveScynamoEncoder[Snake[A]]
}

case class Foo(i: Int)
Expand Down