diff options
| author | David Biancolin | 2019-10-24 10:44:04 -0700 |
|---|---|---|
| committer | David Biancolin | 2019-10-24 10:44:04 -0700 |
| commit | f6db9d4bd6156bb8af7dfdbcced20cd6a098920f (patch) | |
| tree | 635da09f6f8cd74c84f34264b7a23762ccde798a /src | |
| parent | f5e6e2bc201c6206a705244d8977bda4b83e6efd (diff) | |
Supply a trait to allow user annotations to provide SERDES type hints
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/firrtl/annotations/JsonProtocol.scala | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/src/main/scala/firrtl/annotations/JsonProtocol.scala b/src/main/scala/firrtl/annotations/JsonProtocol.scala index b09155d8..9fe575c7 100644 --- a/src/main/scala/firrtl/annotations/JsonProtocol.scala +++ b/src/main/scala/firrtl/annotations/JsonProtocol.scala @@ -9,6 +9,20 @@ import org.json4s.native.JsonMethods._ import org.json4s.native.Serialization import org.json4s.native.Serialization.{read, writePretty} +trait HasSerializationHints { + // For serialization of complicated constuctor arguments, let the annotation + // writer specify additional type hints for relevant classes that might be + // contained within + def typeHints(): Seq[Class[_]] +} + +/** + * An annotation carrying fully qualified class names for which we'd like the + * deserialization protocol to generate type hints for. + * + * @param typeTags the the additional class names + */ +case class DeserializationTypeHintsAnnotation(typeTags: Seq[String]) extends NoTargetAnnotation object JsonProtocol { class TransformClassSerializer extends CustomSerializer[Class[_ <: Transform]](format => ( @@ -74,7 +88,7 @@ object JsonProtocol { )) /** Construct Json formatter for annotations */ - def jsonFormat(tags: Seq[Class[_ <: Annotation]]) = { + def jsonFormat(tags: Seq[Class[_]]) = { Serialization.formats(FullTypeHints(tags.toList)).withTypeHintFieldName("class") + new TransformClassSerializer + new NamedSerializer + new CircuitNameSerializer + new ModuleNameSerializer + new ComponentNameSerializer + new TargetSerializer + @@ -87,9 +101,13 @@ object JsonProtocol { def serialize(annos: Seq[Annotation]): String = serializeTry(annos).get def serializeTry(annos: Seq[Annotation]): Try[String] = { - val tags = annos.map(_.getClass).distinct - implicit val formats = jsonFormat(tags) - Try(writePretty(annos)) + val tags = annos.flatMap({ + case anno: HasSerializationHints => anno.getClass +: anno.typeHints + case other => Seq(other.getClass) + }).distinct + + implicit val formats = jsonFormat(classOf[DeserializationTypeHintsAnnotation] +: tags) + Try(writePretty(DeserializationTypeHintsAnnotation(tags.map(_.getName)) +: annos)) } def deserialize(in: JsonInput): Seq[Annotation] = deserializeTry(in).get @@ -102,8 +120,11 @@ object JsonProtocol { s"Annotations must be serialized as a JArray, got ${x.getClass.getSimpleName} instead!") } // Gather classes so we can deserialize arbitrary Annotations - val classes = annos.map({ - case JObject(("class", JString(c)) :: tail) => c + val typeHintAnnoName = classOf[DeserializationTypeHintsAnnotation].getName + val classes = annos.flatMap({ + case JObject(("class", JString(name)) :: ("typeTags", JArray(classes)) :: Nil) if name == typeHintAnnoName => + typeHintAnnoName +: classes.collect({ case JString(className) => className }) + case JObject(("class", JString(c)) :: tail) => Seq(c) case obj => throw new InvalidAnnotationJSONException(s"Expected field 'class' not found! $obj") }).distinct val loaded = classes.map(Class.forName(_).asInstanceOf[Class[_ <: Annotation]]) |
