This commit is contained in:
Bel LaPointe
2021-12-15 07:33:50 -07:00
parent bc8a0d82df
commit 44ce475100
5 changed files with 147 additions and 13 deletions

132
yaml.go
View File

@@ -2,9 +2,12 @@ package storage
import (
"bytes"
"encoding/base64"
"errors"
"fmt"
"io"
"io/ioutil"
"local/storage/resolve"
"os"
"path"
"path/filepath"
@@ -43,7 +46,19 @@ func (y *Yaml) Namespaces() ([][]string, error) {
}
func (y *Yaml) List(ns []string, limits ...string) ([]string, error) {
return nil, errors.New("not impl")
namespace := resolve.Namespace(ns)
m, err := y.getMap(namespace)
if err != nil {
return nil, err
}
limits = resolve.Limits(limits)
ks := make([]string, 0, len(m))
for k := range m {
if k >= limits[0] && k <= limits[1] {
ks = append(ks, k)
}
}
return ks, nil
}
func (y *Yaml) Get(key string, ns ...string) ([]byte, error) {
@@ -55,7 +70,21 @@ func (y *Yaml) Get(key string, ns ...string) ([]byte, error) {
}
func (y *Yaml) GetStream(key string, ns ...string) (io.Reader, error) {
return nil, errors.New("not impl")
namespace := resolve.Namespace(ns)
m, err := y.getMap(namespace)
if err != nil {
return nil, err
}
v, ok := m[key]
if !ok {
return nil, ErrNotFound
}
s, ok := v.(string)
if !ok {
return nil, ErrNotFound
}
b, err := base64.StdEncoding.DecodeString(s)
return bytes.NewReader(b), err
}
func (y *Yaml) Set(key string, value []byte, ns ...string) error {
@@ -67,30 +96,98 @@ func (y *Yaml) Set(key string, value []byte, ns ...string) error {
}
func (y *Yaml) Del(key string, ns ...string) error {
return errors.New("not impl")
return y.SetStream(key, nil, ns...)
}
func (y *Yaml) SetStream(key string, r io.Reader, ns ...string) error {
return errors.New("not impl")
namespace := resolve.Namespace(ns)
var v interface{} = nil
if r != nil {
b, err := ioutil.ReadAll(r)
if err != nil {
return err
}
v = base64.StdEncoding.EncodeToString(b)
}
m, err := y.getMap()
if err != nil {
return err
}
if err := setInMap(m, []string{namespace}, key, v); err != nil {
return err
}
return y.setMap(m)
}
func (y *Yaml) Close() error {
return nil
}
func (y *Yaml) getMap() (map[string]interface{}, error) {
func (y *Yaml) getMap(keys ...string) (map[string]interface{}, error) {
b, err := y.get()
if err != nil {
return nil, err
}
var m map[string]interface{}
err = yaml.Unmarshal(b, &m)
var mBad map[interface{}]interface{}
if err := yaml.Unmarshal(b, &mBad); err != nil {
return nil, err
}
m, err := mbadToM(mBad)
if err != nil {
return nil, err
}
if m == nil {
m = map[string]interface{}{}
}
for _, k := range keys {
subv, ok := m[k]
if !ok {
subv = map[string]interface{}{}
m[k] = subv
}
subm, ok := subv.(map[string]interface{})
if !ok {
return nil, ErrNotFound
}
m = subm
}
return m, err
}
func (y *Yaml) setMap(m map[string]interface{}) error {
b, err := yaml.Marshal(m)
if err != nil {
return err
}
return y.set(b)
}
func setInMap(m map[string]interface{}, keys []string, key string, v interface{}) error {
if len(keys) == 0 {
m[key] = v
if v == nil {
delete(m, key)
}
return nil
}
subv, ok := m[keys[0]]
if !ok {
subv = map[string]interface{}{}
}
subm, ok := subv.(map[string]interface{})
if !ok {
return errors.New("clobber")
}
if err := setInMap(subm, keys[1:], key, v); err != nil {
return err
}
m[keys[0]] = subm
return nil
}
func (y *Yaml) get() ([]byte, error) {
b, err := ioutil.ReadFile(y.path)
if err == os.ErrNotExist {
if os.IsNotExist(err) {
return []byte{}, nil
}
return b, err
@@ -127,3 +224,22 @@ func _keysDFS(m map[string]interface{}) ([][]string, bool, error) {
}
return keys, hasNonMaps, nil
}
func mbadToM(mBad map[interface{}]interface{}) (map[string]interface{}, error) {
m := map[string]interface{}{}
for k, v := range mBad {
s, ok := k.(string)
if !ok {
s = fmt.Sprint(k)
}
m[s] = v
if m2, ok := v.(map[interface{}]interface{}); ok {
v2, err := mbadToM(m2)
if err != nil {
return nil, err
}
m[s] = v2
}
}
return m, nil
}