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  }