common

package
v0.0.0-...-43f7920 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 5, 2023 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Examples

Constants

View Source
const (
	ContentType = "application/json"
)
View Source
const (
	// ISODate is the date layout defined in ISO 8601 or RFC 3339.
	ISODate = "2006-01-02"
)
View Source
const (
	RequestTimeout = 20 * time.Second
)

Variables

This section is empty.

Functions

func AesCbcDecrypt

func AesCbcDecrypt(cipherText, key, iv []byte) (plainText []byte)

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

func AesCbcEncrypt(plainText, key, iv []byte) (cipherText []byte)

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

func AesEcbDecrypt(cipherText, key []byte) (plainText []byte)

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

func AesEcbEncrypt(plainText, key []byte) (cipherText []byte)

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

func ApproxEqualUnitNo(original, proposed string) bool

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

func DesEcbDecrypt(cipherText, key []byte) (plainText []byte)

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

func DesEcbEncrypt(plainText, key []byte) (cipherText []byte)

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 MockConf

func MockConf()

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

func NormalizeTrainNo(trainNo string) (results []string)

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

func NormalizeUnitNo(unitNo string) string
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

func PKCS7Padding(input []byte, blockSize int) (buf []byte)

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

func PKCS7Unpadding(padded []byte) []byte

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 ReadMockFile(mockFile string) (content []byte)

func SetCookies

func SetCookies(req *http.Request, cookies []*http.Cookie)

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

func UnixMilli(args ...time.Time) int64

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

type Duration time.Duration

Duration is a TOML wrapper type for time.Duration. https://github.com/golang/go/issues/16039

func (Duration) MarshalText

func (d Duration) MarshalText() (text []byte, err error)

MarshalText formats a Duration value into a TOML string.

func (Duration) String

func (d Duration) String() string

String provide a human readable string representing the duration.

func (*Duration) UnmarshalText

func (d *Duration) UnmarshalText(text []byte) error

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

type RequestConf

type RequestConf struct {
	Interval  Duration `toml:"interval,omitempty"   json:"interval,omitempty"`
	UserAgent string   `toml:"user-agent,omitempty" json:"user-agent,omitempty"`
	SessionID string   `toml:"session-id,omitempty" json:"session-id,omitempty"`
}

func (*RequestConf) RoundTrip

func (conf *RequestConf) RoundTrip(req *http.Request) (*http.Response, error)

type ScheduleConf

type ScheduleConf struct {
	StartTime Duration `toml:"start-time,omitempty"`
	EndTime   Duration `toml:"end-time,omitempty"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL