Location.fromBytes constructor
Deserialize Location from bytes
Implementation
factory Location.fromBytes(String name, List<int> rawData) {
final data = rawData is Uint8List ? rawData : Uint8List.fromList(rawData);
final bdata =
data.buffer.asByteData(data.offsetInBytes, data.lengthInBytes);
final magic1 = bdata.getUint32(0);
if (magic1 != _ziMagic) {
throw InvalidZoneInfoDataException('Invalid magic header "$magic1"');
}
final version1 = bdata.getUint8(4);
var offset = 20;
switch (version1) {
case 0:
final header = _Header.fromBytes(
Uint8List.view(bdata.buffer, offset, _Header.size));
// calculating data offsets
final dataOffset = offset + _Header.size;
final transitionAtOffset = dataOffset;
final transitionZoneOffset =
transitionAtOffset + header.tzh_timecnt * 5;
final abbreviationsOffset =
transitionZoneOffset + header.tzh_typecnt * 6;
final leapOffset = abbreviationsOffset + header.tzh_charcnt;
final stdOrWctOffset = leapOffset + header.tzh_leapcnt * 8;
final utcOrGmtOffset = stdOrWctOffset + header.tzh_ttisstdcnt;
// read transitions
final transitionAt = <int>[];
final transitionZone = <int>[];
offset = transitionAtOffset;
for (var i = 0; i < header.tzh_timecnt; i++) {
transitionAt.add(bdata.getInt32(offset));
offset += 4;
}
for (var i = 0; i < header.tzh_timecnt; i++) {
transitionZone.add(bdata.getUint8(offset));
offset += 1;
}
// function to read from abbreviation buffer
final abbreviationsData = data.buffer.asUint8List(
data.offsetInBytes + abbreviationsOffset, header.tzh_charcnt);
final abbreviations = <String>[];
final abbreviationsCache = HashMap<int, int>();
int readAbbreviation(int offset) {
var result = abbreviationsCache[offset];
if (result == null) {
result = abbreviations.length;
abbreviationsCache[offset] = result;
abbreviations.add(_readByteString(abbreviationsData, offset));
}
return result;
}
// read zones
final zones = <TimeZone>[];
offset = transitionZoneOffset;
for (var i = 0; i < header.tzh_typecnt; i++) {
final tt_gmtoff = bdata.getInt32(offset);
final tt_isdst = bdata.getInt8(offset + 4);
final tt_abbrind = bdata.getUint8(offset + 5);
offset += 6;
zones.add(TimeZone(tt_gmtoff,
isDst: tt_isdst == 1,
abbreviationIndex: readAbbreviation(tt_abbrind)));
}
// read leap seconds
final leapAt = <int>[];
final leapDiff = <int>[];
offset = leapOffset;
for (var i = 0; i < header.tzh_leapcnt; i++) {
leapAt.add(bdata.getInt32(offset));
leapDiff.add(bdata.getInt32(offset + 4));
offset += 5;
}
// read std flags
final isStd = <int>[];
offset = stdOrWctOffset;
for (var i = 0; i < header.tzh_ttisstdcnt; i++) {
isStd.add(bdata.getUint8(offset));
offset += 1;
}
// read utc flags
final isUtc = <int>[];
offset = utcOrGmtOffset;
for (var i = 0; i < header.tzh_ttisgmtcnt; i++) {
isUtc.add(bdata.getUint8(offset));
offset += 1;
}
return Location(name, transitionAt, transitionZone, abbreviations,
zones, leapAt, leapDiff, isStd, isUtc);
case 50:
case 51:
// skip old version header/data
final header1 = _Header.fromBytes(
Uint8List.view(bdata.buffer, offset, _Header.size));
offset += _Header.size + header1.dataLength(4);
final magic2 = bdata.getUint32(offset);
if (magic2 != _ziMagic) {
throw InvalidZoneInfoDataException(
'Invalid second magic header "$magic2"');
}
final version2 = bdata.getUint8(offset + 4);
if (version2 != version1) {
throw InvalidZoneInfoDataException(
'Second version "$version2" doesn\'t match first version '
'"$version1"');
}
offset += 20;
final header2 = _Header.fromBytes(
Uint8List.view(bdata.buffer, offset, _Header.size));
// calculating data offsets
final dataOffset = offset + _Header.size;
final transitionAtOffset = dataOffset;
final transitionZoneOffset =
transitionAtOffset + header2.tzh_timecnt * 9;
final abbreviationsOffset =
transitionZoneOffset + header2.tzh_typecnt * 6;
final leapOffset = abbreviationsOffset + header2.tzh_charcnt;
final stdOrWctOffset = leapOffset + header2.tzh_leapcnt * 12;
final utcOrGmtOffset = stdOrWctOffset + header2.tzh_ttisstdcnt;
// read transitions
final transitionAt = <int>[];
final transitionZone = <int>[];
offset = transitionAtOffset;
for (var i = 0; i < header2.tzh_timecnt; i++) {
transitionAt.add(bdata.getInt64(offset));
offset += 8;
}
for (var i = 0; i < header2.tzh_timecnt; i++) {
transitionZone.add(bdata.getUint8(offset));
offset += 1;
}
// function to read from abbreviation buffer
final abbreviationsData = data.buffer.asUint8List(
data.offsetInBytes + abbreviationsOffset, header2.tzh_charcnt);
final abbreviations = <String>[];
final abbreviationsCache = HashMap<int, int>();
int readAbbreviation(int offset) {
var result = abbreviationsCache[offset];
if (result == null) {
result = abbreviations.length;
abbreviationsCache[offset] = result;
abbreviations.add(_readByteString(abbreviationsData, offset));
}
return result;
}
// read transition info
final zones = <TimeZone>[];
offset = transitionZoneOffset;
for (var i = 0; i < header2.tzh_typecnt; i++) {
final tt_gmtoff = bdata.getInt32(offset);
final tt_isdst = bdata.getInt8(offset + 4);
final tt_abbrind = bdata.getUint8(offset + 5);
offset += 6;
zones.add(TimeZone(tt_gmtoff,
isDst: tt_isdst == 1,
abbreviationIndex: readAbbreviation(tt_abbrind)));
}
// read leap seconds
final leapAt = <int>[];
final leapDiff = <int>[];
offset = leapOffset;
for (var i = 0; i < header2.tzh_leapcnt; i++) {
leapAt.add(bdata.getInt64(offset));
leapDiff.add(bdata.getInt32(offset + 8));
offset += 9;
}
// read std flags
final isStd = <int>[];
offset = stdOrWctOffset;
for (var i = 0; i < header2.tzh_ttisstdcnt; i++) {
isStd.add(bdata.getUint8(offset));
offset += 1;
}
// read utc flags
final isUtc = <int>[];
offset = utcOrGmtOffset;
for (var i = 0; i < header2.tzh_ttisgmtcnt; i++) {
isUtc.add(bdata.getUint8(offset));
offset += 1;
}
return Location(name, transitionAt, transitionZone, abbreviations,
zones, leapAt, leapDiff, isStd, isUtc);
default:
throw InvalidZoneInfoDataException('Unknown version: $version1');
}
}