package safereflect

import (
	"fmt"
	"reflect"
)

// Set attempts to assign `from` to `to` using reflection
func Set(from interface{}, to reflect.Value) error {
	if from == nil {
		return nil
	}

	fv := reflect.ValueOf(from)
	if fv.Type().AssignableTo(to.Type()) {
		// Assign if it's assignable
		to.Set(fv)
	} else if fv.Type().ConvertibleTo(to.Type()) {
		// Assign if convertible
		cfv := fv.Convert(to.Type())
		to.Set(cfv)
	} else {
		// Short-circuit if assigning is not possible. The types in the code would have to be fixed.
		return fmt.Errorf("value of type %v is not assignable to type %v", fv.Type(), to.Type())
	}

	return nil
}
