Skip to content
This repository has been archived by the owner on Dec 17, 2021. It is now read-only.

Commit

Permalink
feat: add dereferencing with default value
Browse files Browse the repository at this point in the history
This allows you to extract a value from a pointer by setting values for
nil pointers instead of getting the default value.
  • Loading branch information
xorcare committed Jan 23, 2020
1 parent 1239fd0 commit 247b915
Show file tree
Hide file tree
Showing 3 changed files with 357 additions and 1 deletion.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BSD 3-Clause License

Copyright © 2019 Vasiliy Vasilyuk <xorcare@gmail.com>
Copyright © 2019-2020 Vasiliy Vasilyuk <xorcare@gmail.com>
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
180 changes: 180 additions & 0 deletions derefed/derefed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
// Copyright © 2019-2020 Vasiliy Vasilyuk. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package derefed contains helper routines for simplifying the getting of
// optional fields of basic type. This allows you to get the value from the
// pointer even if it is nil, and if the pointer is nil it returns a value of
// second parameter.
package derefed

// Bool dereference a pointer bool from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Bool(v *bool, def bool) bool {
if v == nil {
return def
}
return *v
}

// Byte dereference a pointer byte from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Byte(v *byte, def byte) byte {
if v == nil {
return def
}
return *v
}

// Complex64 dereference a pointer complex64 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Complex64(v *complex64, def complex64) complex64 {
if v == nil {
return def
}
return *v
}

// Complex128 dereference a pointer complex128 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Complex128(v *complex128, def complex128) complex128 {
if v == nil {
return def
}
return *v
}

// Float32 dereference a pointer float32 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Float32(v *float32, def float32) float32 {
if v == nil {
return def
}
return *v
}

// Float64 dereference a pointer float64 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Float64(v *float64, def float64) float64 {
if v == nil {
return def
}
return *v
}

// Int dereference a pointer int from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Int(v *int, def int) int {
if v == nil {
return def
}
return *v
}

// Int8 dereference a pointer int8 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Int8(v *int8, def int8) int8 {
if v == nil {
return def
}
return *v
}

// Int16 dereference a pointer int16 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Int16(v *int16, def int16) int16 {
if v == nil {
return def
}
return *v
}

// Int32 dereference a pointer int32 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Int32(v *int32, def int32) int32 {
if v == nil {
return def
}
return *v
}

// Int64 dereference a pointer int64 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Int64(v *int64, def int64) int64 {
if v == nil {
return def
}
return *v
}

// Rune dereference a pointer rune from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Rune(v *rune, def rune) rune {
if v == nil {
return def
}
return *v
}

// String dereference a pointer string from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func String(v *string, def string) string {
if v == nil {
return def
}
return *v
}

// Uint dereference a pointer uint from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Uint(v *uint, def uint) uint {
if v == nil {
return def
}
return *v
}

// Uint8 dereference a pointer uint8 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Uint8(v *uint8, def uint8) uint8 {
if v == nil {
return def
}
return *v
}

// Uint16 dereference a pointer uint16 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Uint16(v *uint16, def uint16) uint16 {
if v == nil {
return def
}
return *v
}

// Uint32 dereference a pointer uint32 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Uint32(v *uint32, def uint32) uint32 {
if v == nil {
return def
}
return *v
}

// Uint64 dereference a pointer uint64 from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Uint64(v *uint64, def uint64) uint64 {
if v == nil {
return def
}
return *v
}

// Uintptr dereference a pointer uintptr from the structure of a literal or
// variable, and if the pointer is nil it returns a value of second parameter.
func Uintptr(v *uintptr, def uintptr) uintptr {
if v == nil {
return def
}
return *v
}
176 changes: 176 additions & 0 deletions derefed/derefed_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// Copyright © 2019-2020 Vasiliy Vasilyuk. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package derefed

import (
"fmt"
"reflect"
"testing"
)

func equal(t testing.TB, expected, actual interface{}) {
if h, ok := t.(interface{ Helper() }); ok {
h.Helper()
}

t.Logf("expected: %q (%T), actual: %q (%T)", fmt.Sprint(expected), expected, fmt.Sprint(actual), actual)

if !reflect.DeepEqual(expected, actual) {
t.Fatalf("values obtained are not equal, expected: %v, actual: %v", expected, actual)
}
}

var _bool = true
var _byte = byte(1)
var _complex64 = complex64(1.1)
var _complex128 = complex128(1.1)
var _float32 = float32(1.1)
var _float64 = float64(1.1)
var _int = int(1)
var _int8 = int8(8)
var _int16 = int16(16)
var _int32 = int32(32)
var _int64 = int64(64)
var _rune = rune(1)
var _string = "derefed"
var _uint = uint(1)
var _uint8 = uint8(8)
var _uint16 = uint16(16)
var _uint32 = uint32(32)
var _uint64 = uint64(64)
var _uintptr = uintptr(64)

func TestBool(t *testing.T) {
equal(t, false, Bool(nil, false))
equal(t, true, Bool(nil, true))
equal(t, false, Bool(new(bool), true))
equal(t, true, Bool(&_bool, false))
}

func TestByte(t *testing.T) {
equal(t, byte(0), Byte(nil, 0))
equal(t, byte(1), Byte(nil, 1))
equal(t, byte(0), Byte(new(byte), 1))
equal(t, byte(1), Byte(&_byte, 2))
}

func TestComplex64(t *testing.T) {
equal(t, complex64(0), Complex64(nil, 0))
equal(t, complex64(1.1), Complex64(nil, 1.1))
equal(t, complex64(0), Complex64(new(complex64), 2.2))
equal(t, complex64(1.1), Complex64(&_complex64, 2.2))
}

func TestComplex128(t *testing.T) {
equal(t, complex128(0), Complex128(nil, 0))
equal(t, complex128(1.1), Complex128(nil, 1.1))
equal(t, complex128(0), Complex128(new(complex128), 1.1))
equal(t, complex128(1.1), Complex128(&_complex128, 2.2))
}

func TestFloat32(t *testing.T) {
equal(t, float32(0), Float32(nil, 0))
equal(t, float32(1.1), Float32(nil, 1.1))
equal(t, float32(0), Float32(new(float32), 1.1))
equal(t, float32(1.1), Float32(&_float32, 2.2))
}

func TestFloat64(t *testing.T) {
equal(t, float64(0), Float64(nil, 0))
equal(t, float64(1.1), Float64(nil, 1.1))
equal(t, float64(0), Float64(new(float64), 1.1))
equal(t, float64(1.1), Float64(&_float64, 2.2))
}

func TestInt(t *testing.T) {
equal(t, 0, Int(nil, 0))
equal(t, 1, Int(nil, 1))
equal(t, 0, Int(new(int), 1))
equal(t, 1, Int(&_int, 2))
}

func TestInt8(t *testing.T) {
equal(t, int8(0), Int8(nil, 0))
equal(t, int8(1), Int8(nil, 1))
equal(t, int8(0), Int8(new(int8), 1))
equal(t, int8(8), Int8(&_int8, 2))
}

func TestInt16(t *testing.T) {
equal(t, int16(0), Int16(nil, 0))
equal(t, int16(1), Int16(nil, 1))
equal(t, int16(0), Int16(new(int16), 1))
equal(t, int16(16), Int16(&_int16, 2))
}

func TestInt32(t *testing.T) {
equal(t, int32(0), Int32(nil, 0))
equal(t, int32(1), Int32(nil, 1))
equal(t, int32(0), Int32(new(int32), 1))
equal(t, int32(32), Int32(&_int32, 2))
}

func TestInt64(t *testing.T) {
equal(t, int64(0), Int64(nil, 0))
equal(t, int64(1), Int64(nil, 1))
equal(t, int64(0), Int64(new(int64), 1))
equal(t, int64(64), Int64(&_int64, 2))
}

func TestRune(t *testing.T) {
equal(t, rune(0), Rune(nil, 0))
equal(t, rune(1), Rune(nil, 1))
equal(t, rune(0), Rune(new(rune), 1))
equal(t, rune(1), Rune(&_rune, 1))
}

func TestString(t *testing.T) {
equal(t, "", String(nil, ""))
equal(t, "derefer", String(nil, "derefer"))
equal(t, "", String(new(string), "derefed"))
equal(t, "derefed", String(&_string, "derefer"))
}

func TestUint(t *testing.T) {
equal(t, uint(0), Uint(nil, 0))
equal(t, uint(1), Uint(nil, 1))
equal(t, uint(0), Uint(new(uint), 1))
equal(t, uint(1), Uint(&_uint, 2))
}

func TestUint8(t *testing.T) {
equal(t, uint8(0), Uint8(nil, 0))
equal(t, uint8(1), Uint8(nil, 1))
equal(t, uint8(0), Uint8(new(uint8), 1))
equal(t, uint8(8), Uint8(&_uint8, 2))
}

func TestUint16(t *testing.T) {
equal(t, uint16(0), Uint16(nil, 0))
equal(t, uint16(1), Uint16(nil, 1))
equal(t, uint16(0), Uint16(new(uint16), 1))
equal(t, uint16(16), Uint16(&_uint16, 2))
}

func TestUint32(t *testing.T) {
equal(t, uint32(0), Uint32(nil, 0))
equal(t, uint32(1), Uint32(nil, 1))
equal(t, uint32(0), Uint32(new(uint32), 1))
equal(t, uint32(32), Uint32(&_uint32, 2))
}

func TestUint64(t *testing.T) {
equal(t, uint64(0), Uint64(nil, 0))
equal(t, uint64(1), Uint64(nil, 1))
equal(t, uint64(0), Uint64(new(uint64), 1))
equal(t, uint64(64), Uint64(&_uint64, 2))
}

func TestUintptr(t *testing.T) {
equal(t, uintptr(0), Uintptr(nil, 0))
equal(t, uintptr(1), Uintptr(nil, 1))
equal(t, uintptr(0), Uintptr(new(uintptr), 1))
equal(t, uintptr(64), Uintptr(&_uintptr, 2))
}

0 comments on commit 247b915

Please sign in to comment.