All Downloads are FREE. Search and download functionalities are using the official Maven repository.

protocbridge.ProtocBridge.scala Maven / Gradle / Ivy

package protocbridge

import java.io.File
import java.nio.file.Path

import protocbridge.frontend.PluginFrontend

import scala.language.implicitConversions

/** Target is a generator call and a path to output the generated files */
case class Target(generator: Generator, outputPath: File, options: Seq[String] = Seq.empty)

object Target {
  import scala.language.implicitConversions
  def builtin(name: String, options: Seq[String] = Seq.empty) = (BuiltinGenerator(name), options)

  def apply(generatorAndOpts: (Generator, Seq[String]), outputPath: File): Target = {
    apply(generatorAndOpts._1, outputPath, generatorAndOpts._2)
  }

  implicit def generatorOptsFileTupleToTarget(s: ((Generator, Seq[String]), File)) =
    Target(s._1, s._2)

  implicit def generatorFileTupleToTarget(s: (Generator, File)) =
    Target(s._1, s._2)

  implicit def protocCodeGeneratorFile(s: (ProtocCodeGenerator, File)) =
    Target(s._1, s._2)

  implicit def protocCodeGeneratorOptsFile(s: ((ProtocCodeGenerator, Seq[String]), File)) =
    Target(ProtocCodeGenerator.toGenerator(s._1._1), s._2, s._1._2)
}

object ProtocBridge {

  /*** Runs protoc with a given set of targets.
    *
    * @param protoc a function that runs protoc with the given command line arguments.
    * @param targets a sequence of generators to invokes
    * @param params a sequence of additional params to pass to protoc
    * @param pluginFrontend frontend to use.
    * @tparam A
    * @return the return value from the protoc function.
    */
  def run[A](protoc: Seq[String] => A,
             targets: Seq[Target],
             params: Seq[String],
             pluginFrontend: PluginFrontend = PluginFrontend.newInstance()): A = {

    val namedGenerators: Seq[(String, ProtocCodeGenerator)] =
      targets.collect {
        case Target(gen: JvmGenerator, _, _) =>
          (gen.name, gen.gen)
      }

    val cmdLine: Seq[String] = targets.map {
      p =>
        s"--${p.generator.name}_out=${p.options.mkString(",")}:${p.outputPath.getAbsolutePath}"
    } ++ params

    runWithGenerators(protoc, namedGenerators, cmdLine, pluginFrontend)
  }

  def runWithGenerators[A](protoc: Seq[String] => A,
                           namedGenerators: Seq[(String, ProtocCodeGenerator)],
                           params: Seq[String],
                           pluginFrontend: PluginFrontend = PluginFrontend.newInstance()): A = {

    val generatorScriptState: Seq[(String, (Path, pluginFrontend.InternalState))] =
      namedGenerators.map {
        case (name, plugin) => (name, pluginFrontend.prepare(plugin))
      }

    val cmdLine: Seq[String] = generatorScriptState.map {
      case (name, (scriptPath, _)) => s"--plugin=protoc-gen-${name}=${scriptPath}"
    } ++ params

    try {
      protoc(cmdLine)
    } finally {
      generatorScriptState.foreach {
        case (_, (_, state)) => pluginFrontend.cleanup(state)
      }
    }
  }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy