github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/services/fn.go (about) 1 /* 2 * Copyright 2023 Wang Min Xiang 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package services 19 20 import ( 21 "github.com/aacfactory/fns/context" 22 "github.com/aacfactory/fns/transports" 23 "sort" 24 "strings" 25 "unsafe" 26 ) 27 28 type FnInfo struct { 29 Name string `json:"name"` 30 Readonly bool `json:"readonly"` 31 Internal bool `json:"internal"` 32 } 33 34 type FnInfos []FnInfo 35 36 func (f FnInfos) Len() int { 37 return len(f) 38 } 39 40 func (f FnInfos) Less(i, j int) bool { 41 return strings.Compare(f[i].Name, f[j].Name) < 0 42 } 43 44 func (f FnInfos) Swap(i, j int) { 45 f[i], f[j] = f[j], f[i] 46 } 47 48 func (f FnInfos) Find(name []byte) (info FnInfo, found bool) { 49 ns := unsafe.String(unsafe.SliceData(name), len(name)) 50 n := f.Len() 51 if n < 65 { 52 for _, fn := range f { 53 if fn.Name == ns { 54 info = fn 55 found = true 56 break 57 } 58 } 59 return 60 } 61 i, j := 0, n 62 for i < j { 63 h := int(uint(i+j) >> 1) 64 if strings.Compare(f[h].Name, ns) < 0 { 65 i = h + 1 66 } else { 67 j = h 68 } 69 } 70 found = i < n && f[i].Name == ns 71 if found { 72 info = f[i] 73 } 74 return 75 } 76 77 type Fn interface { 78 Name() string 79 Internal() bool 80 Readonly() bool 81 Handle(ctx Request) (v any, err error) 82 } 83 84 type Fns []Fn 85 86 func (f Fns) Len() int { 87 return len(f) 88 } 89 90 func (f Fns) Less(i, j int) bool { 91 return strings.Compare(f[i].Name(), f[j].Name()) < 0 92 } 93 94 func (f Fns) Swap(i, j int) { 95 f[i], f[j] = f[j], f[i] 96 } 97 98 func (f Fns) Add(v Fn) Fns { 99 ff := append(f, v) 100 sort.Sort(ff) 101 return ff 102 } 103 104 func (f Fns) Find(name []byte) (v Fn, found bool) { 105 ns := unsafe.String(unsafe.SliceData(name), len(name)) 106 n := f.Len() 107 if n < 65 { 108 for _, fn := range f { 109 if fn.Name() == ns { 110 v = fn 111 found = true 112 break 113 } 114 } 115 return 116 } 117 i, j := 0, n 118 for i < j { 119 h := int(uint(i+j) >> 1) 120 if strings.Compare(f[h].Name(), ns) < 0 { 121 i = h + 1 122 } else { 123 j = h 124 } 125 } 126 found = i < n && f[i].Name() == ns 127 if found { 128 v = f[i] 129 } 130 return 131 } 132 133 func MarkDeprecated(ctx context.Context) { 134 if header, has := transports.TryLoadResponseHeader(ctx); has { 135 header.Set(transports.DeprecatedHeaderName, []byte{'t', 'r', 'u', 'e'}) 136 } 137 }