chromium/mojo/public/cpp/bindings/type_converter.h

// Copyright 2014 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_TYPE_CONVERTER_H_
#define MOJO_PUBLIC_CPP_BINDINGS_TYPE_CONVERTER_H_

#include <stdint.h>

#include <concepts>
#include <memory>
#include <type_traits>

#include "base/types/to_address.h"

namespace mojo {

// NOTE: When possible, please consider using StructTraits / UnionTraits /
// EnumTraits / ArrayTraits / MapTraits / StringTraits if you would like to
// convert between custom types and the wire format of mojom types. The use of
// TypeConverter should be limited as much as possible: ideally, only use it in
// renderers, e.g., for Blink IDL and Oilpan types.
//
// Specialize the following class:
//   template <typename T, typename U> struct TypeConverter;
// to perform type conversion for Mojom-defined structs and arrays. Here, T is
// the target type; U is the input type.
//
// Specializations should implement the following interfaces:
//   namespace mojo {
//   template <>
//   struct TypeConverter<X, Y> {
//     static X Convert(const Y& input);
//   };
//   template <>
//   struct TypeConverter<Y, X> {
//     static Y Convert(const X& input);
//   };
//   }
//
// EXAMPLE:
//
// Suppose you have the following Mojom-defined struct:
//
//   module geometry {
//   struct Point {
//     int32_t x;
//     int32_t y;
//   };
//   }
//
// Now, imagine you wanted to write a TypeConverter specialization for
// gfx::Point. It might look like this:
//
//   namespace mojo {
//   template <>
//   struct TypeConverter<geometry::PointPtr, gfx::Point> {
//     static geometry::PointPtr Convert(const gfx::Point& input) {
//       geometry::PointPtr result;
//       result->x = input.x();
//       result->y = input.y();
//       return result;
//     }
//   };
//   template <>
//   struct TypeConverter<gfx::Point, geometry::PointPtr> {
//     static gfx::Point Convert(const geometry::PointPtr& input) {
//       return input ? gfx::Point(input->x, input->y) : gfx::Point();
//     }
//   };
//   }
//
// With the above TypeConverter defined, it is possible to write code like this:
//
//   void AcceptPoint(const geometry::PointPtr& input) {
//     // With an explicit cast using the .To<> method.
//     gfx::Point pt = input.To<gfx::Point>();
//
//     // With an explicit cast using the static From() method.
//     geometry::PointPtr output = geometry::Point::From(pt);
//
//     // Inferring the input type using the ConvertTo helper function.
//     gfx::Point pt2 = ConvertTo<gfx::Point>(input);
//   }
//
template <typename T, typename U>
struct TypeConverter;

// The following helper functions are useful shorthand. The compiler can infer
// the input type, so you can write:
//   OutputType out = ConvertTo<OutputType>(input);
template <typename T, typename U>
  requires requires(U* obj) {}

template <typename T, typename U>
  requires requires(const U& obj) {}

template <typename T, typename U>
  requires requires(const U& obj) {}

TypeConverter<T, T>;

namespace internal {

VecValueType;

VecPtrLikeUnderlyingValueType;

}  // namespace internal

// Generic specialization for converting between different vector-like
// containers.
TypeConverter<OutVec, InVec>;

// Specialization for converting from Vector<U> to Vector<PtrLike<T>> with only
// TypeConverter<T*, U> defined.
TypeConverter<OutVec, InVec>;

}  // namespace mojo

#endif  // MOJO_PUBLIC_CPP_BINDINGS_TYPE_CONVERTER_H_