2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 #pragma mark - Codec for basic message channel
12 @implementation FlutterStandardMessageCodec {
14 }
15 + (instancetype)sharedInstance {
16 static id _sharedInstance = nil;
17 if (!_sharedInstance) {
19 _sharedInstance = [[ FlutterStandardMessageCodec alloc] initWithReaderWriter:readerWriter];
20 }
21 return _sharedInstance;
22 }
24 + (instancetype)codecWithReaderWriter:( FlutterStandardReaderWriter *)readerWriter {
25 return [[ FlutterStandardMessageCodec alloc] initWithReaderWriter:readerWriter];
26 }
28 - (instancetype)initWithReaderWriter:( FlutterStandardReaderWriter *)readerWriter {
29 self = [ super init];
30 NSAssert( self , @"Super init cannot be nil" );
31 _readerWriter = readerWriter;
32 return self ;
33 }
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 }
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
56 #pragma mark - Codec for method channel
58 @implementation FlutterStandardMethodCodec {
60 }
61 + (instancetype)sharedInstance {
62 static id _sharedInstance = nil;
63 if (!_sharedInstance) {
65 _sharedInstance = [[ FlutterStandardMethodCodec alloc] initWithReaderWriter:readerWriter];
66 }
67 return _sharedInstance;
68 }
70 + (instancetype)codecWithReaderWriter:( FlutterStandardReaderWriter *)readerWriter {
71 return [[ FlutterStandardMethodCodec alloc] initWithReaderWriter:readerWriter];
72 }
74 - (instancetype)initWithReaderWriter:( FlutterStandardReaderWriter *)readerWriter {
75 self = [ super init];
76 NSAssert( self , @"Super init cannot be nil" );
77 _readerWriter = readerWriter;
78 return self ;
79 }
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 }
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 }
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 }
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 }
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
141 using namespace flutter ;
143 #pragma mark - Standard serializable types
145 @implementation FlutterStandardTypedData
146 + (instancetype)typedDataWithBytes:(NSData*)data {
147 return [ FlutterStandardTypedData typedDataWithData:data type:FlutterStandardDataTypeUInt8];
148 }
150 + (instancetype)typedDataWithInt32:(NSData*)data {
151 return [ FlutterStandardTypedData typedDataWithData:data type:FlutterStandardDataTypeInt32];
152 }
154 + (instancetype)typedDataWithInt64:(NSData*)data {
155 return [ FlutterStandardTypedData typedDataWithData:data type:FlutterStandardDataTypeInt64];
156 }
158 + (instancetype)typedDataWithFloat32:(NSData*)data {
159 return [ FlutterStandardTypedData typedDataWithData:data type:FlutterStandardDataTypeFloat32];
160 }
162 + (instancetype)typedDataWithFloat64:(NSData*)data {
163 return [ FlutterStandardTypedData typedDataWithData:data type:FlutterStandardDataTypeFloat64];
164 }
166 + (instancetype)typedDataWithData:(NSData*)data type:(FlutterStandardDataType)type {
167 return [[ FlutterStandardTypedData alloc] initWithData:data type:type];
168 }
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 }
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 }
195 - (NSUInteger)hash {
196 return [ self .data hash] ^ self .type;
197 }
198 @end
200 #pragma mark - Writer and reader of standard codec
202 @implementation FlutterStandardWriter {
203 NSMutableData* _data;
204 }
206 - (instancetype)initWithData:(NSMutableData*)data {
207 self = [ super init];
208 NSAssert( self , @"Super init cannot be nil" );
209 _data = data;
210 return self ;
211 }
213 - (void)writeByte:(UInt8)value {
214 FlutterStandardCodecHelperWriteByte ((__bridge CFMutableDataRef)_data, value);
215 }
217 - (void)writeBytes:(const void *)bytes length:(NSUInteger)length {
218 FlutterStandardCodecHelperWriteBytes ((__bridge CFMutableDataRef)_data, bytes, length);
219 }
221 - (void)writeData:(NSData*)data {
222 FlutterStandardCodecHelperWriteData ((__bridge CFMutableDataRef)_data, (__bridge CFDataRef)data);
223 }
225 - (void)writeSize:(UInt32)size {
226 FlutterStandardCodecHelperWriteSize ((__bridge CFMutableDataRef)_data, size);
227 }
229 - (void)writeAlignment:(UInt8)alignment {
230 FlutterStandardCodecHelperWriteAlignment ((__bridge CFMutableDataRef)_data, alignment);
231 }
233 - (void)writeUTF8:(NSString*)value {
234 FlutterStandardCodecHelperWriteUTF8 ((__bridge CFMutableDataRef)_data,
235 (__bridge CFStringRef)value);
236 }
238 static FlutterStandardCodecObjcType GetWriteType( id value) {
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 }
259 CFTypeRef writer ;
260 CFMutableDataRef data ;
261 };
263 static void WriteKeyValues(CFTypeRef key, CFTypeRef value, void * context) {
265 FastWriteValueOfType(info-> writer , info-> data , key);
266 FastWriteValueOfType(info-> writer , info-> data , value);
267 }
269 // Recurses into WriteValueOfType directly if it is writing a known type,
270 // otherwise recurses with objc_msgSend.
271 static 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 }
280 static void WriteValueOfType(CFTypeRef writer,
281 CFMutableDataRef data,
283 CFTypeRef value) {
284 switch (type) {
287 break ;
289 CFNumberRef number = (CFNumberRef)value;
290 BOOL success = FlutterStandardCodecHelperWriteNumber (data, number);
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 }
347 - (void)writeValue:( id )value {
348 FlutterStandardCodecObjcType type = GetWriteType(value);
349 WriteValueOfType((__bridge CFTypeRef) self , (__bridge CFMutableDataRef) self ->_data, type,
350 (__bridge CFTypeRef)value);
351 }
352 @end
355 NSData* _data;
356 NSRange _range ;
357 }
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 }
367 - (BOOL)hasMore {
368 return _range .location < _data.length;
369 }
371 - (void)readBytes:( void *)destination length:(NSUInteger)length {
372 FlutterStandardCodecHelperReadBytes (& _range .location, length, destination,
373 (__bridge CFDataRef)_data);
374 }
376 - (UInt8)readByte {
377 return FlutterStandardCodecHelperReadByte (& _range .location, (__bridge CFDataRef)_data);
378 }
380 - (UInt32)readSize {
381 return FlutterStandardCodecHelperReadSize (& _range .location, (__bridge CFDataRef)_data);
382 }
384 - (NSData*)readData:(NSUInteger)length {
385 _range .length = length;
386 NSData* data = [_data subdataWithRange:_range];
387 _range .location += _range .length;
388 return data;
389 }
391 - (NSString*)readUTF8 {
392 return (__bridge NSString*) FlutterStandardCodecHelperReadUTF8 (& _range .location,
393 (__bridge CFDataRef)_data);
394 }
396 - (void)readAlignment:(UInt8)alignment {
398 }
400 - (nullable id)readValue {
401 return (__bridge id )ReadValue((__bridge CFTypeRef) self );
402 }
404 static 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 }
411 static 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);
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 }
429 - (nullable id)readValueOfType:(UInt8)type {
431 & _range .location, (__bridge CFDataRef)_data, type, ReadValue, ReadTypedDataOfType,
432 (__bridge CFTypeRef) self );
433 }
434 @end
437 - ( FlutterStandardWriter *)writerWithData:(NSMutableData*)data {
438 return [[ FlutterStandardWriter alloc] initWithData:data];
439 }
441 - ( FlutterStandardReader *)readerWithData:(NSData*)data {
442 return [[ FlutterStandardReader alloc] initWithData:data];
443 }
444 @end
FlutterStandardField FlutterStandardFieldForDataType(FlutterStandardDataType type)
CFStringRef FlutterStandardCodecHelperReadUTF8(unsigned long *location, CFDataRef data)
Definition: FlutterStandardCodecHelper.cc:75
instancetype methodCallWithMethodName:arguments:(NSString *method,[arguments] id _Nullable arguments)
uint32_t FlutterStandardCodecHelperReadSize(unsigned long *location, CFDataRef data)
NSRange _range
FlutterStandardDataType type
void FlutterStandardCodecHelperWriteUTF8(CFMutableDataRef data, CFStringRef value)
FlutterStandardDataType FlutterStandardDataTypeForField(FlutterStandardField field)
void FlutterStandardCodecHelperWriteAlignment(CFMutableDataRef data, uint8_t alignment)
uint8_t FlutterStandardCodecHelperReadByte(unsigned long *location, CFDataRef data)
instancetype errorWithCode:message:details:(NSString *code,[message] NSString *_Nullable message,[details] id _Nullable details)
CFTypeRef FlutterStandardCodecHelperReadValueOfType(unsigned long *location, CFDataRef data, uint8_t type, CFTypeRef(*ReadValue)(CFTypeRef), CFTypeRef(*ReadTypedDataOfType)(FlutterStandardField, CFTypeRef), CFTypeRef user_data)
@ FlutterStandardCodecObjcTypeFlutterStandardTypedData
@ FlutterStandardCodecObjcTypeNSString
UInt8 elementSizeForFlutterStandardDataType(FlutterStandardDataType type)
@ FlutterStandardCodecObjcTypeNSArray
void FlutterStandardCodecHelperReadBytes(unsigned long *location, unsigned long length, void *destination, CFDataRef data)
void FlutterStandardCodecHelperWriteSize(CFMutableDataRef data, uint32_t size)
bool FlutterStandardCodecHelperWriteNumber(CFMutableDataRef data, CFNumberRef number)
void FlutterStandardCodecHelperWriteData(CFMutableDataRef data, CFDataRef value)
void FlutterStandardCodecHelperWriteBytes(CFMutableDataRef data, const void *bytes, unsigned long length)
void FlutterStandardCodecHelperReadAlignment(unsigned long *location, uint8_t alignment)
@ FlutterStandardCodecObjcTypeNSNumber
nullable id readValueOfType:(UInt8 type)
void FlutterStandardCodecHelperWriteByte(CFMutableDataRef data, uint8_t value)
@ FlutterStandardCodecObjcTypeUnknown
@ FlutterStandardCodecObjcTypeNil
@ FlutterStandardCodecObjcTypeNSDictionary
@ FlutterStandardCodecObjcTypeNSData