-
Notifications
You must be signed in to change notification settings - Fork 7
feat: Replace jsoniter macros with circe #83
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
Open
ghostbuster91
wants to merge
16
commits into
smithy4s-integration
Choose a base branch
from
circe
base: smithy4s-integration
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
e289ba8
feat: Replace jsoniter macros with circe
ghostbuster91 b7a5c6d
Downgrade jsoniter-scala version
ghostbuster91 61bce62
Fix fs2 tests
ghostbuster91 415a2d7
Remove references to jsoniter from example server/client
ghostbuster91 24632c5
Remove dependency on circe-generic
ghostbuster91 7390e61
Remove useless comments
ghostbuster91 2ede4b5
Disable mima
ghostbuster91 c311806
Remove core-compile workaround
ghostbuster91 a7e06fd
Make codecs private
ghostbuster91 6db2741
Change Payload to carry circe.Json
ghostbuster91 a792e4d
Rewrite CallIdDecoder with the use of or operator
ghostbuster91 28170e4
Fix CI sbt command
ghostbuster91 d8e69d3
Revert "Make codecs private"
ghostbuster91 f60ddf5
Create circeCodec from schema via document
ghostbuster91 cb46dd9
Remove custom Codec abstraction
ghostbuster91 275def7
Restore behavior in case of missing payload
ghostbuster91 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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 |
---|---|---|
@@ -1,32 +1,26 @@ | ||
package jsonrpclib | ||
|
||
import com.github.plokhotnyuk.jsoniter_scala.core._ | ||
import scala.annotation.switch | ||
import io.circe.{Decoder, Encoder, Json, Codec} | ||
|
||
sealed trait CallId | ||
object CallId { | ||
final case class NumberId(long: Long) extends CallId | ||
final case class StringId(string: String) extends CallId | ||
case object NullId extends CallId | ||
|
||
implicit val callIdRW: JsonValueCodec[CallId] = new JsonValueCodec[CallId] { | ||
def decodeValue(in: JsonReader, default: CallId): CallId = { | ||
val nt = in.nextToken() | ||
|
||
(nt: @switch) match { | ||
case 'n' => in.readNullOrError(default, "expected null") | ||
case '"' => in.rollbackToken(); StringId(in.readString(null)) | ||
case _ => in.rollbackToken(); NumberId(in.readLong()) | ||
|
||
implicit val callIdDecoder: Decoder[CallId] = | ||
Decoder | ||
.decodeOption(Decoder.decodeString.map(StringId(_): CallId).or(Decoder.decodeLong.map(NumberId(_): CallId))) | ||
.map { | ||
case None => NullId | ||
case Some(v) => v | ||
} | ||
} | ||
|
||
def encodeValue(x: CallId, out: JsonWriter): Unit = x match { | ||
case NumberId(long) => out.writeVal(long) | ||
case StringId(string) => out.writeVal(string) | ||
case NullId => out.writeNull() | ||
} | ||
|
||
def nullValue: CallId = CallId.NullId | ||
implicit val callIdEncoder: Encoder[CallId] = Encoder.instance { | ||
case NumberId(n) => Json.fromLong(n) | ||
case StringId(str) => Json.fromString(str) | ||
case NullId => Json.Null | ||
} | ||
|
||
implicit val codec: Codec[CallId] = Codec.from(callIdDecoder, callIdEncoder) | ||
} |
This file contains hidden or 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
This file was deleted.
Oops, something went wrong.
This file contains hidden or 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 |
---|---|---|
@@ -1,5 +1,7 @@ | ||
package jsonrpclib | ||
|
||
import io.circe.Codec | ||
|
||
sealed trait Endpoint[F[_]] { | ||
def method: String | ||
} | ||
|
This file contains hidden or 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 |
---|---|---|
@@ -1,15 +1,16 @@ | ||
package jsonrpclib | ||
|
||
import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec | ||
import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker | ||
import io.circe.{Decoder, Encoder} | ||
|
||
case class ErrorPayload(code: Int, message: String, data: Option[Payload]) extends Throwable { | ||
override def getMessage(): String = s"JsonRPC Error $code: $message" | ||
} | ||
|
||
object ErrorPayload { | ||
|
||
implicit val rawMessageStubJsonValueCodecs: JsonValueCodec[ErrorPayload] = | ||
JsonCodecMaker.make | ||
implicit val errorPayloadEncoder: Encoder[ErrorPayload] = | ||
Encoder.forProduct3("code", "message", "data")(e => (e.code, e.message, e.data)) | ||
|
||
implicit val errorPayloadDecoder: Decoder[ErrorPayload] = | ||
Decoder.forProduct3("code", "message", "data")(ErrorPayload.apply) | ||
} |
This file contains hidden or 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 |
---|---|---|
@@ -1,42 +1,43 @@ | ||
package jsonrpclib | ||
|
||
import com.github.plokhotnyuk.jsoniter_scala.core.JsonReader | ||
import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec | ||
import com.github.plokhotnyuk.jsoniter_scala.core.JsonWriter | ||
import io.circe.{Decoder, Encoder} | ||
import io.circe.syntax._ | ||
|
||
sealed trait Message { def maybeCallId: Option[CallId] } | ||
sealed trait InputMessage extends Message { def method: String } | ||
sealed trait OutputMessage extends Message { | ||
def callId: CallId; final override def maybeCallId: Option[CallId] = Some(callId) | ||
def callId: CallId | ||
final override def maybeCallId: Option[CallId] = Some(callId) | ||
} | ||
|
||
object InputMessage { | ||
case class RequestMessage(method: String, callId: CallId, params: Option[Payload]) extends InputMessage { | ||
def maybeCallId: Option[CallId] = Some(callId) | ||
} | ||
|
||
case class NotificationMessage(method: String, params: Option[Payload]) extends InputMessage { | ||
def maybeCallId: Option[CallId] = None | ||
} | ||
|
||
} | ||
|
||
object OutputMessage { | ||
def errorFrom(callId: CallId, protocolError: ProtocolError): OutputMessage = | ||
ErrorMessage(callId, ErrorPayload(protocolError.code, protocolError.getMessage(), None)) | ||
|
||
case class ErrorMessage(callId: CallId, payload: ErrorPayload) extends OutputMessage | ||
case class ResponseMessage(callId: CallId, data: Payload) extends OutputMessage | ||
|
||
} | ||
|
||
object Message { | ||
import jsonrpclib.internals.RawMessage | ||
|
||
implicit val decoder: Decoder[Message] = Decoder.instance { c => | ||
c.as[RawMessage].flatMap(_.toMessage.left.map(e => io.circe.DecodingFailure(e.getMessage, c.history))) | ||
} | ||
|
||
implicit val messageJsonValueCodecs: JsonValueCodec[Message] = new JsonValueCodec[Message] { | ||
val rawMessageCodec = implicitly[JsonValueCodec[internals.RawMessage]] | ||
def decodeValue(in: JsonReader, default: Message): Message = | ||
rawMessageCodec.decodeValue(in, null).toMessage match { | ||
case Left(error) => throw error | ||
case Right(value) => value | ||
} | ||
def encodeValue(x: Message, out: JsonWriter): Unit = | ||
rawMessageCodec.encodeValue(internals.RawMessage.from(x), out) | ||
def nullValue: Message = null | ||
implicit val encoder: Encoder[Message] = Encoder.instance { msg => | ||
RawMessage.from(msg).asJson | ||
} | ||
} |
This file contains hidden or 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 |
---|---|---|
@@ -1,50 +1,15 @@ | ||
package jsonrpclib | ||
|
||
import com.github.plokhotnyuk.jsoniter_scala.core.JsonReader | ||
import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec | ||
import com.github.plokhotnyuk.jsoniter_scala.core.JsonWriter | ||
import io.circe.{Decoder, Encoder, Json} | ||
|
||
import java.util.Base64 | ||
import jsonrpclib.Payload.Data | ||
import jsonrpclib.Payload.NullPayload | ||
|
||
sealed trait Payload extends Product with Serializable { | ||
def stripNull: Option[Payload.Data] = this match { | ||
case d @ Data(_) => Some(d) | ||
case NullPayload => None | ||
} | ||
case class Payload(data: Json) { | ||
def stripNull: Option[Payload] = Option(Payload(data)).filter(p => !p.data.isNull) | ||
} | ||
|
||
object Payload { | ||
def apply(value: Array[Byte]) = { | ||
if (value == null) NullPayload | ||
else Data(value) | ||
} | ||
final case class Data(array: Array[Byte]) extends Payload { | ||
override def equals(other: Any) = other match { | ||
case bytes: Data => java.util.Arrays.equals(array, bytes.array) | ||
case _ => false | ||
} | ||
|
||
override lazy val hashCode: Int = java.util.Arrays.hashCode(array) | ||
|
||
override def toString = Base64.getEncoder.encodeToString(array) | ||
} | ||
|
||
case object NullPayload extends Payload | ||
|
||
implicit val payloadJsonValueCodec: JsonValueCodec[Payload] = new JsonValueCodec[Payload] { | ||
def decodeValue(in: JsonReader, default: Payload): Payload = { | ||
Data(in.readRawValAsBytes()) | ||
} | ||
|
||
def encodeValue(bytes: Payload, out: JsonWriter): Unit = | ||
bytes match { | ||
case Data(array) => out.writeRawVal(array) | ||
case NullPayload => out.writeNull() | ||
|
||
} | ||
val NullPayload: Payload = Payload(Json.Null) | ||
|
||
def nullValue: Payload = null | ||
} | ||
implicit val payloadEncoder: Encoder[Payload] = Encoder[Json].contramap(_.data) | ||
implicit val payloadDecoder: Decoder[Payload] = Decoder[Json].map(Payload(_)) | ||
} |
This file contains hidden or 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
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
question: does the bincompat breakage affect langoustine? conversely, are the codec instances even used / need to be visible outside of jsonrpclib?
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.
good question, I checked it manually and it seems that there is one place where it does:
and there is another one in tests:
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.
should we make the circe codecs package private?
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.
sigh... removing jsoniter macros was supposed to help us in the compilation flakiness 😓
not sure about circe codecs. I can see it being useful for tests (like what langoustine did), but the tracer's usecase should probably be supported with something more high-level