Flutter Engine
The Flutter Engine
FlutterStandardCodec.mm
Go to the documentation of this file.
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#import "flutter/shell/platform/darwin/common/framework/Source/FlutterStandardCodecHelper.h"
6#import "flutter/shell/platform/darwin/common/framework/Source/FlutterStandardCodec_Internal.h"
7
9
10#pragma mark - Codec for basic message channel
11
12@implementation FlutterStandardMessageCodec {
13 FlutterStandardReaderWriter* _readerWriter;
14}
15+ (instancetype)sharedInstance {
16 static id _sharedInstance = nil;
17 if (!_sharedInstance) {
18 FlutterStandardReaderWriter* readerWriter = [[FlutterStandardReaderWriter alloc] init];
19 _sharedInstance = [[FlutterStandardMessageCodec alloc] initWithReaderWriter:readerWriter];
20 }
21 return _sharedInstance;
22}
23
24+ (instancetype)codecWithReaderWriter:(FlutterStandardReaderWriter*)readerWriter {
25 return [[FlutterStandardMessageCodec alloc] initWithReaderWriter:readerWriter];
26}
27
28- (instancetype)initWithReaderWriter:(FlutterStandardReaderWriter*)readerWriter {
29 self = [super init];
30 NSAssert(self, @"Super init cannot be nil");
31 _readerWriter = readerWriter;
32 return self;
33}
34
35- (NSData*)encode:(id)message {
36 if (message == nil) {
37 return nil;
38 }
39 NSMutableData* data = [NSMutableData dataWithCapacity:32];
40 FlutterStandardWriter* writer = [_readerWriter writerWithData:data];
41 [writer writeValue:message];
42 return data;
43}
44
45- (id)decode:(NSData*)message {
46 if ([message length] == 0) {
47 return nil;
48 }
49 FlutterStandardReader* reader = [_readerWriter readerWithData:message];
50 id value = [reader readValue];
51 NSAssert(![reader hasMore], @"Corrupted standard message");
52 return value;
53}
54@end
55
56#pragma mark - Codec for method channel
57
58@implementation FlutterStandardMethodCodec {
59 FlutterStandardReaderWriter* _readerWriter;
60}
61+ (instancetype)sharedInstance {
62 static id _sharedInstance = nil;
63 if (!_sharedInstance) {
64 FlutterStandardReaderWriter* readerWriter = [[FlutterStandardReaderWriter alloc] init];
65 _sharedInstance = [[FlutterStandardMethodCodec alloc] initWithReaderWriter:readerWriter];
66 }
67 return _sharedInstance;
68}
69
70+ (instancetype)codecWithReaderWriter:(FlutterStandardReaderWriter*)readerWriter {
71 return [[FlutterStandardMethodCodec alloc] initWithReaderWriter:readerWriter];
72}
73
74- (instancetype)initWithReaderWriter:(FlutterStandardReaderWriter*)readerWriter {
75 self = [super init];
76 NSAssert(self, @"Super init cannot be nil");
77 _readerWriter = readerWriter;
78 return self;
79}
80
81- (NSData*)encodeMethodCall:(FlutterMethodCall*)call {
82 NSMutableData* data = [NSMutableData dataWithCapacity:32];
83 FlutterStandardWriter* writer = [_readerWriter writerWithData:data];
84 [writer writeValue:call.method];
85 [writer writeValue:call.arguments];
86 return data;
87}
88
89- (NSData*)encodeSuccessEnvelope:(id)result {
90 NSMutableData* data = [NSMutableData dataWithCapacity:32];
91 FlutterStandardWriter* writer = [_readerWriter writerWithData:data];
92 [writer writeByte:0];
93 [writer writeValue:result];
94 return data;
95}
96
97- (NSData*)encodeErrorEnvelope:(FlutterError*)error {
98 NSMutableData* data = [NSMutableData dataWithCapacity:32];
99 FlutterStandardWriter* writer = [_readerWriter writerWithData:data];
100 [writer writeByte:1];
101 [writer writeValue:error.code];
102 [writer writeValue:error.message];
103 [writer writeValue:error.details];
104 return data;
105}
106
107- (FlutterMethodCall*)decodeMethodCall:(NSData*)message {
108 FlutterStandardReader* reader = [_readerWriter readerWithData:message];
109 id value1 = [reader readValue];
110 id value2 = [reader readValue];
111 NSAssert(![reader hasMore], @"Corrupted standard method call");
112 NSAssert([value1 isKindOfClass:[NSString class]], @"Corrupted standard method call");
114}
115
116- (id)decodeEnvelope:(NSData*)envelope {
117 FlutterStandardReader* reader = [_readerWriter readerWithData:envelope];
118 UInt8 flag = [reader readByte];
119 NSAssert(flag <= 1, @"Corrupted standard envelope");
120 id result;
121 switch (flag) {
122 case 0: {
123 result = [reader readValue];
124 NSAssert(![reader hasMore], @"Corrupted standard envelope");
125 } break;
126 case 1: {
127 id code = [reader readValue];
128 id message = [reader readValue];
129 id details = [reader readValue];
130 NSAssert(![reader hasMore], @"Corrupted standard envelope");
131 NSAssert([code isKindOfClass:[NSString class]], @"Invalid standard envelope");
132 NSAssert(message == nil || [message isKindOfClass:[NSString class]],
133 @"Invalid standard envelope");
134 result = [FlutterError errorWithCode:code message:message details:details];
135 } break;
136 }
137 return result;
138}
139@end
140
141using namespace flutter;
142
143#pragma mark - Standard serializable types
144
145@implementation FlutterStandardTypedData
146+ (instancetype)typedDataWithBytes:(NSData*)data {
147 return [FlutterStandardTypedData typedDataWithData:data type:FlutterStandardDataTypeUInt8];
148}
149
150+ (instancetype)typedDataWithInt32:(NSData*)data {
151 return [FlutterStandardTypedData typedDataWithData:data type:FlutterStandardDataTypeInt32];
152}
153
154+ (instancetype)typedDataWithInt64:(NSData*)data {
155 return [FlutterStandardTypedData typedDataWithData:data type:FlutterStandardDataTypeInt64];
156}
157
158+ (instancetype)typedDataWithFloat32:(NSData*)data {
159 return [FlutterStandardTypedData typedDataWithData:data type:FlutterStandardDataTypeFloat32];
160}
161
162+ (instancetype)typedDataWithFloat64:(NSData*)data {
163 return [FlutterStandardTypedData typedDataWithData:data type:FlutterStandardDataTypeFloat64];
164}
165
166+ (instancetype)typedDataWithData:(NSData*)data type:(FlutterStandardDataType)type {
167 return [[FlutterStandardTypedData alloc] initWithData:data type:type];
168}
169
170- (instancetype)initWithData:(NSData*)data type:(FlutterStandardDataType)type {
172 NSAssert(data, @"Data cannot be nil");
173 NSAssert(data.length % elementSize == 0, @"Data must contain integral number of elements");
174 self = [super init];
175 NSAssert(self, @"Super init cannot be nil");
176 _data = [data copy];
177 _type = type;
178 _elementSize = elementSize;
179 _elementCount = data.length / elementSize;
180 return self;
181}
182
183- (BOOL)isEqual:(id)object {
184 if (self == object) {
185 return YES;
186 }
187 if (![object isKindOfClass:[FlutterStandardTypedData class]]) {
188 return NO;
189 }
191 return self.type == other.type && self.elementCount == other.elementCount &&
192 [self.data isEqual:other.data];
193}
194
195- (NSUInteger)hash {
196 return [self.data hash] ^ self.type;
197}
198@end
199
200#pragma mark - Writer and reader of standard codec
201
202@implementation FlutterStandardWriter {
203 NSMutableData* _data;
204}
205
206- (instancetype)initWithData:(NSMutableData*)data {
207 self = [super init];
208 NSAssert(self, @"Super init cannot be nil");
209 _data = data;
210 return self;
211}
212
213- (void)writeByte:(UInt8)value {
214 FlutterStandardCodecHelperWriteByte((__bridge CFMutableDataRef)_data, value);
215}
216
217- (void)writeBytes:(const void*)bytes length:(NSUInteger)length {
218 FlutterStandardCodecHelperWriteBytes((__bridge CFMutableDataRef)_data, bytes, length);
219}
220
221- (void)writeData:(NSData*)data {
222 FlutterStandardCodecHelperWriteData((__bridge CFMutableDataRef)_data, (__bridge CFDataRef)data);
223}
224
225- (void)writeSize:(UInt32)size {
226 FlutterStandardCodecHelperWriteSize((__bridge CFMutableDataRef)_data, size);
227}
228
229- (void)writeAlignment:(UInt8)alignment {
230 FlutterStandardCodecHelperWriteAlignment((__bridge CFMutableDataRef)_data, alignment);
231}
232
233- (void)writeUTF8:(NSString*)value {
234 FlutterStandardCodecHelperWriteUTF8((__bridge CFMutableDataRef)_data,
235 (__bridge CFStringRef)value);
236}
237
239 if (value == nil || (__bridge CFNullRef)value == kCFNull) {
241 } else if ([value isKindOfClass:[NSNumber class]]) {
243 } else if ([value isKindOfClass:[NSString class]]) {
245 } else if ([value isKindOfClass:[FlutterStandardTypedData class]]) {
247 } else if ([value isKindOfClass:[NSData class]]) {
249 } else if ([value isKindOfClass:[NSArray class]]) {
251 } else if ([value isKindOfClass:[NSDictionary class]]) {
253 } else {
255 }
256}
257
259 CFTypeRef writer;
260 CFMutableDataRef data;
261};
262
263static void WriteKeyValues(CFTypeRef key, CFTypeRef value, void* context) {
265 FastWriteValueOfType(info->writer, info->data, key);
266 FastWriteValueOfType(info->writer, info->data, value);
267}
268
269// Recurses into WriteValueOfType directly if it is writing a known type,
270// otherwise recurses with objc_msgSend.
271static void FastWriteValueOfType(CFTypeRef writer, CFMutableDataRef data, CFTypeRef value) {
272 FlutterStandardCodecObjcType type = GetWriteType((__bridge id)value);
274 WriteValueOfType(writer, data, type, value);
275 } else {
276 [(__bridge FlutterStandardWriter*)writer writeValue:(__bridge id)value];
277 }
278}
279
280static void WriteValueOfType(CFTypeRef writer,
281 CFMutableDataRef data,
283 CFTypeRef value) {
284 switch (type) {
287 break;
289 CFNumberRef number = (CFNumberRef)value;
291 if (!success) {
292 NSLog(@"Unsupported value: %@ of number type %ld", value, CFNumberGetType(number));
293 NSCAssert(NO, @"Unsupported value for standard codec");
294 }
295 break;
296 }
298 CFStringRef string = (CFStringRef)value;
301 break;
302 }
308 FlutterStandardCodecHelperWriteData(data, (__bridge CFDataRef)typedData.data);
309 break;
310 }
313 (__bridge CFTypeRef)
314 [FlutterStandardTypedData typedDataWithBytes:(__bridge NSData*)value]);
315 break;
317 CFArrayRef array = (CFArrayRef)value;
319 CFIndex count = CFArrayGetCount(array);
321 for (CFIndex i = 0; i < count; ++i) {
322 FastWriteValueOfType(writer, data, CFArrayGetValueAtIndex(array, i));
323 }
324 break;
325 }
327 CFDictionaryRef dict = (CFDictionaryRef)value;
329 CFIndex count = CFDictionaryGetCount(dict);
332 .writer = writer,
333 .data = data,
334 };
335 CFDictionaryApplyFunction(dict, WriteKeyValues, (void*)&info);
336 break;
337 }
339 id objc_value = (__bridge id)value;
340 NSLog(@"Unsupported value: %@ of type %@", objc_value, [objc_value class]);
341 NSCAssert(NO, @"Unsupported value for standard codec");
342 break;
343 }
344 }
345}
346
347- (void)writeValue:(id)value {
349 WriteValueOfType((__bridge CFTypeRef)self, (__bridge CFMutableDataRef)self->_data, type,
350 (__bridge CFTypeRef)value);
351}
352@end
353
354@implementation FlutterStandardReader {
355 NSData* _data;
356 NSRange _range;
357}
358
359- (instancetype)initWithData:(NSData*)data {
360 self = [super init];
361 NSAssert(self, @"Super init cannot be nil");
362 _data = [data copy];
363 _range = NSMakeRange(0, 0);
364 return self;
365}
366
367- (BOOL)hasMore {
368 return _range.location < _data.length;
369}
370
371- (void)readBytes:(void*)destination length:(NSUInteger)length {
372 FlutterStandardCodecHelperReadBytes(&_range.location, length, destination,
373 (__bridge CFDataRef)_data);
374}
375
376- (UInt8)readByte {
377 return FlutterStandardCodecHelperReadByte(&_range.location, (__bridge CFDataRef)_data);
378}
379
380- (UInt32)readSize {
381 return FlutterStandardCodecHelperReadSize(&_range.location, (__bridge CFDataRef)_data);
382}
383
384- (NSData*)readData:(NSUInteger)length {
385 _range.length = length;
386 NSData* data = [_data subdataWithRange:_range];
387 _range.location += _range.length;
388 return data;
389}
390
391- (NSString*)readUTF8 {
392 return (__bridge NSString*)FlutterStandardCodecHelperReadUTF8(&_range.location,
393 (__bridge CFDataRef)_data);
394}
395
396- (void)readAlignment:(UInt8)alignment {
398}
399
400- (nullable id)readValue {
401 return (__bridge id)ReadValue((__bridge CFTypeRef)self);
402}
403
404static CFTypeRef ReadValue(CFTypeRef user_data) {
406 uint8_t type = FlutterStandardCodecHelperReadByte(&reader->_range.location,
407 (__bridge CFDataRef)reader->_data);
408 return (__bridge CFTypeRef)[reader readValueOfType:type];
409}
410
411static CFTypeRef ReadTypedDataOfType(FlutterStandardField field, CFTypeRef user_data) {
413 unsigned long* location = &reader->_range.location;
414 CFDataRef data = (__bridge CFDataRef)reader->_data;
415 FlutterStandardDataType type = FlutterStandardDataTypeForField(field);
416
417 UInt64 elementCount = FlutterStandardCodecHelperReadSize(location, data);
418 UInt64 elementSize = elementSizeForFlutterStandardDataType(type);
419 FlutterStandardCodecHelperReadAlignment(location, elementSize);
420 UInt64 length = elementCount * elementSize;
421 NSRange range = NSMakeRange(*location, length);
422 // Note: subdataWithRange performs better than CFDataCreate and
423 // CFDataCreateBytesNoCopy crashes.
424 NSData* bytes = [(__bridge NSData*)data subdataWithRange:range];
425 *location += length;
426 return (__bridge CFTypeRef)[FlutterStandardTypedData typedDataWithData:bytes type:type];
427}
428
429- (nullable id)readValueOfType:(UInt8)type {
431 &_range.location, (__bridge CFDataRef)_data, type, ReadValue, ReadTypedDataOfType,
432 (__bridge CFTypeRef)self);
433}
434@end
435
436@implementation FlutterStandardReaderWriter
437- (FlutterStandardWriter*)writerWithData:(NSMutableData*)data {
438 return [[FlutterStandardWriter alloc] initWithData:data];
439}
440
441- (FlutterStandardReader*)readerWithData:(NSData*)data {
442 return [[FlutterStandardReader alloc] initWithData:data];
443}
444@end
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
CFTypeRef FlutterStandardCodecHelperReadValueOfType(unsigned long *location, CFDataRef data, uint8_t type, CFTypeRef(*ReadValue)(CFTypeRef), CFTypeRef(*ReadTypedDataOfType)(FlutterStandardField, CFTypeRef), CFTypeRef user_data)
bool FlutterStandardCodecHelperWriteNumber(CFMutableDataRef data, CFNumberRef number)
void FlutterStandardCodecHelperWriteData(CFMutableDataRef data, CFDataRef value)
uint8_t FlutterStandardCodecHelperReadByte(unsigned long *location, CFDataRef data)
void FlutterStandardCodecHelperWriteSize(CFMutableDataRef data, uint32_t size)
CFStringRef FlutterStandardCodecHelperReadUTF8(unsigned long *location, CFDataRef data)
void FlutterStandardCodecHelperWriteBytes(CFMutableDataRef data, const void *bytes, unsigned long length)
void FlutterStandardCodecHelperWriteUTF8(CFMutableDataRef data, CFStringRef value)
void FlutterStandardCodecHelperWriteByte(CFMutableDataRef data, uint8_t value)
uint32_t FlutterStandardCodecHelperReadSize(unsigned long *location, CFDataRef data)
void FlutterStandardCodecHelperReadAlignment(unsigned long *location, uint8_t alignment)
void FlutterStandardCodecHelperWriteAlignment(CFMutableDataRef data, uint8_t alignment)
void FlutterStandardCodecHelperReadBytes(unsigned long *location, unsigned long length, void *destination, CFDataRef data)
@ FlutterStandardFieldMap
@ FlutterStandardFieldList
@ FlutterStandardFieldNil
@ FlutterStandardFieldString
FlutterStandardCodecObjcType
@ FlutterStandardCodecObjcTypeNSArray
@ FlutterStandardCodecObjcTypeFlutterStandardTypedData
@ FlutterStandardCodecObjcTypeNSData
@ FlutterStandardCodecObjcTypeNSString
@ FlutterStandardCodecObjcTypeNil
@ FlutterStandardCodecObjcTypeUnknown
@ FlutterStandardCodecObjcTypeNSDictionary
@ FlutterStandardCodecObjcTypeNSNumber
NSRange _range
int count
Definition: FontMgrTest.cpp:50
static void encode(uint8_t output[16], const uint32_t input[4])
Definition: SkMD5.cpp:240
static uint32_t hash(const SkShaderBase::GradientInfo &v)
GLenum type
FlutterSemanticsFlag flag
uint8_t value
GAsyncResult * result
instancetype errorWithCode:message:details:(NSString *code,[message] NSString *_Nullable message,[details] id _Nullable details)
instancetype methodCallWithMethodName:arguments:(NSString *method,[arguments] id _Nullable arguments)
static CFTypeRef ReadValue(CFTypeRef user_data)
nullable id readValueOfType:(UInt8 type)
FlutterStandardDataType type
instancetype typedDataWithData:type:(NSData *data, [type] FlutterStandardDataType type)
static void FastWriteValueOfType(CFTypeRef writer, CFMutableDataRef data, CFTypeRef value)
static FlutterStandardCodecObjcType GetWriteType(id value)
static void WriteKeyValues(CFTypeRef key, CFTypeRef value, void *context)
size_t length
Win32Message message
FlutterStandardField FlutterStandardFieldForDataType(FlutterStandardDataType type)
FlutterStandardDataType FlutterStandardDataTypeForField(FlutterStandardField field)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
UInt8 elementSizeForFlutterStandardDataType(FlutterStandardDataType type)
static DecodeResult decode(std::string path)
Definition: png_codec.cpp:124
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
void * user_data
const uintptr_t id
int BOOL
Definition: windows_types.h:37