Esempio n. 1
0
// Decode converts Sass Value to Go compatible data types.
func Unmarshal(arg SassValue, v ...interface{}) error {
	var err error
	sv := arg.Val()
	var l int
	if libs.IsList(sv) {
		l = libs.Len(sv)
	}
	if arg.Val() == nil {
		return errors.New("I can't work with this. arg UnionSassValue must not be nil. - Unmarshaller")
	} else if len(v) == 0 {
		return errors.New("Cannot Unmarshal an empty value - Michael Scott")
	} else if len(v) > 1 {
		if len(v) < l { //check for optional arguements that are not passed and pad with nil
			return fmt.Errorf(
				"Arguments mismatch %d C arguments did not match %d",
				l, len(v))
		}
		for i := 0; i < l; i++ {
			val := libs.Index(sv, i)
			err = unmarshal(SassValue{value: val}, v[i])
			if err != nil {
				return err
			}
		}
		return err
	} else if libs.IsList(sv) &&
		getKind(v[0]) != reflect.Slice &&
		l == 1 { //arg is a slice of 1 but we want back a non slice
		val := libs.Index(sv, 0)
		return unmarshal(SassValue{value: val}, v[0])
	} else if libs.IsList(sv) &&
		getKind(v[0]) == reflect.Slice &&
		libs.IsList(libs.Index(sv, 0)) &&
		l == 1 { //arg is a list of single list and we only want back a list so we need to unwrap
		val := libs.Index(sv, 0)
		return unmarshal(SassValue{value: val}, v[0])
		//return unmarshal(C.sass_list_get_value(arg, C.size_t(0)), v[0])
	} else {
		return unmarshal(arg, v[0])
	}
}
Esempio n. 2
0
func unmarshal(arg SassValue, v interface{}) error {
	sv := arg.Val()
	//Get the underlying value of v and its kind
	f := reflect.ValueOf(v)

	if f.Kind() == reflect.Ptr {
		f = f.Elem()
	}

	k := f.Kind()
	t := f.Type()

	if k == reflect.Interface {
		switch {
		case libs.IsNil(sv):
			f.Set(reflect.ValueOf("<nil>"))
			return nil
		case libs.IsString(sv):
			k = reflect.String
		case libs.IsBool(sv):
			k = reflect.Bool
		case libs.IsNumber(sv):
			k = reflect.Struct
		case libs.IsList(sv):
			k = reflect.Slice
			t = reflect.SliceOf(t)
		case libs.IsError(sv):
			// This should get implemented as type error
			k = reflect.String
		case libs.IsColor(sv):
			k = reflect.Struct
		default:
			return errors.New("Uncovertable interface value.")
		}
	}

	switch k {
	case reflect.Invalid:
		return errors.New("Invalid SASS Value - Taylor Swift")
	case reflect.String:
		if libs.IsString(sv) || libs.IsError(sv) {
			gc := libs.String(sv)
			//drop quotes
			if t, err := strconv.Unquote(gc); err == nil {
				gc = t
			}
			if strings.HasPrefix(gc, "'") && strings.HasSuffix(gc, "'") {
				gc = gc[1 : len(gc)-1]
			}
			if !f.CanSet() {
				return errors.New("Can not set string")
			}

			switch t := f.Kind(); t {
			case reflect.String:
				f.SetString(gc)
			case reflect.Interface:
				f.Set(reflect.ValueOf(gc))
			}
		} else {
			return throwMisMatchTypeError(arg, "string")
		}
	case reflect.Bool:
		if libs.IsBool(sv) {
			b := libs.Bool(sv)
			f.Set(reflect.ValueOf(b))
		} else {
			return throwMisMatchTypeError(arg, "bool")
		}
	case reflect.Struct:
		switch {
		case libs.IsColor(sv):
			col := libs.Color(sv)
			f.Set(reflect.ValueOf(col))
		case libs.IsNumber(sv):
			u, err := getSassNumberUnit(arg)
			if err != nil {
				return err
			}
			sn := libs.SassNumber{
				Value: libs.Float(sv),
				Unit:  u,
			}
			f.Set(reflect.ValueOf(sn))
		default:
			return throwMisMatchTypeError(arg, "color.RGBA or SassNumber")
		}
	case reflect.Slice:
		if !libs.IsList(sv) {
			return throwMisMatchTypeError(arg, "slice")
		}
		libs.Slice(arg.Val(), v)
	default:
		return errors.New("Unsupported SassValue")
	}
	return nil
}