kawipiko/sources/lib/common/metadata.go

109 lines
2.6 KiB
Go
Raw Normal View History

package common
import "bytes"
import "fmt"
import "regexp"
import "sort"
func MetadataEncode (_metadata map[string]string) ([]byte, error) {
_metadataArray := make ([][2]string, 0, len (_metadata))
for _key, _value := range _metadata {
_metadataArray = append (_metadataArray, [2]string {_key, _value})
}
sort.Slice (_metadataArray,
func (i int, j int) (bool) {
return _metadataArray[i][0] < _metadataArray[j][0]
})
_buffer := & bytes.Buffer {}
for _, _metadata := range _metadataArray {
_key := _metadata[0]
_value := _metadata[1]
if ! metadataKeyRegex.MatchString (_key) {
return nil, fmt.Errorf ("[2f761e02] invalid metadata key: `%s`", _key)
}
if _value == "" {
continue
}
if ! metadataValueRegex.MatchString (_value) {
return nil, fmt.Errorf ("[e8faf5bd] invalid metadata value: `%s`", _value)
}
_buffer.Write ([]byte (_key))
_buffer.Write ([]byte (": "))
_buffer.Write ([]byte (_value))
_buffer.Write ([]byte ("\r\n"))
}
_data := _buffer.Bytes ()
return _data, nil
}
func MetadataDecode (_data []byte) ([][2]string, error) {
_metadata := make ([][2]string, 0, 16)
_metadataAppend := func (_key []byte, _value []byte) () {
_metadata = append (_metadata, [2]string { string (_key), string (_value) })
}
if _error := MetadataDecodeIterate (_data, _metadataAppend); _error != nil {
return nil, _error
} else {
return _metadata, nil
}
}
func MetadataDecodeIterate (_data []byte, _callback func ([]byte, []byte) ()) (error) {
_dataSize := len (_data)
_headerOffset := 0
for {
if _headerOffset == _dataSize {
return nil
}
_data := _data[_headerOffset :]
_headerLimit := bytes.IndexByte (_data, '\r')
if (_headerLimit == -1) {
return fmt.Errorf ("[2d0d442a] invalid metadata encoding")
}
if ((_headerOffset + _headerLimit) == (_dataSize - 1)) || (_data[_headerLimit + 1] != '\n') {
return fmt.Errorf ("[0e319685] invalid metadata encoding")
}
_headerOffset += _headerLimit + 2
_data = _data[: _headerLimit]
_separator := bytes.Index (_data, []byte (": "))
if _separator == -1 {
return fmt.Errorf ("[41f3756c] invalid metadata encoding")
}
_key := _data[: _separator]
_value := _data[_separator + 3 :]
if len (_key) == 0 {
return fmt.Errorf ("[c3f5e8f3] invalid metadata encoding (empty key)")
}
if len (_value) == 0 {
return fmt.Errorf ("[d6a923b6] invalid metadata encoding (empty value)")
}
_callback (_key, _value)
}
}
var metadataKeyRegex = regexp.MustCompile (`\A(?:[A-Z0-9](?:[a-z0-9]?[a-z]+)(?:-[A-Z0-9](?:[a-z0-9]?[a-z]+))*)|ETag\z`)
var metadataValueRegex = regexp.MustCompile (`\A[[:graph:]](?: ?[[:graph:]]+)*\z`)