Commit a456ad3f authored by qsr's avatar qsr Committed by Commit bot

mojo: Add maps to java bindings.

BUG=413863
R=ppi@chromium.org,erg@chromium.org

Review URL: https://codereview.chromium.org/648683003

Cr-Commit-Position: refs/heads/master@{#299295}
parent 98ff22ab
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
package org.chromium.mojo.bindings; package org.chromium.mojo.bindings;
import org.chromium.mojo.bindings.Struct.DataHeader;
import org.chromium.mojo.system.AsyncWaiter; import org.chromium.mojo.system.AsyncWaiter;
import org.chromium.mojo.system.Handle; import org.chromium.mojo.system.Handle;
...@@ -29,16 +30,14 @@ public class BindingsHelper { ...@@ -29,16 +30,14 @@ public class BindingsHelper {
public static final int POINTER_SIZE = 8; public static final int POINTER_SIZE = 8;
/** /**
* The value used for the expected length of a non-fixed size array. * The header for a serialized map element.
*/ */
public static final int UNSPECIFIED_ARRAY_LENGTH = -1; public static final DataHeader MAP_STRUCT_HEADER = new DataHeader(24, 2);
/** /**
* Align |size| on {@link BindingsHelper#ALIGNMENT}. * The value used for the expected length of a non-fixed size array.
*/ */
public static int align(int size) { public static final int UNSPECIFIED_ARRAY_LENGTH = -1;
return (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
}
/** /**
* Passed as |arrayNullability| when neither the array nor its elements are nullable. * Passed as |arrayNullability| when neither the array nor its elements are nullable.
...@@ -63,6 +62,13 @@ public class BindingsHelper { ...@@ -63,6 +62,13 @@ public class BindingsHelper {
return (arrayNullability & ELEMENT_NULLABLE) > 0; return (arrayNullability & ELEMENT_NULLABLE) > 0;
} }
/**
* Align |size| on {@link BindingsHelper#ALIGNMENT}.
*/
public static int align(int size) {
return (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
}
/** /**
* Align |size| on {@link BindingsHelper#ALIGNMENT}. * Align |size| on {@link BindingsHelper#ALIGNMENT}.
*/ */
......
...@@ -144,6 +144,21 @@ public class Decoder { ...@@ -144,6 +144,21 @@ public class Decoder {
return readDataHeaderForArray(8, expectedLength); return readDataHeaderForArray(8, expectedLength);
} }
/**
* Deserializes a {@link DataHeader} at the given offset and checks if it is correct for a map.
*/
public void readDataHeaderForMap() {
DataHeader si = readDataHeader();
if (si.size != BindingsHelper.MAP_STRUCT_HEADER.size) {
throw new DeserializationException(
"Incorrect header for map. The size is incorrect.");
}
if (si.numFields != BindingsHelper.MAP_STRUCT_HEADER.numFields) {
throw new DeserializationException(
"Incorrect header for map. The number of fields is incorrect.");
}
}
/** /**
* Deserializes a byte at the given offset. * Deserializes a byte at the given offset.
*/ */
......
...@@ -422,6 +422,11 @@ public class Encoder { ...@@ -422,6 +422,11 @@ public class Encoder {
} }
} }
public Encoder encoderForMap(int offset) {
encodePointerToNextUnclaimedData(offset);
return getEncoderAtDataOffset(BindingsHelper.MAP_STRUCT_HEADER);
}
/** /**
* Encodes an array of {@link InterfaceRequest}. * Encodes an array of {@link InterfaceRequest}.
*/ */
......
{% from "constant_definition.tmpl" import constant_def %} {% from "constant_definition.tmpl" import constant_def %}
{% from "enum_definition.tmpl" import enum_def %} {% from "enum_definition.tmpl" import enum_def %}
{%- macro array_expected_length(kind) -%}
{%- if kind|is_fixed_array_kind -%}
{{kind.length}}
{%- else -%}
org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH
{%- endif -%}
{%- endmacro -%}
{% macro encode(variable, kind, offset, bit, level=0) %} {% macro encode(variable, kind, offset, bit, level=0) %}
{% if kind|is_pointer_array_kind %} {% if kind|is_pointer_array_kind %}
{% set sub_kind = kind.kind %} {% set sub_kind = kind.kind %}
if ({{variable}} == null) { if ({{variable}} == null) {
encoder{{level}}.encodeNullPointer({{offset}}, {{kind|is_nullable_kind|java_true_false}}); encoder{{level}}.encodeNullPointer({{offset}}, {{kind|is_nullable_kind|java_true_false}});
} else { } else {
org.chromium.mojo.bindings.Encoder encoder{{level + 1}} = encoder{{level}}.encodePointerArray({{variable}}.length, {{offset}}, {{array_expected_length(kind)}}); org.chromium.mojo.bindings.Encoder encoder{{level + 1}} = encoder{{level}}.encodePointerArray({{variable}}.length, {{offset}}, {{kind|array_expected_length}});
for (int i{{level}} = 0; i{{level}} < {{variable}}.length; ++i{{level}}) { for (int i{{level}} = 0; i{{level}} < {{variable}}.length; ++i{{level}}) {
{{encode(variable~'[i'~level~']', sub_kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~level, 0, level+1)|indent(8)}} {{encode(variable~'[i'~level~']', sub_kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~level, 0, level+1)|indent(8)}}
} }
} }
{% elif kind|is_map_kind %}
if ({{variable}} == null) {
encoder{{level}}.encodeNullPointer({{offset}}, {{kind|is_nullable_kind|java_true_false}});
} else {
org.chromium.mojo.bindings.Encoder encoder{{level + 1}} = encoder{{level}}.encoderForMap({{offset}});
int size{{level}} = {{variable}}.size();
{{kind.key_kind|java_type}}[] keys{{level}} = {{kind.key_kind|array|new_array('size'~level)}};
{{kind.value_kind|java_type}}[] values{{level}} = {{kind.value_kind|array|new_array('size'~level)}};
int index{{level}} = 0;
for (java.util.Map.Entry<{{kind.key_kind|java_type(true)}}, {{kind.value_kind|java_type(true)}}> entry{{level}} : {{variable}}.entrySet()) {
keys{{level}}[index{{level}}] = entry{{level}}.getKey();
values{{level}}[index{{level}}] = entry{{level}}.getValue();
}
{{encode('keys'~level, kind.key_kind|array, 'DataHeader.HEADER_SIZE', 0, level+1)|indent(4)}}
{{encode('values'~level, kind.value_kind|array, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE', 0, level+1)|indent(4)}}
}
{% else %} {% else %}
encoder{{level}}.{{kind|encode_method(variable, offset, bit)}}; encoder{{level}}.{{kind|encode_method(variable, offset, bit)}};
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}
{% macro decode(variable, kind, offset, bit, level=0) %} {% macro decode(variable, kind, offset, bit, level=0) %}
{% if kind|is_struct_kind or kind|is_pointer_array_kind %} {% if kind|is_struct_kind or kind|is_pointer_array_kind or kind|is_map_kind %}
org.chromium.mojo.bindings.Decoder decoder{{level+1}} = decoder{{level}}.readPointer({{offset}}, {{kind|is_nullable_kind|java_true_false}}); org.chromium.mojo.bindings.Decoder decoder{{level+1}} = decoder{{level}}.readPointer({{offset}}, {{kind|is_nullable_kind|java_true_false}});
{% if kind|is_struct_kind %} {% if kind|is_struct_kind %}
{{variable}} = {{kind|java_type}}.decode(decoder{{level+1}}); {{variable}} = {{kind|java_type}}.decode(decoder{{level+1}});
{% else %}{# kind|is_pointer_array_kind #} {% else %}{# kind|is_pointer_array_kind or is_map_kind #}
if (decoder{{level+1}} == null) { if (decoder{{level+1}} == null) {
{{variable}} = null; {{variable}} = null;
} else { } else {
DataHeader si{{level+1}} = decoder{{level+1}}.readDataHeaderForPointerArray({{array_expected_length(kind)}}); {% if kind|is_map_kind %}
decoder{{level+1}}.readDataHeaderForMap();
{{kind.key_kind|java_type}}[] keys{{level}};
{{kind.value_kind|java_type}}[] values{{level}};
{
{{decode('keys'~level, kind.key_kind|array, 'DataHeader.HEADER_SIZE', 0, level+1)|indent(8)}}
}
{
{{decode('values'~level, kind.value_kind|array('keys'~level~'.length'), 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE', 0, level+1)|indent(8)}}
}
{{variable}} = new java.util.HashMap<{{kind.key_kind|java_type(true)}}, {{kind.value_kind|java_type(true)}}>();
for (int index{{level}} = 0; index{{level}} < keys{{level}}.length; ++index{{level}}) {
{{variable}}.put(keys{{level}}[index{{level}}], values{{level}}[index{{level}}]);
}
{% else %}
DataHeader si{{level+1}} = decoder{{level+1}}.readDataHeaderForPointerArray({{kind|array_expected_length}});
{{variable}} = {{kind|new_array('si'~(level+1)~'.numFields')}}; {{variable}} = {{kind|new_array('si'~(level+1)~'.numFields')}};
for (int i{{level+1}} = 0; i{{level+1}} < si{{level+1}}.numFields; ++i{{level+1}}) { for (int i{{level+1}} = 0; i{{level+1}} < si{{level+1}}.numFields; ++i{{level+1}}) {
{{decode(variable~'[i'~(level+1)~']', kind.kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~(level+1), 0, level+1)|indent(8)}} {{decode(variable~'[i'~(level+1)~']', kind.kind, 'DataHeader.HEADER_SIZE + org.chromium.mojo.bindings.BindingsHelper.POINTER_SIZE * i'~(level+1), 0, level+1)|indent(8)}}
} }
{% endif %}
} }
{% endif %} {% endif %}
{% else %} {% else %}
......
...@@ -181,11 +181,7 @@ def AppendEncodeDecodeParams(initial_params, context, kind, bit): ...@@ -181,11 +181,7 @@ def AppendEncodeDecodeParams(initial_params, context, kind, bit):
else: else:
params.append(GetJavaTrueFalse(mojom.IsNullableKind(kind))) params.append(GetJavaTrueFalse(mojom.IsNullableKind(kind)))
if mojom.IsAnyArrayKind(kind): if mojom.IsAnyArrayKind(kind):
if mojom.IsFixedArrayKind(kind): params.append(GetArrayExpectedLength(kind))
params.append(str(kind.length))
else:
params.append(
'org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH');
if mojom.IsInterfaceKind(kind): if mojom.IsInterfaceKind(kind):
params.append('%s.MANAGER' % GetJavaType(context, kind)) params.append('%s.MANAGER' % GetJavaType(context, kind))
if mojom.IsAnyArrayKind(kind) and mojom.IsInterfaceKind(kind.kind): if mojom.IsAnyArrayKind(kind) and mojom.IsInterfaceKind(kind.kind):
...@@ -253,6 +249,10 @@ def GetJavaType(context, kind, boxed=False): ...@@ -253,6 +249,10 @@ def GetJavaType(context, kind, boxed=False):
if mojom.IsInterfaceRequestKind(kind): if mojom.IsInterfaceRequestKind(kind):
return ('org.chromium.mojo.bindings.InterfaceRequest<%s>' % return ('org.chromium.mojo.bindings.InterfaceRequest<%s>' %
GetNameForKind(context, kind.kind)) GetNameForKind(context, kind.kind))
if mojom.IsMapKind(kind):
return 'java.util.Map<%s, %s>' % (
GetBoxedJavaType(context, kind.key_kind),
GetBoxedJavaType(context, kind.value_kind))
if mojom.IsAnyArrayKind(kind): if mojom.IsAnyArrayKind(kind):
return '%s[]' % GetJavaType(context, kind.kind) return '%s[]' % GetJavaType(context, kind.kind)
if mojom.IsEnumKind(kind): if mojom.IsEnumKind(kind):
...@@ -323,6 +323,20 @@ def ExpressionToText(context, token, kind_spec=''): ...@@ -323,6 +323,20 @@ def ExpressionToText(context, token, kind_spec=''):
return 'java.lang.Float.NaN' return 'java.lang.Float.NaN'
return token return token
def GetArrayKind(kind, size = None):
if size is None:
return mojom.Array(kind)
else:
array = mojom.FixedArray(0, kind)
array.java_map_size = size
return array
def GetArrayExpectedLength(kind):
if mojom.IsFixedArrayKind(kind):
return getattr(kind, 'java_map_size', str(kind.length))
else:
return 'org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH'
def IsPointerArrayKind(kind): def IsPointerArrayKind(kind):
if not mojom.IsAnyArrayKind(kind): if not mojom.IsAnyArrayKind(kind):
return False return False
...@@ -379,6 +393,8 @@ def ZipContentInto(root, zip_filename): ...@@ -379,6 +393,8 @@ def ZipContentInto(root, zip_filename):
class Generator(generator.Generator): class Generator(generator.Generator):
java_filters = { java_filters = {
'array': GetArrayKind,
'array_expected_length': GetArrayExpectedLength,
'interface_response_name': GetInterfaceResponseName, 'interface_response_name': GetInterfaceResponseName,
'constant_value': ConstantValue, 'constant_value': ConstantValue,
'default_value': DefaultValue, 'default_value': DefaultValue,
...@@ -389,6 +405,7 @@ class Generator(generator.Generator): ...@@ -389,6 +405,7 @@ class Generator(generator.Generator):
'has_method_without_response': HasMethodWithoutResponse, 'has_method_without_response': HasMethodWithoutResponse,
'is_fixed_array_kind': mojom.IsFixedArrayKind, 'is_fixed_array_kind': mojom.IsFixedArrayKind,
'is_handle': mojom.IsNonInterfaceHandleKind, 'is_handle': mojom.IsNonInterfaceHandleKind,
'is_map_kind': mojom.IsMapKind,
'is_nullable_kind': mojom.IsNullableKind, 'is_nullable_kind': mojom.IsNullableKind,
'is_pointer_array_kind': IsPointerArrayKind, 'is_pointer_array_kind': IsPointerArrayKind,
'is_struct_kind': mojom.IsStructKind, 'is_struct_kind': mojom.IsStructKind,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment