From 6d4d82cd8fdc0cb30216b9aad53c2d4710b77ce6 Mon Sep 17 00:00:00 2001 From: Charles Iliya Krempeaux Date: Thu, 30 Nov 2023 07:22:18 -0800 Subject: [PATCH] utf8.RuneScanner.Buffered() --- runescanner.go | 19 ++++ runescanner_buffered_test.go | 206 +++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 runescanner_buffered_test.go diff --git a/runescanner.go b/runescanner.go index d867c54..d648003 100644 --- a/runescanner.go +++ b/runescanner.go @@ -29,6 +29,25 @@ func NewRuneScanner(reader io.Reader) *RuneScanner { return &runescanner } +// Buffered returns the number of bytes the UTF-8 encoding of the current buffered rune takes up, if there is a buffered rune. +// +// A buffered rune would come from someone calleding .UnreadRune(). +// +// If there is not buffered rune then .Buffered() returns zero (0). +// +// So, for example, if .UnreadRune() was called for the rune 'A' (U+0041), then .Buffered() would return 1. +// +// And, for example, if .UnreadRune() was called for the rune '🙂' (U+1F642), then .Buffered() would return 4. +// +// This method has been made to be semantically the same as bufio.Reader.Buffered() +func (receiver *RuneScanner) Buffered() int { + if !receiver.peeked { + return 0 + } + + return receiver.prevSize +} + func (receiver *RuneScanner) ReadRune() (rune, int, error) { if nil == receiver { return RuneError, 0, errNilReceiver diff --git a/runescanner_buffered_test.go b/runescanner_buffered_test.go new file mode 100644 index 0000000..979221c --- /dev/null +++ b/runescanner_buffered_test.go @@ -0,0 +1,206 @@ +package utf8_test + +import ( + "testing" + + "io" + "strings" + "sourcecode.social/reiver/go-utf8" +) + +func TestRuneScanner_Buffered(t *testing.T) { + + var s string = "🙂 apple 😈 banana 👾 cherry 🎃" + + var reader io.Reader = strings.NewReader(s) + var runescanner utf8.RuneScanner = utf8.WrapRuneScanner(reader) + + { + expected := 0 + actual := runescanner.Buffered() + + if expected != actual { + t.Errorf("The actual number of buffered-bytes is not was expected.") + t.Logf("EXPECTED: %d", expected) + t.Logf("ACTUAL: %d", actual) + return + } + } + + { + r, n, err := runescanner.ReadRune() + if nil != err { + t.Errorf("Did not expect an error when trying to .ReadRune() but actually got one.") + t.Logf("ERROR: (%T) %s", err, err) + return + } + + { + expected := '🙂' + actual := r + + if expected != actual { + t.Errorf("The actual read rune is not what was expected.") + t.Logf("EXPECTED: %q (%U)", expected, expected) + t.Logf("ACTUAL: %q (%U)", actual, actual) + return + } + } + + { + expected := 4 + actual := n + + if expected != actual { + t.Errorf("The actual number of bytes read is not what was expected.") + t.Logf("EXPECTED: %d", expected) + t.Logf("ACTUAL: %d", actual) + return + } + } + } + + { + expected := 0 + actual := runescanner.Buffered() + + if expected != actual { + t.Errorf("The actual number of buffered-bytes is not was expected.") + t.Logf("EXPECTED: %d", expected) + t.Logf("ACTUAL: %d", actual) + return + } + } + + { + err := runescanner.UnreadRune() + if nil != err { + t.Errorf("Did not expect an error when trying to .UnreadRune() but actually got one.") + t.Logf("ERROR: (%T) %s", err, err) + return + } + } + + { + expected := 4 + actual := runescanner.Buffered() + + if expected != actual { + t.Errorf("The actual number of buffered-bytes is not was expected.") + t.Logf("EXPECTED: %d", expected) + t.Logf("ACTUAL: %d", actual) + return + } + } + + { + r, n, err := runescanner.ReadRune() + if nil != err { + t.Errorf("Did not expect an error when trying to .ReadRune() but actually got one.") + t.Logf("ERROR: (%T) %s", err, err) + return + } + + { + expected := '🙂' + actual := r + + if expected != actual { + t.Errorf("The actual read rune is not what was expected.") + t.Logf("EXPECTED: %q (%U)", expected, expected) + t.Logf("ACTUAL: %q (%U)", actual, actual) + return + } + } + + { + expected := 4 + actual := n + + if expected != actual { + t.Errorf("The actual number of bytes read is not what was expected.") + t.Logf("EXPECTED: %d", expected) + t.Logf("ACTUAL: %d", actual) + return + } + } + } + + { + expected := 0 + actual := runescanner.Buffered() + + if expected != actual { + t.Errorf("The actual number of buffered-bytes is not was expected.") + t.Logf("EXPECTED: %d", expected) + t.Logf("ACTUAL: %d", actual) + return + } + } + + { + r, n, err := runescanner.ReadRune() + if nil != err { + t.Errorf("Did not expect an error when trying to .ReadRune() but actually got one.") + t.Logf("ERROR: (%T) %s", err, err) + return + } + + { + expected := ' ' + actual := r + + if expected != actual { + t.Errorf("The actual read rune is not what was expected.") + t.Logf("EXPECTED: %q (%U)", expected, expected) + t.Logf("ACTUAL: %q (%U)", actual, actual) + return + } + } + + { + expected := 1 + actual := n + + if expected != actual { + t.Errorf("The actual number of bytes read is not what was expected.") + t.Logf("EXPECTED: %d", expected) + t.Logf("ACTUAL: %d", actual) + return + } + } + } + + { + expected := 0 + actual := runescanner.Buffered() + + if expected != actual { + t.Errorf("The actual number of buffered-bytes is not was expected.") + t.Logf("EXPECTED: %d", expected) + t.Logf("ACTUAL: %d", actual) + return + } + } + + { + err := runescanner.UnreadRune() + if nil != err { + t.Errorf("Did not expect an error when trying to .UnreadRune() but actually got one.") + t.Logf("ERROR: (%T) %s", err, err) + return + } + } + + { + expected := 1 + actual := runescanner.Buffered() + + if expected != actual { + t.Errorf("The actual number of buffered-bytes is not was expected.") + t.Logf("EXPECTED: %d", expected) + t.Logf("ACTUAL: %d", actual) + return + } + } +}