File: unsafe.go

package info (click to toggle)
golang-github-marten-seemann-qtls-go1-15 0.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 1,852 kB
  • sloc: makefile: 2
file content (89 lines) | stat: -rw-r--r-- 2,242 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package qtls

import (
	"crypto/tls"
	"reflect"
	"unsafe"
)

func init() {
	if !structsEqual(&tls.ConnectionState{}, &connectionState{}) {
		panic("qtls.ConnectionState doesn't match")
	}
	if !structsEqual(&tls.ClientSessionState{}, &clientSessionState{}) {
		panic("qtls.ClientSessionState doesn't match")
	}
	if !structsEqual(&tls.Config{}, &config{}) {
		panic("qtls.Config doesn't match")
	}
	if !structsEqual(&tls.ClientHelloInfo{}, &clientHelloInfo{}) {
		panic("qtls.ClientHelloInfo doesn't match")
	}
}

func toConnectionState(c connectionState) ConnectionState {
	return *(*ConnectionState)(unsafe.Pointer(&c))
}

func toClientSessionState(s *clientSessionState) *ClientSessionState {
	return (*ClientSessionState)(unsafe.Pointer(s))
}

func fromClientSessionState(s *ClientSessionState) *clientSessionState {
	return (*clientSessionState)(unsafe.Pointer(s))
}

func toConfig(c *config) *Config {
	return (*Config)(unsafe.Pointer(c))
}

func fromConfig(c *Config) *config {
	return (*config)(unsafe.Pointer(c))
}

func toClientHelloInfo(chi *clientHelloInfo) *ClientHelloInfo {
	return (*ClientHelloInfo)(unsafe.Pointer(chi))
}

func structsEqual(a, b interface{}) bool {
	return compare(reflect.ValueOf(a), reflect.ValueOf(b))
}

func compare(a, b reflect.Value) bool {
	sa := a.Elem()
	sb := b.Elem()
	if sa.NumField() != sb.NumField() {
		return false
	}
	for i := 0; i < sa.NumField(); i++ {
		fa := sa.Type().Field(i)
		fb := sb.Type().Field(i)
		if !reflect.DeepEqual(fa.Index, fb.Index) || fa.Name != fb.Name || fa.Anonymous != fb.Anonymous || fa.Offset != fb.Offset || !reflect.DeepEqual(fa.Type, fb.Type) {
			if fa.Type.Kind() != fb.Type.Kind() {
				return false
			}
			if fa.Type.Kind() == reflect.Slice {
				if !compareStruct(fa.Type.Elem(), fb.Type.Elem()) {
					return false
				}
				continue
			}
			return false
		}
	}
	return true
}

func compareStruct(a, b reflect.Type) bool {
	if a.NumField() != b.NumField() {
		return false
	}
	for i := 0; i < a.NumField(); i++ {
		fa := a.Field(i)
		fb := b.Field(i)
		if !reflect.DeepEqual(fa.Index, fb.Index) || fa.Name != fb.Name || fa.Anonymous != fb.Anonymous || fa.Offset != fb.Offset || !reflect.DeepEqual(fa.Type, fb.Type) {
			return false
		}
	}
	return true
}