From 6a9cceffef481a0589922f405abd6a2865fb1e8a Mon Sep 17 00:00:00 2001 From: Charles Iliya Krempeaux Date: Fri, 8 Dec 2023 03:29:33 -0800 Subject: [PATCH] initial commits --- decnum/bytes.go | 41 +++++ decnum/bytes_test.go | 422 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 463 insertions(+) create mode 100644 decnum/bytes.go create mode 100644 decnum/bytes_test.go diff --git a/decnum/bytes.go b/decnum/bytes.go new file mode 100644 index 0000000..e5387b6 --- /dev/null +++ b/decnum/bytes.go @@ -0,0 +1,41 @@ +package decnum + +import ( + "sourcecode.social/reiver/go-rfc2396/digit" +) + +// Bytes return a 'decnum'. +// +// decnum = 1*digit +// +// 'decnum' doesn't appear in IETF RFC-2396 by name. But instead is part of `IPv4address`. +// +// IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit +// +// I called this a 'decnum' (i.e., "decimal number"). +func Bytes(p []byte) (result []byte, rest []byte, ok bool) { + + length := len(p) + + if length <= 0 { + return nil, nil, false + } + + { + p0 := p[0] + + if !digit.ByteIs(p0) { + return nil, p, false + } + } + + { + for i,b := range p { + if !digit.ByteIs(b) { + return p[:i], p[i:], true + } + } + + return p, nil, true + } +} diff --git a/decnum/bytes_test.go b/decnum/bytes_test.go new file mode 100644 index 0000000..548b12d --- /dev/null +++ b/decnum/bytes_test.go @@ -0,0 +1,422 @@ +package decnum_test + +import ( + "testing" + + "bytes" + + "sourcecode.social/reiver/go-rfc2396/decnum" +) + +func TestBytes(t *testing.T) { + + tests := []struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + { + Value: nil, + ExpectedResult: nil, + ExpectedRest: nil, + ExpectedOK: false, + }, + { + Value: []byte(nil), + ExpectedResult: nil, + ExpectedRest: nil, + ExpectedOK: false, + }, + + + + { + Value: []byte{}, + ExpectedResult: nil, + ExpectedRest: nil, + ExpectedOK: false, + }, + { + Value: []byte(""), + ExpectedResult: nil, + ExpectedRest: nil, + ExpectedOK: false, + }, + + + + { + Value: []byte{'%','f','0', '%','9','f', '%','9','9', '%','8','b'}, // == "🙂" + ExpectedResult: nil, + ExpectedRest: []byte{'%','f','0', '%','9','f', '%','9','9', '%','8','b'}, + ExpectedOK: false, + }, + + + + { + Value: []byte{'$',',',';',':','@','&','=','+', '-','_','.','!','~','*','\'','(',')', '0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F', 'a','b','c','d','e','f', ' '}, + ExpectedResult: nil, + ExpectedRest: []byte{'$',',',';',':','@','&','=','+', '-','_','.','!','~','*','\'','(',')', '0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F', 'a','b','c','d','e','f', ' '}, + ExpectedOK: false, + }, + + + + { + Value: []byte("0"), + ExpectedResult: []byte("0"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("1"), + ExpectedResult: []byte("1"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("2"), + ExpectedResult: []byte("2"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("3"), + ExpectedResult: []byte("3"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("4"), + ExpectedResult: []byte("4"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("5"), + ExpectedResult: []byte("5"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("6"), + ExpectedResult: []byte("6"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("7"), + ExpectedResult: []byte("7"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("8"), + ExpectedResult: []byte("8"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("9"), + ExpectedResult: []byte("9"), + ExpectedRest: nil, + ExpectedOK: true, + }, + + + + { + Value: []byte("8080"), + ExpectedResult: []byte("8080"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("8080 "), + ExpectedResult: []byte("8080"), + ExpectedRest: []byte(" "), + ExpectedOK: true, + }, + { + Value: []byte("8080/"), + ExpectedResult: []byte("8080"), + ExpectedRest: []byte("/"), + ExpectedOK: true, + }, + { + Value: []byte("8080\n"), + ExpectedResult: []byte("8080"), + ExpectedRest: []byte("\n"), + ExpectedOK: true, + }, + { + Value: []byte("8080."), + ExpectedResult: []byte("8080"), + ExpectedRest: []byte("."), + ExpectedOK: true, + }, + + + + + { + Value: []byte("10203040506070809"), + ExpectedResult: []byte("10203040506070809"), + ExpectedRest: nil, + ExpectedOK: true, + }, + { + Value: []byte("10203040506070809 "), + ExpectedResult: []byte("10203040506070809"), + ExpectedRest: []byte(" "), + ExpectedOK: true, + }, + { + Value: []byte("10203040506070809/"), + ExpectedResult: []byte("10203040506070809"), + ExpectedRest: []byte("/"), + ExpectedOK: true, + }, + { + Value: []byte("10203040506070809\n"), + ExpectedResult: []byte("10203040506070809"), + ExpectedRest: []byte("\n"), + ExpectedOK: true, + }, + { + Value: []byte("10203040506070809."), + ExpectedResult: []byte("10203040506070809"), + ExpectedRest: []byte("."), + ExpectedOK: true, + }, + + + + { + Value: []byte("192.168.0.1"), + ExpectedResult: []byte("192"), + ExpectedRest: []byte(".168.0.1"), + ExpectedOK: true, + }, + } + + for _, b1 := range []byte{'0','1','2','3','4','5','6','7','8','9'} { + for _, b2 := range []byte{'0','1','2','3','4','5','6','7','8','9'} { + + { + test := struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + Value: []byte{b1, b2}, + ExpectedResult: []byte{b1, b2}, + ExpectedRest: nil, + ExpectedOK: true, + } + + tests = append(tests, test) + } + + { + test := struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + Value: []byte{b1, b2, ' '}, + ExpectedResult: []byte{b1, b2}, + ExpectedRest: []byte{' '}, + ExpectedOK: true, + } + + tests = append(tests, test) + } + + { + test := struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + Value: []byte{b1, b2, '/'}, + ExpectedResult: []byte{b1, b2}, + ExpectedRest: []byte{'/'}, + ExpectedOK: true, + } + + tests = append(tests, test) + } + + { + test := struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + Value: []byte{b1, b2, '\n'}, + ExpectedResult: []byte{b1, b2}, + ExpectedRest: []byte{'\n'}, + ExpectedOK: true, + } + + tests = append(tests, test) + } + + { + test := struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + Value: []byte{b1, b2, 'A'}, + ExpectedResult: []byte{b1, b2}, + ExpectedRest: []byte{'A'}, + ExpectedOK: true, + } + + tests = append(tests, test) + } + } + } + + for _, b1 := range []byte{'0','1','2','3','4','5','6','7','8','9'} { + for _, b2 := range []byte{'0','1','2','3','4','5','6','7','8','9'} { + for _, b3 := range []byte{'0','1','2','3','4','5','6','7','8','9'} { + + { + test := struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + Value: []byte{b1, b2, b3}, + ExpectedResult: []byte{b1, b2, b3}, + ExpectedRest: nil, + ExpectedOK: true, + } + + tests = append(tests, test) + } + + { + test := struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + Value: []byte{b1, b2, b3, ' '}, + ExpectedResult: []byte{b1, b2, b3}, + ExpectedRest: []byte{' '}, + ExpectedOK: true, + } + + tests = append(tests, test) + } + + { + test := struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + Value: []byte{b1, b2, b3, '/'}, + ExpectedResult: []byte{b1, b2, b3}, + ExpectedRest: []byte{'/'}, + ExpectedOK: true, + } + + tests = append(tests, test) + } + + { + test := struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + Value: []byte{b1, b2, b3, '\n'}, + ExpectedResult: []byte{b1, b2, b3}, + ExpectedRest: []byte{'\n'}, + ExpectedOK: true, + } + + tests = append(tests, test) + } + + { + test := struct{ + Value []byte + ExpectedResult []byte + ExpectedRest []byte + ExpectedOK bool + }{ + Value: []byte{b1, b2, b3, 'A'}, + ExpectedResult: []byte{b1, b2, b3}, + ExpectedRest: []byte{'A'}, + ExpectedOK: true, + } + + tests = append(tests, test) + } + + } + } + } + + for testNumber, test := range tests { + + actualResult, actualRest, actualOK := decnum.Bytes(test.Value) + + { + expected := test.ExpectedOK + actual := actualOK + + if expected != actual { + t.Errorf("For test #%d, the actual ok-result is not what was expected.", testNumber) + t.Logf("EXPECTED: %t", expected) + t.Logf("ACTUAL: %t", actual) + t.Logf("VALUE: %q (%#v)", test.Value, test.Value) + continue + } + } + + { + expected := test.ExpectedResult + actual := actualResult + + if !bytes.Equal(expected,actual) { + t.Errorf("For test #%d, the actual result is not what was expected.", testNumber) + t.Logf("EXPECTED: %q (%#v)", expected, expected) + t.Logf("ACTUAL: %q (%#v)", actual, actual) + t.Logf("VALUE: %q (%#v)", test.Value, test.Value) + t.Logf("ACTUAL-REST: %q (%#v)", actualRest, actualRest) + continue + } + } + + { + expected := test.ExpectedRest + actual := actualRest + + if !bytes.Equal(expected,actual) { + t.Errorf("For test #%d, the actual rest-result is not what was expected.", testNumber) + t.Logf("EXPECTED: %q (%#v)", expected, expected) + t.Logf("ACTUAL: %q (%#v)", actual, actual) + t.Logf("VALUE: %q (%#v)", test.Value, test.Value) + continue + } + } + } +}