#lang racket/base (define (absolutely-write-bytes bytes output start end) (let loop ((cur start)) (if (>= cur end) (- end start) (let ((num (write-bytes bytes output cur end))) (when (not (number? num)) (error "Hit end of file while writing!" output)) (loop (+ cur num)))))) (define (absolutely-read-bytes num input) (let loop ((left num) (result null)) (if (<= left 0) (apply bytes-append (reverse result)) (let ((bytes (read-bytes left input))) (when (eof-object? bytes) (error "Hit end of file while reading" input)) (let ((left (- left (bytes-length bytes)))) (loop left (cons bytes result))))))) (define-struct slice (bytes start end) #:transparent) (define (create (num 0)) (make-slice (make-bytes num) 0 num)) (define (from-bytes bytes) (make-slice bytes 0 (bytes-length bytes))) (define (subslice slice start end) (make-slice (slice-bytes slice) start end)) (define (to-bytes slice) (subbytes (slice-bytes slice) (slice-start slice) (slice-end slice))) (define (write-slice slice (output (current-output-port))) (absolutely-write-bytes (slice-bytes slice) output (slice-start slice) (slice-end slice))) (define (read-slice num (input (current-input-port))) (from-bytes (absolutely-read-bytes num input))) (define (read-slice! slice (input (current-input-port))) (read-bytes! (slice-bytes slice) input (slice-start slice) (slice-end slice))) (define (slice-length slice) (- (slice-end slice) (slice-start slice))) (define (slice-append slices) (define bytes (make-bytes (foldl (λ (slice length) (+ length (slice-length slice))) 0 slices))) (let loop ((offset 0) (slices slices)) (if (null? slices) (from-bytes bytes) (let ((slice (car slices))) (bytes-copy! bytes offset (slice-bytes slice) (slice-start slice) (slice-end slice)) (loop (+ offset (slice-length slice)) (cdr slices)))))) (provide (rename-out (read-slice read) (read-slice! read!) (write-slice write) (slice-length length) (slice-append append) (subslice sub) (slice-start start) (slice-bytes bytes) (slice-end end)) create from-bytes to-bytes slice?)