Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jonbodner committed Jul 31, 2020
0 parents commit f53ed69
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.iml
.idea
.DS_Store
67 changes: 67 additions & 0 deletions data/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package main

import (
"fmt"
"unsafe"
)

type Data struct {
Value uint32 // 4 bytes
Label [10]byte // 10 bytes
Active bool // 1 byte
// padded with 1 byte to make it align
}

func DataFromBytesUnsafe(b [16]byte) Data {
return *(*Data)(unsafe.Pointer(&b))
}

func DataFromBytes(b [16]byte) Data {
d := Data{}
d.Value = uint32(b[3])<<24 + uint32(b[2])<<16 + uint32(b[1])<<8 + uint32(b[0])
copy(d.Label[:], b[4:14])
d.Active = b[14] != 0
return d
}

func BytesFromDataUnsafe(d Data) [16]byte {
return *(*[16]byte)(unsafe.Pointer(&d))
}

func BytesFromData(d Data) [16]byte {
out := [16]byte{}
out[3] = byte(d.Value >> 24)
out[2] = byte(d.Value >> 16)
out[1] = byte(d.Value >> 8)
out[0] = byte(d.Value & 255)
copy(out[4:14], d.Label[:])
if d.Active {
out[14] = 1
}
return out
}

func main() {
d := Data{
Value: 8675309,
Active: true,
}
copy(d.Label[:], "Phone")
fmt.Println(d, unsafe.Alignof(d), unsafe.Alignof(d.Value), unsafe.Alignof(d.Label), unsafe.Alignof(d.Active))

b := [16]byte{237, 95, 132, 0, 80, 104, 111, 110, 101, 0, 0, 0, 0, 0, 1, 0}
fmt.Println(b)

b1 := BytesFromData(d)
b2 := BytesFromDataUnsafe(d)
if b1 != b2 {
panic(fmt.Sprintf("%v %v", b1, b2))
}
fmt.Printf("%+v\n", b1)
d1 := DataFromBytes(b1)
d2 := DataFromBytesUnsafe(b1)
if d1 != d2 {
panic(fmt.Sprintf("%v %v", d1, d2))
}
fmt.Println(d1)
}
59 changes: 59 additions & 0 deletions data/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package main

import (
"testing"
)

var bh [16]byte
var dh Data

var input = [16]byte{237, 95, 132, 0, 80, 104, 111, 110, 101, 0, 0, 0, 0, 0, 1, 0}

var inputData = Data {
Value:8675309,
Label: [10]byte{80, 104, 111, 110, 101, 0, 0, 0, 0, 0},
Active: true,
}

func TestIdentical(t *testing.T) {
b1 := BytesFromData(inputData)
b2 := BytesFromDataUnsafe(inputData)
if b1 != b2 {
t.Fatal(b1,b2)
}
if b1 != input {
t.Fatal(b1,input)
}
d1 := DataFromBytes(b1)
d2 := DataFromBytesUnsafe(b1)
if d1 != d2 {
t.Fatal(d1,d2)
}
if d1 != inputData {
t.Fatal(d1,inputData)
}
}

func BenchmarkBytesFromData(b *testing.B) {
for i := 0;i<b.N;i++ {
bh = BytesFromData(inputData)
}
}

func BenchmarkBytesFromDataUnsafe(b *testing.B) {
for i := 0;i<b.N;i++ {
bh = BytesFromDataUnsafe(inputData)
}
}

func BenchmarkDataFromBytes(b *testing.B) {
for i := 0;i<b.N;i++ {
dh = DataFromBytes(input)
}
}

func BenchmarkDataFromBytesUnsafe(b *testing.B) {
for i := 0;i<b.N;i++ {
dh = DataFromBytesUnsafe(input)
}
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module unsafe_examples

go 1.14
26 changes: 26 additions & 0 deletions numbers/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package main

import (
"fmt"
"unsafe"
)

func main() {
var i64 int64 = 1_000_000
i64ptr := uintptr(unsafe.Pointer(&i64))
bytes := *(*[unsafe.Sizeof(i64)]byte)(unsafe.Pointer(i64ptr))
fmt.Println(bytes)
i32 := *(*int32)(unsafe.Pointer(i64ptr))
fmt.Println(i32)

i64ptr += 4
bytesShifted := *(*[unsafe.Sizeof(i64)]byte)(unsafe.Pointer(i64ptr))
fmt.Println(bytesShifted)

i32Shifted := *(*int32)(unsafe.Pointer(i64ptr))
fmt.Println(i32Shifted)

i64Shifted := *(*int64)(unsafe.Pointer(i64ptr))
fmt.Println(i64Shifted)
}

24 changes: 24 additions & 0 deletions string_modification1/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"fmt"
"reflect"
"unsafe"
)

func main() {
s := "hello"
sHdr := (*reflect.StringHeader)(unsafe.Pointer(&s))
fmt.Println(sHdr.Len) // prints 5

for i :=0;i< sHdr.Len; i++ {
bp := *(*byte)(unsafe.Pointer(sHdr.Data+uintptr(i)))
fmt.Println(string(bp))
}
sHdr.Len = sHdr.Len+10
fmt.Println(s)

bp := (*byte)(unsafe.Pointer(sHdr.Data+2))
*bp = *bp + 1
fmt.Println(s)
}
31 changes: 31 additions & 0 deletions string_modification2/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"fmt"
"reflect"
"unsafe"
)

func main() {
s := "hello"
sHdr := (*reflect.StringHeader)(unsafe.Pointer(&s))
fmt.Println(sHdr.Len) // prints 5

for i :=0;i< sHdr.Len; i++ {
bp := *(*byte)(unsafe.Pointer(sHdr.Data+uintptr(i)))
fmt.Print(string(bp))
}
fmt.Println()

sHdr.Len = sHdr.Len+10
fmt.Println(s)

b := []byte("goodbye")
bHdr := (*reflect.SliceHeader)(unsafe.Pointer(&b))
sHdr.Data = bHdr.Data
sHdr.Len = bHdr.Len
fmt.Println(s)

b[0] = 'x'
fmt.Println(s)
}

0 comments on commit f53ed69

Please sign in to comment.