package specs import "git.zeroonesoft.cn/golib/xiaomihome/miot" // PropertyMapper provides bidirectional mapping between SPEC raw values (integers) // and human-readable enum strings. For example, an air conditioner mode property // might use raw value 0 for "cool", 1 for "heat", etc. // // The mapper is constructed from the SPEC value-list combined with an external // lookup table that maps raw values to their semantic names. type PropertyMapper struct { rawToEnum map[interface{}]string enumToRaw map[string]interface{} } // NewPropertyMapper creates a PropertyMapper from a SPEC value-list and // a mapping of raw values → enum strings. // // Example: // // mapper := NewPropertyMapper(prop.ValueList, map[interface{}]string{ // 0: "cool", // 1: "heat", // 2: "fan", // 3: "dry", // 4: "auto", // }) func NewPropertyMapper(vlist miot.MIoTSpecValueList, valueMap map[interface{}]string) *PropertyMapper { m := &PropertyMapper{ rawToEnum: make(map[interface{}]string), enumToRaw: make(map[string]interface{}), } // Build from the provided valueMap for raw, enum := range valueMap { m.rawToEnum[raw] = enum m.enumToRaw[enum] = raw } // Also build from SPEC value-list descriptions (as a fallback) for _, item := range vlist { if item.Desc != "" { name := item.Desc if item.Name != "" { name = item.Name } m.rawToEnum[item.Value] = name m.enumToRaw[name] = item.Value } } return m } // ToEnum converts a raw SPEC value to its enum string representation. // Returns ("", false) if the raw value is not in the mapping. func (m *PropertyMapper) ToEnum(raw interface{}) (string, bool) { if m == nil { return "", false } s, ok := m.rawToEnum[raw] return s, ok } // ToRaw converts an enum string to its raw SPEC value. // Returns (nil, false) if the enum string is not in the mapping. func (m *PropertyMapper) ToRaw(enum string) (interface{}, bool) { if m == nil { return nil, false } v, ok := m.enumToRaw[enum] return v, ok } // HasEnum checks whether the given enum string exists in the mapping. func (m *PropertyMapper) HasEnum(enum string) bool { if m == nil { return false } _, ok := m.enumToRaw[enum] return ok } // HasRaw checks whether the given raw value exists in the mapping. func (m *PropertyMapper) HasRaw(raw interface{}) bool { if m == nil { return false } _, ok := m.rawToEnum[raw] return ok } // FromValueList creates a PropertyMapper purely from the SPEC value list. // Uses the ValueItem.Desc or ValueItem.Name as the enum string. func FromValueList(vlist miot.MIoTSpecValueList) *PropertyMapper { if len(vlist) == 0 { return &PropertyMapper{ rawToEnum: make(map[interface{}]string), enumToRaw: make(map[string]interface{}), } } m := &PropertyMapper{ rawToEnum: make(map[interface{}]string), enumToRaw: make(map[string]interface{}), } for _, item := range vlist { name := item.Name if name == "" { name = item.Desc } if name != "" { m.rawToEnum[item.Value] = name m.enumToRaw[name] = item.Value } } return m }