deserializeMediaMetadata function
Future<MediaMetadata>
deserializeMediaMetadata(
- Uint8List bytes, {
- required CryptoImplementation crypto,
Implementation
Future<MediaMetadata> deserializeMediaMetadata(
Uint8List bytes, {
required CryptoImplementation crypto,
}) async {
final magicByte = bytes[0];
if (magicByte != metadataMagicByte) {
throw 'Invalid metadata: Unsupported magic byte';
}
final typeAndVersion = bytes[1];
final Uint8List bodyBytes;
final provenPubKeys = <Multihash>[];
if (typeAndVersion == metadataTypeProofs) {
final proofSectionLength = decodeEndian(bytes.sublist(2, 4));
bodyBytes = bytes.sublist(4 + proofSectionLength);
if (proofSectionLength > 0) {
final proofUnpacker = Unpacker(bytes.sublist(4, proofSectionLength + 4));
final b3hash = Uint8List.fromList(
[mhashBlake3Default] + await crypto.hashBlake3(bodyBytes),
);
final proofCount = proofUnpacker.unpackListLength();
for (int i = 0; i < proofCount; i++) {
final List<dynamic> parts = proofUnpacker.unpackList();
final proofType = parts[0] as int;
if (proofType == metadataProofTypeSignature) {
final mhashType = parts[1] as int;
final pubkey = parts[2] as Uint8List;
final signature = parts[3] as Uint8List;
if (mhashType != mhashBlake3Default) {
throw 'Hash type $mhashType not supported';
}
if (pubkey[0] != mkeyEd25519) {
throw 'Only ed25519 keys are supported';
}
if (pubkey.length != 33) {
throw 'Invalid userId';
}
final isValid = await crypto.verifyEd25519(
message: b3hash,
signature: signature,
pk: pubkey.sublist(1),
);
if (!isValid) {
throw 'Invalid signature found';
}
provenPubKeys.add(Multihash(pubkey));
} else {
// ! Unsupported proof type
}
}
}
} else if (typeAndVersion == metadataTypeMedia) {
bodyBytes = bytes.sublist(1);
} else {
throw 'Invalid metadata: Unsupported type $typeAndVersion';
}
// Start of body section
final u = Unpacker(bodyBytes);
final type = u.unpackInt();
if (type != metadataTypeMedia) {
throw 'Invalid metadata: Unsupported type $type';
}
u.unpackListLength();
final name = u.unpackString();
final details = MediaMetadataDetails(u.unpackMap().cast<int, dynamic>());
final parents = <MetadataParentLink>[];
final userCount = u.unpackListLength();
for (int i = 0; i < userCount; i++) {
final m = u.unpackMap();
final cid = CID.fromBytes(m[1] as Uint8List);
parents.add(MetadataParentLink(
cid: cid,
role: m[2] as String?,
type: (m[0] ?? parentLinkTypeUserIdentity) as int,
signed: provenPubKeys.contains(cid.hash),
));
}
final mediaTypesMap = u.unpackMap().cast<String, dynamic>();
final mediaTypes = <String, List<MediaFormat>>{};
for (final m in mediaTypesMap.entries) {
final type = m.key;
mediaTypes[type] = [];
for (final e in m.value) {
mediaTypes[type]!.add(MediaFormat.decode(e.cast<int, dynamic>()));
}
}
final links = u.unpackMap().cast<int, dynamic>();
final extraMetadata = u.unpackMap().cast<int, dynamic>();
return MediaMetadata(
name: name ?? '',
details: details,
parents: parents,
mediaTypes: mediaTypes,
links: links.isEmpty ? null : MediaMetadataLinks.decode(links),
extraMetadata: ExtraMetadata(extraMetadata),
);
}