xref: /aosp_15_r20/external/cronet/third_party/jni_zero/codegen/convert_type.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1# Copyright 2024 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4"""Codegen related to @JniType."""
5
6from codegen import header_common
7import java_types
8
9
10def conversion_declarations(java_to_cpp_types, cpp_to_java_types):
11  declarations = set()
12  for java_type in java_to_cpp_types:
13    T = java_type.converted_type()
14    J = java_type.to_cpp()
15    declarations.add(f'template<> {T} '
16                     f'FromJniType<{T}, {J}>(JNIEnv*, const JavaRef<{J}>&);')
17
18  for java_type in cpp_to_java_types:
19    T = java_type.converted_type()
20    J = java_type.to_cpp()
21    declarations.add(f'template<> jni_zero::ScopedJavaLocalRef<{J}> '
22                     f'ToJniType<{T}, {J}>(JNIEnv*, {T} const&);')
23
24  if not declarations:
25    return ''
26
27  declaration_lines = '\n'.join(sorted(declarations))
28  return f"""\
29// Forward declare used conversion functions to avoid a compiler warning that
30// triggers if a conversion specialization exists within the including .cc file.
31namespace jni_zero {{
32{declaration_lines}
33}}  // namespace jni_zero
34"""
35
36
37def to_jni_expression(sb, rvalue, java_type, clazz_param=None):
38  """Returns a conversion call expression from specified @JniType to default jni type."""
39  if java_type.is_primitive():
40    if java_type.primitive_name == 'int' and not java_type.converted_type():
41      rvalue = f'as_jint({rvalue})'
42    sb(f'static_cast<{java_type.to_cpp()}>({rvalue})')
43    return
44
45  T = java_type.converted_type()
46  if not java_type.is_array():
47    sb(f'jni_zero::ToJniType<{T}, {java_type.to_cpp()}>')
48    sb.param_list(['env', rvalue])
49    return
50
51  element_type = java_type.to_array_element_type()
52  if element_type.is_array():
53    raise Exception(
54        '@JniType() for multi-dimensional arrays are not yet supported. '
55        'Found ' + T)
56  if element_type.is_primitive():
57    sb(f'jni_zero::ConvertArray<{T}>::ToJniType')
58    sb.param_list(['env', rvalue])
59    return
60
61  if clazz_param:
62    clazz_expr = clazz_param.name
63  else:
64    clazz_expr = header_common.class_accessor_expression(
65        element_type.java_class)
66  J = element_type.to_cpp()
67  sb(f'jni_zero::ConvertArray<{T}>::ToJniType<{J}>')
68  sb.param_list(['env', rvalue, clazz_expr])
69
70
71def to_jni_assignment(sb, dest_var_name, src_var_name, java_type):
72  """Returns a conversion statement from specified @JniType to default jni type."""
73  with sb.statement():
74    if java_type.is_primitive():
75      var_type = java_type.to_cpp()
76    else:
77      var_type = f'jni_zero::ScopedJavaLocalRef<{java_type.to_cpp()}>'
78    sb(f'{var_type} {dest_var_name} = ')
79    to_jni_expression(sb, src_var_name, java_type)
80
81
82def from_jni_expression(sb, rvalue, java_type):
83  """Returns a conversion call expression from default jni type to specified @JniType."""
84  T = java_type.converted_type()
85  J = java_type.to_cpp()
86  if java_type.is_primitive():
87    sb(f'static_cast<{T}>({rvalue})')
88    return
89
90  if not java_type.is_primitive():
91    rvalue = header_common.java_param_ref_expression(J, rvalue)
92
93  if not java_type.is_array():
94    sb(f'jni_zero::FromJniType<{T}, {J}>')
95    sb.param_list(['env', rvalue])
96    return
97
98  element_type = java_type.to_array_element_type()
99  if element_type.is_array():
100    raise Exception(
101        '@JniType() for multi-dimensional arrays are not yet supported. '
102        'Found ' + T)
103  if element_type.is_primitive():
104    sb(f'jni_zero::ConvertArray<{T}>::FromJniType')
105    sb.param_list(['env', rvalue])
106    return
107
108  J = java_type.to_array_element_type().to_cpp()
109  sb(f'jni_zero::ConvertArray<{T}>::FromJniType<{J}>')
110  sb.param_list(['env', rvalue])
111
112
113def from_jni_assignment(sb, dst_var_name, src_var_name, java_type):
114  """Returns a conversion statement from default jni type to specified @JniType."""
115  with sb.statement():
116    sb(f'{java_type.converted_type()} {dst_var_name} = ')
117    from_jni_expression(sb, src_var_name, java_type)
118