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  }