| // Copyright 2013 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ |
| #define MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ |
| |
| #include <concepts> |
| #include <type_traits> |
| |
| #include "mojo/public/cpp/bindings/lib/bindings_internal.h" |
| #include "mojo/public/cpp/bindings/lib/serialization_forward.h" |
| #include "mojo/public/cpp/bindings/lib/template_util.h" |
| |
| namespace mojo { |
| namespace internal { |
| |
| template <typename Traits, typename UserType> |
| bool CallIsNullIfExists(const UserType& input) { |
| static_assert(sizeof(Traits), "Traits must be a complete type."); |
| if constexpr (requires { |
| { Traits::IsNull(input) } -> std::same_as<bool>; |
| }) { |
| return Traits::IsNull(input); |
| } else { |
| return false; |
| } |
| } |
| |
| template <typename T, typename UserType> |
| concept HasSetToNullMethod = requires(UserType* u) { |
| { T::SetToNull(u) } -> std::same_as<void>; |
| }; |
| |
| template <typename Traits, typename UserType> |
| bool CallSetToNullIfExists(UserType* output) { |
| static_assert(sizeof(Traits), "Traits must be a complete type."); |
| if constexpr (HasSetToNullMethod<Traits, UserType>) { |
| Traits::SetToNull(output); |
| } |
| |
| // Note that it is not considered an error to attempt to read a null value |
| // into a non-nullable `output` object. In such cases, the caller must have |
| // used a DataView's corresponding MaybeRead[FieldName] method, thus |
| // explicitly choosing to ignore null values without affecting `output`. |
| // |
| // If instead a caller unwittingly attempts to use a corresponding |
| // Read[FieldName] method to read an optional value into the same non-nullable |
| // UserType, it will result in a compile-time error. As such, we don't need to |
| // account for that case here. |
| return true; |
| } |
| |
| template <typename MojomType, typename UserType> |
| struct TraitsFinder { |
| using Traits = StructTraits<MojomType, UserType>; |
| }; |
| |
| template <typename MojomType, typename UserType> |
| requires(BelongsTo<MojomType, MojomTypeCategory::kUnion>::value) |
| struct TraitsFinder<MojomType, UserType> { |
| using Traits = UnionTraits<MojomType, UserType>; |
| }; |
| |
| template <typename UserType> |
| struct TraitsFinder<StringDataView, UserType> { |
| using Traits = StringTraits<UserType>; |
| }; |
| |
| template <typename UserType, typename ElementType> |
| struct TraitsFinder<ArrayDataView<ElementType>, UserType> { |
| using Traits = ArrayTraits<UserType>; |
| }; |
| |
| template <typename UserType, typename KeyType, typename ValueType> |
| struct TraitsFinder<MapDataView<KeyType, ValueType>, UserType> { |
| using Traits = MapTraits<UserType>; |
| }; |
| |
| template <typename MojomType, typename UserType> |
| constexpr bool IsValidUserTypeForOptionalValue() { |
| if constexpr (IsStdOptional<UserType>::value) { |
| return true; |
| } else { |
| using Traits = typename TraitsFinder<MojomType, UserType>::Traits; |
| return HasSetToNullMethod<Traits, UserType>; |
| } |
| } |
| |
| template <typename T, typename U, typename SFINAE = void> |
| struct HasGetBeginMethod : std::false_type { |
| static_assert(sizeof(T), "T must be a complete type."); |
| }; |
| |
| template <typename T, typename U> |
| struct HasGetBeginMethod<T, |
| U, |
| std::void_t<decltype(T::GetBegin(std::declval<U&>()))>> |
| : std::true_type {}; |
| |
| } // namespace internal |
| } // namespace mojo |
| |
| #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SERIALIZATION_UTIL_H_ |