class_name DataFieldValue extends Resource enum DataFieldType { TEXT, MULTILINE_TEXT, NUMBER, BOOL, FORMULA, LIST, REFERENCE_SINGLE, REFERENCE_LIST } @export var field_type: DataFieldType @export var value: Variant # --- TYPE STRING MAPPING --- static func _type_to_string(t: DataFieldType) -> String: match t: DataFieldType.TEXT: return "Text" DataFieldType.MULTILINE_TEXT: return "MultiText" DataFieldType.NUMBER: return "Number" DataFieldType.BOOL: return "Boolean" DataFieldType.FORMULA: return "Formula" DataFieldType.LIST: return "List" DataFieldType.REFERENCE_SINGLE: return "RefSingle" DataFieldType.REFERENCE_LIST: return "RefList" _: return str(int(t)) static func _string_to_type(s: String) -> DataFieldType: match s: "Text": return DataFieldType.TEXT "MultiText": return DataFieldType.MULTILINE_TEXT "Number": return DataFieldType.NUMBER "Boolean": return DataFieldType.BOOL "Formula": return DataFieldType.FORMULA "List": return DataFieldType.LIST "RefSingle": return DataFieldType.REFERENCE_SINGLE "RefList": return DataFieldType.REFERENCE_LIST _: return DataFieldType.TEXT # --- COMPLEX VALUE ACCESS --- func get_concrete_value() -> Variant: match field_type: DataFieldType.FORMULA: return value as FormulaValue DataFieldType.LIST, DataFieldType.REFERENCE_LIST: return value as ListValue _: return value # --- SERIALIZATION HELPERS --- static func _envelope_variant(v: Variant) -> Dictionary: return { "_kind": "gd-variant-b64", "data": Marshalls.raw_to_base64(var_to_bytes(v)) } static func _deenvelope_variant(d: Dictionary) -> Variant: var raw: PackedByteArray = Marshalls.base64_to_raw(d.get("data", "")) return bytes_to_var(raw) static func _serialize_list_value(v: Variant) -> Array: if v is Array: var out: Array = [] for item in v: if item is Dictionary or item is Array or item is String or item is int or item is float or item is bool or item == null: out.append(item) else: out.append(_envelope_variant(item)) return out return [] static func _deserialize_list_value(a: Array) -> Array: var out: Array = [] for item in a: if item is Dictionary and item.get("_kind") == "gd-variant-b64": out.append(_deenvelope_variant(item)) else: out.append(item) return out # --- SERIALIZE/DESERIALIZE VALUE --- static func serialize_value(p_field_type: DataFieldType, v: Variant) -> Variant: match p_field_type: DataFieldType.TEXT, DataFieldType.MULTILINE_TEXT: return str(v) DataFieldType.NUMBER: if v is int or v is float: return v var s := str(v) if s.find(".") >= 0: return float(s) else: return int(s) DataFieldType.BOOL: return bool(v) _: if v is Dictionary or v is Array or v is String or v is int or v is float or v is bool or v == null: return v return _envelope_variant(v) static func deserialize_value(p_field_type: DataFieldType, raw: Variant) -> Variant: match p_field_type: DataFieldType.TEXT, DataFieldType.MULTILINE_TEXT: return str(raw) DataFieldType.NUMBER: return raw if (raw is float or raw is int) else float(str(raw)) DataFieldType.BOOL: return bool(raw) _: if raw is Dictionary and raw.get("_kind") == "gd-variant-b64": return _deenvelope_variant(raw) return raw # --- DICT CONVERSION --- func to_dict() -> Dictionary: return { "field_type": _type_to_string(field_type), "value": serialize_value(field_type, value) } static func from_dict(d: Dictionary) -> DataFieldValue: var inst := DataFieldValue.new() inst.field_type = _string_to_type(d.get("field_type", "Text")) inst.value = deserialize_value(inst.field_type, d.get("value")) return inst