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 }