From 0ceee5ed4bae240b8c8e94d2fd7424d9d0b67ec7 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Wed, 9 Oct 2019 17:10:43 -0400 Subject: Migrate build to mill --- common/js/src/main/scala/JsTemplates.scala | 3 - common/js/src/main/scala/http/XhrBackend.scala | 51 ----- common/js/src/main/scala/http/package.scala | 3 - common/native/src/main/scala/http/ArrayUtils.scala | 28 --- .../native/src/main/scala/http/CurlBackend.scala | 215 --------------------- common/native/src/main/scala/http/curl.scala | 82 -------- common/native/src/main/scala/http/package.scala | 3 - common/shared/src/main/scala/ApiProtocol.scala | 12 -- common/shared/src/main/scala/Message.scala | 42 ---- common/shared/src/main/scala/Templates.scala | 54 ------ common/shared/src/main/scala/TextTemplates.scala | 64 ------ common/shared/src/main/scala/http/Backend.scala | 8 - common/shared/src/main/scala/http/Request.scala | 9 - common/shared/src/main/scala/http/Response.scala | 6 - 14 files changed, 580 deletions(-) delete mode 100644 common/js/src/main/scala/JsTemplates.scala delete mode 100644 common/js/src/main/scala/http/XhrBackend.scala delete mode 100644 common/js/src/main/scala/http/package.scala delete mode 100644 common/native/src/main/scala/http/ArrayUtils.scala delete mode 100644 common/native/src/main/scala/http/CurlBackend.scala delete mode 100644 common/native/src/main/scala/http/curl.scala delete mode 100644 common/native/src/main/scala/http/package.scala delete mode 100644 common/shared/src/main/scala/ApiProtocol.scala delete mode 100644 common/shared/src/main/scala/Message.scala delete mode 100644 common/shared/src/main/scala/Templates.scala delete mode 100644 common/shared/src/main/scala/TextTemplates.scala delete mode 100644 common/shared/src/main/scala/http/Backend.scala delete mode 100644 common/shared/src/main/scala/http/Request.scala delete mode 100644 common/shared/src/main/scala/http/Response.scala (limited to 'common') diff --git a/common/js/src/main/scala/JsTemplates.scala b/common/js/src/main/scala/JsTemplates.scala deleted file mode 100644 index bbb29c5..0000000 --- a/common/js/src/main/scala/JsTemplates.scala +++ /dev/null @@ -1,3 +0,0 @@ -package triad - -object JsTemplates extends Templates(scalatags.JsDom) diff --git a/common/js/src/main/scala/http/XhrBackend.scala b/common/js/src/main/scala/http/XhrBackend.scala deleted file mode 100644 index 3a791c1..0000000 --- a/common/js/src/main/scala/http/XhrBackend.scala +++ /dev/null @@ -1,51 +0,0 @@ -package triad -package http - -import org.scalajs.dom.{ErrorEvent, Event, XMLHttpRequest} - -import scala.concurrent.{Future, Promise, TimeoutException} -import scala.scalajs.js -import scala.scalajs.js.typedarray.{ArrayBuffer, Int8Array} - -trait XhrBackend extends Backend { - - def send(request: Request): Future[Response] = { - val promise = Promise[Response] - val xhr = new XMLHttpRequest() - - xhr.open(request.method, request.url) - xhr.responseType = "arraybuffer" - for ((name, value) <- request.headers) { - xhr.setRequestHeader(name, value) - } - - xhr.send(js.Array(request.body: _*)) - - xhr.onload = (e: Event) => { - val body: Array[Byte] = if (!js.isUndefined(xhr.response)) { - val buffer = new Int8Array(xhr.response.asInstanceOf[ArrayBuffer]) - buffer.toArray - } else { - Array.empty[Byte] - } - - val response = Response( - xhr.status, - Map.empty, - body - ) - promise.success(response) - } - - xhr.onerror = (e: ErrorEvent) => { - promise.failure(new RuntimeException(s"XHR error: ${e.message}")) - } - xhr.ontimeout = (e: Event) => { - promise.failure( - new TimeoutException(s"Request timed out: ${xhr.statusText}")) - } - - promise.future - } - -} diff --git a/common/js/src/main/scala/http/package.scala b/common/js/src/main/scala/http/package.scala deleted file mode 100644 index 7b680eb..0000000 --- a/common/js/src/main/scala/http/package.scala +++ /dev/null @@ -1,3 +0,0 @@ -package triad - -package object http extends XhrBackend diff --git a/common/native/src/main/scala/http/ArrayUtils.scala b/common/native/src/main/scala/http/ArrayUtils.scala deleted file mode 100644 index 00c1067..0000000 --- a/common/native/src/main/scala/http/ArrayUtils.scala +++ /dev/null @@ -1,28 +0,0 @@ -package triad -package http - -import scala.scalanative.native._ - -object ArrayUtils { - - def toBuffer(array: Array[Byte])(implicit z: Zone): Ptr[Byte] = { - val buffer = z.alloc(array.size) - var i = 0 - while (i < array.size) { - buffer(i) = array(i) - i += 1 - } - buffer - } - - def toArray(buffer: Ptr[Byte], size: CSize): Array[Byte] = { - val array = new Array[Byte](size.toInt) - var i = 0 - while (i < array.size) { - array(i) = buffer(i) - i += 1 - } - array - } - -} diff --git a/common/native/src/main/scala/http/CurlBackend.scala b/common/native/src/main/scala/http/CurlBackend.scala deleted file mode 100644 index 4dc8577..0000000 --- a/common/native/src/main/scala/http/CurlBackend.scala +++ /dev/null @@ -1,215 +0,0 @@ -package triad -package http - -import curl._ -import curlh._ - -import scala.collection.{Map, mutable} -import scala.collection.mutable.ArrayBuffer -import scala.concurrent.Future -import scala.scalanative.native._ -import scala.util.{Failure, Success, Try} - -object CurlBackend { - - type Chunk = CStruct4[Ptr[CStruct0], Ptr[CStruct0], CSize, Ptr[Byte]] - implicit class ChunksOps(val self: Ptr[Chunk]) extends AnyVal { - @inline def prev: Ptr[Chunk] = (!self._1).cast[Ptr[Chunk]] - @inline def prev_=(other: Ptr[Chunk]): Unit = - !(self._1) = other.cast[Ptr[CStruct0]] - @inline def next: Ptr[Chunk] = (!self._2).cast[Ptr[Chunk]] - @inline def next_=(other: Ptr[Chunk]): Unit = - !(self._2) = other.cast[Ptr[CStruct0]] - @inline def size: CSize = !(self._3) - @inline def size_=(value: CSize): Unit = !(self._3) = value - @inline def buffer: Ptr[Byte] = !(self._4) - @inline def buffer_=(value: Ptr[Byte]): Unit = !(self._4) = value - } - - object Chunk { - - @inline def NullPtr[T] = 0.cast[Ptr[T]] - - def allocHead() = allocAppend(0, NullPtr[Chunk]) - - def allocAppend(size: CSize, - head: Ptr[Chunk] = NullPtr[Chunk]): Ptr[Chunk] = { - val chunk: Ptr[Chunk] = stdlib.malloc(sizeof[Chunk]).cast[Ptr[Chunk]] - if (chunk == NullPtr[Chunk]) return NullPtr[Chunk] - - chunk.buffer = stdlib.malloc(size) - - if (chunk.buffer == NullPtr[Chunk] && size != 0) { - stdlib.free(chunk.cast[Ptr[Byte]]) - return NullPtr[Chunk] - } - chunk.size = size - - if (head == NullPtr[Chunk]) { // this will be the head - chunk.next = chunk - chunk.prev = chunk - } else { - val last = head.prev - last.next = chunk - chunk.prev = last - head.prev = chunk - chunk.next = head - } - chunk - } - - def freeAll(head: Ptr[Chunk]): Unit = { - var chunk: Ptr[Chunk] = head - do { - val next = chunk.next - stdlib.free(chunk.buffer) - stdlib.free(chunk.cast[Ptr[Byte]]) - chunk = next - } while (chunk != head) - } - - def toArray(head: Ptr[Chunk]): Array[Byte] = { - val buffer = new ArrayBuffer[Byte]() - var chunk = head - do { - val next = chunk.next - var i = 0l - while (i < next.size) { - buffer += next.buffer(i) - i += 1 - } - chunk = next - } while (chunk != head) - buffer.toArray - } - - def traverse(head: Ptr[Chunk])(fct: Array[Byte] => Unit) = { - var chunk = head - do { - val next = chunk.next - val buffer = new ArrayBuffer[Byte]() - var i = 0l - while (i < next.size) { - buffer += next.buffer(i) - i += 1 - } - chunk = next - fct(buffer.toArray) - } while (chunk != head) - } - - } - - private def receive(data: Ptr[Byte], - size: CSize, - nmemb: CSize, - userdata: Ptr[Byte]): CSize = { - val head = userdata.cast[Ptr[Chunk]] - val length = size * nmemb - val chunk = Chunk.allocAppend(length, head) - string.memcpy(chunk.buffer, data, chunk.size) - chunk.size - } - private val receivePtr: WriteFunction = CFunctionPtr.fromFunction4(receive) - - private def chain[A](success: A)(calls: (() => A)*) = { - var result: A = success - for (c <- calls if result == success) { - result = c() - } - result - } - - private def request(request: Request)(implicit z: Zone): Try[Response] = { - val curl: CURL = curl_easy_init() - if (curl != null) { - val errorBuffer = stackalloc[Byte](CURL_ERROR_SIZE) - !errorBuffer = 0 - val requestHeaders = stackalloc[curl_slist](1) - !requestHeaders = 0.cast[curl_slist] - - val responseChunks = Chunk.allocHead() - val responseHeaderChunks = Chunk.allocHead() - - val curlResult = chain(CURLcode.CURL_OK)( - () => - curl_easy_setopt(curl, CURLoption.CURLOPT_ERRORBUFFER, errorBuffer), - () => - curl_easy_setopt(curl, - CURLoption.CURLOPT_CUSTOMREQUEST, - toCString(request.method)), - () => - curl_easy_setopt(curl, - CURLoption.CURLOPT_URL, - toCString(request.url)), - () => { - val buffer = ArrayUtils.toBuffer(request.body) - curl_easy_setopt(curl, CURLoption.CURLOPT_POSTFIELDS, buffer) - curl_easy_setopt(curl, - CURLoption.CURLOPT_POSTFIELDSIZE, - request.body.size) - }, - () => { - for ((k, v) <- request.headers) { - !requestHeaders = - curl_slist_append(!requestHeaders, toCString(s"$k:$v")) - } - curl_easy_setopt(curl, CURLoption.CURLOPT_HTTPHEADER, !requestHeaders) - }, - () => - curl_easy_setopt(curl, CURLoption.CURLOPT_WRITEFUNCTION, receivePtr), - () => - curl_easy_setopt(curl, CURLoption.CURLOPT_WRITEDATA, responseChunks), - () => - curl_easy_setopt(curl, - CURLoption.CURLOPT_HEADERDATA, - responseHeaderChunks), - () => curl_easy_perform(curl) - ) - - val result = curlResult match { - case CURLcode.CURL_OK => - val responseCode: Ptr[Long] = stackalloc[Long](1) - curl_easy_getinfo(curl, CURLINFO.CURLINFO_RESPONSE_CODE, responseCode) - - val responseHeaders = mutable.HashMap.empty[String, String] - Chunk.traverse(responseHeaderChunks) { headerChunk => - val line = new String(headerChunk, "utf-8").trim - if (line.contains(":")) { - val parts = line.split(":", 2) - responseHeaders += parts(0) -> parts(1) - } - } - - Success( - Response( - statusCode = (!responseCode).toInt, - headers = responseHeaders.toMap, - body = Chunk.toArray(responseChunks) - )) - - case code => - val message = curl_easy_strerror(curl, code) - Failure( - new RuntimeException( - s"${fromCString(errorBuffer)} (curl exit status $code)")) - } - Chunk.freeAll(responseChunks) - Chunk.freeAll(responseHeaderChunks) - curl_slist_free_all(!requestHeaders) - curl_easy_cleanup(curl) - result - } else { - Failure(new RuntimeException(s"curl failed to initialize")) - } - } - - def curlVersion = fromCString(curl_version()) - -} - -trait CurlBackend extends Backend { - def send(req: Request): Future[Response] = Zone { implicit z => - Future.fromTry(CurlBackend.request(req)) - } -} diff --git a/common/native/src/main/scala/http/curl.scala b/common/native/src/main/scala/http/curl.scala deleted file mode 100644 index 1eda584..0000000 --- a/common/native/src/main/scala/http/curl.scala +++ /dev/null @@ -1,82 +0,0 @@ -package triad -package http - -import scala.scalanative.native._ - -object curlh { - final val CURL_ERROR_SIZE = 256 - - type CURL = Ptr[CStruct0] - - /* - * #define CURLOPTTYPE_LONG 0 - * #define CURLOPTTYPE_OBJECTPOINT 10000 - * #define CURLOPTTYPE_STRINGPOINT 10000 - * #define CURLOPTTYPE_FUNCTIONPOINT 20000 - * #define CURLOPTTYPE_OFF_T 30000 - */ - - type CURLcode = CInt - object CURLcode { - final val CURL_OK: CInt = 0 - } - - type CURLoption = CInt - object CURLoption { - final val CURLOPT_VERBOSE: CInt = 41 - final val CURLOPT_POSTFIELDSIZE: CInt = 60 - final val CURLOPT_WRITEDATA: CInt = 10001 - final val CURLOPT_URL: CInt = 10002 - final val CURLOPT_ERRORBUFFER: CInt = 10010 - final val CURLOPT_POSTFIELDS: CInt = 10015 - final val CURLOPT_HTTPHEADER: CInt = 10023 - final val CURLOPT_HEADERDATA: CInt = 10029 - final val CURLOPT_CUSTOMREQUEST: CInt = 10036 - final val CURLOPT_WRITEFUNCTION: CInt = 20011 - } - - type CURLINFO = CInt - object CURLINFO { - final val CURLINFO_RESPONSE_CODE = 0x200002 - } - - type WriteFunction = CFunctionPtr4[ - Ptr[Byte], // data - CSize, // size - CSize, // nmemb - Ptr[Byte], // userdata - CSize // return - ] - - type curl_slist = Ptr[CStruct0] - -} - -@link("curl") -@extern -object curl { - import curlh._ - - def curl_easy_init(): CURL = extern - - def curl_easy_setopt(curl: CURL, - option: CURLoption, - parameter: CVararg*): CURLcode = extern - - def curl_easy_perform(curl: CURL): CURLcode = extern - - def curl_easy_getinfo(curl: CURL, - option: CURLINFO, - parameter: CVararg*): CURLcode = extern - - def curl_easy_cleanup(curl: CURL): Unit = extern - - def curl_easy_strerror(curl: CURL, code: CURLcode): CString = extern - - def curl_slist_append(head: curl_slist, string: CString): curl_slist = extern - - def curl_slist_free_all(head: curl_slist): Unit = extern - - def curl_version(): CString = extern - -} diff --git a/common/native/src/main/scala/http/package.scala b/common/native/src/main/scala/http/package.scala deleted file mode 100644 index 63b5405..0000000 --- a/common/native/src/main/scala/http/package.scala +++ /dev/null @@ -1,3 +0,0 @@ -package triad - -package object http extends CurlBackend diff --git a/common/shared/src/main/scala/ApiProtocol.scala b/common/shared/src/main/scala/ApiProtocol.scala deleted file mode 100644 index 5d0e00a..0000000 --- a/common/shared/src/main/scala/ApiProtocol.scala +++ /dev/null @@ -1,12 +0,0 @@ -package triad - -import java.time.Instant -import spray.json.{DerivedJsonProtocol, JsNumber, JsValue, JsonFormat} - -object ApiProtocol extends DerivedJsonProtocol { - implicit val timestampFormat: JsonFormat[Instant] = new JsonFormat[Instant] { - def read(js: JsValue) = Instant.ofEpochMilli(js.convertTo[Long]) - def write(i: Instant) = JsNumber(i.toEpochMilli) - } - implicit val messageFormat = jsonFormat[Message] -} diff --git a/common/shared/src/main/scala/Message.scala b/common/shared/src/main/scala/Message.scala deleted file mode 100644 index 84c733e..0000000 --- a/common/shared/src/main/scala/Message.scala +++ /dev/null @@ -1,42 +0,0 @@ -package triad - -import java.security.MessageDigest -import java.time.Instant - -case class Message(content: String, - author: String, - timestamp: Instant = Instant.now()) { - - lazy val id: String = { - val digest = MessageDigest.getInstance("SHA-256") - digest.update(content.getBytes) - digest.update(author.getBytes) - digest.update((timestamp.getEpochSecond & 0xff).toByte) - digest.update(((timestamp.getEpochSecond >> 8) & 0xff).toByte) - digest.update(((timestamp.getEpochSecond >> 16) & 0xff).toByte) - digest.update(((timestamp.getEpochSecond >> 24) & 0xff).toByte) - digest.update(((timestamp.getEpochSecond >> 32) & 0xff).toByte) - digest.update(((timestamp.getEpochSecond >> 40) & 0xff).toByte) - digest.update(((timestamp.getEpochSecond >> 48) & 0xff).toByte) - digest.update(((timestamp.getEpochSecond >> 56) & 0xff).toByte) - Message.bytesToHex(digest.digest()) - } - - def hashTags: Seq[String] = - content.split("\\s").filter(_.startsWith("#")).map(_.drop(1)) - -} - -object Message { - private def bytesToHex(hash: Array[Byte]): String = { - val hexString = new StringBuffer(hash.length * 2) - var i = 0 - while (i < hash.length) { - val hex = Integer.toHexString(0xff & hash(i)) - if (hex.length == 1) hexString.append('0') - hexString.append(hex) - i += 1 - } - hexString.toString - } -} diff --git a/common/shared/src/main/scala/Templates.scala b/common/shared/src/main/scala/Templates.scala deleted file mode 100644 index 10ee116..0000000 --- a/common/shared/src/main/scala/Templates.scala +++ /dev/null @@ -1,54 +0,0 @@ -package triad - -class Templates[Builder, Output <: FragT, FragT]( - val bundle: scalatags.generic.Bundle[Builder, Output, FragT]) { - import bundle.all._ - - val colorStyles = List( - "bg-primary", - "bg-secondary", - "bg-success", - "bg-danger", - "bg-warning", - "bg-info", - "bg-dark" - ) - // pick a "random" style by computing a hash of arbitrary data - def dataStyle(data: String) = { - val dataHash = data.foldLeft(7) { - case (hash, char) => - (hash * 31 + char.toInt) - } - colorStyles( - ((dataHash % colorStyles.length) + colorStyles.length) % colorStyles.length) - } - - def message(msg: Message) = { - val tags = msg.hashTags.map( - hashTag => - span(`class` := "badge badge-light float-right ml-1")( - hashTag - )) - div(`class` := "col-xs-12 col-sm-6 col-md-3 col-lg-2")( - div(`class` := s"card text-white mb-3 ${dataStyle(msg.author)}")( - div(`class` := "card-header")( - msg.author, - tags - ), - div(`class` := "card-body")( - div(`class` := "card-text")( - msg.content - ) - ) - ) - ) - } - - def conversation(messages: Seq[Message]): Tag = - div(`class` := "container-fluid")( - div(id := "conversation", `class` := "row")( - for (msg <- messages.sortBy(_.timestamp)) yield message(msg) - ) - ) - -} diff --git a/common/shared/src/main/scala/TextTemplates.scala b/common/shared/src/main/scala/TextTemplates.scala deleted file mode 100644 index e7e364a..0000000 --- a/common/shared/src/main/scala/TextTemplates.scala +++ /dev/null @@ -1,64 +0,0 @@ -package triad - -object TextTemplates extends Templates(scalatags.Text) { - import bundle.all._ - - def scripts(js: Boolean = true) = - if (js) - Seq( - div(id := "scalajs-error", style := "display: none;")( - "ScalaJS raised an exception. See the log for more information." - ), - script(`type` := "text/javascript", - src := "/assets/ui/js/ui-fastopt.js"), - script(`type` := "text/javascript")( - raw( - """|document.addEventListener("DOMContentLoaded", function(event) { - | try { - | // root element that will contain the ScalaJS application - | var root = document.getElementById("conversation"); - | - | // clear any existing content - | while (root.firstChild) { - | root.removeChild(root.firstChild); - | } - | - | // run ScalaJS application - | console.info("Starting ScalaJS application...") - | triad.Main().main(root) - | } catch(ex) { - | // display warning message in case of exception - | document.getElementById("scalajs-error").style.display = "block"; - | throw ex; - | } - |}); - |""".stripMargin - ) - ) - ) - else Seq.empty - - def page(messages: Seq[Message], js: Boolean = true) = html( - head( - link(rel := "stylesheet", - `type` := "text/css", - href := "/assets/lib/bootstrap-4.1.0/css/bootstrap-reboot.min.css"), - link(rel := "stylesheet", - `type` := "text/css", - href := "/assets/lib/bootstrap-4.1.0/css/bootstrap-grid.min.css"), - link(rel := "stylesheet", - `type` := "text/css", - href := "/assets/lib/bootstrap-4.1.0/css/bootstrap.min.css"), - link(rel := "stylesheet", - `type` := "text/css", - href := "/assets/main.css"), - meta(name := "viewport", - content := "width=device-width, initial-scale=1, shrink-to-fit=no") - ), - body( - conversation(messages), - scripts(js) - ) - ) - -} diff --git a/common/shared/src/main/scala/http/Backend.scala b/common/shared/src/main/scala/http/Backend.scala deleted file mode 100644 index f3ce5f8..0000000 --- a/common/shared/src/main/scala/http/Backend.scala +++ /dev/null @@ -1,8 +0,0 @@ -package triad -package http - -import scala.concurrent.Future - -trait Backend { - def send(request: Request): Future[Response] -} diff --git a/common/shared/src/main/scala/http/Request.scala b/common/shared/src/main/scala/http/Request.scala deleted file mode 100644 index ec7d28d..0000000 --- a/common/shared/src/main/scala/http/Request.scala +++ /dev/null @@ -1,9 +0,0 @@ -package triad -package http - -case class Request( - method: String, - url: String, - headers: Map[String, String] = Map.empty, - body: Array[Byte] = Array.empty -) diff --git a/common/shared/src/main/scala/http/Response.scala b/common/shared/src/main/scala/http/Response.scala deleted file mode 100644 index 4ba2342..0000000 --- a/common/shared/src/main/scala/http/Response.scala +++ /dev/null @@ -1,6 +0,0 @@ -package triad -package http - -case class Response(statusCode: Int, - headers: Map[String, String], - body: Array[Byte]) -- cgit v1.2.3