mirror of
https://github.com/anyproto/anytype-heart.git
synced 2025-06-08 13:57:12 +09:00
231 lines
4.8 KiB
Go
231 lines
4.8 KiB
Go
package pbtypes
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/gogo/protobuf/types"
|
|
|
|
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
|
|
"github.com/anyproto/anytype-heart/util/slice"
|
|
)
|
|
|
|
func StructEqualIgnore(det1 *types.Struct, det2 *types.Struct, excludeKeys []string) (equal bool) {
|
|
var m1, m2 map[string]*types.Value
|
|
if det1 == nil || det1.Fields == nil {
|
|
m1 = make(map[string]*types.Value)
|
|
} else {
|
|
m1 = det1.Fields
|
|
}
|
|
|
|
if det2 == nil || det2.Fields == nil {
|
|
m2 = make(map[string]*types.Value)
|
|
} else {
|
|
m2 = det2.Fields
|
|
}
|
|
|
|
for key, v1 := range m1 {
|
|
if slice.FindPos(excludeKeys, key) >= 0 {
|
|
continue
|
|
}
|
|
if v2, exists := m2[key]; !exists {
|
|
return false
|
|
} else if !v2.Equal(v1) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
for key, _ := range m2 {
|
|
if slice.FindPos(excludeKeys, key) >= 0 {
|
|
continue
|
|
}
|
|
if _, exists := m1[key]; !exists {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// StructFilterKeys returns provided keys reusing underlying pb values pointers
|
|
func StructFilterKeys(st *types.Struct, filteredKeys []string) *types.Struct {
|
|
return StructFilterKeysFunc(st, func(key string, _ *types.Value) bool {
|
|
return slice.FindPos(filteredKeys, key) > -1
|
|
})
|
|
}
|
|
|
|
func StructFilterKeysFunc(st *types.Struct, filter func(key string, val *types.Value) bool) *types.Struct {
|
|
if st == nil || st.Fields == nil {
|
|
return st
|
|
}
|
|
|
|
m := make(map[string]*types.Value, len(st.Fields))
|
|
for k, v := range st.Fields {
|
|
if filter(k, v) {
|
|
m[k] = v
|
|
}
|
|
}
|
|
return &types.Struct{Fields: m}
|
|
}
|
|
|
|
// StructCutKeys excludes provided keys reusing underlying pb values pointers
|
|
func StructCutKeys(st *types.Struct, excludeKeys []string) *types.Struct {
|
|
return StructFilterKeysFunc(st, func(key string, _ *types.Value) bool {
|
|
return slice.FindPos(excludeKeys, key) == -1
|
|
})
|
|
}
|
|
|
|
func StructMerge(st1, st2 *types.Struct, copyVals bool) *types.Struct {
|
|
var res *types.Struct
|
|
if st1 == nil || st1.Fields == nil {
|
|
return CopyStruct(st2, copyVals)
|
|
}
|
|
|
|
if st2 == nil || st2.Fields == nil {
|
|
return CopyStruct(st1, copyVals)
|
|
}
|
|
|
|
res = CopyStruct(st1, copyVals)
|
|
for k, v := range st2.Fields {
|
|
if copyVals {
|
|
res.Fields[k] = CopyVal(v)
|
|
} else {
|
|
res.Fields[k] = v
|
|
}
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
func DataviewSortsEqualSorted(sorts1, sorts2 []*model.BlockContentDataviewSort) bool {
|
|
if len(sorts1) != len(sorts2) {
|
|
return false
|
|
}
|
|
for i := range sorts1 {
|
|
if !DataviewSortEqual(sorts1[i], sorts2[i]) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func DataviewFiltersEqualSorted(filters1, filters2 []*model.BlockContentDataviewFilter) bool {
|
|
if len(filters1) != len(filters2) {
|
|
return false
|
|
}
|
|
for i := range filters1 {
|
|
if !DataviewFilterEqual(filters1[i], filters2[i]) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func DataviewViewsEqualSorted(views1, views2 []*model.BlockContentDataviewView) bool {
|
|
if len(views1) != len(views2) {
|
|
return false
|
|
}
|
|
for i := range views1 {
|
|
if !DataviewViewEqual(views1[i], views2[i]) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func DataviewSortEqual(sort1, sort2 *model.BlockContentDataviewSort) bool {
|
|
if sort1 == nil && sort2 != nil {
|
|
return false
|
|
}
|
|
if sort1 != nil && sort2 == nil {
|
|
return false
|
|
}
|
|
if sort1 == nil && sort2 == nil {
|
|
return true
|
|
}
|
|
if sort1.RelationKey != sort2.RelationKey {
|
|
return false
|
|
}
|
|
if sort1.Type != sort2.Type {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func DataviewFilterEqual(filter1, filter2 *model.BlockContentDataviewFilter) bool {
|
|
if filter1 == nil && filter2 != nil {
|
|
return false
|
|
}
|
|
if filter1 != nil && filter2 == nil {
|
|
return false
|
|
}
|
|
if filter1 == nil && filter2 == nil {
|
|
return true
|
|
}
|
|
if filter1.RelationKey != filter2.RelationKey {
|
|
return false
|
|
}
|
|
if filter1.Condition != filter2.Condition {
|
|
return false
|
|
}
|
|
if filter1.Operator != filter2.Operator {
|
|
return false
|
|
}
|
|
if filter1.RelationProperty != filter2.RelationProperty {
|
|
return false
|
|
}
|
|
if filter1.Value.Compare(filter2.Value) != 0 {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func DataviewViewEqual(view1, view2 *model.BlockContentDataviewView) bool {
|
|
if view1 == nil && view2 != nil {
|
|
return false
|
|
}
|
|
if view1 != nil && view2 == nil {
|
|
return false
|
|
}
|
|
if view1 == nil && view2 == nil {
|
|
return true
|
|
}
|
|
if view1.Id != view2.Id {
|
|
return false
|
|
}
|
|
if view1.Name != view2.Name {
|
|
return false
|
|
}
|
|
if view1.Type != view2.Type {
|
|
return false
|
|
}
|
|
if !DataviewFiltersEqualSorted(view1.Filters, view2.Filters) {
|
|
return false
|
|
}
|
|
if !DataviewSortsEqualSorted(view1.Sorts, view2.Sorts) {
|
|
return false
|
|
}
|
|
if len(view1.Relations) != len(view2.Relations) {
|
|
return false
|
|
// todo add relations check
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func SortedRange(s *types.Struct, f func(k string, v *types.Value)) {
|
|
if s == nil || s.Fields == nil {
|
|
return
|
|
}
|
|
var keys = make([]string, 0, len(s.Fields))
|
|
for k := range s.Fields {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
for _, k := range keys {
|
|
f(k, s.Fields[k])
|
|
}
|
|
}
|