summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/text/internal/catmsg/catmsg.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/text/internal/catmsg/catmsg.go')
-rw-r--r--vendor/golang.org/x/text/internal/catmsg/catmsg.go376
1 files changed, 0 insertions, 376 deletions
diff --git a/vendor/golang.org/x/text/internal/catmsg/catmsg.go b/vendor/golang.org/x/text/internal/catmsg/catmsg.go
deleted file mode 100644
index 32d6c20..0000000
--- a/vendor/golang.org/x/text/internal/catmsg/catmsg.go
+++ /dev/null
@@ -1,376 +0,0 @@
-// Copyright 2017 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package catmsg contains support types for package x/text/message/catalog.
-//
-// This package contains the low-level implementations of Message used by the
-// catalog package and provides primitives for other packages to implement their
-// own. For instance, the plural package provides functionality for selecting
-// translation strings based on the plural category of substitution arguments.
-//
-//
-// Encoding and Decoding
-//
-// Catalogs store Messages encoded as a single string. Compiling a message into
-// a string both results in compacter representation and speeds up evaluation.
-//
-// A Message must implement a Compile method to convert its arbitrary
-// representation to a string. The Compile method takes an Encoder which
-// facilitates serializing the message. Encoders also provide more context of
-// the messages's creation (such as for which language the message is intended),
-// which may not be known at the time of the creation of the message.
-//
-// Each message type must also have an accompanying decoder registered to decode
-// the message. This decoder takes a Decoder argument which provides the
-// counterparts for the decoding.
-//
-//
-// Renderers
-//
-// A Decoder must be initialized with a Renderer implementation. These
-// implementations must be provided by packages that use Catalogs, typically
-// formatting packages such as x/text/message. A typical user will not need to
-// worry about this type; it is only relevant to packages that do string
-// formatting and want to use the catalog package to handle localized strings.
-//
-// A package that uses catalogs for selecting strings receives selection results
-// as sequence of substrings passed to the Renderer. The following snippet shows
-// how to express the above example using the message package.
-//
-// message.Set(language.English, "You are %d minute(s) late.",
-// catalog.Var("minutes", plural.Select(1, "one", "minute")),
-// catalog.String("You are %[1]d ${minutes} late."))
-//
-// p := message.NewPrinter(language.English)
-// p.Printf("You are %d minute(s) late.", 5) // always 5 minutes late.
-//
-// To evaluate the Printf, package message wraps the arguments in a Renderer
-// that is passed to the catalog for message decoding. The call sequence that
-// results from evaluating the above message, assuming the person is rather
-// tardy, is:
-//
-// Render("You are %[1]d ")
-// Arg(1)
-// Render("minutes")
-// Render(" late.")
-//
-// The calls to Arg is caused by the plural.Select execution, which evaluates
-// the argument to determine whether the singular or plural message form should
-// be selected. The calls to Render reports the partial results to the message
-// package for further evaluation.
-package catmsg
-
-import (
- "errors"
- "fmt"
- "strconv"
- "strings"
- "sync"
-
- "golang.org/x/text/language"
-)
-
-// A Handle refers to a registered message type.
-type Handle int
-
-// A Handler decodes and evaluates data compiled by a Message and sends the
-// result to the Decoder. The output may depend on the value of the substitution
-// arguments, accessible by the Decoder's Arg method. The Handler returns false
-// if there is no translation for the given substitution arguments.
-type Handler func(d *Decoder) bool
-
-// Register records the existence of a message type and returns a Handle that
-// can be used in the Encoder's EncodeMessageType method to create such
-// messages. The prefix of the name should be the package path followed by
-// an optional disambiguating string.
-// Register will panic if a handle for the same name was already registered.
-func Register(name string, handler Handler) Handle {
- mutex.Lock()
- defer mutex.Unlock()
-
- if _, ok := names[name]; ok {
- panic(fmt.Errorf("catmsg: handler for %q already exists", name))
- }
- h := Handle(len(handlers))
- names[name] = h
- handlers = append(handlers, handler)
- return h
-}
-
-// These handlers require fixed positions in the handlers slice.
-const (
- msgVars Handle = iota
- msgFirst
- msgRaw
- msgString
- numFixed
-)
-
-const prefix = "golang.org/x/text/internal/catmsg."
-
-var (
- mutex sync.Mutex
- names = map[string]Handle{
- prefix + "Vars": msgVars,
- prefix + "First": msgFirst,
- prefix + "Raw": msgRaw,
- prefix + "String": msgString,
- }
- handlers = make([]Handler, numFixed)
-)
-
-func init() {
- // This handler is a message type wrapper that initializes a decoder
- // with a variable block. This message type, if present, is always at the
- // start of an encoded message.
- handlers[msgVars] = func(d *Decoder) bool {
- blockSize := int(d.DecodeUint())
- d.vars = d.data[:blockSize]
- d.data = d.data[blockSize:]
- return d.executeMessage()
- }
-
- // First takes the first message in a sequence that results in a match for
- // the given substitution arguments.
- handlers[msgFirst] = func(d *Decoder) bool {
- for !d.Done() {
- if d.ExecuteMessage() {
- return true
- }
- }
- return false
- }
-
- handlers[msgRaw] = func(d *Decoder) bool {
- d.Render(d.data)
- return true
- }
-
- // A String message alternates between a string constant and a variable
- // substitution.
- handlers[msgString] = func(d *Decoder) bool {
- for !d.Done() {
- if str := d.DecodeString(); str != "" {
- d.Render(str)
- }
- if d.Done() {
- break
- }
- d.ExecuteSubstitution()
- }
- return true
- }
-}
-
-var (
- // ErrIncomplete indicates a compiled message does not define translations
- // for all possible argument values. If this message is returned, evaluating
- // a message may result in the ErrNoMatch error.
- ErrIncomplete = errors.New("catmsg: incomplete message; may not give result for all inputs")
-
- // ErrNoMatch indicates no translation message matched the given input
- // parameters when evaluating a message.
- ErrNoMatch = errors.New("catmsg: no translation for inputs")
-)
-
-// A Message holds a collection of translations for the same phrase that may
-// vary based on the values of substitution arguments.
-type Message interface {
- // Compile encodes the format string(s) of the message as a string for later
- // evaluation.
- //
- // The first call Compile makes on the encoder must be EncodeMessageType.
- // The handle passed to this call may either be a handle returned by
- // Register to encode a single custom message, or HandleFirst followed by
- // a sequence of calls to EncodeMessage.
- //
- // Compile must return ErrIncomplete if it is possible for evaluation to
- // not match any translation for a given set of formatting parameters.
- // For example, selecting a translation based on plural form may not yield
- // a match if the form "Other" is not one of the selectors.
- //
- // Compile may return any other application-specific error. For backwards
- // compatibility with package like fmt, which often do not do sanity
- // checking of format strings ahead of time, Compile should still make an
- // effort to have some sensible fallback in case of an error.
- Compile(e *Encoder) error
-}
-
-// Compile converts a Message to a data string that can be stored in a Catalog.
-// The resulting string can subsequently be decoded by passing to the Execute
-// method of a Decoder.
-func Compile(tag language.Tag, macros Dictionary, m Message) (data string, err error) {
- // TODO: pass macros so they can be used for validation.
- v := &Encoder{inBody: true} // encoder for variables
- v.root = v
- e := &Encoder{root: v, parent: v, tag: tag} // encoder for messages
- err = m.Compile(e)
- // This package serves te message package, which in turn is meant to be a
- // drop-in replacement for fmt. With the fmt package, format strings are
- // evaluated lazily and errors are handled by substituting strings in the
- // result, rather then returning an error. Dealing with multiple languages
- // makes it more important to check errors ahead of time. We chose to be
- // consistent and compatible and allow graceful degradation in case of
- // errors.
- buf := e.buf[stripPrefix(e.buf):]
- if len(v.buf) > 0 {
- // Prepend variable block.
- b := make([]byte, 1+maxVarintBytes+len(v.buf)+len(buf))
- b[0] = byte(msgVars)
- b = b[:1+encodeUint(b[1:], uint64(len(v.buf)))]
- b = append(b, v.buf...)
- b = append(b, buf...)
- buf = b
- }
- if err == nil {
- err = v.err
- }
- return string(buf), err
-}
-
-// FirstOf is a message type that prints the first message in the sequence that
-// resolves to a match for the given substitution arguments.
-type FirstOf []Message
-
-// Compile implements Message.
-func (s FirstOf) Compile(e *Encoder) error {
- e.EncodeMessageType(msgFirst)
- err := ErrIncomplete
- for i, m := range s {
- if err == nil {
- return fmt.Errorf("catalog: message argument %d is complete and blocks subsequent messages", i-1)
- }
- err = e.EncodeMessage(m)
- }
- return err
-}
-
-// Var defines a message that can be substituted for a placeholder of the same
-// name. If an expression does not result in a string after evaluation, Name is
-// used as the substitution. For example:
-// Var{
-// Name: "minutes",
-// Message: plural.Select(1, "one", "minute"),
-// }
-// will resolve to minute for singular and minutes for plural forms.
-type Var struct {
- Name string
- Message Message
-}
-
-var errIsVar = errors.New("catmsg: variable used as message")
-
-// Compile implements Message.
-//
-// Note that this method merely registers a variable; it does not create an
-// encoded message.
-func (v *Var) Compile(e *Encoder) error {
- if err := e.addVar(v.Name, v.Message); err != nil {
- return err
- }
- // Using a Var by itself is an error. If it is in a sequence followed by
- // other messages referring to it, this error will be ignored.
- return errIsVar
-}
-
-// Raw is a message consisting of a single format string that is passed as is
-// to the Renderer.
-//
-// Note that a Renderer may still do its own variable substitution.
-type Raw string
-
-// Compile implements Message.
-func (r Raw) Compile(e *Encoder) (err error) {
- e.EncodeMessageType(msgRaw)
- // Special case: raw strings don't have a size encoding and so don't use
- // EncodeString.
- e.buf = append(e.buf, r...)
- return nil
-}
-
-// String is a message consisting of a single format string which contains
-// placeholders that may be substituted with variables.
-//
-// Variable substitutions are marked with placeholders and a variable name of
-// the form ${name}. Any other substitutions such as Go templates or
-// printf-style substitutions are left to be done by the Renderer.
-//
-// When evaluation a string interpolation, a Renderer will receive separate
-// calls for each placeholder and interstitial string. For example, for the
-// message: "%[1]v ${invites} %[2]v to ${their} party." The sequence of calls
-// is:
-// d.Render("%[1]v ")
-// d.Arg(1)
-// d.Render(resultOfInvites)
-// d.Render(" %[2]v to ")
-// d.Arg(2)
-// d.Render(resultOfTheir)
-// d.Render(" party.")
-// where the messages for "invites" and "their" both use a plural.Select
-// referring to the first argument.
-//
-// Strings may also invoke macros. Macros are essentially variables that can be
-// reused. Macros may, for instance, be used to make selections between
-// different conjugations of a verb. See the catalog package description for an
-// overview of macros.
-type String string
-
-// Compile implements Message. It parses the placeholder formats and returns
-// any error.
-func (s String) Compile(e *Encoder) (err error) {
- msg := string(s)
- const subStart = "${"
- hasHeader := false
- p := 0
- b := []byte{}
- for {
- i := strings.Index(msg[p:], subStart)
- if i == -1 {
- break
- }
- b = append(b, msg[p:p+i]...)
- p += i + len(subStart)
- if i = strings.IndexByte(msg[p:], '}'); i == -1 {
- b = append(b, "$!(MISSINGBRACE)"...)
- err = fmt.Errorf("catmsg: missing '}'")
- p = len(msg)
- break
- }
- name := strings.TrimSpace(msg[p : p+i])
- if q := strings.IndexByte(name, '('); q == -1 {
- if !hasHeader {
- hasHeader = true
- e.EncodeMessageType(msgString)
- }
- e.EncodeString(string(b))
- e.EncodeSubstitution(name)
- b = b[:0]
- } else if j := strings.IndexByte(name[q:], ')'); j == -1 {
- // TODO: what should the error be?
- b = append(b, "$!(MISSINGPAREN)"...)
- err = fmt.Errorf("catmsg: missing ')'")
- } else if x, sErr := strconv.ParseUint(strings.TrimSpace(name[q+1:q+j]), 10, 32); sErr != nil {
- // TODO: handle more than one argument
- b = append(b, "$!(BADNUM)"...)
- err = fmt.Errorf("catmsg: invalid number %q", strings.TrimSpace(name[q+1:q+j]))
- } else {
- if !hasHeader {
- hasHeader = true
- e.EncodeMessageType(msgString)
- }
- e.EncodeString(string(b))
- e.EncodeSubstitution(name[:q], int(x))
- b = b[:0]
- }
- p += i + 1
- }
- b = append(b, msg[p:]...)
- if !hasHeader {
- // Simplify string to a raw string.
- Raw(string(b)).Compile(e)
- } else if len(b) > 0 {
- e.EncodeString(string(b))
- }
- return err
-}