github.com/cornelk/go-cloud@v0.17.1/docstore/memdocstore/codec.go (about) 1 // Copyright 2019 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package memdocstore 16 17 import ( 18 "fmt" 19 "reflect" 20 "time" 21 22 "github.com/cornelk/go-cloud/gcerrors" 23 24 "github.com/cornelk/go-cloud/docstore/driver" 25 ) 26 27 // encodeDoc encodes a driver.Document as a storedDoc. 28 func encodeDoc(doc driver.Document) (storedDoc, error) { 29 var e encoder 30 if err := doc.Encode(&e); err != nil { 31 return nil, err 32 } 33 return storedDoc(e.val.(map[string]interface{})), nil 34 } 35 36 func encodeValue(v interface{}) (interface{}, error) { 37 var e encoder 38 if err := driver.Encode(reflect.ValueOf(v), &e); err != nil { 39 return nil, err 40 } 41 return e.val, nil 42 } 43 44 type encoder struct { 45 val interface{} 46 } 47 48 func (e *encoder) EncodeNil() { e.val = nil } 49 func (e *encoder) EncodeBool(x bool) { e.val = x } 50 func (e *encoder) EncodeInt(x int64) { e.val = x } 51 func (e *encoder) EncodeUint(x uint64) { e.val = int64(x) } 52 func (e *encoder) EncodeBytes(x []byte) { e.val = x } 53 func (e *encoder) EncodeFloat(x float64) { e.val = x } 54 func (e *encoder) EncodeString(x string) { e.val = x } 55 func (e *encoder) ListIndex(int) { panic("impossible") } 56 func (e *encoder) MapKey(string) { panic("impossible") } 57 58 var typeOfGoTime = reflect.TypeOf(time.Time{}) 59 60 func (e *encoder) EncodeSpecial(v reflect.Value) (bool, error) { 61 if v.Type() == typeOfGoTime { 62 e.val = v.Interface() 63 return true, nil 64 } 65 return false, nil 66 } 67 68 func (e *encoder) EncodeList(n int) driver.Encoder { 69 // All slices and arrays are encoded as []interface{} 70 s := make([]interface{}, n) 71 e.val = s 72 return &listEncoder{s: s} 73 } 74 75 type listEncoder struct { 76 s []interface{} 77 encoder 78 } 79 80 func (e *listEncoder) ListIndex(i int) { e.s[i] = e.val } 81 82 type mapEncoder struct { 83 m map[string]interface{} 84 encoder 85 } 86 87 func (e *encoder) EncodeMap(n int) driver.Encoder { 88 m := make(map[string]interface{}, n) 89 e.val = m 90 return &mapEncoder{m: m} 91 } 92 93 func (e *mapEncoder) MapKey(k string) { e.m[k] = e.val } 94 95 //////////////////////////////////////////////////////////////// 96 97 // decodeDoc decodes m into ddoc. 98 func decodeDoc(m storedDoc, ddoc driver.Document, fps [][]string) error { 99 var m2 map[string]interface{} 100 if len(fps) == 0 { 101 m2 = m 102 } else { 103 // Make a document to decode from that has only the field paths. 104 // (We don't need the key field because ddoc must already have it.) 105 m2 = map[string]interface{}{} 106 for _, fp := range fps { 107 val, err := getAtFieldPath(m, fp) 108 if err != nil { 109 if gcerrors.Code(err) == gcerrors.NotFound { 110 continue 111 } 112 return err 113 } 114 if err := setAtFieldPath(m2, fp, val); err != nil { 115 return err 116 } 117 } 118 } 119 return ddoc.Decode(decoder{m2}) 120 } 121 122 type decoder struct { 123 val interface{} 124 } 125 126 func (d decoder) String() string { 127 return fmt.Sprint(d.val) 128 } 129 130 func (d decoder) AsNull() bool { 131 return d.val == nil 132 } 133 134 func (d decoder) AsBool() (bool, bool) { 135 b, ok := d.val.(bool) 136 return b, ok 137 } 138 139 func (d decoder) AsString() (string, bool) { 140 s, ok := d.val.(string) 141 return s, ok 142 } 143 144 func (d decoder) AsInt() (int64, bool) { 145 i, ok := d.val.(int64) 146 return i, ok 147 } 148 149 func (d decoder) AsUint() (uint64, bool) { 150 i, ok := d.val.(int64) 151 return uint64(i), ok 152 } 153 154 func (d decoder) AsFloat() (float64, bool) { 155 f, ok := d.val.(float64) 156 return f, ok 157 } 158 159 func (d decoder) AsBytes() ([]byte, bool) { 160 bs, ok := d.val.([]byte) 161 return bs, ok 162 } 163 164 func (d decoder) AsInterface() (interface{}, error) { 165 return d.val, nil 166 } 167 168 func (d decoder) ListLen() (int, bool) { 169 if s, ok := d.val.([]interface{}); ok { 170 return len(s), true 171 } 172 return 0, false 173 } 174 175 func (d decoder) DecodeList(f func(i int, d2 driver.Decoder) bool) { 176 for i, e := range d.val.([]interface{}) { 177 if !f(i, decoder{e}) { 178 return 179 } 180 } 181 } 182 183 func (d decoder) MapLen() (int, bool) { 184 if m, ok := d.val.(map[string]interface{}); ok { 185 return len(m), true 186 } 187 return 0, false 188 } 189 190 func (d decoder) DecodeMap(f func(key string, d2 driver.Decoder, _ bool) bool) { 191 for k, v := range d.val.(map[string]interface{}) { 192 if !f(k, decoder{v}, true) { 193 return 194 } 195 } 196 } 197 198 func (d decoder) AsSpecial(v reflect.Value) (bool, interface{}, error) { 199 if v.Type() == typeOfGoTime { 200 return true, d.val, nil 201 } 202 return false, nil, nil 203 }