func ComparePos(a, b Pos) (int, error) {
	if a.Generation != b.Generation {
		return 0, fmt.Errorf("generation mismatch")
	}
	if a.Index < b.Index {
		return -1, nil
	} else if a.Index > b.Index {
		return 1, nil
	} else if a.Offset < b.Offset {
		return -1, nil
	} else if a.Offset > b.Offset {
		return 1, nil
	}
	return 0, nil
}
ComparePos returns -1 if a is less than b, 1 if a is greater than b, and
returns 0 if a and b are equal. Only index & offset are compared.
Returns an error if generations are not equal.
package litestream
import (
	"database/sql"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)
const (
	MetaDirSuffix = "-litestream"
	WALDirName    = "wal"
	WALExt        = ".wal"
	WALSegmentExt = ".wal.lz4"
	SnapshotExt   = ".snapshot.lz4"
	GenerationNameLen = 16
)
const (
	CheckpointModePassive  = "PASSIVE"
	CheckpointModeFull     = "FULL"
	CheckpointModeRestart  = "RESTART"
	CheckpointModeTruncate = "TRUNCATE"
)
var (
	ErrNoGeneration     = errors.New("no generation available")
	ErrNoSnapshots      = errors.New("no snapshots available")
	ErrChecksumMismatch = errors.New("invalid replica, checksum mismatch")
)
var (
	LogWriter = os.Stderr
	LogFlags = 0
)
type SnapshotIterator interface {
	io.Closer
	Next() bool
	Err() error
	Snapshot() SnapshotInfo
}
func SliceSnapshotIterator(itr SnapshotIterator) ([]SnapshotInfo, error) {
	var a []SnapshotInfo
	for itr.Next() {
		a = append(a, itr.Snapshot())
	}
	return a, itr.Close()
}
var _ SnapshotIterator = (*SnapshotInfoSliceIterator)(nil)
type SnapshotInfoSliceIterator struct {
	init bool
	a    []SnapshotInfo
}
func NewSnapshotInfoSliceIterator(a []SnapshotInfo) *SnapshotInfoSliceIterator {
	return &SnapshotInfoSliceIterator{a: a}
}
func (itr *SnapshotInfoSliceIterator) Close() error { return nil }
func (itr *SnapshotInfoSliceIterator) Next() bool {
	if !itr.init {
		itr.init = true
		return len(itr.a) > 0
	}
	itr.a = itr.a[1:]
	return len(itr.a) > 0
}
func (itr *SnapshotInfoSliceIterator) Err() error { return nil }
func (itr *SnapshotInfoSliceIterator) Snapshot() SnapshotInfo {
	if len(itr.a) == 0 {
		return SnapshotInfo{}
	}
	return itr.a[0]
}
type WALSegmentIterator interface {
	io.Closer
	Next() bool
	Err() error
	WALSegment() WALSegmentInfo
}
func SliceWALSegmentIterator(itr WALSegmentIterator) ([]WALSegmentInfo, error) {
	var a []WALSegmentInfo
	for itr.Next() {
		a = append(a, itr.WALSegment())
	}
	return a, itr.Close()
}
var _ WALSegmentIterator = (*WALSegmentInfoSliceIterator)(nil)
type WALSegmentInfoSliceIterator struct {
	init bool
	a    []WALSegmentInfo
}
func NewWALSegmentInfoSliceIterator(a []WALSegmentInfo) *WALSegmentInfoSliceIterator {
	return &WALSegmentInfoSliceIterator{a: a}
}
func (itr *WALSegmentInfoSliceIterator) Close() error { return nil }
func (itr *WALSegmentInfoSliceIterator) Next() bool {
	if !itr.init {
		itr.init = true
		return len(itr.a) > 0
	}
	itr.a = itr.a[1:]
	return len(itr.a) > 0
}
func (itr *WALSegmentInfoSliceIterator) Err() error { return nil }
func (itr *WALSegmentInfoSliceIterator) WALSegment() WALSegmentInfo {
	if len(itr.a) == 0 {
		return WALSegmentInfo{}
	}
	return itr.a[0]
}
type SnapshotInfo struct {
	Generation string
	Index      int
	Size       int64
	CreatedAt  time.Time
}
func (info *SnapshotInfo) Pos() Pos {
	return Pos{Generation: info.Generation, Index: info.Index}
}
type SnapshotInfoSlice []SnapshotInfo
func (a SnapshotInfoSlice) Len() int { return len(a) }
func (a SnapshotInfoSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a SnapshotInfoSlice) Less(i, j int) bool {
	if a[i].Generation != a[j].Generation {
		return a[i].Generation < a[j].Generation
	}
	return a[i].Index < a[j].Index
}
func FilterSnapshotsAfter(a []SnapshotInfo, t time.Time) []SnapshotInfo {
	other := make([]SnapshotInfo, 0, len(a))
	for _, snapshot := range a {
		if !snapshot.CreatedAt.Before(t) {
			other = append(other, snapshot)
		}
	}
	return other
}
func FindMinSnapshotByGeneration(a []SnapshotInfo, generation string) *SnapshotInfo {
	var min *SnapshotInfo
	for _, snapshot := range a {
		if snapshot.Generation != generation {
			continue
		} else if min == nil || snapshot.Index < min.Index {
			min = &snapshot
		}
	}
	return min
}
type WALInfo struct {
	Generation string
	Index      int
	CreatedAt  time.Time
}
type WALInfoSlice []WALInfo
func (a WALInfoSlice) Len() int { return len(a) }
func (a WALInfoSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a WALInfoSlice) Less(i, j int) bool {
	if a[i].Generation != a[j].Generation {
		return a[i].Generation < a[j].Generation
	}
	return a[i].Index < a[j].Index
}
type WALSegmentInfo struct {
	Generation string
	Index      int
	Offset     int64
	Size       int64
	CreatedAt  time.Time
}
func (info *WALSegmentInfo) Pos() Pos {
	return Pos{Generation: info.Generation, Index: info.Index, Offset: info.Offset}
}
type WALSegmentInfoSlice []WALSegmentInfo
func (a WALSegmentInfoSlice) Len() int { return len(a) }
func (a WALSegmentInfoSlice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a WALSegmentInfoSlice) Less(i, j int) bool {
	if a[i].Generation != a[j].Generation {
		return a[i].Generation < a[j].Generation
	} else if a[i].Index != a[j].Index {
		return a[i].Index < a[j].Index
	}
	return a[i].Offset < a[j].Offset
}
type Pos struct {
	Generation string  
	Index      int     
	Offset     int64   
}
func (p Pos) String() string {
	if p.IsZero() {
		return ""
	}
	return fmt.Sprintf("%s/%08x:%d", p.Generation, p.Index, p.Offset)
}
func (p Pos) IsZero() bool {
	return p == (Pos{})
}
func (p Pos) Truncate() Pos {
	return Pos{Generation: p.Generation, Index: p.Index}
}