about summary refs log tree commit diff
path: root/third_party/lisp/mime4cl/mime.lisp
diff options
context:
space:
mode:
authorsterni <sternenseemann@systemli.org>2023-05-15T21·36+0200
committerclbot <clbot@tvl.fyi>2023-05-18T16·14+0000
commit3d2e55ad535371d1152a221dc31a8773b3a09ddf (patch)
tree2c036f24436431882536615f3aa8d0176e4604cc /third_party/lisp/mime4cl/mime.lisp
parentb379e44dfb871100546b3d60bd3c77fbeac61adc (diff)
refactor(mime4cl): replace *-input-adapter-stream with flexi-streams r/6152
The input adapter streams were input streams yielding either binary or
character data that could be constructed from a variable data source.
The stream would take care not to destroy the underlying data
source (i.e. not close it if it was a stream), so similar to with
FILE-PORTIONs, but simpler.

Unfortunately, the implementation was quite inefficient: They are
ultimately defined in terms of a function that retrieves the next
character in the source. This only allows for an implementation of
READ-CHAR (and READ-BYTE). Thanks to cl/8559, READ-SEQUENCE can be used
on e.g. FILE-PORTION, but this was still negated by a input adapter
based on one—then, READ-SEQUENCE would need to fall back on READ-CHAR or
READ-BYTE again.

Luckily, we can replace BINARY-INPUT-ADAPTER-STREAM and
CHARACTER-INPUT-ADAPTER-STREAM with a much simpler abstraction: Instead
of extra stream classes, we have a function, MAKE-INPUT-ADAPTER, which
returns an appropriate instance of FLEXI-STREAM based on a given source.
This way, the need for a distinction between binary and character input
adapter is eliminated, since FLEXI-STREAMS supports both binary and
character reads (external format is not yet handled, though).
Consequently, the :binary keyword argument to MIME-BODY-STREAM can be
dropped.

flexi-streams provides stream classes for everything except a stream
that doesn't close the underlying one. Since we have already implemented
this in POSITIONED-FLEXI-INPUT-STREAM, we can split this functionality
into a new superclass ADAPTER-FLEXI-INPUT-STREAM.

This change also allows addressing the performance regression
encountered in cl/8559: It seems that flexi-streams performs worse when
we are reading byte by byte or char by char. (After this change mblog is
still two times slower than on r/6150.) By eliminating the adapter
streams, we can start utilizing READ-SEQUENCE via decoding code that
supports it (i.e. qbase64) and bring performance on par with r/6150
again. Surely there are also ways to gain back even more performance
which has to be determined using profiling. Buffering more aggressively
seems like a sure bet, though.

Switching to flexi-streams still seems like a no-brainer, as it allows
us to drop a lot of code that was quite hacky (e.g. DELIMITED-INPUT-
STREAM) and implements en/decoding handling we did not support before,
but would need for improved correctness.

Change-Id: Ie2d1f4e42b47512a5660a1ccc0deeec2bff9788d
Reviewed-on: https://cl.tvl.fyi/c/depot/+/8581
Autosubmit: sterni <sternenseemann@systemli.org>
Reviewed-by: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
Diffstat (limited to 'third_party/lisp/mime4cl/mime.lisp')
-rw-r--r--third_party/lisp/mime4cl/mime.lisp13
1 files changed, 5 insertions, 8 deletions
diff --git a/third_party/lisp/mime4cl/mime.lisp b/third_party/lisp/mime4cl/mime.lisp
index ac828216cbcc..3e7d83847e14 100644
--- a/third_party/lisp/mime4cl/mime.lisp
+++ b/third_party/lisp/mime4cl/mime.lisp
@@ -183,11 +183,8 @@
                :test #'string=)
        (mime= (mime-body part1) (mime-body part2))))
 
-(defun mime-body-stream (mime-part &key (binary t))
-  (make-instance (if binary
-                     'binary-input-adapter-stream
-                     'character-input-adapter-stream)
-                 :source (mime-body mime-part)))
+(defun mime-body-stream (mime-part)
+  (make-input-adapter (mime-body mime-part)))
 
 (defun mime-body-length (mime-part)
   (be body (mime-body mime-part)
@@ -207,8 +204,8 @@
             while byte
             count byte))))))
 
-(defmacro with-input-from-mime-body-stream ((stream part &key (binary t)) &body forms)
-  `(with-open-stream (,stream (mime-body-stream ,part :binary ,binary))
+(defmacro with-input-from-mime-body-stream ((stream part) &body forms)
+  `(with-open-stream (,stream (mime-body-stream ,part))
      ,@forms))
 
 (defmethod mime= ((part1 mime-bodily-part) (part2 mime-bodily-part))
@@ -799,7 +796,7 @@ returns a MIME-MESSAGE object."
                      (otherwise
                       '8bit-encoder-input-stream))
                    :underlying-stream
-                   (make-instance 'binary-input-adapter-stream :source body))))
+                   (make-input-adapter body))))
 
 (defun choose-boundary (parts &optional default)
   (labels ((match-in-parts (boundary parts)