jsoncodec.go raw

   1  package nostr
   2  
   3  // This is torly's hand-written JSON codec for the wire path. It follows the
   4  // Moxie/Nostr decoder: a single pass over the bytes, object keys dispatched
   5  // explicitly, and no encoding/json. Object keys are compared as strings rather
   6  // than by key[0], and an empty key is rejected before any indexing; `{"":1}`
   7  // is legal JSON and previously caused an index-out-of-range panic.
   8  //
   9  // String decoding validates every escape, rejects C0 controls, and bounds the
  10  // surrogate-pair lookahead correctly (i+10 < len, not <=).
  11  
  12  import (
  13  	"errors"
  14  	"fmt"
  15  	"strconv"
  16  	"strings"
  17  	"unicode/utf8"
  18  )
  19  
  20  var (
  21  	errJSONUnexpected = errors.New("nostr: unexpected JSON")
  22  	errJSONEmptyKey   = errors.New("nostr: empty JSON object key")
  23  )
  24  
  25  type jparser struct {
  26  	s []byte
  27  	i int
  28  }
  29  
  30  func (p *jparser) ws() {
  31  	for p.i < len(p.s) {
  32  		switch p.s[p.i] {
  33  		case ' ', '\t', '\n', '\r':
  34  			p.i++
  35  		default:
  36  			return
  37  		}
  38  	}
  39  }
  40  
  41  func (p *jparser) eof() bool { return p.i >= len(p.s) }
  42  
  43  func (p *jparser) expect(c byte) error {
  44  	if p.i >= len(p.s) || p.s[p.i] != c {
  45  		return fmt.Errorf("%w: expected %q at %d", errJSONUnexpected, c, p.i)
  46  	}
  47  	p.i++
  48  	return nil
  49  }
  50  
  51  func (p *jparser) finish() error {
  52  	p.ws()
  53  	if !p.eof() {
  54  		return fmt.Errorf("%w: trailing data at %d", errJSONUnexpected, p.i)
  55  	}
  56  	return nil
  57  }
  58  
  59  // ParseJSONString parses exactly one JSON string literal.
  60  func ParseJSONString(raw []byte) (string, error) {
  61  	p := &jparser{s: raw}
  62  	p.ws()
  63  	v, err := p.parseString()
  64  	if err != nil {
  65  		return "", err
  66  	}
  67  	if err := p.finish(); err != nil {
  68  		return "", err
  69  	}
  70  	return v, nil
  71  }
  72  
  73  // SplitArray splits a JSON array into its raw element slices. It is used for
  74  // relay messages such as ["EVENT",{...}] without allocating an interface tree.
  75  func SplitArray(raw []byte) ([][]byte, error) {
  76  	p := &jparser{s: raw}
  77  	p.ws()
  78  	if err := p.expect('['); err != nil {
  79  		return nil, err
  80  	}
  81  	p.ws()
  82  	if !p.eof() && p.s[p.i] == ']' {
  83  		p.i++
  84  		if err := p.finish(); err != nil {
  85  			return nil, err
  86  		}
  87  		return nil, nil
  88  	}
  89  	var out [][]byte
  90  	for {
  91  		p.ws()
  92  		start := p.i
  93  		if err := p.skipValue(); err != nil {
  94  			return nil, err
  95  		}
  96  		part := make([]byte, p.i-start)
  97  		copy(part, p.s[start:p.i])
  98  		out = append(out, part)
  99  		p.ws()
 100  		if p.eof() {
 101  			return nil, fmt.Errorf("%w: unterminated array", errJSONUnexpected)
 102  		}
 103  		switch p.s[p.i] {
 104  		case ',':
 105  			p.i++
 106  		case ']':
 107  			p.i++
 108  			if err := p.finish(); err != nil {
 109  				return nil, err
 110  			}
 111  			return out, nil
 112  		default:
 113  			return nil, fmt.Errorf("%w: expected , or ] at %d", errJSONUnexpected, p.i)
 114  		}
 115  	}
 116  }
 117  
 118  func (p *jparser) parseString() (string, error) {
 119  	if err := p.expect('"'); err != nil {
 120  		return "", err
 121  	}
 122  	out := make([]byte, 0, 32)
 123  	for p.i < len(p.s) {
 124  		c := p.s[p.i]
 125  		switch {
 126  		case c == '"':
 127  			p.i++
 128  			if !utf8.Valid(out) {
 129  				return "", fmt.Errorf("%w: invalid UTF-8 in string", errJSONUnexpected)
 130  			}
 131  			return string(out), nil
 132  		case c == '\\':
 133  			p.i++
 134  			if p.i >= len(p.s) {
 135  				return "", fmt.Errorf("%w: unterminated escape", errJSONUnexpected)
 136  			}
 137  			switch p.s[p.i] {
 138  			case '"', '\\', '/':
 139  				out = append(out, p.s[p.i])
 140  				p.i++
 141  			case 'b':
 142  				out = append(out, '\b')
 143  				p.i++
 144  			case 'f':
 145  				out = append(out, '\f')
 146  				p.i++
 147  			case 'n':
 148  				out = append(out, '\n')
 149  				p.i++
 150  			case 'r':
 151  				out = append(out, '\r')
 152  				p.i++
 153  			case 't':
 154  				out = append(out, '\t')
 155  				p.i++
 156  			case 'u':
 157  				r, err := p.parseUnicodeEscape()
 158  				if err != nil {
 159  					return "", err
 160  				}
 161  				out = append(out, string(rune(r))...)
 162  			default:
 163  				return "", fmt.Errorf("%w: bad escape \\%c", errJSONUnexpected, p.s[p.i])
 164  			}
 165  		case c < 0x20:
 166  			return "", fmt.Errorf("%w: control byte in string", errJSONUnexpected)
 167  		default:
 168  			out = append(out, c)
 169  			p.i++
 170  		}
 171  	}
 172  	return "", fmt.Errorf("%w: unterminated string", errJSONUnexpected)
 173  }
 174  
 175  // parseUnicodeEscape is called with p.i at 'u'. It consumes the four hex
 176  // digits and an optional low surrogate, with a bounds check that cannot run
 177  // past the end of the input.
 178  func (p *jparser) parseUnicodeEscape() (rune, error) {
 179  	if p.i+4 >= len(p.s) {
 180  		return 0, fmt.Errorf("%w: short \\u escape", errJSONUnexpected)
 181  	}
 182  	hi, ok := hex4(p.s[p.i+1 : p.i+5])
 183  	if !ok {
 184  		return 0, fmt.Errorf("%w: bad \\u escape", errJSONUnexpected)
 185  	}
 186  	p.i += 5 // 'u' + four digits
 187  	if hi >= 0xD800 && hi <= 0xDBFF {
 188  		// A high surrogate must be followed by a low surrogate: six more
 189  		// bytes, \uXXXX. The strict < is what prevents s[i+10] on truncation.
 190  		if p.i+6 > len(p.s) || p.s[p.i] != '\\' || p.s[p.i+1] != 'u' {
 191  			return 0, fmt.Errorf("%w: unpaired surrogate", errJSONUnexpected)
 192  		}
 193  		lo, ok := hex4(p.s[p.i+2 : p.i+6])
 194  		if !ok || lo < 0xDC00 || lo > 0xDFFF {
 195  			return 0, fmt.Errorf("%w: bad low surrogate", errJSONUnexpected)
 196  		}
 197  		p.i += 6
 198  		return rune(0x10000 + (hi-0xD800)*0x400 + (lo - 0xDC00)), nil
 199  	}
 200  	if hi >= 0xDC00 && hi <= 0xDFFF {
 201  		return 0, fmt.Errorf("%w: lone low surrogate", errJSONUnexpected)
 202  	}
 203  	return rune(hi), nil
 204  }
 205  
 206  func hex4(b []byte) (int, bool) {
 207  	if len(b) != 4 {
 208  		return 0, false
 209  	}
 210  	v := 0
 211  	for _, c := range b {
 212  		var d int
 213  		switch {
 214  		case c >= '0' && c <= '9':
 215  			d = int(c - '0')
 216  		case c >= 'a' && c <= 'f':
 217  			d = int(c-'a') + 10
 218  		case c >= 'A' && c <= 'F':
 219  			d = int(c-'A') + 10
 220  		default:
 221  			return 0, false
 222  		}
 223  		v = v<<4 | d
 224  	}
 225  	return v, true
 226  }
 227  
 228  func (p *jparser) parseInt64() (int64, error) {
 229  	p.ws()
 230  	start := p.i
 231  	if p.i < len(p.s) && p.s[p.i] == '-' {
 232  		p.i++
 233  	}
 234  	digits := false
 235  	for p.i < len(p.s) && p.s[p.i] >= '0' && p.s[p.i] <= '9' {
 236  		p.i++
 237  		digits = true
 238  	}
 239  	if !digits {
 240  		return 0, fmt.Errorf("%w: expected integer at %d", errJSONUnexpected, start)
 241  	}
 242  	if p.i < len(p.s) && (p.s[p.i] == '.' || p.s[p.i] == 'e' || p.s[p.i] == 'E') {
 243  		return 0, fmt.Errorf("%w: non-integer number at %d", errJSONUnexpected, start)
 244  	}
 245  	return strconv.ParseInt(string(p.s[start:p.i]), 10, 64)
 246  }
 247  
 248  func (p *jparser) parseStringArray() ([]string, error) {
 249  	p.ws()
 250  	if err := p.expect('['); err != nil {
 251  		return nil, err
 252  	}
 253  	p.ws()
 254  	if !p.eof() && p.s[p.i] == ']' {
 255  		p.i++
 256  		return nil, nil
 257  	}
 258  	var out []string
 259  	for {
 260  		p.ws()
 261  		v, err := p.parseString()
 262  		if err != nil {
 263  			return nil, err
 264  		}
 265  		out = append(out, v)
 266  		p.ws()
 267  		if p.eof() {
 268  			return nil, fmt.Errorf("%w: unterminated array", errJSONUnexpected)
 269  		}
 270  		switch p.s[p.i] {
 271  		case ',':
 272  			p.i++
 273  		case ']':
 274  			p.i++
 275  			return out, nil
 276  		default:
 277  			return nil, fmt.Errorf("%w: expected , or ]", errJSONUnexpected)
 278  		}
 279  	}
 280  }
 281  
 282  func (p *jparser) parseIntArray() ([]int, error) {
 283  	p.ws()
 284  	if err := p.expect('['); err != nil {
 285  		return nil, err
 286  	}
 287  	p.ws()
 288  	if !p.eof() && p.s[p.i] == ']' {
 289  		p.i++
 290  		return nil, nil
 291  	}
 292  	var out []int
 293  	for {
 294  		n, err := p.parseInt64()
 295  		if err != nil {
 296  			return nil, err
 297  		}
 298  		out = append(out, int(n))
 299  		p.ws()
 300  		if p.eof() {
 301  			return nil, fmt.Errorf("%w: unterminated array", errJSONUnexpected)
 302  		}
 303  		switch p.s[p.i] {
 304  		case ',':
 305  			p.i++
 306  		case ']':
 307  			p.i++
 308  			return out, nil
 309  		default:
 310  			return nil, fmt.Errorf("%w: expected , or ]", errJSONUnexpected)
 311  		}
 312  	}
 313  }
 314  
 315  func (p *jparser) parseTags() (Tags, error) {
 316  	p.ws()
 317  	if err := p.expect('['); err != nil {
 318  		return nil, err
 319  	}
 320  	p.ws()
 321  	if !p.eof() && p.s[p.i] == ']' {
 322  		p.i++
 323  		return nil, nil
 324  	}
 325  	var tags Tags
 326  	for {
 327  		p.ws()
 328  		inner, err := p.parseStringArray()
 329  		if err != nil {
 330  			return nil, err
 331  		}
 332  		tags = append(tags, Tag(inner))
 333  		p.ws()
 334  		if p.eof() {
 335  			return nil, fmt.Errorf("%w: unterminated tags", errJSONUnexpected)
 336  		}
 337  		switch p.s[p.i] {
 338  		case ',':
 339  			p.i++
 340  		case ']':
 341  			p.i++
 342  			return tags, nil
 343  		default:
 344  			return nil, fmt.Errorf("%w: expected , or ] in tags", errJSONUnexpected)
 345  		}
 346  	}
 347  }
 348  
 349  func (p *jparser) skipValue() error {
 350  	p.ws()
 351  	if p.eof() {
 352  		return fmt.Errorf("%w: missing value", errJSONUnexpected)
 353  	}
 354  	switch p.s[p.i] {
 355  	case '"':
 356  		_, err := p.parseString()
 357  		return err
 358  	case '{':
 359  		p.i++
 360  		p.ws()
 361  		if !p.eof() && p.s[p.i] == '}' {
 362  			p.i++
 363  			return nil
 364  		}
 365  		for {
 366  			p.ws()
 367  			if _, err := p.parseString(); err != nil {
 368  				return err
 369  			}
 370  			p.ws()
 371  			if err := p.expect(':'); err != nil {
 372  				return err
 373  			}
 374  			if err := p.skipValue(); err != nil {
 375  				return err
 376  			}
 377  			p.ws()
 378  			if p.eof() {
 379  				return fmt.Errorf("%w: unterminated object", errJSONUnexpected)
 380  			}
 381  			switch p.s[p.i] {
 382  			case ',':
 383  				p.i++
 384  			case '}':
 385  				p.i++
 386  				return nil
 387  			default:
 388  				return fmt.Errorf("%w: expected , or }", errJSONUnexpected)
 389  			}
 390  		}
 391  	case '[':
 392  		p.i++
 393  		p.ws()
 394  		if !p.eof() && p.s[p.i] == ']' {
 395  			p.i++
 396  			return nil
 397  		}
 398  		for {
 399  			if err := p.skipValue(); err != nil {
 400  				return err
 401  			}
 402  			p.ws()
 403  			if p.eof() {
 404  				return fmt.Errorf("%w: unterminated array", errJSONUnexpected)
 405  			}
 406  			switch p.s[p.i] {
 407  			case ',':
 408  				p.i++
 409  			case ']':
 410  				p.i++
 411  				return nil
 412  			default:
 413  				return fmt.Errorf("%w: expected , or ]", errJSONUnexpected)
 414  			}
 415  		}
 416  	case 't':
 417  		return p.literal("true")
 418  	case 'f':
 419  		return p.literal("false")
 420  	case 'n':
 421  		return p.literal("null")
 422  	default:
 423  		start := p.i
 424  		if p.s[p.i] == '-' {
 425  			p.i++
 426  		}
 427  		digits := false
 428  		for p.i < len(p.s) && ((p.s[p.i] >= '0' && p.s[p.i] <= '9') || p.s[p.i] == '.' || p.s[p.i] == 'e' || p.s[p.i] == 'E' || p.s[p.i] == '+' || p.s[p.i] == '-') {
 429  			p.i++
 430  			digits = true
 431  		}
 432  		if !digits {
 433  			return fmt.Errorf("%w: bad value at %d", errJSONUnexpected, start)
 434  		}
 435  		return nil
 436  	}
 437  }
 438  
 439  func (p *jparser) literal(v string) error {
 440  	if p.i+len(v) > len(p.s) || string(p.s[p.i:p.i+len(v)]) != v {
 441  		return fmt.Errorf("%w: expected %s", errJSONUnexpected, v)
 442  	}
 443  	p.i += len(v)
 444  	return nil
 445  }
 446  
 447  // ParseEvent decodes one NIP-01 event object. Unlike encoding/json, this
 448  // decoder never indexes an object key without checking it: an empty key is an
 449  // error, not a panic.
 450  func ParseEvent(data []byte) (*Event, error) {
 451  	p := &jparser{s: data}
 452  	p.ws()
 453  	if err := p.expect('{'); err != nil {
 454  		return nil, err
 455  	}
 456  	e := &Event{}
 457  	var haveID, havePub, haveCreated, haveKind, haveTags, haveContent, haveSig bool
 458  	first := true
 459  	for {
 460  		p.ws()
 461  		if p.eof() {
 462  			return nil, fmt.Errorf("%w: unterminated event object", errJSONUnexpected)
 463  		}
 464  		if p.s[p.i] == '}' {
 465  			p.i++
 466  			break
 467  		}
 468  		if !first {
 469  			if err := p.expect(','); err != nil {
 470  				return nil, err
 471  			}
 472  			p.ws()
 473  		}
 474  		key, err := p.parseString()
 475  		if err != nil {
 476  			return nil, err
 477  		}
 478  		if key == "" {
 479  			return nil, errJSONEmptyKey
 480  		}
 481  		p.ws()
 482  		if err := p.expect(':'); err != nil {
 483  			return nil, err
 484  		}
 485  		p.ws()
 486  		switch key {
 487  		case "id":
 488  			v, err := p.parseString()
 489  			if err != nil {
 490  				return nil, err
 491  			}
 492  			if err := Decode32(v, e.ID[:]); err != nil {
 493  				return nil, fmt.Errorf("%w: %q", ErrBadID, v)
 494  			}
 495  			haveID = true
 496  		case "pubkey":
 497  			v, err := p.parseString()
 498  			if err != nil {
 499  				return nil, err
 500  			}
 501  			if err := Decode32(v, e.PubKey[:]); err != nil {
 502  				return nil, fmt.Errorf("%w: %q", ErrBadPubKey, v)
 503  			}
 504  			havePub = true
 505  		case "created_at":
 506  			n, err := p.parseInt64()
 507  			if err != nil {
 508  				return nil, fmt.Errorf("%w: %v", ErrBadCreated, err)
 509  			}
 510  			e.CreatedAt = n
 511  			haveCreated = true
 512  		case "kind":
 513  			n, err := p.parseInt64()
 514  			if err != nil || n < 0 || n > MaxKind {
 515  				return nil, fmt.Errorf("%w: %d", ErrBadKind, n)
 516  			}
 517  			e.Kind = int(n)
 518  			haveKind = true
 519  		case "tags":
 520  			tags, err := p.parseTags()
 521  			if err != nil {
 522  				return nil, err
 523  			}
 524  			e.Tags = tags
 525  			haveTags = true
 526  		case "content":
 527  			v, err := p.parseString()
 528  			if err != nil {
 529  				return nil, err
 530  			}
 531  			e.Content = v
 532  			haveContent = true
 533  		case "sig":
 534  			v, err := p.parseString()
 535  			if err != nil {
 536  				return nil, err
 537  			}
 538  			if err := DecodeRaw(v, e.Sig[:]); err != nil {
 539  				return nil, fmt.Errorf("%w: %q", ErrBadSig, v)
 540  			}
 541  			haveSig = true
 542  		default:
 543  			if err := p.skipValue(); err != nil {
 544  				return nil, err
 545  			}
 546  		}
 547  		first = false
 548  	}
 549  	if err := p.finish(); err != nil {
 550  		return nil, err
 551  	}
 552  	if !(haveID && havePub && haveCreated && haveKind && haveTags && haveContent && haveSig) {
 553  		return nil, errors.New("nostr: event is missing a required field")
 554  	}
 555  	return e, nil
 556  }
 557  
 558  // ExtractID scans an object for a valid id without requiring the rest of the
 559  // event to be well formed. It is used to address an OK response to a malformed
 560  // event. An empty key is skipped, never indexed.
 561  func ExtractID(data []byte) string {
 562  	p := &jparser{s: data}
 563  	p.ws()
 564  	if err := p.expect('{'); err != nil {
 565  		return ""
 566  	}
 567  	for {
 568  		p.ws()
 569  		if p.eof() || p.s[p.i] == '}' {
 570  			return ""
 571  		}
 572  		key, err := p.parseString()
 573  		if err != nil {
 574  			return ""
 575  		}
 576  		p.ws()
 577  		if err := p.expect(':'); err != nil {
 578  			return ""
 579  		}
 580  		p.ws()
 581  		if key == "id" {
 582  			v, err := p.parseString()
 583  			if err != nil || !IsHex64(v) {
 584  				return ""
 585  			}
 586  			return v
 587  		}
 588  		if err := p.skipValue(); err != nil {
 589  			return ""
 590  		}
 591  		p.ws()
 592  		if p.eof() {
 593  			return ""
 594  		}
 595  		if p.s[p.i] == ',' {
 596  			p.i++
 597  			continue
 598  		}
 599  		return ""
 600  	}
 601  }
 602  
 603  // parseGraphQuery decodes the _graph filter extension. Both the canonical
 604  // four-element array and the legacy object form are accepted.
 605  func (p *jparser) parseGraphQuery() (*GraphQuery, error) {
 606  	p.ws()
 607  	if p.eof() {
 608  		return nil, fmt.Errorf("%w: missing _graph value", errJSONUnexpected)
 609  	}
 610  	switch p.s[p.i] {
 611  	case '[':
 612  		return p.parseGraphArray()
 613  	case '{':
 614  		return p.parseGraphObject()
 615  	default:
 616  		return nil, fmt.Errorf("%w: _graph must be an array or object", errJSONUnexpected)
 617  	}
 618  }
 619  
 620  // parseGraphArray decodes ["<pubkey>", <depth>, "<edge>", "<direction>"].
 621  func (p *jparser) parseGraphArray() (*GraphQuery, error) {
 622  	if err := p.expect('['); err != nil {
 623  		return nil, err
 624  	}
 625  	q := &GraphQuery{}
 626  	for i := 0; i < 4; i++ {
 627  		p.ws()
 628  		if p.eof() {
 629  			return nil, fmt.Errorf("%w: unterminated _graph array", errJSONUnexpected)
 630  		}
 631  		switch i {
 632  		case 0:
 633  			v, err := p.parseString()
 634  			if err != nil {
 635  				return nil, fmt.Errorf("_graph seed: %w", err)
 636  			}
 637  			q.Seed = v
 638  		case 1:
 639  			n, err := p.parseInt64()
 640  			if err != nil {
 641  				return nil, fmt.Errorf("_graph depth: %w", err)
 642  			}
 643  			if n > GraphMaxDepth {
 644  				return nil, errGraphDepth
 645  			}
 646  			q.Depth = int(n)
 647  		case 2:
 648  			v, err := p.parseString()
 649  			if err != nil {
 650  				return nil, fmt.Errorf("_graph edge: %w", err)
 651  			}
 652  			q.Edge = v
 653  		case 3:
 654  			v, err := p.parseString()
 655  			if err != nil {
 656  				return nil, fmt.Errorf("_graph direction: %w", err)
 657  			}
 658  			q.Direction = v
 659  		}
 660  		p.ws()
 661  		if p.eof() {
 662  			return nil, fmt.Errorf("%w: unterminated _graph array", errJSONUnexpected)
 663  		}
 664  		if i < 3 {
 665  			if err := p.expect(','); err != nil {
 666  				return nil, err
 667  			}
 668  		} else if p.s[p.i] != ']' {
 669  			return nil, fmt.Errorf("%w: _graph needs exactly four elements", errJSONUnexpected)
 670  		}
 671  	}
 672  	p.i++ // ']'
 673  	if err := q.normalize(); err != nil {
 674  		return nil, err
 675  	}
 676  	return q, nil
 677  }
 678  
 679  // parseGraphObject decodes the object form. Unknown keys are skipped, which
 680  // keeps the extension forward-compatible without making an empty key legal.
 681  func (p *jparser) parseGraphObject() (*GraphQuery, error) {
 682  	if err := p.expect('{'); err != nil {
 683  		return nil, err
 684  	}
 685  	q := &GraphQuery{}
 686  	first := true
 687  	for {
 688  		p.ws()
 689  		if p.eof() {
 690  			return nil, fmt.Errorf("%w: unterminated _graph object", errJSONUnexpected)
 691  		}
 692  		if p.s[p.i] == '}' {
 693  			p.i++
 694  			break
 695  		}
 696  		if !first {
 697  			if err := p.expect(','); err != nil {
 698  				return nil, err
 699  			}
 700  			p.ws()
 701  		}
 702  		key, err := p.parseString()
 703  		if err != nil {
 704  			return nil, err
 705  		}
 706  		if key == "" {
 707  			return nil, errJSONEmptyKey
 708  		}
 709  		p.ws()
 710  		if err := p.expect(':'); err != nil {
 711  			return nil, err
 712  		}
 713  		p.ws()
 714  		switch strings.ToLower(key) {
 715  		case "pubkey", "seed":
 716  			v, err := p.parseString()
 717  			if err != nil {
 718  				return nil, fmt.Errorf("_graph %s: %w", key, err)
 719  			}
 720  			q.Seed = v
 721  		case "depth":
 722  			n, err := p.parseInt64()
 723  			if err != nil {
 724  				return nil, fmt.Errorf("_graph depth: %w", err)
 725  			}
 726  			if n > GraphMaxDepth {
 727  				return nil, errGraphDepth
 728  			}
 729  			q.Depth = int(n)
 730  		case "edge":
 731  			v, err := p.parseString()
 732  			if err != nil {
 733  				return nil, fmt.Errorf("_graph edge: %w", err)
 734  			}
 735  			q.Edge = v
 736  		case "direction":
 737  			v, err := p.parseString()
 738  			if err != nil {
 739  				return nil, fmt.Errorf("_graph direction: %w", err)
 740  			}
 741  			q.Direction = v
 742  		default:
 743  			if err := p.skipValue(); err != nil {
 744  				return nil, err
 745  			}
 746  		}
 747  		first = false
 748  	}
 749  	if err := q.normalize(); err != nil {
 750  		return nil, err
 751  	}
 752  	return q, nil
 753  }
 754  
 755  // ParseFilter decodes one NIP-01 filter object. As with events, keys are
 756  // compared as strings and an empty key is an explicit error.
 757  func ParseFilter(raw []byte) (*Filter, error) {
 758  	p := &jparser{s: raw}
 759  	p.ws()
 760  	if err := p.expect('{'); err != nil {
 761  		return nil, fmt.Errorf("%w: %v", errBadFilter, err)
 762  	}
 763  	f := &Filter{}
 764  	first := true
 765  	for {
 766  		p.ws()
 767  		if p.eof() {
 768  			return nil, fmt.Errorf("%w: unterminated filter", errBadFilter)
 769  		}
 770  		if p.s[p.i] == '}' {
 771  			p.i++
 772  			break
 773  		}
 774  		if !first {
 775  			if err := p.expect(','); err != nil {
 776  				return nil, fmt.Errorf("%w: %v", errBadFilter, err)
 777  			}
 778  			p.ws()
 779  		}
 780  		key, err := p.parseString()
 781  		if err != nil {
 782  			return nil, fmt.Errorf("%w: %v", errBadFilter, err)
 783  		}
 784  		if key == "" {
 785  			return nil, fmt.Errorf("%w: %v", errBadFilter, errJSONEmptyKey)
 786  		}
 787  		p.ws()
 788  		if err := p.expect(':'); err != nil {
 789  			return nil, fmt.Errorf("%w: %v", errBadFilter, err)
 790  		}
 791  		p.ws()
 792  		switch key {
 793  		case "ids":
 794  			values, err := p.parseStringArray()
 795  			if err != nil {
 796  				return nil, fmt.Errorf("%w: ids: %v", errBadFilter, err)
 797  			}
 798  			for _, id := range values {
 799  				if !IsHex64(id) {
 800  					return nil, fmt.Errorf("%w: id %q is not 64 lowercase hex characters", errBadFilter, id)
 801  				}
 802  			}
 803  			f.IDs = values
 804  		case "authors":
 805  			values, err := p.parseStringArray()
 806  			if err != nil {
 807  				return nil, fmt.Errorf("%w: authors: %v", errBadFilter, err)
 808  			}
 809  			for _, a := range values {
 810  				if !IsHex64(a) {
 811  					return nil, fmt.Errorf("%w: author %q is not 64 lowercase hex characters", errBadFilter, a)
 812  				}
 813  			}
 814  			f.Authors = values
 815  		case "kinds":
 816  			values, err := p.parseIntArray()
 817  			if err != nil {
 818  				return nil, fmt.Errorf("%w: kinds: %v", errBadFilter, err)
 819  			}
 820  			for _, k := range values {
 821  				if k < 0 || k > MaxKind {
 822  					return nil, fmt.Errorf("%w: kind %d", errBadFilter, k)
 823  				}
 824  			}
 825  			f.Kinds = values
 826  		case "since":
 827  			n, err := p.parseInt64()
 828  			if err != nil {
 829  				return nil, fmt.Errorf("%w: since: %v", errBadFilter, err)
 830  			}
 831  			f.Since = n
 832  		case "until":
 833  			n, err := p.parseInt64()
 834  			if err != nil {
 835  				return nil, fmt.Errorf("%w: until: %v", errBadFilter, err)
 836  			}
 837  			f.Until = n
 838  		case "limit":
 839  			n, err := p.parseInt64()
 840  			if err != nil {
 841  				return nil, fmt.Errorf("%w: limit: %v", errBadFilter, err)
 842  			}
 843  			if n > 0 {
 844  				if n > 1<<31-1 {
 845  					n = 1<<31 - 1
 846  				}
 847  				f.Limit = int(n)
 848  			}
 849  		case "search":
 850  			v, err := p.parseString()
 851  			if err != nil {
 852  				return nil, fmt.Errorf("%w: search: %v", errBadFilter, err)
 853  			}
 854  			f.Search = v
 855  		case "_graph":
 856  			q, err := p.parseGraphQuery()
 857  			if err != nil {
 858  				return nil, fmt.Errorf("%w: _graph: %v", errBadFilter, err)
 859  			}
 860  			f.Graph = q
 861  		default:
 862  			if len(key) >= 2 && key[0] == '#' {
 863  				values, err := p.parseStringArray()
 864  				if err != nil {
 865  					return nil, fmt.Errorf("%w: %s: %v", errBadFilter, key, err)
 866  				}
 867  				if f.Tags == nil {
 868  					f.Tags = make(map[string][]string, 1)
 869  				}
 870  				f.Tags[key[1:]] = values
 871  			} else if err := p.skipValue(); err != nil {
 872  				return nil, fmt.Errorf("%w: %s: %v", errBadFilter, key, err)
 873  			}
 874  		}
 875  		first = false
 876  	}
 877  	if err := p.finish(); err != nil {
 878  		return nil, fmt.Errorf("%w: %v", errBadFilter, err)
 879  	}
 880  	return f, nil
 881  }
 882