Add core packages, configuration system, and initial application structure

This commit is contained in:
2025-08-21 11:04:03 +01:00
parent b8db587d7b
commit ecaf52b98f
18 changed files with 12889 additions and 0 deletions

127
pkg/encoders/text/escape.go Normal file
View File

@@ -0,0 +1,127 @@
package text
// NostrEscape for JSON encoding according to RFC8259.
//
// This is the efficient implementation based on the NIP-01 specification:
//
// To prevent implementation differences from creating a different event ID for
// the same event, the following rules MUST be followed while serializing:
//
// No whitespace, line breaks or other unnecessary formatting should be included
// in the output JSON. No characters except the following should be escaped, and
// instead should be included verbatim:
//
// - A line break, 0x0A, as \n
// - A double quote, 0x22, as \"
// - A backslash, 0x5C, as \\
// - A carriage return, 0x0D, as \r
// - A tab character, 0x09, as \t
// - A backspace, 0x08, as \b
// - A form feed, 0x0C, as \f
//
// UTF-8 should be used for encoding.
func NostrEscape(dst, src []byte) []byte {
l := len(src)
for i := 0; i < l; i++ {
c := src[i]
switch {
case c == '"':
dst = append(dst, '\\', '"')
case c == '\\':
// if i+1 < l && src[i+1] == 'u' || i+1 < l && src[i+1] == '/' {
if i+1 < l && src[i+1] == 'u' {
dst = append(dst, '\\')
} else {
dst = append(dst, '\\', '\\')
}
case c == '\b':
dst = append(dst, '\\', 'b')
case c == '\t':
dst = append(dst, '\\', 't')
case c == '\n':
dst = append(dst, '\\', 'n')
case c == '\f':
dst = append(dst, '\\', 'f')
case c == '\r':
dst = append(dst, '\\', 'r')
default:
dst = append(dst, c)
}
}
return dst
}
// NostrUnescape reverses the operation of NostrEscape except instead of
// appending it to the provided slice, it rewrites it, eliminating a memory
// copy. Keep in mind that the original JSON will be mangled by this operation,
// but the resultant slices will cost zero allocations.
func NostrUnescape(dst []byte) (b []byte) {
var r, w int
for ; r < len(dst); r++ {
if dst[r] == '\\' {
r++
c := dst[r]
switch {
// nip-01 specifies the following single letter C-style escapes for control
// codes under 0x20.
//
// no others are specified but must be preserved, so only these can be
// safely decoded at runtime as they must be re-encoded when marshalled.
case c == '"':
dst[w] = '"'
w++
case c == '\\':
dst[w] = '\\'
w++
case c == 'b':
dst[w] = '\b'
w++
case c == 't':
dst[w] = '\t'
w++
case c == 'n':
dst[w] = '\n'
w++
case c == 'f':
dst[w] = '\f'
w++
case c == 'r':
dst[w] = '\r'
w++
// special cases for non-nip-01 specified json escapes (must be preserved for ID
// generation).
case c == 'u':
dst[w] = '\\'
w++
dst[w] = 'u'
w++
case c == '/':
dst[w] = '\\'
w++
dst[w] = '/'
w++
// special case for octal escapes (must be preserved for ID generation).
case c >= '0' && c <= '9':
dst[w] = '\\'
w++
dst[w] = c
w++
// anything else after a reverse solidus just preserve it.
default:
dst[w] = dst[r]
w++
dst[w] = c
w++
}
} else {
dst[w] = dst[r]
w++
}
}
b = dst[:w]
return
}