>Given that ‘get-bytevector-n!’ already has a variant in
suspendable-ports.scm, my preference would be to rewrite
‘get-bytevector-all’ in Scheme (patch attached).  That way, it would
naturally be suspendable.  (It’s also in line with the general strategy
of moving things to Scheme.)

It currently is difficult to write a correct implementation of 
get-bytevector-all in pure Scheme, because ‘get-bytevector-all’ needs to return 
a _fresh_ bytevector and could return twice (e.g. in case of system-async-mark 
+ call-with-prompt shenanigans). I think the proposed implementation is 
incorrect in this way.

Could be resolved with call-with-blocked-asyncs, but given the title of the 
patch, that’s against the point.

However, given the sequential and stateful nature of ports, I don’t think it’s 
useful to implement support for these ‘return twice’ situations, so I think it 
would be best to simply adjust the documentation to disallow this situation.

Since it is not unique to get-bytevector-all, maybe it could be mentioned in 
https://www.gnu.org/software/guile/manual/html_node/Ports.html that it isn’t 
allowed to put any non-pure operation (where we include allocations as a 
side-effect, e.g. for open-input-bytevector etc, ) related to ports in such a 
situations?

+(define (get-bytevector-all port)
+  (define %initial-length 4096)
+
+  (let read-loop ((total 0)
+                  (result-length %initial-length)
+                  (result (make-bytevector %initial-length)))

I sense a lack of tests for the test suite ...
Also, to avoid avoidable allocations and copying, it would be nice if 
%initial-length could be overridden (optional #:initial-length keyword 
argument), in case the user has a better guess available.

Best regards,
Maxime Devos

Reply via email to