Documentation
¶
Index ¶
- Constants
- func AesCbcDecrypt(cipherText, key, iv []byte) (plainText []byte)
- func AesCbcEncrypt(plainText, key, iv []byte) (cipherText []byte)
- func AesEcbDecrypt(cipherText, key []byte) (plainText []byte)
- func AesEcbEncrypt(plainText, key []byte) (cipherText []byte)
- func AppPath() string
- func ApproxEqualUnitNo(original, proposed string) bool
- func Catch(err *error)
- func DesEcbDecrypt(cipherText, key []byte) (plainText []byte)
- func DesEcbEncrypt(plainText, key []byte) (cipherText []byte)
- func DisableMockHTTPClient()
- func GetField(object interface{}, fieldName string) interface{}
- func MockConf()
- func MockHTTPClientError(err error)
- func MockHTTPClientRespBody(body string)
- func MockHTTPClientRespBodyFromFile(mockFile string)
- func MockStaticUnixMilli(t int64)
- func Must(err error)
- func NormalizeTrainNo(trainNo string) (results []string)
- func NormalizeUnitNo(unitNo string) string
- func PKCS7Padding(input []byte, blockSize int) (buf []byte)
- func PKCS7Unpadding(padded []byte) []byte
- func PrettyPrint(obj interface{})
- func ReadMockFile(mockFile string) (content []byte)
- func SetCookies(req *http.Request, cookies []*http.Cookie)
- func StructDecode(src interface{}, dest interface{}) error
- func UnixMilli(args ...time.Time) int64
- type AdapterConf
- type Duration
- type GenerationRule
- type GlobalConf
- type HTTPRequester
- type RequestConf
- type ScheduleConf
Examples ¶
Constants ¶
const (
ContentType = "application/json"
)
const (
// ISODate is the date layout defined in ISO 8601 or RFC 3339.
ISODate = "2006-01-02"
)
const (
RequestTimeout = 20 * time.Second
)
Variables ¶
This section is empty.
Functions ¶
func AesCbcDecrypt ¶
AesCbcDecrypt is the counterpart of AesCbcEncrypt; it decrypts the cipher text and strips the PKCS #7 padding bytes off the end of the plain text.
Example ¶
package main
import (
"bytes"
"fmt"
"math/rand"
"github.com/arnie97/emu-log/common"
)
func main() {
entropy := make([]byte, 42)
rand.Read(entropy)
key, iv, text := entropy[:16], entropy[16:32], entropy[32:]
cipherText := common.AesCbcEncrypt(text, key, iv)
fmt.Println(bytes.Compare(common.AesCbcDecrypt(cipherText, key, iv), text))
}
Output: 0
func AesCbcEncrypt ¶
AesCbcEncrypt encrypts the plain text with PKCS #7 padding, block chaining mode of operation, and a predefined initial vector.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
fmt.Println(common.AesCbcEncrypt(
[]byte("Arnie97"),
[]byte("$ecure*P@$$w0rd$"),
[]byte("initialVector128"),
))
}
Output: [46 169 15 51 223 19 237 171 243 81 115 177 56 118 214 219]
func AesEcbDecrypt ¶
AesEcbDecrypt is the counterpart of AesEcbEncrypt; it decrypts the cipher text and strips the PKCS #7 padding bytes off the end of the plain text.
Example ¶
package main
import (
"bytes"
"fmt"
"math/rand"
"github.com/arnie97/emu-log/common"
)
func main() {
entropy := make([]byte, 100)
rand.Read(entropy)
key, text := entropy[:32], entropy[32:]
cipherText := common.AesEcbEncrypt(text, key)
fmt.Println(bytes.Compare(common.AesEcbDecrypt(cipherText, key), text))
}
Output: 0
func AesEcbEncrypt ¶
AesEcbEncrypt encrypts the plain text with PKCS #7 padding and electronic codebook mode of operation.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
fmt.Println(common.AesEcbEncrypt(
[]byte("Arnie97"),
[]byte("$ecure*P@$$w0rd$"),
))
}
Output: [65 104 5 194 136 199 209 10 240 48 109 82 11 205 74 176]
func AppPath ¶
func AppPath() string
AppPath returns the relative path for the directory in which the binary executable of this application resides.
func ApproxEqualUnitNo ¶
ApproxEqualUnitNo compares whether the proposed unit number is approximately the same as the original one.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
fmt.Println(
common.ApproxEqualUnitNo("CRH380B3626", "CHR380B3626"),
common.ApproxEqualUnitNo("CR400BF5033", "5033"),
common.ApproxEqualUnitNo("CRH5A5124", "CRH5A15124"),
common.ApproxEqualUnitNo("CRH2E2462", "CR8+8-0@459"),
common.ApproxEqualUnitNo("CRH2A2002", "CRH6A4002"),
common.ApproxEqualUnitNo("CR", "CR"),
common.ApproxEqualUnitNo("CRH6C2145", ""),
common.ApproxEqualUnitNo("", "CRH2C2150"),
)
}
Output: true true true true false true false true
func Catch ¶
func Catch(err *error)
Catch captures a possible panic and return it as an error.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
fmt.Println(panicFree())
}
func panicFree() (err error) {
defer common.Catch(&err)
panic("BOOM!")
}
Output: panic: BOOM!
func DesEcbDecrypt ¶
DesEcbDecrypt is the counterpart of DesEcbEncrypt; it decrypts the cipher text and strips the PKCS #7 padding bytes off the end of the plain text.
Example ¶
package main
import (
"bytes"
"fmt"
"math/rand"
"github.com/arnie97/emu-log/common"
)
func main() {
entropy := make([]byte, 100)
rand.Read(entropy)
key, text := entropy[:8], entropy[8:]
cipherText := common.DesEcbEncrypt(text, key)
fmt.Println(bytes.Compare(common.DesEcbDecrypt(cipherText, key), text))
}
Output: 0
func DesEcbEncrypt ¶
DesEcbEncrypt encrypts the plain text with PKCS #7 padding and electronic codebook mode of operation.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
fmt.Println(common.DesEcbEncrypt(
[]byte("Arnie97"),
[]byte("P@$$w0rd"),
))
}
Output: [175 255 31 191 150 239 19 134]
func DisableMockHTTPClient ¶
func DisableMockHTTPClient()
func GetField ¶
func GetField(object interface{}, fieldName string) interface{}
GetField takes an arbitary structure, and uses reflection to retrieve the field with specified name from it. Panics if the field does not exist.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
station := struct {
Pinyin, Telegraphy string
TMIS int
}{"HGT", "HTT", 53144}
fmt.Println(
common.GetField(station, "Pinyin"),
common.GetField(station, "Telegraphy"),
common.GetField(station, "TMIS"),
)
defer func() {
if recover() == nil {
fmt.Println("panic expected here!")
}
}()
common.GetField(station, "Nonexistent")
}
Output: HGT HTT 53144
func MockHTTPClientError ¶
func MockHTTPClientError(err error)
func MockHTTPClientRespBody ¶
func MockHTTPClientRespBody(body string)
func MockHTTPClientRespBodyFromFile ¶
func MockHTTPClientRespBodyFromFile(mockFile string)
Example ¶
package main
import (
"bufio"
"bytes"
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
common.MockHTTPClientRespBodyFromFile("../http_client_mock_test.go")
x := common.HTTPClient()
a, e := x.Do(nil)
b, f := x.Get("")
c, g := x.Post("", "", bytes.NewReader(nil))
d, h := x.PostForm("", nil)
fmt.Println("same resp:", a == b || b == c || c == d)
body, i := bufio.NewReader(d.Body).ReadString('\n')
j := d.Body.Close()
fmt.Println("no errors:", isAllNil(e, f, g, h, i, j))
fmt.Print("resp body: ", body)
common.MockHTTPClientError(fmt.Errorf("my sample error"))
k, m := common.HTTPClient().Do(nil)
fmt.Printf("err mock: %v, %v", k.Body, m)
}
func isAllNil(values ...interface{}) bool {
for _, v := range values {
if v != nil {
return false
}
}
return true
}
Output: same resp: false no errors: true resp body: package common_test err mock: <nil>, my sample error
func MockStaticUnixMilli ¶
func MockStaticUnixMilli(t int64)
Example ¶
package main
import (
"fmt"
"math/rand"
"github.com/arnie97/emu-log/common"
)
func main() {
mockTime := int64(rand.Uint32())
common.MockStaticUnixMilli(mockTime)
fmt.Println(common.UnixMilli() == mockTime)
}
Output: true
func Must ¶
func Must(err error)
Must prints the error message and exit immediately if error is not nil.
func NormalizeTrainNo ¶
NormalizeTrainNo converts possibly abbreviated train number pairs to an array of full qualified train number strings.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
fmt.Println(
common.NormalizeTrainNo("C1040/37/40"),
common.NormalizeTrainNo("G1040/1"),
common.NormalizeTrainNo("D1040"),
common.NormalizeTrainNo("1040/1"),
common.NormalizeTrainNo("CRH6"),
)
}
Output: [C1040 C1037 C1040] [G1040 G1041] [D1040] [] []
func NormalizeUnitNo ¶
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
for _, unitNo := range []string{
"CRH_6-002A",
"CRH5A1-5028",
"CR200J2-4001",
"CHR380B-3770",
"CRH380DV-1503",
"CRH380D-V1-1504",
"CR400BFB-1-5097 ",
" CR400AFBZ2-2249 ",
} {
fmt.Println(common.NormalizeUnitNo(unitNo))
}
}
Output: CRH6002A CRH5A5028 CR200J4001 CRH380B3770 CRH380D1503 CRH380D1504 CR400BFB5097 CR400AFBZ2249
func PKCS7Padding ¶
PKCS7Padding pads the input octet vector to a multiple of blockSize octets with the scheme defined in RFC 2315.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
fmt.Println(common.PKCS7Padding([]byte("abcdefgh"), 8))
fmt.Println(common.PKCS7Padding([]byte("abcdefg"), 16))
fmt.Println(common.PKCS7Padding([]byte("abcdef"), 256))
}
Output: [97 98 99 100 101 102 103 104 8 8 8 8 8 8 8 8] [97 98 99 100 101 102 103 9 9 9 9 9 9 9 9 9] []
func PKCS7Unpadding ¶
PKCS7Unpadding removes the padded bytes from the decrypted text according to the last decrypted byte to recover the original payload.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
fmt.Println(common.PKCS7Unpadding([]byte{}))
fmt.Println(common.PKCS7Unpadding([]byte{1, 2, 3, 5, 5, 5, 5, 5}))
}
Output: [] [1 2 3]
func PrettyPrint ¶
func PrettyPrint(obj interface{})
PrettyPrint displays a nested structure in human readable JSON format.
Example ¶
package main
import (
"github.com/arnie97/emu-log/common"
)
func main() {
common.PrettyPrint(map[string]interface{}{
"CIT380A": "CRH2C-2150",
"CR200J": nil,
"CR400AF": []string{"0207", "0208"},
"CR400BF": []string{"0503", "0507", "0305"},
"CRH6A": 4002,
})
}
Output: { "CIT380A": "CRH2C-2150", "CR200J": null, "CR400AF": [ "0207", "0208" ], "CR400BF": [ "0503", "0507", "0305" ], "CRH6A": 4002 }
func ReadMockFile ¶
func StructDecode ¶
func StructDecode(src interface{}, dest interface{}) error
StructDecode takes a source structure, and uses reflection to translate it to the destination structure. Typically used to convert native Go structures to map[string]interface{}, and vice versa.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
var dest struct {
Field []int64 `json:"root"`
}
testCases := []interface{}{
func() {},
map[string]interface{}{"root": "123"},
map[string]interface{}{"root": []float32{1, 2, 3}},
}
for _, testCase := range testCases {
err := common.StructDecode(testCase, &dest)
fmt.Printf("%+v %v\n", dest, err != nil)
}
}
Output: {Field:[]} true {Field:[]} true {Field:[1 2 3]} false
func UnixMilli ¶
UnixMilli backports time.UnixMilli() from Go 1.17 and later versions.
Example ¶
package main
import (
"fmt"
"time"
"github.com/arnie97/emu-log/common"
)
func main() {
// The doomsday of gophers!
t, err := time.Parse(time.RFC1123, "Sat, 12 Apr 2262 07:47:16 CST")
fmt.Println(common.UnixMilli(t), err)
fmt.Println(common.UnixMilli(time.Now()) == common.UnixMilli())
defer func() {
fmt.Println(recover() != nil)
}()
common.UnixMilli(time.Now(), time.Now())
}
Output: 9223372036000 <nil> true true
Types ¶
type AdapterConf ¶
type AdapterConf struct {
Request *RequestConf `toml:"request,omitempty"`
SearchSpace []GenerationRule `toml:"search,omitempty"`
}
func (AdapterConf) EmitSerials ¶
func (a AdapterConf) EmitSerials(serials chan<- string)
type Duration ¶
Duration is a TOML wrapper type for time.Duration. https://github.com/golang/go/issues/16039
func (Duration) MarshalText ¶
MarshalText formats a Duration value into a TOML string.
func (*Duration) UnmarshalText ¶
UnmarshalText parses a TOML string into a Duration value.
type GenerationRule ¶
type GenerationRule struct {
Format string `toml:"format,omitempty"`
Min *int `toml:"min,omitempty"`
Max *int `toml:"max,omitempty"`
Step *int `toml:"step,omitempty"`
}
func (*GenerationRule) EmitSerials ¶
func (rule *GenerationRule) EmitSerials(serials chan<- string)
type GlobalConf ¶
type GlobalConf struct {
Request *RequestConf `toml:"request,omitempty"`
Schedule ScheduleConf `toml:"schedule,omitempty"`
Adapters map[string]AdapterConf `toml:"adapters,omitempty"`
}
func Conf ¶
func Conf() *GlobalConf
Conf loads configuration from a TOML file on the filesystem when the function is being called for the first time.
Example ¶
package main
import (
"fmt"
"github.com/arnie97/emu-log/common"
)
func main() {
common.MockConf()
fmt.Println(int64(common.Conf().Request.Interval))
common.PrettyPrint(common.Conf().Request.Interval)
serials := make(chan string)
for _, a := range common.Conf().Adapters {
if len(a.SearchSpace) > 0 {
go a.EmitSerials(serials)
}
}
for s := range serials {
fmt.Println(s)
}
}
Output: 2460 "2.46µs" CRH5-001A CRH3-002C CRH3-004C CRH3-009C CRH2-001A CRH2-002A CRH2-003A
type HTTPRequester ¶
type HTTPRequester interface {
Do(*http.Request) (*http.Response, error)
Get(url string) (*http.Response, error)
Post(url, contentType string, body io.Reader) (*http.Response, error)
PostForm(url string, data url.Values) (*http.Response, error)
}
func HTTPClient ¶
func HTTPClient(roundTripper ...http.RoundTripper) HTTPRequester
Example ¶
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"github.com/arnie97/emu-log/common"
)
func main() {
common.DisableMockHTTPClient()
common.MockConf()
x := common.HTTPClient()
y := common.HTTPClient(http.DefaultTransport)
fmt.Println("x == y: ", x == y)
const api = "https://httpbin.org/anything"
req, _ := http.NewRequest(http.MethodPut, api, nil)
common.SetCookies(req, nil)
common.SetCookies(req, []*http.Cookie{
{Name: "model", Value: "CRH6A"},
{Name: "serial", Value: "4002"},
})
cookies := req.Header.Get("cookie")
fmt.Println("cookies: ", cookies)
resp, err := x.Do(req)
fmt.Println("get err: ", err)
body, err := ioutil.ReadAll(resp.Body)
fmt.Println("read err:", err)
s := struct {
Headers struct {
Cookies string `json:"cookie"`
UserAgent string `json:"user-agent"`
} `json:"headers"`
}{}
err = json.Unmarshal(body, &s)
fmt.Println("load err:", err)
fmt.Println("ua equal:", s.Headers.UserAgent == "Mozilla/5.0")
fmt.Println("cookies: ", s.Headers.Cookies == cookies)
}
Output: x == y: false cookies: model=CRH6A; serial=4002 get err: <nil> read err: <nil> load err: <nil> ua equal: true cookies: true