vendor/github.com/magiconair/properties/parser.go
author rjp <zimpenfish@gmail.com>
Mon, 23 Jan 2023 16:39:02 +0000
changeset 267 5b91a65ba95a
parent 260 445e01aede7e
child 265 05c40b36d3b2
permissions -rw-r--r--
Update to handle non-int64 IDs Pleroma/Akkoma and GotoSocial use opaque IDs rather than `int64`s like Mastodon which means that `madon` can't talk to either of those. This commit updates everything that can be an ID to `madon.ActivityID` which is an alias for `string` - can't create a specific type for it since there's more than a few places where they're concatenated directly to strings for URLs, etc. Which means it could just as easily be a direct `string` type itself but I find that having distinct types can often make the code more readable and understandable. One extra bit is that `statusOpts` has grown a `_hasReplyTo` boolean to indicate whether the `--in-reply-to` flag was given or not because we can't distinguish because "empty because default" or "empty because given and empty". Another way around this would be to set the default to some theoretically impossible or unlikely string but you never know when someone might spin up an instance where, e.g., admin posts have negative integer IDs.

// Copyright 2018 Frank Schroeder. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package properties

import (
	"fmt"
	"runtime"
)

type parser struct {
	lex *lexer
}

func parse(input string) (properties *Properties, err error) {
	p := &parser{lex: lex(input)}
	defer p.recover(&err)

	properties = NewProperties()
	key := ""
	comments := []string{}

	for {
		token := p.expectOneOf(itemComment, itemKey, itemEOF)
		switch token.typ {
		case itemEOF:
			goto done
		case itemComment:
			comments = append(comments, token.val)
			continue
		case itemKey:
			key = token.val
			if _, ok := properties.m[key]; !ok {
				properties.k = append(properties.k, key)
			}
		}

		token = p.expectOneOf(itemValue, itemEOF)
		if len(comments) > 0 {
			properties.c[key] = comments
			comments = []string{}
		}
		switch token.typ {
		case itemEOF:
			properties.m[key] = ""
			goto done
		case itemValue:
			properties.m[key] = token.val
		}
	}

done:
	return properties, nil
}

func (p *parser) errorf(format string, args ...interface{}) {
	format = fmt.Sprintf("properties: Line %d: %s", p.lex.lineNumber(), format)
	panic(fmt.Errorf(format, args...))
}

func (p *parser) expectOneOf(expected ...itemType) (token item) {
	token = p.lex.nextItem()
	for _, v := range expected {
		if token.typ == v {
			return token
		}
	}
	p.unexpected(token)
	panic("unexpected token")
}

func (p *parser) unexpected(token item) {
	p.errorf(token.String())
}

// recover is the handler that turns panics into returns from the top level of Parse.
func (p *parser) recover(errp *error) {
	e := recover()
	if e != nil {
		if _, ok := e.(runtime.Error); ok {
			panic(e)
		}
		*errp = e.(error)
	}
}