main.ss
#lang scheme

(define (wrap-at max i)
  (if (i . >= . max)
      (wrap-at max (- i max))
      i))
(define (wrap+ max x y)
  (wrap-at max (+ x y))) 

(define-struct ring-buffer (length [fst #:mutable] [nxt #:mutable] vals)
  #:property prop:sequence
  (lambda (rb)
    (match rb
      [(struct ring-buffer (max fst _ vals))
       (make-do-sequence
        (lambda ()
          (values 
           (lambda (p) 
             (ring-buffer-ref rb p))
           (lambda (p) (add1 p))
           0
           (lambda (p) (< p max))
           (lambda (v) v)
           (lambda (p v) (and (< p max) v)))))])))

(define (empty-ring-buffer max)
  (make-ring-buffer max #f 0 (make-vector max #f)))
(define (ring-buffer-push! rb m)
  (match rb
    [(struct ring-buffer (max fst nxt vals))
     (unless (zero? max)
       (when (and fst (= fst nxt))
         (set-ring-buffer-fst! rb (wrap+ max (ring-buffer-fst rb) 1)))
       (vector-set! vals nxt m)
       (set-ring-buffer-nxt! rb (wrap+ max nxt 1))       
       (unless fst
         (set-ring-buffer-fst! rb 0)))]))

(define (ring-buffer-ref rb i)
  (match rb
    [(struct ring-buffer (max fst _ vals))
     (vector-ref vals (wrap+ max (if fst fst 0) i))]))
(define (ring-buffer-set! rb i v)
  (match rb
    [(struct ring-buffer (max fst _ vals))
     (vector-set! vals (wrap+ max (if fst fst 0) i) v)]))

(provide/contract
 [empty-ring-buffer (exact-nonnegative-integer? . -> . ring-buffer?)]
 [ring-buffer? (any/c . -> . boolean?)]
 [ring-buffer-length (ring-buffer? . -> . exact-nonnegative-integer?)]
 [ring-buffer-ref (ring-buffer? exact-nonnegative-integer? . -> . (or/c any/c false/c))]
 [ring-buffer-set! (ring-buffer? exact-nonnegative-integer? (and/c any/c (not/c false/c)) . -> . void)]
 [ring-buffer-push! (ring-buffer? (and/c any/c (not/c false/c)) . -> . void)])