         [ 4drop ] dip
     ] if ; inline recursive
 
-M: input-port stream-read-until ( seps port -- str/f sep/f )
+PRIVATE>
+
+M: input-port stream-read-until ( seps port -- byte-array/f sep/f )
     2dup read-until-step dup [ [ 2drop ] 2dip ] [
         over [
             drop

    } cond
    { fixnum c-ptr } declare ; inline

: prepare-read ( count stream -- count stream )
    dup check-disposed [ 0 max >fixnum ] dip ; inline

M: input-port stream-read-partial-unsafe ( n dst port -- count )
    [ swap ] dip prepare-read read-step
    [ swap [ memcpy ] keep ] [ 2drop 0 ] if* ;

:: read-loop ( n-remaining n-read port dst -- n-total )
    n-remaining 0 > [
        n-remaining port read-step :> ( n-buffered ptr )
        ptr [
            dst ptr n-buffered memcpy
            n-remaining n-buffered - :> n-remaining'
            n-read n-buffered + :> n-read'
            n-buffered dst <displaced-alien> :> dst'
            n-remaining' n-read' port dst' read-loop
        ] [ n-read ] if
    ] [ n-read ] if ; inline recursive

M:: input-port stream-read-unsafe ( n dst port -- count )
    n port prepare-read :> ( n' port' )
    n' port' read-step :> ( n-buffered ptr )
    ptr [
        dst ptr n-buffered memcpy
        n-buffered n' < [
            n-buffered dst <displaced-alien> :> dst'
            n' n-buffered - n-buffered port dst' read-loop
        ] [
            n-buffered
        ] if
    ] [ 0 ] if ;

: read-until-step ( separators port -- string/f separator/f )
    dup wait-to-read [ 2drop f f ] [
        buffer>> buffer-read-until
    ] if ; inline

: read-until-loop ( seps port accum -- separator/f )
    2over read-until-step over [
        [ append! ] dip dup [
            [ 3drop ] dip

    dup check-disposed
    dup wait-to-read [ drop f ] [ buffer>> buffer-pop ] if ; inline

<PRIVATE

: read-step ( count port -- count ptr/f )
    {
        { [ over 0 = ] [ 2drop 0 f ] }
