1 // Copyright 2013 The Flutter Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package io.flutter.plugin.common; 6 7 import io.flutter.plugin.common.StandardMessageCodec.ExposedByteArrayOutputStream; 8 import java.nio.ByteBuffer; 9 import java.nio.ByteOrder; 10 11 /** 12 * A {@link MethodCodec} using the Flutter standard binary encoding. 13 * 14 * <p>This codec is guaranteed to be compatible with the corresponding 15 * <a href="https://docs.flutter.io/flutter/services/StandardMethodCodec-class.html">StandardMethodCodec</a> 16 * on the Dart side. These parts of the Flutter SDK are evolved synchronously.</p> 17 * 18 * <p>Values supported as method arguments and result payloads are those supported by 19 * {@link StandardMessageCodec}.</p> 20 */ 21 public final class StandardMethodCodec implements MethodCodec { 22 public static final StandardMethodCodec INSTANCE = new StandardMethodCodec(StandardMessageCodec.INSTANCE); 23 private final StandardMessageCodec messageCodec; 24 25 /** 26 * Creates a new method codec based on the specified message codec. 27 */ StandardMethodCodec(StandardMessageCodec messageCodec)28 public StandardMethodCodec(StandardMessageCodec messageCodec) { 29 this.messageCodec = messageCodec; 30 } 31 32 @Override encodeMethodCall(MethodCall methodCall)33 public ByteBuffer encodeMethodCall(MethodCall methodCall) { 34 final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream(); 35 messageCodec.writeValue(stream, methodCall.method); 36 messageCodec.writeValue(stream, methodCall.arguments); 37 final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size()); 38 buffer.put(stream.buffer(), 0, stream.size()); 39 return buffer; 40 } 41 42 @Override decodeMethodCall(ByteBuffer methodCall)43 public MethodCall decodeMethodCall(ByteBuffer methodCall) { 44 methodCall.order(ByteOrder.nativeOrder()); 45 final Object method = messageCodec.readValue(methodCall); 46 final Object arguments = messageCodec.readValue(methodCall); 47 if (method instanceof String && !methodCall.hasRemaining()) { 48 return new MethodCall((String) method, arguments); 49 } 50 throw new IllegalArgumentException("Method call corrupted"); 51 } 52 53 @Override encodeSuccessEnvelope(Object result)54 public ByteBuffer encodeSuccessEnvelope(Object result) { 55 final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream(); 56 stream.write(0); 57 messageCodec.writeValue(stream, result); 58 final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size()); 59 buffer.put(stream.buffer(), 0, stream.size()); 60 return buffer; 61 } 62 63 @Override encodeErrorEnvelope(String errorCode, String errorMessage, Object errorDetails)64 public ByteBuffer encodeErrorEnvelope(String errorCode, String errorMessage, 65 Object errorDetails) { 66 final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream(); 67 stream.write(1); 68 messageCodec.writeValue(stream, errorCode); 69 messageCodec.writeValue(stream, errorMessage); 70 messageCodec.writeValue(stream, errorDetails); 71 final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size()); 72 buffer.put(stream.buffer(), 0, stream.size()); 73 return buffer; 74 } 75 76 @Override decodeEnvelope(ByteBuffer envelope)77 public Object decodeEnvelope(ByteBuffer envelope) { 78 envelope.order(ByteOrder.nativeOrder()); 79 final byte flag = envelope.get(); 80 switch (flag) { 81 case 0: { 82 final Object result = messageCodec.readValue(envelope); 83 if (!envelope.hasRemaining()) { 84 return result; 85 } 86 } 87 // Falls through intentionally. 88 case 1: { 89 final Object code = messageCodec.readValue(envelope); 90 final Object message = messageCodec.readValue(envelope); 91 final Object details = messageCodec.readValue(envelope); 92 if (code instanceof String 93 && (message == null || message instanceof String) 94 && !envelope.hasRemaining()) { 95 throw new FlutterException((String) code, (String) message, details); 96 } 97 } 98 } 99 throw new IllegalArgumentException("Envelope corrupted"); 100 } 101 } 102