2023-10-07 04:08:00 +00:00
package rfc3986
import (
"io"
2023-10-07 07:54:15 +00:00
2024-08-24 14:05:17 +00:00
"github.com/reiver/go-erorr"
2023-10-07 04:08:00 +00:00
)
2023-10-07 08:05:48 +00:00
const pctencodedprefix = '%'
2023-10-07 08:02:03 +00:00
func IsPctEncodedPrefix ( r rune ) bool {
2023-10-07 08:05:48 +00:00
return pctencodedprefix == r
2023-10-07 08:02:03 +00:00
}
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 [ : ]
{
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 )
}
2023-10-07 08:05:48 +00:00
b0 := buffer [ 0 ]
2023-10-07 07:54:15 +00:00
2023-10-07 08:05:48 +00:00
if ! IsPctEncodedPrefix ( rune ( b0 ) ) {
return 0 , erorr . Errorf ( "rfc3986:the 1st byte in pct-encoded string is not a percent-sign (%U) (%q) is actually %U (%q)" , pctencodedprefix , pctencodedprefix , b0 , b0 )
2023-10-07 07:54:15 +00:00
}
}
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
}