2023-10-07 04:08:00 +00:00
|
|
|
package rfc3986
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
2023-10-07 07:54:15 +00:00
|
|
|
|
|
|
|
"sourcecode.social/reiver/go-erorr"
|
2023-10-07 04:08:00 +00:00
|
|
|
)
|
|
|
|
|
2023-10-07 08:02:03 +00:00
|
|
|
func IsPctEncodedPrefix(r rune) bool {
|
|
|
|
return '%' == r
|
|
|
|
}
|
|
|
|
|
2023-10-07 07:54:15 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-10-07 04:08:00 +00:00
|
|
|
func WritePctEncodedByte(writer io.Writer, b byte) error {
|
|
|
|
if nil == writer {
|
|
|
|
return errNilWriter
|
|
|
|
}
|
|
|
|
|
|
|
|
var buffer [3]byte = [3]byte{'%','.','.'}
|
|
|
|
|
|
|
|
{
|
|
|
|
var x byte = ((b>>4) % 16)
|
|
|
|
|
|
|
|
if x < 10 {
|
|
|
|
x += '0'
|
|
|
|
} else {
|
|
|
|
x += ('A' - 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer[1] = x
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
var x byte = (b & 0x0f)
|
|
|
|
|
|
|
|
if x < 10 {
|
|
|
|
x += '0'
|
|
|
|
} else {
|
|
|
|
x += ('A' - 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer[2] = x
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := writer.Write(buffer[:])
|
|
|
|
return err
|
|
|
|
}
|