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 @@
package org.chromium.mojo.bindings;
import org.chromium.mojo.bindings.Struct.DataHeader;
import org.chromium.mojo.system.AsyncWaiter;
import org.chromium.mojo.system.Handle;
......@@ -29,16 +30,14 @@ public class BindingsHelper {
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) {
return (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
}
public static final int UNSPECIFIED_ARRAY_LENGTH = -1;
/**
* Passed as |arrayNullability| when neither the array nor its elements are nullable.
......@@ -63,6 +62,13 @@ public class BindingsHelper {
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}.
*/
......
......@@ -144,6 +144,21 @@ public class Decoder {
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.
*/
......
......@@ -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}.
*/
......
{% from "constant_definition.tmpl" import constant_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) %}
{% if kind|is_pointer_array_kind %}
{% set sub_kind = kind.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}}.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}}) {
{{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 %}
encoder{{level}}.{{kind|encode_method(variable, offset, bit)}};
{% endif %}
{% endmacro %}
{% 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}});
{% if kind|is_struct_kind %}
{{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) {
{{variable}} = null;
} 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')}};
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)}}
}
{% endif %}
}
{% endif %}
{% else %}
......
......@@ -181,11 +181,7 @@ def AppendEncodeDecodeParams(initial_params, context, kind, bit):
else:
params.append(GetJavaTrueFalse(mojom.IsNullableKind(kind)))
if mojom.IsAnyArrayKind(kind):
if mojom.IsFixedArrayKind(kind):
params.append(str(kind.length))
else:
params.append(
'org.chromium.mojo.bindings.BindingsHelper.UNSPECIFIED_ARRAY_LENGTH');
params.append(GetArrayExpectedLength(kind))
if mojom.IsInterfaceKind(kind):
params.append('%s.MANAGER' % GetJavaType(context, kind))
if mojom.IsAnyArrayKind(kind) and mojom.IsInterfaceKind(kind.kind):
......@@ -253,6 +249,10 @@ def GetJavaType(context, kind, boxed=False):
if mojom.IsInterfaceRequestKind(kind):
return ('org.chromium.mojo.bindings.InterfaceRequest<%s>' %
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):
return '%s[]' % GetJavaType(context, kind.kind)
if mojom.IsEnumKind(kind):
......@@ -323,6 +323,20 @@ def ExpressionToText(context, token, kind_spec=''):
return 'java.lang.Float.NaN'
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):
if not mojom.IsAnyArrayKind(kind):
return False
......@@ -379,6 +393,8 @@ def ZipContentInto(root, zip_filename):
class Generator(generator.Generator):
java_filters = {
'array': GetArrayKind,
'array_expected_length': GetArrayExpectedLength,
'interface_response_name': GetInterfaceResponseName,
'constant_value': ConstantValue,
'default_value': DefaultValue,
......@@ -389,6 +405,7 @@ class Generator(generator.Generator):
'has_method_without_response': HasMethodWithoutResponse,
'is_fixed_array_kind': mojom.IsFixedArrayKind,
'is_handle': mojom.IsNonInterfaceHandleKind,
'is_map_kind': mojom.IsMapKind,
'is_nullable_kind': mojom.IsNullableKind,
'is_pointer_array_kind': IsPointerArrayKind,
'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