>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