gitmote

gitmote / internal / store / mem.go  ·  history  ·  branches

1389 bytes · raw

package store

import (
	"bytes"
	"context"
	"io"
	"sort"
	"strings"
	"sync"
)

// Mem is an in-memory Store for tests. It must stay in lockstep with the S3
// implementation — the conformance suite runs against both.
type Mem struct {
	mu      sync.RWMutex
	objects map[string][]byte
}

// NewMem returns an empty in-memory store.
func NewMem() *Mem {
	return &Mem{objects: make(map[string][]byte)}
}

var _ Store = (*Mem)(nil)

// Put implements Store.
func (m *Mem) Put(ctx context.Context, key string, r io.Reader) error {
	data, err := io.ReadAll(r)
	if err != nil {
		return err
	}
	m.mu.Lock()
	defer m.mu.Unlock()
	m.objects[key] = data
	return nil
}

// Get implements Store.
func (m *Mem) Get(ctx context.Context, key string) (io.ReadCloser, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()
	data, ok := m.objects[key]
	if !ok {
		return nil, ErrNotFound
	}
	return io.NopCloser(bytes.NewReader(data)), nil
}

// Exists implements Store.
func (m *Mem) Exists(ctx context.Context, key string) (bool, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()
	_, ok := m.objects[key]
	return ok, nil
}

// List implements Store.
func (m *Mem) List(ctx context.Context, prefix string) ([]string, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()
	var keys []string
	for k := range m.objects {
		if strings.HasPrefix(k, prefix) {
			keys = append(keys, k)
		}
	}
	sort.Strings(keys)
	return keys, nil
}