 USING: accessors combinators destructors io io.streams.plain
 kernel math namespaces sbufs sequences sequences.private
 splitting strings ;
+USING: locals ; ! XXX
+
 IN: io.encodings
 
 ! The encoding descriptor protocol

    ] when nip ; inline

M: decoder stream-element-type
    drop +character+ ;

M: decoder stream-tell stream>> stream-tell ;

M: decoder stream-seek stream>> stream-seek ;

M: decoder stream-read1
    dup >decoder< decode-char fix-read1 ;

: fix-read ( stream string -- string )
    over cr>> [
        over cr-
        "\n" ?head [
            over stream-read1 [ suffix ] when*
        ] when
    ] when nip ; inline

! If we read the entire buffer, chars-read is f
! If we hit EOF while reading, chars-read indicates how many chars were read
: (read) ( chars-requested quot -- chars-read/f string )
    over 0 <string> [
        [
            over [ swapd set-nth-unsafe f ] [ 3drop t ] if
        ] curry compose find-integer
    ] keep ; inline

: finish-read ( n/f string -- string/f )
    swap {
        { [ dup zero? ] [ 2drop f ] }
        { [ dup not   ] [ drop ] }
        [ head ]
    } cond ; inline

M: decoder stream-read
    over 0 = [
        2drop f
    ] [
        [ nip ]
        [ >decoder< [ decode-char ] 2curry (read) finish-read ] 2bi
        fix-read
    ] if ;

M: decoder stream-read-partial stream-read ;

: line-ends/eof ( stream str -- str ) f like swap cr- ; inline



CONSTANT: replacement-char HEX: fffd

TUPLE: decoder { stream read-only } { code read-only } { cr boolean } ;
INSTANCE: decoder noncopying-reader

ERROR: decode-error ;

GENERIC: <encoder> ( stream encoding -- newstream )

TUPLE: encoder { stream read-only } { code read-only } ;

ERROR: encode-error ;

