This repository has been archived by the owner on Nov 29, 2021. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove hand-written ScalaSodium boilerplate!
Replace with a combo sun.tools + scalameta + scalafmt Frankenstein monster of a scala script ran from within SBT. Simply type > gensodium whenever the `sodium.i` file is changed, and `ScalaSodium0.scala` will be updated as necessary. Also tweak the setup scripts to work mo' bettah on OS X, for brainwashed mac users like myself.
- Loading branch information
Showing
10 changed files
with
1,934 additions
and
1,175 deletions.
There are no files selected for viewing
This file contains 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 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 |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package tsec.build | ||
|
||
object GenSodiumPlugin extends sbt.AutoPlugin { | ||
import sbt._ | ||
|
||
override def requires = empty | ||
override def trigger = allRequirements | ||
|
||
object autoImport { | ||
lazy val gensodium = taskKey[Unit]("Generate ScalaSodium0.scala") | ||
} | ||
import autoImport._ | ||
|
||
override def buildSettings = Seq( | ||
/* See plugins.sbt for why this is dynamically loaded */ | ||
gensodium := { | ||
getClass.getClassLoader | ||
.loadClass("tsec.build.GenSodium") | ||
.getMethod("main", classOf[Array[String]]) | ||
.invoke(null, Array.empty[String]) | ||
} | ||
) | ||
|
||
} |
This file contains 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 |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package tsec.build | ||
|
||
import scala.collection.JavaConverters._ | ||
|
||
object GenSodium extends App { | ||
|
||
val FormatConfig = { | ||
import org.scalafmt.config._ | ||
ScalafmtConfig.intellij.copy( | ||
align = Align.none, | ||
newlines = ScalafmtConfig.intellij.newlines.copy( | ||
alwaysBeforeTopLevelStatements = true, | ||
) | ||
) | ||
} | ||
|
||
import com.sun.source.{tree => jtree} | ||
import javax.lang.model.`type`.TypeKind | ||
import java.nio.charset._ | ||
|
||
val jMethods: Seq[jtree.MethodTree] = { | ||
import com.sun.tools.javac._ | ||
import tree.{JCTree => tree} | ||
import scala.io._ | ||
|
||
val source = Source | ||
.fromFile("tsec-libsodium/jni/Sodium.java") // looking here b/c param names not in SodiumJNI | ||
.mkString | ||
val ctx = new util.Context() | ||
new file.JavacFileManager(ctx, true, StandardCharsets.UTF_8) | ||
util.Options.instance(ctx).put(com.sun.tools.javac.main.Option.PARAMETERS, "true") | ||
val parse = parser.ParserFactory | ||
.instance(ctx) | ||
.newParser(source, false, false, false) | ||
val unit = parse.parseCompilationUnit() | ||
val clasz = unit.getTypeDecls.asScala.collectFirst { | ||
case decl: tree.JCClassDecl if decl.name.toString == "Sodium" => decl | ||
}.getOrElse(sys.error("could not find Sodium class")) | ||
|
||
clasz.defs.asScala.collect { | ||
case decl: tree.JCMethodDecl => decl | ||
} | ||
} | ||
|
||
import scala.meta._ | ||
|
||
def transType(jt: jtree.Tree): Type = jt match { | ||
case prim: jtree.PrimitiveTypeTree => prim.getPrimitiveTypeKind match { | ||
case TypeKind.BOOLEAN => t"Boolean" | ||
case TypeKind.BYTE => t"Byte" | ||
case TypeKind.SHORT => t"Short" | ||
case TypeKind.INT => t"Int" | ||
case TypeKind.LONG => t"Long" | ||
case TypeKind.CHAR => t"Char" | ||
case TypeKind.FLOAT => t"Float" | ||
case TypeKind.DOUBLE => t"Double" | ||
case TypeKind.VOID => t"Unit" | ||
case other => sys.error(s"Unsupported primitive type kind $other") | ||
} | ||
case arr: jtree.ArrayTypeTree => t"Array[${transType(arr.getType)}]" | ||
} | ||
|
||
val sMethods = jMethods.map { jm => | ||
val params: List[Term.Param] = jm.getParameters.asScala.map { jp => | ||
val name = Term.Name(jp.getName.toString) | ||
val tpe = transType(jp.getType) | ||
Term.Param(mods = Nil, name = name, decltpe = Some(tpe), default = None) | ||
}.toList | ||
val name = Term.Name(jm.getName.toString) | ||
val tpe = transType(jm.getReturnType) | ||
val args = params.map { p => Term.Name(p.name.value) } | ||
val rhs = q"SodiumJNI.$name(..$args)" | ||
Defn.Def( | ||
mods = Mod.Final() :: Nil, | ||
name = name, | ||
tparams = Nil, | ||
paramss = List(params), | ||
decltpe = Some(tpe), | ||
body = rhs | ||
) | ||
}.sortBy(_.name.value).toList | ||
|
||
val noSelfType = Term.Param(Nil, Name.Anonymous(), None, None) | ||
|
||
val clsDef = Defn.Class( | ||
mods = Mod.Abstract() :: Mod.Protected(within = Term.Name("tsec")):: Nil, | ||
name = Type.Name("ScalaSodium0"), | ||
tparams = Nil, | ||
ctor = Ctor.Primary(Mod.Private(within = Term.Name("tsec")) :: Nil, name = Ctor.Name("ScalaSodium0"), paramss = Nil), | ||
templ = Template(early = Nil, parents = Nil, self = noSelfType, Some(sMethods)) | ||
) | ||
|
||
val warning = | ||
s"""/* !!! GENERATED CODE: DO NOT EDIT !!! */ | ||
|/* This file is generated by project/boiler/gensodium.scala from tsec-libsodium/jni/sodium.i */ | ||
|/* Timestamp: ${java.time.Instant.now.toString} */ | ||
| | ||
""".stripMargin | ||
|
||
val pkg = Pkg(q"tsec.jni", clsDef :: Nil) | ||
|
||
val src = org.scalafmt.Scalafmt.format(warning + pkg.toString, style = FormatConfig).get | ||
|
||
import java.io._ | ||
|
||
new FileOutputStream(new File("tsec-libsodium/src/main/scala/tsec/jni/ScalaSodium0.scala")) | ||
.write(src.getBytes(StandardCharsets.UTF_8)) | ||
} |
This file contains 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 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 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 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.