Skip to content

Commit d1bab9b

Browse files
praihanmeta-codesync[bot]
authored andcommitted
Add helper to create TypeSystem from SerializableTypeSystem
Summary: This is a common operation so having a top-level free function is helpful. Reviewed By: iahs Differential Revision: D95283694 fbshipit-source-id: 29847d601152fa2616e32238f40b33eaa47d881c
1 parent e533086 commit d1bab9b

File tree

3 files changed

+178
-0
lines changed

3 files changed

+178
-0
lines changed

third-party/thrift/src/thrift/lib/cpp2/dynamic/TypeSystemBuilder.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,13 @@ void TypeSystemBuilder::addTypes(SerializableTypeSystem typeSystemDef) {
743743
}
744744
}
745745

746+
std::unique_ptr<TypeSystem> fromSerializable(
747+
SerializableTypeSystem typeSystemDef) {
748+
TypeSystemBuilder builder;
749+
builder.addTypes(std::move(typeSystemDef));
750+
return std::move(builder).build();
751+
}
752+
746753
void TypeSystemBuilder::tryEmplace(Uri uri, DefinitionEntry&& def) {
747754
auto [_, inserted] = definitions_.try_emplace(std::move(uri), std::move(def));
748755
if (!inserted) {

third-party/thrift/src/thrift/lib/cpp2/dynamic/TypeSystemBuilder.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,4 +288,24 @@ class TypeSystemBuilder {
288288
void tryEmplace(Uri, DefinitionEntry&&);
289289
};
290290

291+
/**
292+
* Builds a standalone TypeSystem from a SerializableTypeSystem.
293+
*
294+
* This is a convenience function that constructs a fully-resolved TypeSystem
295+
* from the serializable (Thrift-generated) representation. It is equivalent to:
296+
*
297+
* TypeSystemBuilder builder;
298+
* builder.addTypes(std::move(serializable));
299+
* return std::move(builder).build();
300+
*
301+
* The resulting TypeSystem is self-contained and owns all of its type
302+
* definitions.
303+
*
304+
* Throws:
305+
* - InvalidTypeError if the SerializableTypeSystem contains invalid or
306+
* inconsistent definitions (e.g. duplicate URIs, unresolvable TypeIds,
307+
* non-optional union fields, duplicate field IDs or names, etc.).
308+
*/
309+
std::unique_ptr<TypeSystem> fromSerializable(SerializableTypeSystem);
310+
291311
} // namespace apache::thrift::type_system

third-party/thrift/src/thrift/lib/cpp2/dynamic/test/TypeSystemTest.cpp

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,4 +1618,155 @@ TEST(TypeSystemTest, MatchKind) {
16181618
}
16191619
}
16201620

1621+
namespace {
1622+
1623+
// Helper to construct a SerializableTypeSystem with a single
1624+
// SerializableTypeDefinitionEntry from a struct definition.
1625+
SerializableTypeSystem makeSerializableWithStruct(
1626+
Uri uri, SerializableStructDefinition structDef) {
1627+
SerializableTypeDefinitionEntry entry;
1628+
entry.definition()->set_structDef(std::move(structDef));
1629+
1630+
SerializableTypeSystem sts;
1631+
sts.types()[std::move(uri)] = std::move(entry);
1632+
return sts;
1633+
}
1634+
1635+
} // namespace
1636+
1637+
TEST(FromSerializableTest, Empty) {
1638+
SerializableTypeSystem sts;
1639+
auto typeSystem = fromSerializable(std::move(sts));
1640+
EXPECT_TRUE(typeSystem->getKnownUris()->empty());
1641+
}
1642+
1643+
TEST(FromSerializableTest, SimpleStruct) {
1644+
auto sts = makeSerializableWithStruct(
1645+
"meta.com/test/MyStruct",
1646+
def::Struct({
1647+
def::Field(def::Identity(1, "field1"), def::Optional, TypeIds::I32),
1648+
def::Field(
1649+
def::Identity(2, "field2"), def::AlwaysPresent, TypeIds::String),
1650+
}));
1651+
1652+
auto typeSystem = fromSerializable(std::move(sts));
1653+
1654+
auto defRef =
1655+
typeSystem->getUserDefinedTypeOrThrow(Uri("meta.com/test/MyStruct"));
1656+
EXPECT_TRUE(defRef.isStruct());
1657+
1658+
const auto& fields = defRef.asStruct().fields();
1659+
EXPECT_EQ(fields.size(), 2);
1660+
EXPECT_EQ(fields[0].identity().name(), "field1");
1661+
EXPECT_TRUE(fields[0].type().isI32());
1662+
EXPECT_EQ(fields[1].identity().name(), "field2");
1663+
EXPECT_TRUE(fields[1].type().isString());
1664+
}
1665+
1666+
TEST(FromSerializableTest, MultipleTypesWithReferences) {
1667+
SerializableTypeDefinitionEntry structEntry;
1668+
structEntry.definition()->set_structDef(
1669+
def::Struct({
1670+
def::Field(
1671+
def::Identity(1, "inner"),
1672+
def::Optional,
1673+
TypeIds::uri("meta.com/test/InnerUnion")),
1674+
}));
1675+
1676+
SerializableTypeDefinitionEntry unionEntry;
1677+
unionEntry.definition()->set_unionDef(
1678+
def::Union({
1679+
def::Field(def::Identity(1, "x"), def::Optional, TypeIds::I64),
1680+
}));
1681+
1682+
SerializableTypeSystem sts;
1683+
sts.types()["meta.com/test/OuterStruct"] = std::move(structEntry);
1684+
sts.types()["meta.com/test/InnerUnion"] = std::move(unionEntry);
1685+
1686+
auto typeSystem = fromSerializable(std::move(sts));
1687+
1688+
auto outerRef =
1689+
typeSystem->getUserDefinedTypeOrThrow(Uri("meta.com/test/OuterStruct"));
1690+
EXPECT_TRUE(outerRef.isStruct());
1691+
EXPECT_EQ(outerRef.asStruct().fields().size(), 1);
1692+
1693+
const auto& innerFieldType = outerRef.asStruct().fields()[0].type();
1694+
EXPECT_TRUE(innerFieldType.isUnion());
1695+
1696+
auto innerRef =
1697+
typeSystem->getUserDefinedTypeOrThrow(Uri("meta.com/test/InnerUnion"));
1698+
EXPECT_TRUE(innerRef.isUnion());
1699+
EXPECT_EQ(innerRef.asUnion().fields().size(), 1);
1700+
EXPECT_TRUE(innerRef.asUnion().fields()[0].type().isI64());
1701+
}
1702+
1703+
TEST(FromSerializableTest, EnumType) {
1704+
SerializableTypeDefinitionEntry entry;
1705+
entry.definition()->set_enumDef(
1706+
def::Enum({{"FOO", 0}, {"BAR", 1}, {"BAZ", 2}}));
1707+
1708+
SerializableTypeSystem sts;
1709+
sts.types()["meta.com/test/MyEnum"] = std::move(entry);
1710+
1711+
auto typeSystem = fromSerializable(std::move(sts));
1712+
1713+
auto defRef =
1714+
typeSystem->getUserDefinedTypeOrThrow(Uri("meta.com/test/MyEnum"));
1715+
EXPECT_TRUE(defRef.isEnum());
1716+
EXPECT_EQ(defRef.asEnum().values().size(), 3);
1717+
EXPECT_EQ(defRef.asEnum().values()[0].name, "FOO");
1718+
EXPECT_EQ(defRef.asEnum().values()[1].i32, 1);
1719+
}
1720+
1721+
TEST(FromSerializableTest, EquivalentToBuilderPath) {
1722+
// Build via TypeSystemBuilder directly
1723+
TypeSystemBuilder builder;
1724+
builder.addType(
1725+
"meta.com/test/S",
1726+
def::Struct({
1727+
def::Field(def::Identity(1, "f"), def::Optional, TypeIds::Bool),
1728+
}));
1729+
auto fromBuilder = std::move(builder).build();
1730+
1731+
// Build via fromSerializable
1732+
auto sts = makeSerializableWithStruct(
1733+
"meta.com/test/S",
1734+
def::Struct({
1735+
def::Field(def::Identity(1, "f"), def::Optional, TypeIds::Bool),
1736+
}));
1737+
auto fromHelper = fromSerializable(std::move(sts));
1738+
1739+
// Both should produce equivalent TypeSystems
1740+
auto refBuilder =
1741+
fromBuilder->getUserDefinedTypeOrThrow(Uri("meta.com/test/S"));
1742+
auto refHelper =
1743+
fromHelper->getUserDefinedTypeOrThrow(Uri("meta.com/test/S"));
1744+
1745+
EXPECT_EQ(refBuilder.asStruct().fields().size(), 1);
1746+
EXPECT_EQ(refHelper.asStruct().fields().size(), 1);
1747+
EXPECT_EQ(
1748+
refBuilder.asStruct().fields()[0].identity().name(),
1749+
refHelper.asStruct().fields()[0].identity().name());
1750+
EXPECT_EQ(
1751+
refBuilder.asStruct().fields()[0].type().kind(),
1752+
refHelper.asStruct().fields()[0].type().kind());
1753+
}
1754+
1755+
TEST(FromSerializableTest, ThrowsOnDuplicateFieldIds) {
1756+
// Constructing a SerializableTypeSystem with a map means URIs are inherently
1757+
// unique in the map itself, but we can verify the builder still validates
1758+
// definitions correctly (e.g. duplicate field IDs within a struct).
1759+
SerializableTypeSystem sts;
1760+
1761+
SerializableTypeDefinitionEntry entry;
1762+
entry.definition()->set_structDef(
1763+
def::Struct({
1764+
def::Field(def::Identity(1, "a"), def::Optional, TypeIds::I32),
1765+
def::Field(def::Identity(1, "b"), def::Optional, TypeIds::I64),
1766+
}));
1767+
sts.types()["meta.com/test/BadStruct"] = std::move(entry);
1768+
1769+
EXPECT_THROW(fromSerializable(std::move(sts)), InvalidTypeError);
1770+
}
1771+
16211772
} // namespace apache::thrift::type_system

0 commit comments

Comments
 (0)