message/catalog: separate concerns of firstInSequence

The code really should be in catmsg.
Expose the functionality there and remove from
pacakge catalog. Use type aliases to make this
work in a more convenient way.

Change-Id: I250a5ae193e890ec0e20e8b04f3bd26c06448c7b
Reviewed-on: https://go-review.googlesource.com/80595
Run-TryBot: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: Nigel Tao <nigeltao@golang.org>
diff --git a/internal/catmsg/catmsg.go b/internal/catmsg/catmsg.go
index f8abf37..32d6c20 100644
--- a/internal/catmsg/catmsg.go
+++ b/internal/catmsg/catmsg.go
@@ -74,13 +74,6 @@
 // A Handle refers to a registered message type.
 type Handle int
 
-// First is used as a Handle to EncodeMessageType, followed by a series of calls
-// to EncodeMessage, to implement selecting the first matching Message.
-//
-// TODO: this can be removed once we either can use type aliases or if the
-// internals of this package are merged with the catalog package.
-var First Handle = msgFirst
-
 // 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
@@ -236,6 +229,23 @@
 	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:
diff --git a/internal/catmsg/catmsg_test.go b/internal/catmsg/catmsg_test.go
index df913a1..485d19c 100644
--- a/internal/catmsg/catmsg_test.go
+++ b/internal/catmsg/catmsg_test.go
@@ -246,7 +246,7 @@
 
 func (s seq) Compile(e *Encoder) (err error) {
 	err = ErrIncomplete
-	e.EncodeMessageType(First)
+	e.EncodeMessageType(msgFirst)
 	for _, m := range s {
 		// Pass only the last error, but allow erroneous or complete messages
 		// here to allow testing different scenarios.
diff --git a/internal/catmsg/codec.go b/internal/catmsg/codec.go
index ab587f8..49c9fc9 100755
--- a/internal/catmsg/codec.go
+++ b/internal/catmsg/codec.go
@@ -169,7 +169,7 @@
 	case err == ErrIncomplete:
 		if Handle(e.buf[0]) != msgFirst {
 			seq := &Encoder{root: e.root, parent: e}
-			seq.EncodeMessageType(First)
+			seq.EncodeMessageType(msgFirst)
 			e.flushTo(seq)
 			e = seq
 		}
diff --git a/message/catalog/catalog.go b/message/catalog/catalog.go
index 957444c..d641d61 100644
--- a/message/catalog/catalog.go
+++ b/message/catalog/catalog.go
@@ -154,7 +154,6 @@
 
 import (
 	"errors"
-	"fmt"
 
 	"golang.org/x/text/internal/catmsg"
 	"golang.org/x/text/language"
@@ -223,12 +222,6 @@
 // ErrNotFound indicates there was no message for the given key.
 var ErrNotFound = errors.New("catalog: message not found")
 
-// A Message holds a collection of translations for the same phrase that may
-// vary based on the values of substitution arguments.
-type Message interface {
-	catmsg.Message
-}
-
 // String specifies a plain message string. It can be used as fallback if no
 // other strings match or as a simple standalone message.
 //
@@ -247,22 +240,6 @@
 	return &catmsg.Var{Name: name, Message: firstInSequence(msg)}
 }
 
-// firstInSequence is a message type that prints the first message in the
-// sequence that resolves to a match for the given substitution arguments.
-type firstInSequence []Message
-
-func (s firstInSequence) Compile(e *catmsg.Encoder) error {
-	e.EncodeMessageType(catmsg.First)
-	err := catmsg.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
-}
-
 // Context returns a Context for formatting messages.
 // Only one Message may be formatted per context at any given time.
 func (c *Catalog) Context(tag language.Tag, r catmsg.Renderer) *Context {
diff --git a/message/catalog/go19.go b/message/catalog/go19.go
new file mode 100644
index 0000000..147fc7c
--- /dev/null
+++ b/message/catalog/go19.go
@@ -0,0 +1,15 @@
+// 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.
+
+// +build go1.9
+
+package catalog
+
+import "golang.org/x/text/internal/catmsg"
+
+// A Message holds a collection of translations for the same phrase that may
+// vary based on the values of substitution arguments.
+type Message = catmsg.Message
+
+type firstInSequence = catmsg.FirstOf
diff --git a/message/catalog/gopre19.go b/message/catalog/gopre19.go
new file mode 100644
index 0000000..a9753b9
--- /dev/null
+++ b/message/catalog/gopre19.go
@@ -0,0 +1,23 @@
+// 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.
+
+// +build !go1.9
+
+package catalog
+
+import "golang.org/x/text/internal/catmsg"
+
+// A Message holds a collection of translations for the same phrase that may
+// vary based on the values of substitution arguments.
+type Message interface {
+	catmsg.Message
+}
+
+func firstInSequence(m []Message) catmsg.Message {
+	a := []catmsg.Message{}
+	for _, m := range m {
+		a = append(a, m)
+	}
+	return catmsg.FirstOf(a)
+}