| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library test.src.summary.flat_buffers_test; | 5 library test.src.summary.flat_buffers_test; |
| 6 | 6 |
| 7 import 'dart:typed_data'; | 7 import 'dart:typed_data'; |
| 8 | 8 |
| 9 import 'package:analyzer/src/summary/flat_buffers.dart'; | 9 import 'package:analyzer/src/summary/flat_buffers.dart'; |
| 10 import 'package:unittest/unittest.dart'; | 10 import 'package:unittest/unittest.dart'; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 List<int> byteList; | 102 List<int> byteList; |
| 103 { | 103 { |
| 104 Builder builder = new Builder(initialSize: 0); | 104 Builder builder = new Builder(initialSize: 0); |
| 105 builder.startTable(); | 105 builder.startTable(); |
| 106 builder.addInt32(0, 10, 10); | 106 builder.addInt32(0, 10, 10); |
| 107 builder.addInt32(1, 20, 10); | 107 builder.addInt32(1, 20, 10); |
| 108 Offset offset = builder.endTable(); | 108 Offset offset = builder.endTable(); |
| 109 byteList = builder.finish(offset); | 109 byteList = builder.finish(offset); |
| 110 } | 110 } |
| 111 // read and verify | 111 // read and verify |
| 112 BufferPointer object = new BufferPointer.fromBytes(byteList).derefObject(); | 112 BufferContext buffer = new BufferContext.fromBytes(byteList); |
| 113 int objectOffset = buffer.derefObject(0); |
| 113 // was not written, so uses the new default value | 114 // was not written, so uses the new default value |
| 114 expect(const Int32Reader().vTableGet(object, 0, 15), 15); | 115 expect(const Int32Reader().vTableGet(buffer, objectOffset, 0, 15), 15); |
| 115 // has the written value | 116 // has the written value |
| 116 expect(const Int32Reader().vTableGet(object, 1, 15), 20); | 117 expect(const Int32Reader().vTableGet(buffer, objectOffset, 1, 15), 20); |
| 117 } | 118 } |
| 118 | 119 |
| 119 void test_table_format() { | 120 void test_table_format() { |
| 120 Uint8List byteList; | 121 Uint8List byteList; |
| 121 { | 122 { |
| 122 Builder builder = new Builder(initialSize: 0); | 123 Builder builder = new Builder(initialSize: 0); |
| 123 builder.startTable(); | 124 builder.startTable(); |
| 124 builder.addInt32(0, 10); | 125 builder.addInt32(0, 10); |
| 125 builder.addInt32(1, 20); | 126 builder.addInt32(1, 20); |
| 126 builder.addInt32(2, 30); | 127 builder.addInt32(2, 30); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 157 Builder builder = new Builder(initialSize: 0); | 158 Builder builder = new Builder(initialSize: 0); |
| 158 Offset<String> latinStringOffset = builder.writeString(latinString); | 159 Offset<String> latinStringOffset = builder.writeString(latinString); |
| 159 Offset<String> unicodeStringOffset = builder.writeString(unicodeString); | 160 Offset<String> unicodeStringOffset = builder.writeString(unicodeString); |
| 160 builder.startTable(); | 161 builder.startTable(); |
| 161 builder.addOffset(0, latinStringOffset); | 162 builder.addOffset(0, latinStringOffset); |
| 162 builder.addOffset(1, unicodeStringOffset); | 163 builder.addOffset(1, unicodeStringOffset); |
| 163 Offset offset = builder.endTable(); | 164 Offset offset = builder.endTable(); |
| 164 byteList = builder.finish(offset); | 165 byteList = builder.finish(offset); |
| 165 } | 166 } |
| 166 // read and verify | 167 // read and verify |
| 167 BufferPointer object = new BufferPointer.fromBytes(byteList).derefObject(); | 168 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 168 expect(const StringReader().vTableGet(object, 0), latinString); | 169 int objectOffset = buf.derefObject(0); |
| 169 expect(const StringReader().vTableGet(object, 1), unicodeString); | 170 expect(const StringReader().vTableGet(buf, objectOffset, 0), latinString); |
| 171 expect(const StringReader().vTableGet(buf, objectOffset, 1), unicodeString); |
| 170 } | 172 } |
| 171 | 173 |
| 172 void test_table_types() { | 174 void test_table_types() { |
| 173 List<int> byteList; | 175 List<int> byteList; |
| 174 { | 176 { |
| 175 Builder builder = new Builder(initialSize: 0); | 177 Builder builder = new Builder(initialSize: 0); |
| 176 Offset<String> stringOffset = builder.writeString('12345'); | 178 Offset<String> stringOffset = builder.writeString('12345'); |
| 177 builder.startTable(); | 179 builder.startTable(); |
| 178 builder.addBool(0, true); | 180 builder.addBool(0, true); |
| 179 builder.addInt8(1, 10); | 181 builder.addInt8(1, 10); |
| 180 builder.addInt32(2, 20); | 182 builder.addInt32(2, 20); |
| 181 builder.addOffset(3, stringOffset); | 183 builder.addOffset(3, stringOffset); |
| 182 builder.addInt32(4, 40); | 184 builder.addInt32(4, 40); |
| 183 builder.addUint32(5, 0x9ABCDEF0); | 185 builder.addUint32(5, 0x9ABCDEF0); |
| 184 builder.addUint8(6, 0x9A); | 186 builder.addUint8(6, 0x9A); |
| 185 Offset offset = builder.endTable(); | 187 Offset offset = builder.endTable(); |
| 186 byteList = builder.finish(offset); | 188 byteList = builder.finish(offset); |
| 187 } | 189 } |
| 188 // read and verify | 190 // read and verify |
| 189 BufferPointer object = new BufferPointer.fromBytes(byteList).derefObject(); | 191 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 190 expect(const BoolReader().vTableGet(object, 0), true); | 192 int objectOffset = buf.derefObject(0); |
| 191 expect(const Int8Reader().vTableGet(object, 1), 10); | 193 expect(const BoolReader().vTableGet(buf, objectOffset, 0), true); |
| 192 expect(const Int32Reader().vTableGet(object, 2), 20); | 194 expect(const Int8Reader().vTableGet(buf, objectOffset, 1), 10); |
| 193 expect(const StringReader().vTableGet(object, 3), '12345'); | 195 expect(const Int32Reader().vTableGet(buf, objectOffset, 2), 20); |
| 194 expect(const Int32Reader().vTableGet(object, 4), 40); | 196 expect(const StringReader().vTableGet(buf, objectOffset, 3), '12345'); |
| 195 expect(const Uint32Reader().vTableGet(object, 5), 0x9ABCDEF0); | 197 expect(const Int32Reader().vTableGet(buf, objectOffset, 4), 40); |
| 196 expect(const Uint8Reader().vTableGet(object, 6), 0x9A); | 198 expect(const Uint32Reader().vTableGet(buf, objectOffset, 5), 0x9ABCDEF0); |
| 199 expect(const Uint8Reader().vTableGet(buf, objectOffset, 6), 0x9A); |
| 197 } | 200 } |
| 198 | 201 |
| 199 void test_writeList_of_Uint32() { | 202 void test_writeList_of_Uint32() { |
| 200 List<int> values = <int>[10, 100, 12345, 0x9abcdef0]; | 203 List<int> values = <int>[10, 100, 12345, 0x9abcdef0]; |
| 201 // write | 204 // write |
| 202 List<int> byteList; | 205 List<int> byteList; |
| 203 { | 206 { |
| 204 Builder builder = new Builder(initialSize: 0); | 207 Builder builder = new Builder(initialSize: 0); |
| 205 Offset offset = builder.writeListUint32(values); | 208 Offset offset = builder.writeListUint32(values); |
| 206 byteList = builder.finish(offset); | 209 byteList = builder.finish(offset); |
| 207 } | 210 } |
| 208 // read and verify | 211 // read and verify |
| 209 BufferPointer root = new BufferPointer.fromBytes(byteList); | 212 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 210 List<int> items = const Uint32ListReader().read(root); | 213 List<int> items = const Uint32ListReader().read(buf, 0); |
| 211 expect(items, hasLength(4)); | 214 expect(items, hasLength(4)); |
| 212 expect(items, orderedEquals(values)); | 215 expect(items, orderedEquals(values)); |
| 213 } | 216 } |
| 214 | 217 |
| 215 void test_writeList_ofBool() { | 218 void test_writeList_ofBool() { |
| 216 void verifyListBooleans(int len, List<int> trueBits) { | 219 void verifyListBooleans(int len, List<int> trueBits) { |
| 217 // write | 220 // write |
| 218 List<int> byteList; | 221 List<int> byteList; |
| 219 { | 222 { |
| 220 Builder builder = new Builder(initialSize: 0); | 223 Builder builder = new Builder(initialSize: 0); |
| 221 List<bool> values = new List<bool>.filled(len, false); | 224 List<bool> values = new List<bool>.filled(len, false); |
| 222 for (int bit in trueBits) { | 225 for (int bit in trueBits) { |
| 223 values[bit] = true; | 226 values[bit] = true; |
| 224 } | 227 } |
| 225 Offset offset = builder.writeListBool(values); | 228 Offset offset = builder.writeListBool(values); |
| 226 byteList = builder.finish(offset); | 229 byteList = builder.finish(offset); |
| 227 } | 230 } |
| 228 // read and verify | 231 // read and verify |
| 229 BufferPointer root = new BufferPointer.fromBytes(byteList); | 232 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 230 List<bool> items = const BoolListReader().read(root); | 233 List<bool> items = const BoolListReader().read(buf, 0); |
| 231 expect(items, hasLength(len)); | 234 expect(items, hasLength(len)); |
| 232 for (int i = 0; i < items.length; i++) { | 235 for (int i = 0; i < items.length; i++) { |
| 233 expect(items[i], trueBits.contains(i), reason: 'bit $i of $len'); | 236 expect(items[i], trueBits.contains(i), reason: 'bit $i of $len'); |
| 234 } | 237 } |
| 235 } | 238 } |
| 236 verifyListBooleans(0, <int>[]); | 239 verifyListBooleans(0, <int>[]); |
| 237 verifyListBooleans(1, <int>[]); | 240 verifyListBooleans(1, <int>[]); |
| 238 verifyListBooleans(1, <int>[0]); | 241 verifyListBooleans(1, <int>[0]); |
| 239 verifyListBooleans(31, <int>[0, 1]); | 242 verifyListBooleans(31, <int>[0, 1]); |
| 240 verifyListBooleans(31, <int>[1, 2, 24, 25, 30]); | 243 verifyListBooleans(31, <int>[1, 2, 24, 25, 30]); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 256 void test_writeList_ofFloat64() { | 259 void test_writeList_ofFloat64() { |
| 257 List<double> values = <double>[-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13]; | 260 List<double> values = <double>[-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13]; |
| 258 // write | 261 // write |
| 259 List<int> byteList; | 262 List<int> byteList; |
| 260 { | 263 { |
| 261 Builder builder = new Builder(initialSize: 0); | 264 Builder builder = new Builder(initialSize: 0); |
| 262 Offset offset = builder.writeListFloat64(values); | 265 Offset offset = builder.writeListFloat64(values); |
| 263 byteList = builder.finish(offset); | 266 byteList = builder.finish(offset); |
| 264 } | 267 } |
| 265 // read and verify | 268 // read and verify |
| 266 BufferPointer root = new BufferPointer.fromBytes(byteList); | 269 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 267 List<double> items = const Float64ListReader().read(root); | 270 List<double> items = const Float64ListReader().read(buf, 0); |
| 268 expect(items, hasLength(5)); | 271 expect(items, hasLength(5)); |
| 269 expect(items, orderedEquals(values)); | 272 expect(items, orderedEquals(values)); |
| 270 } | 273 } |
| 271 | 274 |
| 272 void test_writeList_ofInt32() { | 275 void test_writeList_ofInt32() { |
| 273 List<int> byteList; | 276 List<int> byteList; |
| 274 { | 277 { |
| 275 Builder builder = new Builder(initialSize: 0); | 278 Builder builder = new Builder(initialSize: 0); |
| 276 Offset offset = builder.writeListInt32(<int>[1, 2, 3, 4, 5]); | 279 Offset offset = builder.writeListInt32(<int>[1, 2, 3, 4, 5]); |
| 277 byteList = builder.finish(offset); | 280 byteList = builder.finish(offset); |
| 278 } | 281 } |
| 279 // read and verify | 282 // read and verify |
| 280 BufferPointer root = new BufferPointer.fromBytes(byteList); | 283 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 281 List<int> items = const ListReader<int>(const Int32Reader()).read(root); | 284 List<int> items = const ListReader<int>(const Int32Reader()).read(buf, 0); |
| 282 expect(items, hasLength(5)); | 285 expect(items, hasLength(5)); |
| 283 expect(items, orderedEquals(<int>[1, 2, 3, 4, 5])); | 286 expect(items, orderedEquals(<int>[1, 2, 3, 4, 5])); |
| 284 } | 287 } |
| 285 | 288 |
| 286 void test_writeList_ofObjects() { | 289 void test_writeList_ofObjects() { |
| 287 List<int> byteList; | 290 List<int> byteList; |
| 288 { | 291 { |
| 289 Builder builder = new Builder(initialSize: 0); | 292 Builder builder = new Builder(initialSize: 0); |
| 290 // write the object #1 | 293 // write the object #1 |
| 291 Offset object1; | 294 Offset object1; |
| 292 { | 295 { |
| 293 builder.startTable(); | 296 builder.startTable(); |
| 294 builder.addInt32(0, 10); | 297 builder.addInt32(0, 10); |
| 295 builder.addInt32(1, 20); | 298 builder.addInt32(1, 20); |
| 296 object1 = builder.endTable(); | 299 object1 = builder.endTable(); |
| 297 } | 300 } |
| 298 // write the object #1 | 301 // write the object #1 |
| 299 Offset object2; | 302 Offset object2; |
| 300 { | 303 { |
| 301 builder.startTable(); | 304 builder.startTable(); |
| 302 builder.addInt32(0, 100); | 305 builder.addInt32(0, 100); |
| 303 builder.addInt32(1, 200); | 306 builder.addInt32(1, 200); |
| 304 object2 = builder.endTable(); | 307 object2 = builder.endTable(); |
| 305 } | 308 } |
| 306 // write the list | 309 // write the list |
| 307 Offset offset = builder.writeList([object1, object2]); | 310 Offset offset = builder.writeList([object1, object2]); |
| 308 byteList = builder.finish(offset); | 311 byteList = builder.finish(offset); |
| 309 } | 312 } |
| 310 // read and verify | 313 // read and verify |
| 311 BufferPointer root = new BufferPointer.fromBytes(byteList); | 314 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 312 List<TestPointImpl> items = | 315 List<TestPointImpl> items = |
| 313 const ListReader<TestPointImpl>(const TestPointReader()).read(root); | 316 const ListReader<TestPointImpl>(const TestPointReader()).read(buf, 0); |
| 314 expect(items, hasLength(2)); | 317 expect(items, hasLength(2)); |
| 315 expect(items[0].x, 10); | 318 expect(items[0].x, 10); |
| 316 expect(items[0].y, 20); | 319 expect(items[0].y, 20); |
| 317 expect(items[1].x, 100); | 320 expect(items[1].x, 100); |
| 318 expect(items[1].y, 200); | 321 expect(items[1].y, 200); |
| 319 } | 322 } |
| 320 | 323 |
| 321 void test_writeList_ofStrings_asRoot() { | 324 void test_writeList_ofStrings_asRoot() { |
| 322 List<int> byteList; | 325 List<int> byteList; |
| 323 { | 326 { |
| 324 Builder builder = new Builder(initialSize: 0); | 327 Builder builder = new Builder(initialSize: 0); |
| 325 Offset<String> str1 = builder.writeString('12345'); | 328 Offset<String> str1 = builder.writeString('12345'); |
| 326 Offset<String> str2 = builder.writeString('ABC'); | 329 Offset<String> str2 = builder.writeString('ABC'); |
| 327 Offset offset = builder.writeList([str1, str2]); | 330 Offset offset = builder.writeList([str1, str2]); |
| 328 byteList = builder.finish(offset); | 331 byteList = builder.finish(offset); |
| 329 } | 332 } |
| 330 // read and verify | 333 // read and verify |
| 331 BufferPointer root = new BufferPointer.fromBytes(byteList); | 334 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 332 List<String> items = | 335 List<String> items = |
| 333 const ListReader<String>(const StringReader()).read(root); | 336 const ListReader<String>(const StringReader()).read(buf, 0); |
| 334 expect(items, hasLength(2)); | 337 expect(items, hasLength(2)); |
| 335 expect(items, contains('12345')); | 338 expect(items, contains('12345')); |
| 336 expect(items, contains('ABC')); | 339 expect(items, contains('ABC')); |
| 337 } | 340 } |
| 338 | 341 |
| 339 void test_writeList_ofStrings_inObject() { | 342 void test_writeList_ofStrings_inObject() { |
| 340 List<int> byteList; | 343 List<int> byteList; |
| 341 { | 344 { |
| 342 Builder builder = new Builder(initialSize: 0); | 345 Builder builder = new Builder(initialSize: 0); |
| 343 Offset listOffset = builder.writeList( | 346 Offset listOffset = builder.writeList( |
| 344 [builder.writeString('12345'), builder.writeString('ABC')]); | 347 [builder.writeString('12345'), builder.writeString('ABC')]); |
| 345 builder.startTable(); | 348 builder.startTable(); |
| 346 builder.addOffset(0, listOffset); | 349 builder.addOffset(0, listOffset); |
| 347 Offset offset = builder.endTable(); | 350 Offset offset = builder.endTable(); |
| 348 byteList = builder.finish(offset); | 351 byteList = builder.finish(offset); |
| 349 } | 352 } |
| 350 // read and verify | 353 // read and verify |
| 351 BufferPointer root = new BufferPointer.fromBytes(byteList); | 354 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 352 StringListWrapperImpl reader = new StringListWrapperReader().read(root); | 355 StringListWrapperImpl reader = new StringListWrapperReader().read(buf, 0); |
| 353 List<String> items = reader.items; | 356 List<String> items = reader.items; |
| 354 expect(items, hasLength(2)); | 357 expect(items, hasLength(2)); |
| 355 expect(items, contains('12345')); | 358 expect(items, contains('12345')); |
| 356 expect(items, contains('ABC')); | 359 expect(items, contains('ABC')); |
| 357 } | 360 } |
| 358 | 361 |
| 359 void test_writeList_ofUint32() { | 362 void test_writeList_ofUint32() { |
| 360 List<int> byteList; | 363 List<int> byteList; |
| 361 { | 364 { |
| 362 Builder builder = new Builder(initialSize: 0); | 365 Builder builder = new Builder(initialSize: 0); |
| 363 Offset offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]); | 366 Offset offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]); |
| 364 byteList = builder.finish(offset); | 367 byteList = builder.finish(offset); |
| 365 } | 368 } |
| 366 // read and verify | 369 // read and verify |
| 367 BufferPointer root = new BufferPointer.fromBytes(byteList); | 370 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 368 List<int> items = const Uint32ListReader().read(root); | 371 List<int> items = const Uint32ListReader().read(buf, 0); |
| 369 expect(items, hasLength(3)); | 372 expect(items, hasLength(3)); |
| 370 expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0])); | 373 expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0])); |
| 371 } | 374 } |
| 372 | 375 |
| 373 void test_writeList_ofUint8() { | 376 void test_writeList_ofUint8() { |
| 374 List<int> byteList; | 377 List<int> byteList; |
| 375 { | 378 { |
| 376 Builder builder = new Builder(initialSize: 0); | 379 Builder builder = new Builder(initialSize: 0); |
| 377 Offset offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A]); | 380 Offset offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A]); |
| 378 byteList = builder.finish(offset); | 381 byteList = builder.finish(offset); |
| 379 } | 382 } |
| 380 // read and verify | 383 // read and verify |
| 381 BufferPointer root = new BufferPointer.fromBytes(byteList); | 384 BufferContext buf = new BufferContext.fromBytes(byteList); |
| 382 List<int> items = const Uint8ListReader().read(root); | 385 List<int> items = const Uint8ListReader().read(buf, 0); |
| 383 expect(items, hasLength(5)); | 386 expect(items, hasLength(5)); |
| 384 expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A])); | 387 expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A])); |
| 385 } | 388 } |
| 386 } | 389 } |
| 387 | 390 |
| 388 class StringListWrapperImpl { | 391 class StringListWrapperImpl { |
| 389 final BufferPointer bp; | 392 final BufferContext bp; |
| 393 final int offset; |
| 390 | 394 |
| 391 StringListWrapperImpl(this.bp); | 395 StringListWrapperImpl(this.bp, this.offset); |
| 392 | 396 |
| 393 List<String> get items => | 397 List<String> get items => |
| 394 const ListReader<String>(const StringReader()).vTableGet(bp, 0); | 398 const ListReader<String>(const StringReader()).vTableGet(bp, offset, 0); |
| 395 } | 399 } |
| 396 | 400 |
| 397 class StringListWrapperReader extends TableReader<StringListWrapperImpl> { | 401 class StringListWrapperReader extends TableReader<StringListWrapperImpl> { |
| 398 const StringListWrapperReader(); | 402 const StringListWrapperReader(); |
| 399 | 403 |
| 400 @override | 404 @override |
| 401 StringListWrapperImpl createObject(BufferPointer object) { | 405 StringListWrapperImpl createObject(BufferContext object, int offset) { |
| 402 return new StringListWrapperImpl(object); | 406 return new StringListWrapperImpl(object, offset); |
| 403 } | 407 } |
| 404 } | 408 } |
| 405 | 409 |
| 406 class TestPointImpl { | 410 class TestPointImpl { |
| 407 final BufferPointer bp; | 411 final BufferContext bp; |
| 412 final int offset; |
| 408 | 413 |
| 409 TestPointImpl(this.bp); | 414 TestPointImpl(this.bp, this.offset); |
| 410 | 415 |
| 411 int get x => const Int32Reader().vTableGet(bp, 0, 0); | 416 int get x => const Int32Reader().vTableGet(bp, offset, 0, 0); |
| 412 | 417 |
| 413 int get y => const Int32Reader().vTableGet(bp, 1, 0); | 418 int get y => const Int32Reader().vTableGet(bp, offset, 1, 0); |
| 414 } | 419 } |
| 415 | 420 |
| 416 class TestPointReader extends TableReader<TestPointImpl> { | 421 class TestPointReader extends TableReader<TestPointImpl> { |
| 417 const TestPointReader(); | 422 const TestPointReader(); |
| 418 | 423 |
| 419 @override | 424 @override |
| 420 TestPointImpl createObject(BufferPointer object) { | 425 TestPointImpl createObject(BufferContext object, int offset) { |
| 421 return new TestPointImpl(object); | 426 return new TestPointImpl(object, offset); |
| 422 } | 427 } |
| 423 } | 428 } |
| OLD | NEW |