-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdb.go
91 lines (80 loc) · 2.26 KB
/
db.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*
DB provides a simple key-value-store-like interface using bsearch.Searcher,
returning the first first entry for a given key.
*/
package bsearch
import (
"bytes"
"encoding/csv"
"fmt"
"io"
)
// DB provides a simple key-value-store-like interface using bsearch.Searcher,
// returning the first value from path for a given key (if you need more
// control you're encouraged to use bsearch.Searcher directly).
type DB struct {
bss *Searcher // searcher
}
// NewDB returns a new DB for the file at path. The caller is responsible
// for calling DB.Close() when finished (e.g. via defer).
func NewDB(path string) (*DB, error) {
bss, err := NewSearcher(path)
if err != nil {
return nil, err
}
return &DB{bss: bss}, nil
}
// Get returns the (first) value associated with key in db
// (or ErrNotFound if missing)
func (db *DB) Get(key []byte) ([]byte, error) {
line, err := db.bss.Line(key)
if err != nil {
return nil, err
}
// Remove leading key+delimiter from line
prefix := append(key, db.bss.Index.Delimiter...)
// Sanity check
if !bytes.HasPrefix(line, prefix) {
panic(
fmt.Sprintf("line returned for %q does not begin with key+delim: %s\n",
key, line))
}
line = bytes.TrimPrefix(line, prefix)
return line, nil
}
// GetString returns the (first) value associated with key in db, as a string
// (or ErrNotFound if missing)
func (db *DB) GetString(key string) (string, error) {
val, err := db.Get([]byte(key))
if err != nil {
return "", err
}
return string(val), nil
}
// GetSlice returns the (first) value associated with key in db as a string
// slice (read using a csv.Reader with the appropriate Delimiter)
// (or returns ErrNotFound if missing)
func (db *DB) GetSlice(key string) ([]string, error) {
val, err := db.Get([]byte(key))
if err != nil {
return []string{}, err
}
delim := string(db.bss.Index.Delimiter)
if len(delim) > 1 {
return []string{},
fmt.Errorf("cannot convert multi-character delimiter %q to rune", delim)
}
reader := csv.NewReader(bytes.NewReader(val))
reader.Comma = rune(delim[0])
s, err := reader.Read()
if err != nil {
return []string{}, err
}
return s, nil
}
// Close closes our Searcher's underlying reader (if applicable)
func (db *DB) Close() {
if closer, ok := db.bss.r.(io.Closer); ok {
closer.Close()
}
}