pegic/executor/util/encoding.go (116 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package util import ( "encoding/binary" "errors" "fmt" "strconv" "strings" "unicode/utf8" ) type Encoder interface { // encode string into a bytes EncodeAll(string) ([]byte, error) // decode from bytes to string DecodeAll([]byte) (string, error) // String returns name of the encoding. String() string } type utf8Encoder struct { } func (*utf8Encoder) EncodeAll(s string) ([]byte, error) { if !utf8.ValidString(s) { return nil, errors.New("invalid utf8 string") } return []byte(s), nil // go uses utf8 by default. } func (*utf8Encoder) DecodeAll(s []byte) (string, error) { if !utf8.Valid(s) { return "", errors.New("invalid utf8 bytes") } return string(s), nil } func (*utf8Encoder) String() string { return "UTF8" } type int32Encoder struct { } func (*int32Encoder) EncodeAll(s string) ([]byte, error) { i, err := strconv.ParseInt(s, 10, 32 /*bits*/) if err != nil { return nil, errors.New("invalid INT32") } value := make([]byte, 4 /*bytes*/) binary.BigEndian.PutUint32(value, uint32(i)) return value, nil } func (*int32Encoder) DecodeAll(s []byte) (string, error) { if len(s) != 4 { return "", fmt.Errorf("bytes is not a valid INT32") } i := binary.BigEndian.Uint32(s) return fmt.Sprint(int32(i)), nil } func (*int32Encoder) String() string { return "INT32" } type int64Encoder struct { } func (*int64Encoder) EncodeAll(s string) ([]byte, error) { i, err := strconv.ParseInt(s, 10, 64 /*bits*/) if err != nil { return nil, errors.New("invalid INT64") } value := make([]byte, 8 /*bytes*/) binary.BigEndian.PutUint64(value, uint64(i)) return value, nil } func (*int64Encoder) DecodeAll(s []byte) (string, error) { if len(s) != 8 { return "", fmt.Errorf("bytes is not a valid INT64") } i := binary.BigEndian.Uint64(s) return fmt.Sprint(int64(i)), nil } func (*int64Encoder) String() string { return "INT64" } type goBytesEncoder struct { } func (*goBytesEncoder) EncodeAll(s string) ([]byte, error) { bytesInStrList := strings.Split(s, " ") value := make([]byte, len(bytesInStrList)) for i, byteStr := range bytesInStrList { b, err := strconv.Atoi(byteStr) if err != nil || b > 255 || b < 0 { // byte ranges from [0, 255] return nil, fmt.Errorf("invalid go byte \"%s\"", byteStr) } value[i] = byte(b) } return value, nil } func (*goBytesEncoder) DecodeAll(bytes []byte) (string, error) { s := make([]string, len(bytes)) for i, c := range bytes { s[i] = fmt.Sprint(uint8(c)) } return strings.Join(s, ","), nil } func (*goBytesEncoder) String() string { return "BYTES" } // NewEncoder returns nil if the given name is invalid. func NewEncoder(name string) Encoder { name = strings.ToLower(name) switch name { case "utf8", "utf-8": return &utf8Encoder{} case "int32": return &int32Encoder{} case "int64": return &int64Encoder{} case "bytes": return &goBytesEncoder{} case "javabytes": return &javaBytesEncoder{} case "asciihex": return &asciiHexEncoder{} // TODO(wutao): support hex array, such as 0x37, 0xFF, ... default: return nil } }