Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
ddaba899
Commit
ddaba899
authored
Mar 02, 2017
by
Mikkel Nygaard Ravn
Committed by
GitHub
Mar 02, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PlatformMessageChannel: code cleanup, bugfixes, and unit tests (#8509)
parent
69b6bb87
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
286 additions
and
40 deletions
+286
-40
serialization.dart
packages/flutter/lib/src/foundation/serialization.dart
+12
-20
message_codecs.dart
packages/flutter/lib/src/services/message_codecs.dart
+20
-20
message_codecs_test.dart
packages/flutter/test/services/message_codecs_test.dart
+254
-0
No files found.
packages/flutter/lib/src/foundation/serialization.dart
View file @
ddaba899
...
...
@@ -14,16 +14,16 @@ import 'package:typed_data/typed_buffers.dart' show Uint8Buffer;
/// The byte order of serialized data is [Endianness.BIG_ENDIAN].
/// The byte order of deserialized data is [Endianness.HOST_ENDIAN].
class
WriteBuffer
{
Uint8Buffer
_buffer
;
ByteData
_eightBytes
;
Uint8List
_eightBytesAsList
;
WriteBuffer
()
{
_buffer
=
new
Uint8Buffer
();
_eightBytes
=
new
ByteData
(
8
);
_eightBytesAsList
=
_eightBytes
.
buffer
.
asUint8List
();
}
Uint8Buffer
_buffer
;
ByteData
_eightBytes
;
Uint8List
_eightBytesAsList
;
void
putUint8
(
int
byte
)
{
_buffer
.
add
(
byte
);
}
...
...
@@ -60,9 +60,8 @@ class WriteBuffer {
if
(
Endianness
.
HOST_ENDIAN
==
Endianness
.
BIG_ENDIAN
)
{
_buffer
.
addAll
(
list
.
buffer
.
asUint8List
(
list
.
offsetInBytes
,
4
*
list
.
length
));
}
else
{
for
(
final
int
value
in
list
)
{
for
(
final
int
value
in
list
)
putInt32
(
value
);
}
}
}
...
...
@@ -71,9 +70,8 @@ class WriteBuffer {
if
(
Endianness
.
HOST_ENDIAN
==
Endianness
.
BIG_ENDIAN
)
{
_buffer
.
addAll
(
list
.
buffer
.
asUint8List
(
list
.
offsetInBytes
,
8
*
list
.
length
));
}
else
{
for
(
final
int
value
in
list
)
{
for
(
final
int
value
in
list
)
putInt64
(
value
);
}
}
}
...
...
@@ -82,18 +80,16 @@ class WriteBuffer {
if
(
Endianness
.
HOST_ENDIAN
==
Endianness
.
BIG_ENDIAN
)
{
_buffer
.
addAll
(
list
.
buffer
.
asUint8List
(
list
.
offsetInBytes
,
8
*
list
.
length
));
}
else
{
for
(
final
double
value
in
list
)
{
for
(
final
double
value
in
list
)
putFloat64
(
value
);
}
}
}
void
_alignTo
(
int
alignment
)
{
final
int
mod
=
_buffer
.
length
%
alignment
;
if
(
mod
!=
0
)
{
for
(
int
i
=
0
;
i
<
alignment
-
mod
;
i
++)
{
for
(
int
i
=
0
;
i
<
alignment
-
mod
;
i
++)
_buffer
.
add
(
0
);
}
}
}
...
...
@@ -152,9 +148,8 @@ class ReadBuffer {
list
=
data
.
buffer
.
asInt32List
(
data
.
offsetInBytes
+
position
,
length
);
}
else
{
final
ByteData
invertedData
=
new
ByteData
(
4
*
length
);
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
invertedData
.
setInt32
(
i
*
4
,
data
.
getInt32
(
position
+
i
*
4
,
Endianness
.
HOST_ENDIAN
));
}
list
=
new
Int32List
.
view
(
invertedData
.
buffer
);
}
position
+=
4
*
length
;
...
...
@@ -168,9 +163,8 @@ class ReadBuffer {
list
=
data
.
buffer
.
asInt64List
(
data
.
offsetInBytes
+
position
,
length
);
}
else
{
final
ByteData
invertedData
=
new
ByteData
(
8
*
length
);
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
invertedData
.
setInt64
(
i
*
8
,
data
.
getInt64
(
position
+
i
*
8
,
Endianness
.
HOST_ENDIAN
));
}
list
=
new
Int64List
.
view
(
invertedData
.
buffer
);
}
position
+=
8
*
length
;
...
...
@@ -184,9 +178,8 @@ class ReadBuffer {
list
=
data
.
buffer
.
asFloat64List
(
data
.
offsetInBytes
+
position
,
length
);
}
else
{
final
ByteData
invertedData
=
new
ByteData
(
8
*
length
);
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
invertedData
.
setFloat64
(
i
*
8
,
data
.
getFloat64
(
position
+
i
*
8
,
Endianness
.
HOST_ENDIAN
));
}
list
=
new
Float64List
.
view
(
invertedData
.
buffer
);
}
position
+=
8
*
length
;
...
...
@@ -195,9 +188,8 @@ class ReadBuffer {
void
_alignTo
(
int
alignment
)
{
final
int
mod
=
position
%
alignment
;
if
(
mod
!=
0
)
{
if
(
mod
!=
0
)
position
+=
alignment
-
mod
;
}
}
bool
get
hasRemaining
=>
position
<
data
.
lengthInBytes
;
...
...
packages/flutter/lib/src/services/message_codecs.dart
View file @
ddaba899
...
...
@@ -138,11 +138,13 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
// * The serialization of the value itself follows the type byte.
// * Lengths and sizes of serialized parts are encoded using an expanding
// format optimized for the common case of small non-negative integers:
// * values 0..<254 using one byte with that value;
// * values 254..<2^16 using three bytes, the first of which is 254, the
// next two the usual big-endian unsigned representation of the value;
// * values 2^16..<2^32 using five bytes, the first of which is 255, the
// next four the usual big-endian unsigned representation of the value.
// * values 0..253 inclusive using one byte with that value;
// * values 254..2^16 inclusive using three bytes, the first of which is
// 254, the next two the usual big-endian unsigned representation of the
// value;
// * values 2^16+1..2^32 inclusive using five bytes, the first of which is
// 255, the next four the usual big-endian unsigned representation of the
// value.
// * null, true, and false have empty serialization; they are encoded directly
// in the type byte (using _kNull, _kTrue, _kFalse)
// * Integers representable in 32 bits are encoded using 4 bytes big-endian,
...
...
@@ -208,19 +210,19 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
}
static
void
_writeSize
(
WriteBuffer
buffer
,
int
value
)
{
assert
(
0
<=
value
&&
value
<
0xffffffff
);
assert
(
0
<=
value
&&
value
<
=
0xffffffff
);
if
(
value
<
254
)
{
buffer
.
putUint8
(
value
);
}
else
if
(
value
<
0xffff
)
{
}
else
if
(
value
<
=
0xffff
)
{
buffer
.
putUint8
(
254
);
buffer
.
putUint8
(
value
>>
8
);
buffer
.
putUint8
(
value
&
0xff
);
buffer
.
putUint8
(
value
);
}
else
{
buffer
.
putUint8
(
255
);
buffer
.
putUint8
(
value
>>
24
);
buffer
.
putUint8
(
(
value
>>
16
)
&
0xff
);
buffer
.
putUint8
(
(
value
>>
8
)
&
0xff
);
buffer
.
putUint8
(
value
&
0xff
);
buffer
.
putUint8
(
value
>>
16
);
buffer
.
putUint8
(
value
>>
8
);
buffer
.
putUint8
(
value
);
}
}
...
...
@@ -230,15 +232,13 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
}
else
if
(
value
is
bool
)
{
buffer
.
putUint8
(
value
?
_kTrue
:
_kFalse
);
}
else
if
(
value
is
int
)
{
if
(-
0x7fffffff
<=
value
&&
value
<
0x7fffffff
)
{
if
(-
0x7fffffff
-
1
<=
value
&&
value
<=
0x7fffffff
)
{
buffer
.
putUint8
(
_kInt32
);
buffer
.
putInt32
(
value
);
}
else
if
(-
0x7fffffffffffffff
<=
value
&&
value
<
0x7fffffffffffffff
)
{
}
else
if
(-
0x7fffffffffffffff
-
1
<=
value
&&
value
<=
0x7fffffffffffffff
)
{
buffer
.
putUint8
(
_kInt64
);
buffer
.
putInt64
(
value
);
}
else
{
}
else
{
buffer
.
putUint8
(
_kLargeInt
);
final
List
<
int
>
hex
=
UTF8
.
encoder
.
convert
(
value
.
toRadixString
(
16
));
_writeSize
(
buffer
,
hex
.
length
);
...
...
@@ -292,12 +292,12 @@ class StandardMessageCodec implements MessageCodec<dynamic> {
return
value
;
}
else
if
(
value
==
254
)
{
return
(
buffer
.
getUint8
()
<<
8
)
|
buffer
.
getUint8
();
|
buffer
.
getUint8
();
}
else
{
return
(
buffer
.
getUint8
()
<<
24
)
|
(
buffer
.
getUint8
()
<<
16
)
|
(
buffer
.
getUint8
()
<<
8
)
|
buffer
.
getUint8
();
|
(
buffer
.
getUint8
()
<<
16
)
|
(
buffer
.
getUint8
()
<<
8
)
|
buffer
.
getUint8
();
}
}
...
...
packages/flutter/test/services/message_codecs_test.dart
0 → 100644
View file @
ddaba899
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:typed_data'
;
import
'package:flutter/services.dart'
;
import
'package:test/test.dart'
;
void
main
(
)
{
group
(
'Binary codec'
,
()
{
const
MessageCodec
<
ByteData
>
binary
=
const
BinaryCodec
();
test
(
'should encode and decode simple messages'
,
()
{
_checkEncodeDecode
<
ByteData
>(
binary
,
null
);
_checkEncodeDecode
<
ByteData
>(
binary
,
new
ByteData
(
0
));
_checkEncodeDecode
<
ByteData
>(
binary
,
new
ByteData
(
4
)..
setInt32
(
0
,
-
7
));
});
});
group
(
'String codec'
,
()
{
const
MessageCodec
<
String
>
string
=
const
StringCodec
();
test
(
'should encode and decode simple messages'
,
()
{
_checkEncodeDecode
<
String
>(
string
,
null
);
_checkEncodeDecode
<
String
>(
string
,
''
);
_checkEncodeDecode
<
String
>(
string
,
'hello'
);
_checkEncodeDecode
<
String
>(
string
,
'special chars >
\
u263A
\
u{1F602}<'
);
});
});
group
(
'JSON message codec'
,
()
{
const
MessageCodec
<
dynamic
>
json
=
const
JSONMessageCodec
();
test
(
'should encode and decode simple messages'
,
()
{
_checkEncodeDecode
<
dynamic
>(
json
,
null
);
_checkEncodeDecode
<
dynamic
>(
json
,
true
);
_checkEncodeDecode
<
dynamic
>(
json
,
false
);
_checkEncodeDecode
<
dynamic
>(
json
,
7
);
_checkEncodeDecode
<
dynamic
>(
json
,
-
7
);
_checkEncodeDecode
<
dynamic
>(
json
,
98742923489
);
_checkEncodeDecode
<
dynamic
>(
json
,
-
98742923489
);
_checkEncodeDecode
<
dynamic
>(
json
,
98740023429234899324932473298438
);
_checkEncodeDecode
<
dynamic
>(
json
,
-
98740023429234899324932473298438
);
_checkEncodeDecode
<
dynamic
>(
json
,
3.14
);
_checkEncodeDecode
<
dynamic
>(
json
,
''
);
_checkEncodeDecode
<
dynamic
>(
json
,
'hello'
);
_checkEncodeDecode
<
dynamic
>(
json
,
'special chars >
\
u263A
\
u{1F602}<'
);
});
test
(
'should encode and decode composite message'
,
()
{
final
List
<
dynamic
>
message
=
<
dynamic
>[
null
,
true
,
false
,
-
707
,
-
7000000007
,
-
70000000000000000000000000000000000000000000000007
,
-
3.14
,
''
,
'hello'
,
<
dynamic
>[
'nested'
,
<
dynamic
>[]],
<
dynamic
,
dynamic
>{
'a'
:
'nested'
,
'b'
:
<
dynamic
,
dynamic
>{}
},
'world'
,
];
_checkEncodeDecode
<
dynamic
>(
json
,
message
);
});
});
group
(
'Standard message codec'
,
()
{
const
MessageCodec
<
dynamic
>
standard
=
const
StandardMessageCodec
();
test
(
'should encode integers correctly at boundary cases'
,
()
{
_checkEncoding
<
dynamic
>(
standard
,
-
0x7fffffff
-
1
,
<
int
>[
3
,
0x80
,
0x00
,
0x00
,
0x00
],
);
_checkEncoding
<
dynamic
>(
standard
,
-
0x7fffffff
-
2
,
<
int
>[
4
,
0xff
,
0xff
,
0xff
,
0xff
,
0x7f
,
0xff
,
0xff
,
0xff
],
);
_checkEncoding
<
dynamic
>(
standard
,
0x7fffffff
,
<
int
>[
3
,
0x7f
,
0xff
,
0xff
,
0xff
],
);
_checkEncoding
<
dynamic
>(
standard
,
0x7fffffff
+
1
,
<
int
>[
4
,
0x00
,
0x00
,
0x00
,
0x00
,
0x80
,
0x00
,
0x00
,
0x00
],
);
_checkEncoding
<
dynamic
>(
standard
,
-
0x7fffffffffffffff
-
1
,
<
int
>[
4
,
0x80
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
],
);
_checkEncoding
<
dynamic
>(
standard
,
-
0x7fffffffffffffff
-
2
,
<
int
>[
5
,
17
]..
addAll
(
'-8000000000000001'
.
codeUnits
),
);
_checkEncoding
<
dynamic
>(
standard
,
0x7fffffffffffffff
,
<
int
>[
4
,
0x7f
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
],
);
_checkEncoding
<
dynamic
>(
standard
,
0x7fffffffffffffff
+
1
,
<
int
>[
5
,
16
]..
addAll
(
'8000000000000000'
.
codeUnits
),
);
});
test
(
'should encode sizes correctly at boundary cases'
,
()
{
_checkEncoding
<
dynamic
>(
standard
,
new
Uint8List
(
253
),
<
int
>[
8
,
253
]..
addAll
(
new
List
<
int
>.
filled
(
253
,
0
)),
);
_checkEncoding
<
dynamic
>(
standard
,
new
Uint8List
(
254
),
<
int
>[
8
,
254
,
0
,
254
]..
addAll
(
new
List
<
int
>.
filled
(
254
,
0
)),
);
_checkEncoding
<
dynamic
>(
standard
,
new
Uint8List
(
0xffff
),
<
int
>[
8
,
254
,
0xff
,
0xff
]..
addAll
(
new
List
<
int
>.
filled
(
0xffff
,
0
)),
);
_checkEncoding
<
dynamic
>(
standard
,
new
Uint8List
(
0xffff
+
1
),
<
int
>[
8
,
255
,
0
,
1
,
0
,
0
]..
addAll
(
new
List
<
int
>.
filled
(
0xffff
+
1
,
0
)),
);
});
test
(
'should encode and decode simple messages'
,
()
{
_checkEncodeDecode
<
dynamic
>(
standard
,
null
);
_checkEncodeDecode
<
dynamic
>(
standard
,
true
);
_checkEncodeDecode
<
dynamic
>(
standard
,
false
);
_checkEncodeDecode
<
dynamic
>(
standard
,
7
);
_checkEncodeDecode
<
dynamic
>(
standard
,
-
7
);
_checkEncodeDecode
<
dynamic
>(
standard
,
98742923489
);
_checkEncodeDecode
<
dynamic
>(
standard
,
-
98742923489
);
_checkEncodeDecode
<
dynamic
>(
standard
,
98740023429234899324932473298438
);
_checkEncodeDecode
<
dynamic
>(
standard
,
-
98740023429234899324932473298438
);
_checkEncodeDecode
<
dynamic
>(
standard
,
3.14
);
_checkEncodeDecode
<
dynamic
>(
standard
,
double
.
INFINITY
);
_checkEncodeDecode
<
dynamic
>(
standard
,
double
.
NAN
);
_checkEncodeDecode
<
dynamic
>(
standard
,
''
);
_checkEncodeDecode
<
dynamic
>(
standard
,
'hello'
);
_checkEncodeDecode
<
dynamic
>(
standard
,
'special chars >
\
u263A
\
u{1F602}<'
);
});
test
(
'should encode and decode composite message'
,
()
{
final
List
<
dynamic
>
message
=
<
dynamic
>[
null
,
true
,
false
,
-
707
,
-
7000000007
,
-
70000000000000000000000000000000000000000000000007
,
-
3.14
,
''
,
'hello'
,
new
Uint8List
.
fromList
(<
int
>[
0xBA
,
0x5E
,
0xBA
,
0x11
]),
new
Int32List
.
fromList
(<
int
>[-
0x7fffffff
-
1
,
0
,
0x7fffffff
]),
null
,
// ensures the offset of the following list is unaligned.
new
Int64List
.
fromList
(
<
int
>[-
0x7fffffffffffffff
-
1
,
0
,
0x7fffffffffffffff
]),
null
,
// ensures the offset of the following list is unaligned.
new
Float64List
.
fromList
(<
double
>[
double
.
NEGATIVE_INFINITY
,
-
double
.
MAX_FINITE
,
-
double
.
MIN_POSITIVE
,
-
0.0
,
0.0
,
double
.
MIN_POSITIVE
,
double
.
MAX_FINITE
,
double
.
INFINITY
,
double
.
NAN
]),
<
dynamic
>[
'nested'
,
<
dynamic
>[]],
<
dynamic
,
dynamic
>{
'a'
:
'nested'
,
null
:
<
dynamic
,
dynamic
>{}
},
'world'
,
];
_checkEncodeDecode
<
dynamic
>(
standard
,
message
);
});
});
}
void
_checkEncoding
<
T
>(
MessageCodec
<
T
>
codec
,
T
message
,
List
<
int
>
expectedBytes
)
{
final
ByteData
encoded
=
codec
.
encodeMessage
(
message
);
expect
(
encoded
.
buffer
.
asUint8List
(
0
,
encoded
.
lengthInBytes
),
orderedEquals
(
expectedBytes
),
);
}
void
_checkEncodeDecode
<
T
>(
MessageCodec
<
T
>
codec
,
T
message
)
{
final
ByteData
encoded
=
codec
.
encodeMessage
(
message
);
final
T
decoded
=
codec
.
decodeMessage
(
encoded
);
if
(
message
==
null
)
{
expect
(
encoded
,
isNull
);
expect
(
decoded
,
isNull
);
}
else
{
expect
(
_deepEquals
(
message
,
decoded
),
isTrue
);
final
ByteData
encodedAgain
=
codec
.
encodeMessage
(
decoded
);
expect
(
encodedAgain
.
buffer
.
asUint8List
(),
orderedEquals
(
encoded
.
buffer
.
asUint8List
()),
);
}
}
bool
_deepEquals
(
dynamic
valueA
,
dynamic
valueB
)
{
if
(
valueA
is
TypedData
)
return
valueB
is
TypedData
&&
_deepEqualsTypedData
(
valueA
,
valueB
);
if
(
valueA
is
List
)
return
valueB
is
List
&&
_deepEqualsList
(
valueA
,
valueB
);
if
(
valueA
is
Map
)
return
valueB
is
Map
&&
_deepEqualsMap
(
valueA
,
valueB
);
if
(
valueA
is
double
&&
valueA
.
isNaN
)
return
valueB
is
double
&&
valueB
.
isNaN
;
return
valueA
==
valueB
;
}
bool
_deepEqualsTypedData
(
TypedData
valueA
,
TypedData
valueB
)
{
if
(
valueA
is
ByteData
)
{
return
valueB
is
ByteData
&&
_deepEqualsList
(
valueA
.
buffer
.
asUint8List
(),
valueB
.
buffer
.
asUint8List
());
}
if
(
valueA
is
Uint8List
)
return
valueB
is
Uint8List
&&
_deepEqualsList
(
valueA
,
valueB
);
if
(
valueA
is
Int32List
)
return
valueB
is
Int32List
&&
_deepEqualsList
(
valueA
,
valueB
);
if
(
valueA
is
Int64List
)
return
valueB
is
Int64List
&&
_deepEqualsList
(
valueA
,
valueB
);
if
(
valueA
is
Float64List
)
return
valueB
is
Float64List
&&
_deepEqualsList
(
valueA
,
valueB
);
throw
'Unexpected typed data:
$valueA
'
;
}
bool
_deepEqualsList
(
List
<
dynamic
>
valueA
,
List
<
dynamic
>
valueB
)
{
if
(
valueA
.
length
!=
valueB
.
length
)
return
false
;
for
(
int
i
=
0
;
i
<
valueA
.
length
;
i
++)
{
if
(!
_deepEquals
(
valueA
[
i
],
valueB
[
i
]))
return
false
;
}
return
true
;
}
bool
_deepEqualsMap
(
Map
<
dynamic
,
dynamic
>
valueA
,
Map
<
dynamic
,
dynamic
>
valueB
)
{
if
(
valueA
.
length
!=
valueB
.
length
)
return
false
;
for
(
final
dynamic
key
in
valueA
.
keys
)
{
if
(!
valueB
.
containsKey
(
key
)
||
!
_deepEquals
(
valueA
[
key
],
valueB
[
key
]))
return
false
;
}
return
true
;
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment