parse static method

ScanResult parse(
  1. String rawData
)

Parses raw text, Secure QR XML, or compressed binary payload from an Aadhaar card.

Implementation

static ScanResult parse(String rawData) {
  if (rawData.contains('<?xml') ||
      rawData.contains('<PrintLetterBarcodeData')) {
    return _parseXmlQr(rawData);
  }

  if (isAadhaarPayload(rawData) && !rawData.contains('<?xml')) {
    final secureResult = _parseSecureQr(rawData);
    if (secureResult != null) return secureResult;
  }

  final uidMatch = _uidRegex.firstMatch(rawData);

  if (uidMatch != null) {
    final rawUid = uidMatch.group(0)!;
    final cleanUid = rawUid.replaceAll(' ', '');
    final isVerhoeffValid = validateAadhaarVerhoeff(cleanUid);

    final Map<String, String> fields = {
      'Card Type': 'Aadhaar Card (India)',
      'Aadhaar Number':
          '${cleanUid.substring(0, 4)} ${cleanUid.substring(4, 8)} ${cleanUid.substring(8, 12)}',
      'Verhoeff Checksum': isVerhoeffValid ? 'Valid ✓' : 'Invalid ✗',
      'Verification Status': isVerhoeffValid
          ? 'UIDAI Verhoeff D10 Validated ✓'
          : 'Checksum Mismatch ✗',
    };

    final lines = rawData
        .split(_lineSplitRegex)
        .map((l) => l.trim())
        .toList();
    for (final line in lines) {
      if (_dobHeaderRegex.hasMatch(line)) {
        final dobMatch = _dobMatchRegex.firstMatch(line);
        if (dobMatch != null) {
          fields['Date of Birth'] = dobMatch.group(0)!;
          final yr = int.tryParse(dobMatch.group(0)!.substring(6));
          if (yr != null) {
            fields['Calculated Age'] = '${DateTime.now().year - yr} years';
          }
        }
      } else if (_yobHeaderRegex.hasMatch(line)) {
        final yobMatch = _yobMatchRegex.firstMatch(line);
        if (yobMatch != null) {
          fields['Year of Birth'] = yobMatch.group(0)!;
          final yr = int.tryParse(yobMatch.group(0)!);
          if (yr != null) {
            fields['Approximate Age'] = '${DateTime.now().year - yr} years';
          }
        }
      } else if (_genderRegex.hasMatch(line)) {
        fields['Gender'] = line;
      }
    }

    final pincodeMatch = _pincodeRegex.firstMatch(rawData);
    if (pincodeMatch != null) {
      fields['Pincode'] = pincodeMatch.group(0)!;
    }

    final verifications = {
      'verhoeffChecksum': isVerhoeffValid,
      'uidSyntaxValid': true,
      'pincodeValid': fields.containsKey('Pincode'),
    };

    return ScanResult(
      mode: ScanMode.aadhaar,
      rawValue: rawData,
      isValid: isVerhoeffValid,
      confidence: isVerhoeffValid ? 0.99 : 0.70,
      fields: fields,
      verifications: verifications,
    );
  }

  return ScanResult(
    mode: ScanMode.aadhaar,
    rawValue: rawData,
    isValid: false,
    confidence: 0.3,
    fields: {'Card Type': 'Aadhaar (Unparsed)', 'Raw Input': rawData},
    verifications: {'verhoeffChecksum': false, 'uidSyntaxValid': false},
  );
}