Base64: proper support for large Bytes, with subtle change of types (Bytes instead of String);
--- a/src/Pure/Build/build_manager.scala Sun Jun 16 18:18:55 2024 +0200
+++ b/src/Pure/Build/build_manager.scala Sun Jun 16 18:41:57 2024 +0200
@@ -1174,7 +1174,7 @@
val head =
List(
HTML.title("Isabelle Build Manager"),
- Web_App.More_HTML.icon("data:image/x-icon;base64," + logo.encode_base64),
+ Web_App.More_HTML.icon("data:image/x-icon;base64," + logo.encode_base64.text),
HTML.style_file("https://hawkz.github.io/gdcss/gd.css"),
HTML.style("html { background-color: white; }"))
}
--- a/src/Pure/General/base64.scala Sun Jun 16 18:18:55 2024 +0200
+++ b/src/Pure/General/base64.scala Sun Jun 16 18:41:57 2024 +0200
@@ -1,26 +1,34 @@
/* Title: Pure/General/base64.scala
Author: Makarius
-Support for Base64 data encoding.
+Support for Base64 data representation.
*/
package isabelle
+import java.io.{InputStream, OutputStream}
+
+
object Base64 {
+ /* main operations */
+
def encode(a: Array[Byte]): String = java.util.Base64.getEncoder.encodeToString(a)
def decode(s: String): Array[Byte] = java.util.Base64.getDecoder.decode(s)
+ def encode_stream(s: OutputStream): OutputStream = java.util.Base64.getEncoder.wrap(s)
+ def decode_stream(s: InputStream): InputStream = java.util.Base64.getDecoder.wrap(s)
+
/* Scala functions in ML */
object Decode extends Scala.Fun_Bytes("Base64.decode") {
val here = Scala_Project.here
- def apply(arg: Bytes): Bytes = Bytes.decode_base64(arg.text)
+ def apply(bytes: Bytes): Bytes = bytes.decode_base64
}
object Encode extends Scala.Fun_Bytes("Base64.encode") {
val here = Scala_Project.here
- def apply(arg: Bytes): Bytes = Bytes(arg.encode_base64)
+ def apply(bytes: Bytes): Bytes = bytes.encode_base64
}
}
--- a/src/Pure/General/bytes.scala Sun Jun 16 18:18:55 2024 +0200
+++ b/src/Pure/General/bytes.scala Sun Jun 16 18:41:57 2024 +0200
@@ -55,8 +55,6 @@
val newline: Bytes = apply("\n")
- def decode_base64(s: String): Bytes = Bytes.reuse_array(Base64.decode(s))
-
/* read */
@@ -441,12 +439,22 @@
}
catch { case ERROR(_) => None }
- def encode_base64: String = Base64.encode(make_array)
+
+ /* Base64 data representation */
+
+ def encode_base64: Bytes = {
+ val out = new Bytes.Builder.Stream(hint = (size * 1.5).round)
+ using(Base64.encode_stream(out))(write_stream(_))
+ out.builder.done()
+ }
+
+ def decode_base64: Bytes =
+ using(Base64.decode_stream(stream()))(Bytes.read_stream(_, hint = (size / 1.2).round))
def maybe_encode_base64: (Boolean, String) =
wellformed_text match {
case Some(s) => (false, s)
- case None => (true, encode_base64)
+ case None => (true, encode_base64.text)
}