OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package datastore | 5 package datastore |
6 | 6 |
7 import ( | 7 import ( |
8 "encoding/base64" | 8 "encoding/base64" |
9 "errors" | 9 "errors" |
10 "fmt" | 10 "fmt" |
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 // val, err := helper.GetPLS(&MyStruct{10}).GetMeta("id") | 642 // val, err := helper.GetPLS(&MyStruct{10}).GetMeta("id") |
643 // // val == 10 | 643 // // val == 10 |
644 // // err == nil | 644 // // err == nil |
645 // | 645 // |
646 // type MyStruct struct { | 646 // type MyStruct struct { |
647 // TFlag Toggle `gae:"$flag1,true"` // defaults to true | 647 // TFlag Toggle `gae:"$flag1,true"` // defaults to true |
648 // FFlag Toggle `gae:"$flag2,false"` // defaults to false | 648 // FFlag Toggle `gae:"$flag2,false"` // defaults to false |
649 // // BadFlag Toggle `gae:"$flag3"` // ILLEGAL | 649 // // BadFlag Toggle `gae:"$flag3"` // ILLEGAL |
650 // } | 650 // } |
651 GetMeta(key string) (interface{}, error) | 651 GetMeta(key string) (interface{}, error) |
652 | |
653 // GetMetaDefault is GetMeta, but with a default. | |
654 // | |
655 // If the metadata key is not available, or its type doesn't equal the | |
656 // homogenized type of dflt, then dflt will be returned. | |
657 // | |
658 // Type homogenization: | |
659 // signed integer types -> int64 | |
660 // bool -> Toggle fields (bool) | |
661 // | |
662 // Example: | |
663 // pls.GetMetaDefault("foo", 100).(int64) | |
664 GetMetaDefault(key string, dflt interface{}) interface{} | |
665 } | 652 } |
666 | 653 |
667 // PropertyLoadSaver may be implemented by a user type, and Interface will | 654 // PropertyLoadSaver may be implemented by a user type, and Interface will |
668 // use this interface to serialize the type instead of trying to automatically | 655 // use this interface to serialize the type instead of trying to automatically |
669 // create a serialization codec for it with helper.GetPLS. | 656 // create a serialization codec for it with helper.GetPLS. |
670 type PropertyLoadSaver interface { | 657 type PropertyLoadSaver interface { |
671 // Load takes the values from the given map and attempts to save them in
to | 658 // Load takes the values from the given map and attempts to save them in
to |
672 // the underlying object (usually a struct or a PropertyMap). If a fatal | 659 // the underlying object (usually a struct or a PropertyMap). If a fatal |
673 // error occurs, it's returned via error. If non-fatal conversion errors | 660 // error occurs, it's returned via error. If non-fatal conversion errors |
674 // occur, error will be a MultiError containing one or more ErrFieldMism
atch | 661 // occur, error will be a MultiError containing one or more ErrFieldMism
atch |
675 // objects. | 662 // objects. |
676 Load(PropertyMap) error | 663 Load(PropertyMap) error |
677 | 664 |
678 // Save returns the current property as a PropertyMap. if withMeta is tr
ue, | 665 // Save returns the current property as a PropertyMap. if withMeta is tr
ue, |
679 // then the PropertyMap contains all the metadata (e.g. '$meta' fields) | 666 // then the PropertyMap contains all the metadata (e.g. '$meta' fields) |
680 // which was held by this PropertyLoadSaver. | 667 // which was held by this PropertyLoadSaver. |
681 Save(withMeta bool) (PropertyMap, error) | 668 Save(withMeta bool) (PropertyMap, error) |
682 | |
683 // Problem indicates that this PLS has a fatal problem. Usually this is | |
684 // set when the underlying struct has recursion, invalid field types, ne
sted | |
685 // slices, etc. | |
686 Problem() error | |
687 } | 669 } |
688 | 670 |
689 // MetaGetterSetter is the subset of PropertyLoadSaver which pertains to | 671 // MetaGetterSetter is the subset of PropertyLoadSaver which pertains to |
690 // getting and saving metadata. | 672 // getting and saving metadata. |
691 // | 673 // |
692 // A *struct may implement this interface to provide metadata which is | 674 // A *struct may implement this interface to provide metadata which is |
693 // supplimental to the variety described by GetPLS. For example, this could be | 675 // supplimental to the variety described by GetPLS. For example, this could be |
694 // used to implement a parsed-out $kind or $id. | 676 // used to implement a parsed-out $kind or $id. |
695 type MetaGetterSetter interface { | 677 type MetaGetterSetter interface { |
696 MetaGetter | 678 MetaGetter |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
780 for k, v := range pm { | 762 for k, v := range pm { |
781 if isMetaKey(k) { | 763 if isMetaKey(k) { |
782 newV := make([]Property, len(v)) | 764 newV := make([]Property, len(v)) |
783 copy(newV, v) | 765 copy(newV, v) |
784 ret[k] = newV | 766 ret[k] = newV |
785 } | 767 } |
786 } | 768 } |
787 return ret | 769 return ret |
788 } | 770 } |
789 | 771 |
790 // GetMetaDefault is the implementation of PropertyLoadSaver.GetMetaDefault. | |
791 func (pm PropertyMap) GetMetaDefault(key string, dflt interface{}) interface{} { | |
792 return GetMetaDefaultImpl(pm.GetMeta, key, dflt) | |
793 } | |
794 | |
795 // SetMeta implements PropertyLoadSaver.SetMeta. It will only return an error | 772 // SetMeta implements PropertyLoadSaver.SetMeta. It will only return an error |
796 // if `val` has an invalid type (e.g. not one supported by Property). | 773 // if `val` has an invalid type (e.g. not one supported by Property). |
797 func (pm PropertyMap) SetMeta(key string, val interface{}) error { | 774 func (pm PropertyMap) SetMeta(key string, val interface{}) error { |
798 prop := Property{} | 775 prop := Property{} |
799 if err := prop.SetValue(val, NoIndex); err != nil { | 776 if err := prop.SetValue(val, NoIndex); err != nil { |
800 return err | 777 return err |
801 } | 778 } |
802 pm["$"+key] = []Property{prop} | 779 pm["$"+key] = []Property{prop} |
803 return nil | 780 return nil |
804 } | 781 } |
(...skipping 21 matching lines...) Expand all Loading... |
826 } | 803 } |
827 return ret | 804 return ret |
828 } | 805 } |
829 | 806 |
830 func isMetaKey(k string) bool { | 807 func isMetaKey(k string) bool { |
831 // empty counts as a metakey since it's not a valid data key, but it's | 808 // empty counts as a metakey since it's not a valid data key, but it's |
832 // not really a valid metakey either. | 809 // not really a valid metakey either. |
833 return k == "" || k[0] == '$' | 810 return k == "" || k[0] == '$' |
834 } | 811 } |
835 | 812 |
836 // GetMetaDefaultImpl is the implementation of PropertyLoadSaver.GetMetaDefault. | 813 // GetMetaDefault is a helper for GetMeta, allowing a default value. |
837 // | 814 // |
838 // It takes the normal GetMeta function, the key and the default, and returns | 815 // If the metadata key is not available, or its type doesn't equal the |
839 // the value according to PropertyLoadSaver.GetMetaDefault. | 816 // homogenized type of dflt, then dflt will be returned. |
840 func GetMetaDefaultImpl(gm func(string) (interface{}, error), key string, dflt i
nterface{}) interface{} { | 817 // |
| 818 // Type homogenization: |
| 819 // signed integer types -> int64 |
| 820 // bool -> Toggle fields (bool) |
| 821 // |
| 822 // Example: |
| 823 // pls.GetMetaDefault("foo", 100).(int64) |
| 824 func GetMetaDefault(getter MetaGetter, key string, dflt interface{}) (interface{
}, error) { |
841 dflt = UpconvertUnderlyingType(dflt) | 825 dflt = UpconvertUnderlyingType(dflt) |
842 » cur, err := gm(key) | 826 » cur, err := getter.GetMeta(key) |
843 if err != nil { | 827 if err != nil { |
844 » » return dflt | 828 » » if err == ErrMetaFieldUnset { |
| 829 » » » return dflt, nil |
| 830 » » } |
| 831 » » return nil, err |
845 } | 832 } |
846 if dflt != nil && reflect.TypeOf(cur) != reflect.TypeOf(dflt) { | 833 if dflt != nil && reflect.TypeOf(cur) != reflect.TypeOf(dflt) { |
847 » » return dflt | 834 » » return dflt, nil |
848 } | 835 } |
849 » return cur | 836 » return cur, nil |
850 } | 837 } |
OLD | NEW |