aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorJack Koenig2021-05-14 11:12:19 -0700
committerGitHub2021-05-14 18:12:19 +0000
commitc2d72fd8a4f3558094094eed2f4a12f85d080c41 (patch)
tree6da2b363ae2af6639ff0a8b8aae05410711934fb /src/main
parentf33b93101e0e623dc345b27f18520fd5a5ca921d (diff)
Add JsonProtocol.serializeRecover (#2227)
This function will safely wrap any unserializeable annotations in UnserializeableAnnotations so that they can be safely serialized to JSON for logging.
Diffstat (limited to 'src/main')
-rw-r--r--src/main/scala/firrtl/Compiler.scala12
-rw-r--r--src/main/scala/firrtl/annotations/JsonProtocol.scala29
2 files changed, 27 insertions, 14 deletions
diff --git a/src/main/scala/firrtl/Compiler.scala b/src/main/scala/firrtl/Compiler.scala
index 2998af3c..7354b8ee 100644
--- a/src/main/scala/firrtl/Compiler.scala
+++ b/src/main/scala/firrtl/Compiler.scala
@@ -214,17 +214,7 @@ private[firrtl] object Transform {
val remappedAnnotations = propagateAnnotations(name, logger, before.annotations, after.annotations, after.renames)
logger.trace(s"Annotations:")
- logger.trace {
- JsonProtocol
- .serializeTry(remappedAnnotations)
- .recoverWith {
- case NonFatal(e) =>
- val msg = s"Exception thrown during Annotation serialization:\n " +
- e.toString.replaceAll("\n", "\n ")
- Try(msg)
- }
- .get
- }
+ logger.trace(JsonProtocol.serializeRecover(remappedAnnotations))
logger.trace(s"Circuit:\n${after.circuit.serialize}")
diff --git a/src/main/scala/firrtl/annotations/JsonProtocol.scala b/src/main/scala/firrtl/annotations/JsonProtocol.scala
index c284c788..3a25998d 100644
--- a/src/main/scala/firrtl/annotations/JsonProtocol.scala
+++ b/src/main/scala/firrtl/annotations/JsonProtocol.scala
@@ -5,7 +5,7 @@ package annotations
import firrtl.ir._
-import scala.util.{Failure, Try}
+import scala.util.{Failure, Success, Try}
import org.json4s._
import org.json4s.native.JsonMethods._
@@ -19,6 +19,9 @@ trait HasSerializationHints {
def typeHints: Seq[Class[_]]
}
+/** Wrapper [[Annotation]] for Annotations that cannot be serialized */
+case class UnserializeableAnnotation(error: String, content: String) extends NoTargetAnnotation
+
object JsonProtocol {
class TransformClassSerializer
extends CustomSerializer[Class[_ <: Transform]](format =>
@@ -227,14 +230,17 @@ object JsonProtocol {
): Seq[(Annotation, Throwable)] =
annos.map(a => a -> Try(write(a))).collect { case (a, Failure(e)) => (a, e) }
- def serializeTry(annos: Seq[Annotation]): Try[String] = {
- val tags = annos
+ private def getTags(annos: Seq[Annotation]): Seq[Class[_]] =
+ annos
.flatMap({
case anno: HasSerializationHints => anno.getClass +: anno.typeHints
case anno => Seq(anno.getClass)
})
.distinct
+ def serializeTry(annos: Seq[Annotation]): Try[String] = {
+ val tags = getTags(annos)
+
implicit val formats = jsonFormat(tags)
Try(writePretty(annos)).recoverWith {
case e: org.json4s.MappingException =>
@@ -243,6 +249,23 @@ object JsonProtocol {
}
}
+ /** Serialize annotations to JSON while wrapping unserializeable ones with [[UnserializeableAnnotation]]
+ *
+ * @note this is slower than standard serialization
+ */
+ def serializeRecover(annos: Seq[Annotation]): String = {
+ val tags = classOf[UnserializeableAnnotation] +: getTags(annos)
+ implicit val formats = jsonFormat(tags)
+
+ val safeAnnos = annos.map { anno =>
+ Try(write(anno)) match {
+ case Success(_) => anno
+ case Failure(e) => UnserializeableAnnotation(e.getMessage, anno.toString)
+ }
+ }
+ writePretty(safeAnnos)
+ }
+
def deserialize(in: JsonInput): Seq[Annotation] = deserializeTry(in).get
def deserializeTry(in: JsonInput): Try[Seq[Annotation]] = Try({