| package gbytes | 
 |  | 
 | import ( | 
 | 	"fmt" | 
 | 	"regexp" | 
 |  | 
 | 	"github.com/onsi/gomega/format" | 
 | ) | 
 |  | 
 | //Objects satisfying the BufferProvider can be used with the Say matcher. | 
 | type BufferProvider interface { | 
 | 	Buffer() *Buffer | 
 | } | 
 |  | 
 | /* | 
 | Say is a Gomega matcher that operates on gbytes.Buffers: | 
 |  | 
 | 	Ω(buffer).Should(Say("something")) | 
 |  | 
 | will succeed if the unread portion of the buffer matches the regular expression "something". | 
 |  | 
 | When Say succeeds, it fast forwards the gbytes.Buffer's read cursor to just after the succesful match. | 
 | Thus, subsequent calls to Say will only match against the unread portion of the buffer | 
 |  | 
 | Say pairs very well with Eventually.  To asser that a buffer eventually receives data matching "[123]-star" within 3 seconds you can: | 
 |  | 
 | 	Eventually(buffer, 3).Should(Say("[123]-star")) | 
 |  | 
 | Ditto with consistently.  To assert that a buffer does not receive data matching "never-see-this" for 1 second you can: | 
 |  | 
 | 	Consistently(buffer, 1).ShouldNot(Say("never-see-this")) | 
 |  | 
 | In addition to bytes.Buffers, Say can operate on objects that implement the gbytes.BufferProvider interface. | 
 | In such cases, Say simply operates on the *gbytes.Buffer returned by Buffer() | 
 |  | 
 | If the buffer is closed, the Say matcher will tell Eventually to abort. | 
 | */ | 
 | func Say(expected string, args ...interface{}) *sayMatcher { | 
 | 	formattedRegexp := expected | 
 | 	if len(args) > 0 { | 
 | 		formattedRegexp = fmt.Sprintf(expected, args...) | 
 | 	} | 
 | 	return &sayMatcher{ | 
 | 		re: regexp.MustCompile(formattedRegexp), | 
 | 	} | 
 | } | 
 |  | 
 | type sayMatcher struct { | 
 | 	re              *regexp.Regexp | 
 | 	receivedSayings []byte | 
 | } | 
 |  | 
 | func (m *sayMatcher) buffer(actual interface{}) (*Buffer, bool) { | 
 | 	var buffer *Buffer | 
 |  | 
 | 	switch x := actual.(type) { | 
 | 	case *Buffer: | 
 | 		buffer = x | 
 | 	case BufferProvider: | 
 | 		buffer = x.Buffer() | 
 | 	default: | 
 | 		return nil, false | 
 | 	} | 
 |  | 
 | 	return buffer, true | 
 | } | 
 |  | 
 | func (m *sayMatcher) Match(actual interface{}) (success bool, err error) { | 
 | 	buffer, ok := m.buffer(actual) | 
 | 	if !ok { | 
 | 		return false, fmt.Errorf("Say must be passed a *gbytes.Buffer or BufferProvider.  Got:\n%s", format.Object(actual, 1)) | 
 | 	} | 
 |  | 
 | 	didSay, sayings := buffer.didSay(m.re) | 
 | 	m.receivedSayings = sayings | 
 |  | 
 | 	return didSay, nil | 
 | } | 
 |  | 
 | func (m *sayMatcher) FailureMessage(actual interface{}) (message string) { | 
 | 	return fmt.Sprintf( | 
 | 		"Got stuck at:\n%s\nWaiting for:\n%s", | 
 | 		format.IndentString(string(m.receivedSayings), 1), | 
 | 		format.IndentString(m.re.String(), 1), | 
 | 	) | 
 | } | 
 |  | 
 | func (m *sayMatcher) NegatedFailureMessage(actual interface{}) (message string) { | 
 | 	return fmt.Sprintf( | 
 | 		"Saw:\n%s\nWhich matches the unexpected:\n%s", | 
 | 		format.IndentString(string(m.receivedSayings), 1), | 
 | 		format.IndentString(m.re.String(), 1), | 
 | 	) | 
 | } | 
 |  | 
 | func (m *sayMatcher) MatchMayChangeInTheFuture(actual interface{}) bool { | 
 | 	switch x := actual.(type) { | 
 | 	case *Buffer: | 
 | 		return !x.Closed() | 
 | 	case BufferProvider: | 
 | 		return !x.Buffer().Closed() | 
 | 	default: | 
 | 		return true | 
 | 	} | 
 | } |