func (b *Buffer) updateFirst(fsize uint64) {
	if b.biggest == 0 {
		return
	}
	var (
		start    = b.last % b.capacity
		end      = (start + fsize) % b.capacity
		wrapping = end <= start
	)
	if start == end {
		b.length = 0
		b.first = b.last
		return
	}
	for {
		if b.first == b.last {
			return
		}
		firstWrapped := b.first % b.capacity
		if wrapping {
			if end <= firstWrapped && firstWrapped < start {
				return
			}
		} else {
			if end <= firstWrapped {
				return
			}
			if start > firstWrapped {
				return
			}
		}
		second := b.nextFrameOffset(b.first)
		b.length -= (second - b.first - total)
		b.first = second
	}
}
updateFirst updates the offset of the first record in b.

This should be called before updating b.biggest or writing any data but
after updating b.last to the value where the new record would be written.
package buffer
import (
	"errors"
	"fmt"
	"os"
	"sync"
	"syscall"
	"github.com/ashishgandhi/buffer/binary"
)
const (
	size     = 4  
	sequence = 8  
	total    = size + sequence
	metadata = 4 << 10  
)
var maxBytes uint32 = (1 << (uint(size) * 8)) - total  
type frame []byte
var (
	errFrameTooBig = fmt.Errorf("buffer: data more than max %d bytes", maxBytes)
	errDataTooBig  = errors.New("buffer: data overflows buffer")
)
func newFrame(seq uint64, data []byte) (frame, error) {
	if len(data) > int(maxBytes) {
		return nil, errFrameTooBig
	}
	var f frame = make([]byte, len(data)+total)
	binary.PutLittleEndianUint32(f, 0, uint32(len(f)))
	binary.PutLittleEndianUint64(f, size, seq)
	copy(f[total:], data)
	return f, nil
}
func (f frame) size() uint32 {
	if len(f) < size {
		return 0
	}
	return binary.GetLittleEndianUint32(f, 0)
}
func (f frame) seq() uint64 {
	if len(f) < total {
		return 0
	}
	return binary.GetLittleEndianUint64(f, size)
}
func (f frame) data() []byte {
	if len(f) < total {
		return nil
	}
	return f[total:]
}
type Buffer struct {
	capacity uint64
	nextSeq  uint64
	biggest  uint32  
	length   uint64  
	first uint64
	last  uint64
	filename string
	data     []byte
	mu sync.RWMutex  
}
func New(capacity int, filename string) (*Buffer, error) {
	if _, err := os.Stat(filename); !os.IsNotExist(err) {
		return nil, ErrFileExists
	}
	f, err := os.Create(filename)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	fsize := capacity + metadata
	if err := syscall.Truncate(filename, int64(fsize)); err != nil {
		return nil, err
	}
	data, err := syscall.Mmap(
		int(f.Fd()), 0, fsize,
		syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED,
	)
	if err != nil {
		return nil, err
	}
	b := &Buffer{
		capacity: uint64(capacity),  
		filename: f.Name(),
		data:     data,
	}
	b.updateMeta()
	return b, nil
}
func (b *Buffer) Len() uint64 {
	b.mu.RLock()
	defer b.mu.RUnlock()
	return b.length
}
func (b *Buffer) Remaining(from Cursor) uint64 {
	b.mu.RLock()
	defer b.mu.RUnlock()
	if from.offset > b.last {
		return 0
	}
	off := from.offset
	if off < b.first {
		off = b.first
	}
	remaining := b.last - off
	remaining += uint64(b.frameSize(b.last))
	return remaining
}
func (b *Buffer) updateMeta() {
	off := int(b.capacity)
	binary.PutLittleEndianUint64(b.data, off, b.first)
	binary.PutLittleEndianUint64(b.data, off+8, b.last)
	binary.PutLittleEndianUint64(b.data, off+16, b.nextSeq)
	binary.PutLittleEndianUint32(b.data, off+24, b.biggest)
	binary.PutLittleEndianUint64(b.data, off+28, b.length)
}
func Load(filename string) (*Buffer, error) {
	b := &Buffer{filename: filename}
	err := b.reload()
	return b, err
}
func (b *Buffer) reload() error {
	stat, err := os.Stat(b.filename)
	if err != nil {
		return err
	}
	fsize := uint64(stat.Size())
	b.capacity = fsize - metadata
	f, err := os.OpenFile(b.filename, os.O_RDWR, 0600)
	if err != nil {
		return err
	}
	data, err := syscall.Mmap(
		int(f.Fd()), 0, int(fsize),
		syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED,
	)
	if err != nil {
		return err
	}
	b.data = data
	off := int(b.capacity)
	b.first = binary.GetLittleEndianUint64(b.data, off)
	b.last = binary.GetLittleEndianUint64(b.data, off+8)
	b.nextSeq = binary.GetLittleEndianUint64(b.data, off+16)
	b.biggest = binary.GetLittleEndianUint32(b.data, off+24)
	b.length = binary.GetLittleEndianUint64(b.data, off+28)
	return nil
}
func (b *Buffer) Insert(data []byte) error {
	if len(data) == 0 {
		return nil
	}
	b.mu.Lock()
	defer b.mu.Unlock()
	frame, err := newFrame(b.nextSeq, data)  
	if err != nil {
		return err
	}
	fsize := frame.size()
	fsize64 := uint64(fsize)
	if fsize64 > b.capacity {
		return errDataTooBig
	}
	b.last = b.nextFrameOffset(b.last)  
	b.updateFirst(fsize64)
	start := b.last % b.capacity
	end := start + fsize64
	var wrap bool
	if end > b.capacity {
		wrap = true
		end = b.capacity
	}
	copyoff := end - start
	copy(b.data[start:end], frame[:copyoff])
	if wrap {
		copy(b.data, frame[copyoff:])
	}
	if fsize > b.biggest {
		b.biggest = fsize
	}
	b.nextSeq++
	b.length += uint64(len(data))
	b.updateMeta()
	return nil
}