@@ -1229,3 +1229,112 @@ class MixedStruct:
12291229 annotated_float = 2.0 ,
12301230 )
12311231 validate_full_roundtrip (instance , MixedStruct )
1232+
1233+
1234+ def test_dict_struct_encoding () -> None :
1235+ # Test encoding dict as struct - this should only happen in type-aware context
1236+ # For generic encoding, dict is passed through as-is
1237+ from cocoindex .convert import encode_engine_value
1238+ dict_value = {"name" : "Alice" , "age" : 30 , "city" : "New York" }
1239+ result = encode_engine_value (dict_value )
1240+ assert result == {"name" : "Alice" , "age" : 30 , "city" : "New York" } # Dict preserved
1241+
1242+
1243+ def test_dict_struct_decoding () -> None :
1244+ # Test decoding to dict as struct
1245+ from cocoindex .convert import _make_engine_struct_value_decoder
1246+ from typing import Dict , Any
1247+
1248+ src_fields = [
1249+ {"name" : "name" , "type" : {"kind" : "Str" }},
1250+ {"name" : "age" , "type" : {"kind" : "Int64" }},
1251+ {"name" : "city" , "type" : {"kind" : "Str" }},
1252+ ]
1253+
1254+ decoder = _make_engine_struct_value_decoder ([], src_fields , Dict [str , Any ])
1255+ result = decoder (["Alice" , 30 , "New York" ])
1256+ assert result == {"name" : "Alice" , "age" : 30 , "city" : "New York" }
1257+
1258+
1259+ def test_dict_untyped_struct_decoding () -> None :
1260+ # Test decoding to untyped dict as struct
1261+ from cocoindex .convert import _make_engine_struct_value_decoder
1262+
1263+ src_fields = [
1264+ {"name" : "name" , "type" : {"kind" : "Str" }},
1265+ {"name" : "age" , "type" : {"kind" : "Int64" }},
1266+ {"name" : "city" , "type" : {"kind" : "Str" }},
1267+ ]
1268+
1269+ decoder = _make_engine_struct_value_decoder ([], src_fields , dict )
1270+ result = decoder (["Alice" , 30 , "New York" ])
1271+ assert result == {"name" : "Alice" , "age" : 30 , "city" : "New York" }
1272+
1273+
1274+ def test_dict_struct_vs_ktable () -> None :
1275+ # Test that dict-as-struct and dict-as-KTable are handled differently
1276+ from cocoindex .convert import encode_engine_value , _is_ktable_dict
1277+
1278+ # Dict as struct (simple values) - should be passed through in generic encoding
1279+ dict_struct = {"name" : "Alice" , "age" : 30 }
1280+ assert not _is_ktable_dict (dict_struct )
1281+ struct_result = encode_engine_value (dict_struct )
1282+ assert struct_result == {"name" : "Alice" , "age" : 30 } # Preserved as dict
1283+
1284+ # Dict as KTable (struct values)
1285+ @dataclass
1286+ class Person :
1287+ name : str
1288+ age : int
1289+
1290+ dict_ktable = {"p1" : Person ("Alice" , 30 ), "p2" : Person ("Bob" , 25 )}
1291+ assert _is_ktable_dict (dict_ktable )
1292+ ktable_result = encode_engine_value (dict_ktable )
1293+ assert ktable_result == [["p1" , "Alice" , 30 ], ["p2" , "Bob" , 25 ]]
1294+
1295+
1296+ def test_dict_to_struct_conversion () -> None :
1297+ # Test dict to struct conversion with existing struct types
1298+ from cocoindex .convert import encode_engine_value_with_type
1299+ from dataclasses import dataclass
1300+
1301+ @dataclass
1302+ class Person :
1303+ name : str
1304+ age : int
1305+ city : str
1306+
1307+ dict_value = {"name" : "Alice" , "age" : 30 , "city" : "New York" }
1308+
1309+ # Test encoding dict as struct
1310+ result = encode_engine_value_with_type (dict_value , Person )
1311+ assert result == ["Alice" , 30 , "New York" ]
1312+
1313+
1314+ def test_struct_to_dict_conversion () -> None :
1315+ # Test struct to dict conversion
1316+ from cocoindex .convert import _make_engine_struct_value_decoder
1317+ from dataclasses import dataclass
1318+ from typing import Dict , Any
1319+
1320+ @dataclass
1321+ class Person :
1322+ name : str
1323+ age : int
1324+ city : str
1325+
1326+ src_fields = [
1327+ {"name" : "name" , "type" : {"kind" : "Str" }},
1328+ {"name" : "age" , "type" : {"kind" : "Int64" }},
1329+ {"name" : "city" , "type" : {"kind" : "Str" }},
1330+ ]
1331+
1332+ # Test decoding struct to dict
1333+ decoder = _make_engine_struct_value_decoder ([], src_fields , Dict [str , Any ])
1334+ result = decoder (["Alice" , 30 , "New York" ])
1335+ assert result == {"name" : "Alice" , "age" : 30 , "city" : "New York" }
1336+
1337+ # Test decoding struct to untyped dict
1338+ decoder = _make_engine_struct_value_decoder ([], src_fields , dict )
1339+ result = decoder (["Alice" , 30 , "New York" ])
1340+ assert result == {"name" : "Alice" , "age" : 30 , "city" : "New York" }
0 commit comments