Skip to content

Commit

Permalink
updated to null-safety
Browse files Browse the repository at this point in the history
  • Loading branch information
mars3142 committed Jul 1, 2021
1 parent 7593094 commit 5512621
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 77 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
steps:
- uses: actions/checkout@v2

- uses: axel-op/dart-package-analyzer/with-full-sdk@stable
- uses: axel-op/dart-package-analyzer@v3
id: analysis # set an id for the current step
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.2.0

- package is now null-safety

## 0.1.2+2

- remove dart:io - more web compatibility
Expand Down
1 change: 1 addition & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ include: package:effective_dart/analysis_options.yaml
linter:
rules:
lines_longer_than_80_chars: false
avoid_equals_and_hash_code_on_mutable_classes: false

analyzer:
exclude:
Expand Down
68 changes: 38 additions & 30 deletions example/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import 'dart:io';

import 'package:freewig/freewig.dart';

Future<Cartridge> parseFile(File file) async {
Future<Cartridge?> parseFile(File file) async {
final bytes = await file.readAsBytes();
final completer = Completer<Cartridge>();
await Future<Cartridge>(() => parseData(bytes))
await Future<Cartridge?>(() => parseData(bytes))
.then(completer.complete)
.catchError(completer.completeError);
return completer.future;
Expand All @@ -16,34 +16,42 @@ void main(List<String> arguments) async {
var file = File(arguments[0]); // path/incl/cartridge.gwc
var cartridge = await parseFile(file);

var export = Directory('export');
var exists = await export.exists();
if (exists) {
await export.delete(recursive: true);
}
await export.create(recursive: true);
if (cartridge != null) {
var export = Directory('export');
var exists = await export.exists();
if (exists) {
await export.delete(recursive: true);
}
await export.create(recursive: true);

var contents = '';
contents += 'Cartridge-Id: ${cartridge.cartridgeGuid}\n';
contents += 'Name: ${cartridge.cartridgeName}\n';
contents += 'Description: ${cartridge.cartridgeDesc}\n';
contents += 'StartLocation: ${cartridge.startLocationDesc}\n';
contents += 'Latitude: ${cartridge.latLng.latitude}\n';
contents += 'Longitude: ${cartridge.latLng.longitude}\n';
contents += 'Player: ${cartridge.playerName}\n';
contents += 'Author: ${cartridge.author}\n';
contents += 'Type: ${cartridge.typeOfCartridge}\n';
contents += 'Device: ${cartridge.recommendDevice}\n';
contents += 'Version: ${cartridge.version}\n';
contents += '\n';
contents += 'Completion-Code: ${cartridge.completionCode}\n';
contents += '\n';
contents += 'ItemCount: ${cartridge.mediaObjects.length}\n';
var infoFile = File('${export.path}/cartridge_info.txt');
await infoFile.writeAsString(contents);
var contents = '';
contents += 'Cartridge-Id: ${cartridge.cartridgeGuid}\n';
contents += 'Name: ${cartridge.cartridgeName}\n';
contents += 'Description: ${cartridge.cartridgeDesc}\n';
contents += 'StartLocation: ${cartridge.startLocationDesc}\n';
contents += 'Latitude: ${cartridge.latLng.latitude}\n';
contents += 'Longitude: ${cartridge.latLng.longitude}\n';
contents += 'Player: ${cartridge.playerName}\n';
contents += 'Author: ${cartridge.author}\n';
contents += 'Type: ${cartridge.typeOfCartridge}\n';
contents += 'Device: ${cartridge.recommendDevice}\n';
contents += 'Version: ${cartridge.version}\n';
contents += '\n';
contents += 'Completion-Code: ${cartridge.completionCode}\n';
contents += '\n';
contents += 'ItemCount: ${cartridge.mediaCount}\n';
var infoFile = File('${export.path}/cartridge_info.txt');
await infoFile.writeAsString(contents);

cartridge.mediaObjects.forEach((index, data) async {
var objectFile = File('${export.path}/object_$index.${data.objectType}');
await objectFile.writeAsBytes(data.data);
});
for (var index = 0; index < cartridge.mediaCount; index++) {
final data = cartridge.getMedia(index);
if (data != null) {
var objectFile =
File('${export.path}/object_$index.${data.objectType}');
await objectFile.writeAsBytes(data.data);
}
}
} else {
print("The cartridge is invalid");
}
}
2 changes: 1 addition & 1 deletion lib/src/binary_reader.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class BinaryReader {

/// Initialise the [BinaryReader] with data and endian, so the reader knows how to
/// interpret the bytes.
BinaryReader({ByteData byteData, Endian endian})
BinaryReader({required ByteData byteData, Endian endian = Endian.little})
: _byteData = byteData,
_endian = endian,
_index = 0;
Expand Down
9 changes: 9 additions & 0 deletions lib/src/latlng.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,20 @@ class LatLng {
return _format(_longitude, 'EW');
}

@override
String toString() {
return "$latitude $longitude".trim();
}

String _format(double value, String suffix) {
final isNegative = value < 0;
value = value.abs();

final degrees = value.floor();
if (degrees == 360) {
return "";
}

final minutes = (value - degrees) * 60.0;

var result = '';
Expand Down
67 changes: 43 additions & 24 deletions lib/src/models/cartridge.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@
* all copies or substantial portions of the Software.
*/

import 'package:meta/meta.dart';

import '../../freewig.dart';
import '../binary_reader.dart';
import 'media.dart';

/// A [Cartridge] represents the GWC file
@immutable
class Cartridge {
/// The altitude of the start coordinate
final double altitude;
Expand Down Expand Up @@ -60,16 +57,20 @@ class Cartridge {
/// Completion code (can be encrypted with lua)
final String completionCode;

/// Map of all [Media] objects
final Map<int, Media> mediaObjects;

final int _splashScreenId;

final int _smallIconId;

final BinaryReader _source;

final Map<int, int> _references;

var _lastObject = -1;

Media? _lastMedia;

Cartridge._(
this.cartridgeGuid,
this.mediaObjects,
this.altitude,
this.author,
this.cartridgeDesc,
Expand All @@ -84,11 +85,13 @@ class Cartridge {
this.startLocationDesc,
this.typeOfCartridge,
this.version,
this._references,
this._source,
);

/// Reading the GWC file and create a [Cartridge] or null in case of any
/// parsing error.
factory Cartridge(BinaryReader reader) {
static Cartridge? create(BinaryReader reader) {
try {
final count = reader.getUShort();
final references = <int, int>{};
Expand Down Expand Up @@ -129,14 +132,8 @@ class Cartridge {

final completionCode = reader.getASCIIZ();

// initialise objects after cartridge data is loaded
final objects = <int, Media>{};
references.forEach((index, address) =>
{objects.putIfAbsent(index, () => Media(reader, index, address))});

return Cartridge._(
cartridgeGuid,
objects,
altitude,
author,
cartridgeDesc,
Expand All @@ -154,6 +151,8 @@ class Cartridge {
startLocationDesc,
typeOfCartridge,
version,
references,
reader,
);
} on Exception catch (ex) {
print('Exception: $ex');
Expand All @@ -166,22 +165,42 @@ class Cartridge {
identical(this, other) ||
other is Cartridge &&
runtimeType == other.runtimeType &&
cartridgeGuid == other.cartridgeGuid &&
mediaObjects == other.mediaObjects;
cartridgeGuid == other.cartridgeGuid;

@override
int get hashCode => cartridgeGuid.hashCode ^ mediaObjects.hashCode;
int get hashCode => cartridgeGuid.hashCode;

/// get Media with objectId or null, if not available
Media? getMedia(int objectId) {
if (_lastObject == objectId && _lastMedia != null) {
return _lastMedia!;
}

if (_references.containsKey(objectId)) {
final address = _references[objectId];
final media = Media.create(_source, objectId, address!);

if (media != null) {
if (media.data.length < 128000) {
_lastObject = objectId;
_lastMedia = media;
}

return media;
}
}
return null;
}

/// get the count of attached media
int get mediaCount => _references.length;

/// get splash screen media or null if not available
Media get splashScreen => mediaObjects.containsKey(_splashScreenId)
? mediaObjects[_splashScreenId]
: null;
Media? get splashScreen => getMedia(_splashScreenId);

/// get small icon media or null if not available
Media get smallIcon => mediaObjects.containsKey(_smallIconId)
? mediaObjects[_smallIconId]
: null;
Media? get smallIcon => getMedia(_smallIconId);

/// get luac media or null if not available
Media get luac => mediaObjects.containsKey(0) ? mediaObjects[0] : null;
Media? get luac => getMedia(0);
}
13 changes: 8 additions & 5 deletions lib/src/models/media.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ class Media {
///
/// It starts at address (from [SeekOrigin.begin]) and uses the data for
/// interpret the data as media. If it can be read, the return will be a
/// [Media] object. In case of an exception the result will be null.
factory Media(BinaryReader reader, int objectId, int address) {
/// [Media] object. In case of an exception or empty data the result will be null.
static Media? create(BinaryReader reader, int objectId, int address) {
try {
Uint8List data;
Uint8List? data;
var objectType = 0;
reader.seek(address, SeekOrigin.begin);
if (objectId == 0) {
Expand All @@ -48,8 +48,11 @@ class Media {
data = _readMediaData(reader);
}
}
final object = Media._(_getObjectType(objectType), data);
return object;
if (data != null) {
final object = Media._(_getObjectType(objectType), data);
return object;
}
return null;
} on Exception catch (ex) {
print('Exception: $ex');
return null;
Expand Down
4 changes: 2 additions & 2 deletions lib/src/parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import 'models/cartridge.dart';
/// Parses a byte list and create a [Cartridge]
///
/// If the byte list is a valid GWC file, the result will be [Cartridge] or null, if the parser failed.
Cartridge parseData(Uint8List bytes) {
Cartridge? parseData(Uint8List bytes) {
try {
const header = {0x02, 0x0a, 0x43, 0x41, 0x52, 0x54, 0x00}; // magic header
final reader = BinaryReader(
Expand All @@ -34,7 +34,7 @@ Cartridge parseData(Uint8List bytes) {
}
}

return Cartridge(reader);
return Cartridge.create(reader);
} on Exception catch (_) {
return null;
}
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: freewig
version: 0.1.2+2
version: 0.2.0
description: >
Freewig can be used to extract the meta data and media files from Wherigo Cartridges
homepage: https://github.com/mars3142/freewig

environment:
sdk: '>=2.7.0 <3.0.0'
sdk: '>=2.12.0 <3.0.0'

dependencies:
meta: ^1.1.8
Expand Down
21 changes: 10 additions & 11 deletions test/gwc_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,40 @@
import 'dart:async';
import 'dart:io';

import 'package:test/test.dart';
import 'package:freewig/freewig.dart';
import 'package:test/test.dart';

Future<Cartridge> parseFile(File file) async {
Future<Cartridge?> parseFile(File file) async {
final bytes = await file.readAsBytes();
final completer = Completer<Cartridge>();
await Future<Cartridge>(() => parseData(bytes))
await Future<Cartridge?>(() => parseData(bytes))
.then(completer.complete)
.catchError(completer.completeError);
return completer.future;
}

void main() {
group('Cartridge TESTING.GWC', () {
Cartridge cartridgeData;
Cartridge? cartridgeData;

setUp(() async {
var file = File("testing.gwc");
cartridgeData = await parseFile(file);
});

test('Cartridge not empty', () {
expect(cartridgeData != null, isTrue);
});

test('Cartridge name is "TESTING"', () {
expect(cartridgeData.cartridgeName, "TESTING");
expect(cartridgeData != null, isTrue);
expect(cartridgeData!.cartridgeName, "TESTING");
});

test('Completion Code is "ABCDEFGHIJKLMNOP"', () {
expect(cartridgeData.completionCode, "ABCDEFGHIJKLMNOP");
expect(cartridgeData != null, isTrue);
expect(cartridgeData!.completionCode, "ABCDEFGHIJKLMNOP");
});

test('Cartridge has 2 objects', () {
expect(cartridgeData.mediaObjects.length, 2);
expect(cartridgeData != null, isTrue);
expect(cartridgeData?.mediaCount, 2);
});
});
}
2 changes: 1 addition & 1 deletion test/latlng_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
* all copies or substantial portions of the Software.
*/

import 'package:test/test.dart';
import 'package:freewig/freewig.dart';
import 'package:test/test.dart';

void main() {
group('LatLng testing', () {
Expand Down

0 comments on commit 5512621

Please sign in to comment.