github.com/nbd-wtf/go-nostr@v0.31.2/helpers.go (about)

     1  package nostr
     2  
     3  import (
     4  	"sync"
     5  	"unsafe"
     6  
     7  	"golang.org/x/exp/constraints"
     8  )
     9  
    10  const MAX_LOCKS = 50
    11  
    12  var namedMutexPool = make([]sync.Mutex, MAX_LOCKS)
    13  
    14  //go:noescape
    15  //go:linkname memhash runtime.memhash
    16  func memhash(p unsafe.Pointer, h, s uintptr) uintptr
    17  
    18  func namedLock(name string) (unlock func()) {
    19  	sptr := unsafe.StringData(name)
    20  	idx := uint64(memhash(unsafe.Pointer(sptr), 0, uintptr(len(name)))) % MAX_LOCKS
    21  	namedMutexPool[idx].Lock()
    22  	return namedMutexPool[idx].Unlock
    23  }
    24  
    25  func similar[E constraints.Ordered](as, bs []E) bool {
    26  	if len(as) != len(bs) {
    27  		return false
    28  	}
    29  
    30  	for _, a := range as {
    31  		for _, b := range bs {
    32  			if b == a {
    33  				goto next
    34  			}
    35  		}
    36  		// didn't find a B that corresponded to the current A
    37  		return false
    38  
    39  	next:
    40  		continue
    41  	}
    42  
    43  	return true
    44  }
    45  
    46  // Escaping strings for JSON encoding according to RFC8259.
    47  // Also encloses result in quotation marks "".
    48  func escapeString(dst []byte, s string) []byte {
    49  	dst = append(dst, '"')
    50  	for i := 0; i < len(s); i++ {
    51  		c := s[i]
    52  		switch {
    53  		case c == '"':
    54  			// quotation mark
    55  			dst = append(dst, []byte{'\\', '"'}...)
    56  		case c == '\\':
    57  			// reverse solidus
    58  			dst = append(dst, []byte{'\\', '\\'}...)
    59  		case c >= 0x20:
    60  			// default, rest below are control chars
    61  			dst = append(dst, c)
    62  		case c == 0x08:
    63  			dst = append(dst, []byte{'\\', 'b'}...)
    64  		case c < 0x09:
    65  			dst = append(dst, []byte{'\\', 'u', '0', '0', '0', '0' + c}...)
    66  		case c == 0x09:
    67  			dst = append(dst, []byte{'\\', 't'}...)
    68  		case c == 0x0a:
    69  			dst = append(dst, []byte{'\\', 'n'}...)
    70  		case c == 0x0c:
    71  			dst = append(dst, []byte{'\\', 'f'}...)
    72  		case c == 0x0d:
    73  			dst = append(dst, []byte{'\\', 'r'}...)
    74  		case c < 0x10:
    75  			dst = append(dst, []byte{'\\', 'u', '0', '0', '0', 0x57 + c}...)
    76  		case c < 0x1a:
    77  			dst = append(dst, []byte{'\\', 'u', '0', '0', '1', 0x20 + c}...)
    78  		case c < 0x20:
    79  			dst = append(dst, []byte{'\\', 'u', '0', '0', '1', 0x47 + c}...)
    80  		}
    81  	}
    82  	dst = append(dst, '"')
    83  	return dst
    84  }
    85  
    86  func arePointerValuesEqual[V comparable](a *V, b *V) bool {
    87  	if a == nil && b == nil {
    88  		return true
    89  	}
    90  	if a != nil && b != nil {
    91  		return *a == *b
    92  	}
    93  	return false
    94  }