Skip to content

Commit

Permalink
[C++] Support optional fields/elements in RowEncoder (#1223)
Browse files Browse the repository at this point in the history
  • Loading branch information
PragmaTwice authored Dec 9, 2023
1 parent bc1c50b commit 84747cf
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/fury/encoder/row_encode_trait.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,13 @@ inline constexpr bool IsString =
template <typename T>
inline constexpr bool IsArray = meta::IsIterable<T> && !IsString<T>;

template <typename> inline constexpr bool IsOptional = false;

template <typename T> inline constexpr bool IsOptional<std::optional<T>> = true;

template <typename T>
inline constexpr bool IsClassButNotBuiltin =
std::is_class_v<T> && !(IsString<T> || IsArray<T>);
std::is_class_v<T> && !(IsString<T> || IsArray<T> || IsOptional<T>);

inline decltype(auto) GetChildType(RowWriter &writer, int index) {
return writer.schema()->field(index)->type();
Expand Down Expand Up @@ -140,6 +144,24 @@ struct RowEncodeTrait<
}
};

template <typename T>
struct RowEncodeTrait<
T, std::enable_if_t<details::IsOptional<std::remove_cv_t<T>>>> {
static auto Type() { return RowEncodeTrait<typename T::value_type>::Type(); }

template <typename V, typename W,
std::enable_if_t<meta::IsOneOf<W, RowWriter, ArrayWriter>::value,
int> = 0>
static void Write(V &&visitor, const T &value, W &writer, int index) {
if (value) {
RowEncodeTrait<typename T::value_type>::Write(std::forward<V>(visitor),
*value, writer, index);
} else {
writer.SetNullAt(index);
}
}
};

template <typename T>
struct RowEncodeTrait<
T, std::enable_if_t<details::IsClassButNotBuiltin<std::remove_cv_t<T>>>> {
Expand Down
47 changes: 47 additions & 0 deletions src/fury/encoder/row_encode_trait_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "gtest/gtest.h"
#include <memory>
#include <optional>
#include <type_traits>

#include "fury/encoder/row_encode_trait.h"
Expand Down Expand Up @@ -247,6 +248,52 @@ TEST(RowEncodeTrait, ArrayInArray) {
ASSERT_EQ(array->GetArray(2)->GetInt32(2), 60);
}

struct F {
bool a;
std::optional<int> b;
int c;
};

FURY_FIELD_INFO(F, a, b, c);

TEST(RowEncodeTrait, Optional) {
F x{false, 233, 111}, y{true, std::nullopt, 222};

auto schema = encoder::RowEncodeTrait<F>::Type();
ASSERT_EQ(schema->field(0)->type()->name(), "bool");
ASSERT_EQ(schema->field(1)->type()->name(), "int32");
ASSERT_EQ(schema->field(2)->type()->name(), "int32");

{
RowWriter writer(encoder::RowEncodeTrait<F>::Schema());
writer.Reset();

encoder::RowEncodeTrait<F>::Write(encoder::EmptyWriteVisitor{}, x, writer);

auto row = writer.ToRow();
ASSERT_EQ(row->IsNullAt(0), false);
ASSERT_EQ(row->IsNullAt(1), false);
ASSERT_EQ(row->IsNullAt(2), false);

ASSERT_EQ(row->GetInt32(1), 233);
ASSERT_EQ(row->GetInt32(2), 111);
}

{
RowWriter writer(encoder::RowEncodeTrait<F>::Schema());
writer.Reset();

encoder::RowEncodeTrait<F>::Write(encoder::EmptyWriteVisitor{}, y, writer);

auto row = writer.ToRow();
ASSERT_EQ(row->IsNullAt(0), false);
ASSERT_EQ(row->IsNullAt(1), true);
ASSERT_EQ(row->IsNullAt(2), false);

ASSERT_EQ(row->GetInt32(2), 222);
}
}

} // namespace test

} // namespace fury
Expand Down

0 comments on commit 84747cf

Please sign in to comment.