initial commits
parent
c2d871f6e0
commit
63e3bc4355
|
@ -5,5 +5,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
errNilReader = erorr.Error("rfc3986: nil reader")
|
||||||
errNilWriter = erorr.Error("rfc3986: nil writer")
|
errNilWriter = erorr.Error("rfc3986: nil writer")
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,8 +2,95 @@ package rfc3986
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"sourcecode.social/reiver/go-erorr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ReadPctEncodedByte(reader io.Reader) (byte, error) {
|
||||||
|
if nil == reader {
|
||||||
|
return 0, errNilReader
|
||||||
|
}
|
||||||
|
|
||||||
|
var buffer [1]byte
|
||||||
|
var p []byte = buffer[:]
|
||||||
|
|
||||||
|
{
|
||||||
|
const expected byte = '%'
|
||||||
|
|
||||||
|
n, err := reader.Read(p)
|
||||||
|
if nil != err {
|
||||||
|
return 0, erorr.Errorf("rfc3986: could not read the 1st byte in pct-encoded string because: %w", err)
|
||||||
|
}
|
||||||
|
if 1 != n {
|
||||||
|
return 0, erorr.Errorf("rfc3986: problem reading the 1st byte in pct-encoded string — expected to have read 1 byte but actually read %d bytes.", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := buffer[0]
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
return 0, erorr.Errorf("rfc3986:the 1st byte in pct-encoded string is not a percent-sign (%U) (%q) is actually %U (%q)", expected, expected, actual, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result byte = 0
|
||||||
|
|
||||||
|
{
|
||||||
|
n, err := reader.Read(p)
|
||||||
|
if nil != err {
|
||||||
|
return 0, erorr.Errorf("rfc3986: could not read the 2nd byte in pct-encoded string because: %w", err)
|
||||||
|
}
|
||||||
|
if 1 != n {
|
||||||
|
return 0, erorr.Errorf("rfc3986: problem reading the 2nd byte in pct-encoded string — expected to have read 1 byte but actually read %d bytes.", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
b0 := buffer[0]
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case '0' <= b0 && b0 <= '9':
|
||||||
|
b0 -= '0'
|
||||||
|
case 'A' <= b0 && b0 <= 'F':
|
||||||
|
b0 -= 'A'
|
||||||
|
b0 += 10
|
||||||
|
case 'a' <= b0 && b0 <= 'f':
|
||||||
|
b0 -= 'a'
|
||||||
|
b0 += 10
|
||||||
|
default:
|
||||||
|
return 0, erorr.Errorf("rfc3986: the 2nd byte in the pct-encoded string is not an IETF RFC-2234 'HEXDIG'")
|
||||||
|
}
|
||||||
|
|
||||||
|
result |= (b0 << 4)
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
n, err := reader.Read(p)
|
||||||
|
if nil != err {
|
||||||
|
return 0, erorr.Errorf("rfc3986: could not read the 3rd byte in pct-encoded string because: %w", err)
|
||||||
|
}
|
||||||
|
if 1 != n {
|
||||||
|
return 0, erorr.Errorf("rfc3986: problem reading the 3rd byte in pct-encoded string — expected to have read 1 byte but actually read %d bytes.", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
b0 := buffer[0]
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case '0' <= b0 && b0 <= '9':
|
||||||
|
b0 -= '0'
|
||||||
|
case 'A' <= b0 && b0 <= 'F':
|
||||||
|
b0 -= 'A'
|
||||||
|
b0 += 10
|
||||||
|
case 'a' <= b0 && b0 <= 'f':
|
||||||
|
b0 -= 'a'
|
||||||
|
b0 += 10
|
||||||
|
default:
|
||||||
|
return 0, erorr.Errorf("rfc3986: the 2nd byte in the pct-encoded string is not an IETF RFC-2234 'HEXDIG'")
|
||||||
|
}
|
||||||
|
|
||||||
|
result |= b0
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func WritePctEncodedByte(writer io.Writer, b byte) error {
|
func WritePctEncodedByte(writer io.Writer, b byte) error {
|
||||||
if nil == writer {
|
if nil == writer {
|
||||||
return errNilWriter
|
return errNilWriter
|
||||||
|
|
|
@ -0,0 +1,345 @@
|
||||||
|
package rfc3986_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"sourcecode.social/reiver/go-rfc3986"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReadPctEncodedByte(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct{
|
||||||
|
Value string
|
||||||
|
Expected byte
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Value: "%00",
|
||||||
|
Expected: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%01",
|
||||||
|
Expected: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%02",
|
||||||
|
Expected: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%03",
|
||||||
|
Expected: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%04",
|
||||||
|
Expected: 4,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%05",
|
||||||
|
Expected: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%06",
|
||||||
|
Expected: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%07",
|
||||||
|
Expected: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%08",
|
||||||
|
Expected: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%09",
|
||||||
|
Expected: 9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0A",
|
||||||
|
Expected: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0B",
|
||||||
|
Expected: 11,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0C",
|
||||||
|
Expected: 12,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0D",
|
||||||
|
Expected: 13,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0E",
|
||||||
|
Expected: 14,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0F",
|
||||||
|
Expected: 15,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: "%0a",
|
||||||
|
Expected: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0b",
|
||||||
|
Expected: 11,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0c",
|
||||||
|
Expected: 12,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0d",
|
||||||
|
Expected: 13,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0e",
|
||||||
|
Expected: 14,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%0f",
|
||||||
|
Expected: 15,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: "%10",
|
||||||
|
Expected: 16,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%11",
|
||||||
|
Expected: 17,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%12",
|
||||||
|
Expected: 18,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%13",
|
||||||
|
Expected: 19,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%14",
|
||||||
|
Expected: 20,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%15",
|
||||||
|
Expected: 21,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%16",
|
||||||
|
Expected: 22,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%17",
|
||||||
|
Expected: 23,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%18",
|
||||||
|
Expected: 24,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%19",
|
||||||
|
Expected: 25,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1A",
|
||||||
|
Expected: 26,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1B",
|
||||||
|
Expected: 27,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1C",
|
||||||
|
Expected: 28,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1D",
|
||||||
|
Expected: 29,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1E",
|
||||||
|
Expected: 30,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1F",
|
||||||
|
Expected: 31,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: "%1a",
|
||||||
|
Expected: 26,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1b",
|
||||||
|
Expected: 27,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1c",
|
||||||
|
Expected: 28,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1d",
|
||||||
|
Expected: 29,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1e",
|
||||||
|
Expected: 30,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%1f",
|
||||||
|
Expected: 31,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: "%20F",
|
||||||
|
Expected: 32,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: "%FA",
|
||||||
|
Expected: 250,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%FB",
|
||||||
|
Expected: 251,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%FC",
|
||||||
|
Expected: 252,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%FD",
|
||||||
|
Expected: 253,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%FE",
|
||||||
|
Expected: 254,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%FF",
|
||||||
|
Expected: 255,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: "%Fa",
|
||||||
|
Expected: 250,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%Fb",
|
||||||
|
Expected: 251,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%Fc",
|
||||||
|
Expected: 252,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%Fd",
|
||||||
|
Expected: 253,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%Fe",
|
||||||
|
Expected: 254,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%Ff",
|
||||||
|
Expected: 255,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: "%fA",
|
||||||
|
Expected: 250,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%fB",
|
||||||
|
Expected: 251,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%fC",
|
||||||
|
Expected: 252,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%fD",
|
||||||
|
Expected: 253,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%fE",
|
||||||
|
Expected: 254,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%fF",
|
||||||
|
Expected: 255,
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Value: "%fa",
|
||||||
|
Expected: 250,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%fb",
|
||||||
|
Expected: 251,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%fc",
|
||||||
|
Expected: 252,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%fd",
|
||||||
|
Expected: 253,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%fe",
|
||||||
|
Expected: 254,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: "%ff",
|
||||||
|
Expected: 255,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for testNumber, test := range tests {
|
||||||
|
|
||||||
|
var reader io.Reader = strings.NewReader(test.Value)
|
||||||
|
|
||||||
|
actual, err := rfc3986.ReadPctEncodedByte(reader)
|
||||||
|
if nil != err {
|
||||||
|
t.Errorf("For test #%d, did not expect an error but actually got one." , testNumber)
|
||||||
|
t.Logf("ERROR: (%T) %s", err, err)
|
||||||
|
t.Logf("VALUE: %q", test.Value)
|
||||||
|
t.Logf("EXPECTED: %d (0x%X)", test.Expected, test.Expected)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
expected := test.Expected
|
||||||
|
|
||||||
|
if expected != actual {
|
||||||
|
t.Errorf("For test #%d, the actual byte returned is not what was expected.", testNumber)
|
||||||
|
t.Logf("EXPECTED: %d (0x%X)", expected, expected)
|
||||||
|
t.Logf("ACTUAL: %d (0x%X)", actual, actual)
|
||||||
|
t.Logf("VALUE: %q", test.Value)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue