github.com/ipld/go-ipld-prime@v0.21.0/storage/memstore/memstore.go (about)

     1  package memstore
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"io"
     8  )
     9  
    10  // Store is a simple in-memory storage.
    11  // (It's little more than a map -- in fact, the map is exported,
    12  // and you can poke it directly.)
    13  //
    14  // Store conforms to the storage.ReadableStorage and storage.WritableStorage APIs.
    15  // Additionally, it supports storage.PeekableStorage and storage.StreamingReadableStorage,
    16  // because it can do so while provoking fewer copies.
    17  //
    18  // If you want to use this store with streaming APIs,
    19  // you can still do so by using the functions in the storage package,
    20  // such as storage.GetStream and storage.PutStream, which will synthesize the correct behavior.
    21  //
    22  // You can use this storage with a linking.LinkSystem easily,
    23  // by using the LinkSystem.SetReadStorage and/or LinkSystem.SetWriteStorage methods.
    24  //
    25  // There are no construction parameters for sharding functions nor escaping functions.
    26  // Any keys are acceptable.
    27  //
    28  // This storage is mostly expected to be used for testing and demos,
    29  // and as an example of how you can implement and integrate your own storage systems.
    30  // It does not provide persistence beyond memory.
    31  type Store struct {
    32  	Bag map[string][]byte
    33  }
    34  
    35  func (store *Store) beInitialized() {
    36  	if store.Bag != nil {
    37  		return
    38  	}
    39  	store.Bag = make(map[string][]byte)
    40  }
    41  
    42  // Has implements go-ipld-prime/storage.Storage.Has.
    43  func (store *Store) Has(ctx context.Context, key string) (bool, error) {
    44  	if store.Bag == nil {
    45  		return false, nil
    46  	}
    47  	_, exists := store.Bag[key]
    48  	return exists, nil
    49  }
    50  
    51  // Get implements go-ipld-prime/storage.ReadableStorage.Get.
    52  //
    53  // Note that this internally performs a defensive copy;
    54  // use Peek for higher performance if you are certain you won't mutate the returned slice.
    55  func (store *Store) Get(ctx context.Context, key string) ([]byte, error) {
    56  	store.beInitialized()
    57  	content, exists := store.Bag[key]
    58  	if !exists {
    59  		return nil, fmt.Errorf("404") // FIXME this needs a standard error type
    60  	}
    61  	cpy := make([]byte, len(content))
    62  	copy(cpy, content)
    63  	return cpy, nil
    64  }
    65  
    66  // Put implements go-ipld-prime/storage.WritableStorage.Put.
    67  func (store *Store) Put(ctx context.Context, key string, content []byte) error {
    68  	store.beInitialized()
    69  	if _, exists := store.Bag[key]; exists {
    70  		return nil
    71  	}
    72  	cpy := make([]byte, len(content))
    73  	copy(cpy, content)
    74  	store.Bag[key] = cpy
    75  	return nil
    76  }
    77  
    78  // GetStream implements go-ipld-prime/storage.StreamingReadableStorage.GetStream.
    79  //
    80  // It's useful for this storage implementation to explicitly support this,
    81  // because returning a reader gives us room to avoid needing a defensive copy.
    82  func (store *Store) GetStream(ctx context.Context, key string) (io.ReadCloser, error) {
    83  	content, exists := store.Bag[key]
    84  	if !exists {
    85  		return nil, fmt.Errorf("404") // FIXME this needs a standard error type
    86  	}
    87  	return noopCloser{bytes.NewReader(content)}, nil
    88  }
    89  
    90  // Peek implements go-ipld-prime/storage.PeekableStorage.Peek.
    91  func (store *Store) Peek(ctx context.Context, key string) ([]byte, io.Closer, error) {
    92  	content, exists := store.Bag[key]
    93  	if !exists {
    94  		return nil, nil, fmt.Errorf("404") // FIXME this needs a standard error type
    95  	}
    96  	return content, noopCloser{nil}, nil
    97  }
    98  
    99  type noopCloser struct {
   100  	io.Reader
   101  }
   102  
   103  func (noopCloser) Close() error { return nil }