CID.fromBytes constructor

CID.fromBytes(
  1. Uint8List bytes
)

Decodes a CID from its binary representation (Uint8List).

This factory constructor attempts to parse the input bytes as either a CIDv0 (which is a 34-byte SHA2-256 multihash) or a CIDv1 (which starts with varint-encoded version and codec).

Throws FormatException if the bytes are empty, malformed, or represent an unsupported CID structure.

  • bytes: The Uint8List containing the binary CID data.

Example:

// (Assuming 'cidBytes' is a Uint8List obtained from somewhere)
// final cid = CID.fromBytes(cidBytes);
// print(cid.toString());

Implementation

factory CID.fromBytes(Uint8List bytes) {
  if (bytes.isEmpty) {
    throw FormatException('Cannot parse CID from empty bytes');
  }

  // Try to parse as CIDv1 first by looking for varint prefix.
  // CIDv0 starts with 0x12 (sha2-256 multihash code) and is 34 bytes long.
  // (0x12 = sha2-256, 0x20 = 32 bytes length)
  if (bytes.length == 34 && bytes[0] == codecNameToCode['sha2-256'] && bytes[1] == 0x20) {
    // Potentially a CIDv0.
    // A full CIDv0 is just a multihash.
    // The codec for CIDv0 is implicitly dag-pb.
    try {
      // Validate it's a valid multihash
      mh.Multihash.decode(bytes);
      return CID(V0, codecNameToCode['dag-pb']!, bytes);
    } catch (e) {
      // Not a valid multihash, fall through to CIDv1 parsing or throw.
      // Or it could be a CIDv1 that coincidentally matches the length and prefix.
    }
  }

  // Try to parse as CIDv1
  try {
    int offset = 0;

    final versionEntry = decodeVarint(bytes, offset);
    final cidVersion = versionEntry.key;
    offset += versionEntry.value;

    if (cidVersion != V1) {
      // If we thought it was V0 above but failed multihash validation,
      // and it's not V1 here, then it's an error.
      // Or if it didn't look like V0 and is not V1.
      throw FormatException('Invalid CID version from bytes: $cidVersion. Expected $V1 (or a valid V0 structure).');
    }

    final codecEntry = decodeVarint(bytes, offset);
    final cidCodec = codecEntry.key;
    offset += codecEntry.value;

    final multihashBytes = bytes.sublist(offset);
    if (multihashBytes.isEmpty) {
      throw FormatException('CIDv1 multihash is empty');
    }
    // Validate the extracted multihash
    mh.Multihash.decode(multihashBytes);

    return CID(cidVersion, cidCodec, multihashBytes);
  } catch (e) {
    // If CIDv1 parsing failed, and it wasn't a valid CIDv0 either.
    if (bytes.length == 34 && bytes[0] == codecNameToCode['sha2-256']! && bytes[1] == 0x20) {
       throw FormatException('Bytes resemble CIDv0 but multihash is invalid, and not a valid CIDv1: $e');
    }
    throw FormatException('Failed to parse CID from bytes: $e');
  }
}