decode function Null safety

dynamic decode(
  1. Map<String, Object> typeTable,
  2. String path,
  3. Object type,
  4. Object? value
)

Implementation

dynamic decode(
    Map<String, Object> typeTable, String path, Object type, Object? value) {
  if (type is EnumTypeDescription) {
    if (value is! String || !type.stringValues.contains(value)) {
      throw SdkgenTypeException(
          'Invalid Type at \'$path\', expected ${type.type}, got ${jsonEncode(value)}');
    }
    return type.enumValues[type.stringValues.indexOf(value)];
  } else if (type is StructTypeDescription) {
    if (value is! Map) {
      throw SdkgenTypeException(
          'Invalid Type at \'$path\', expected ${type.type}, got ${jsonEncode(value)}');
    }
    var resultMap = {};
    for (var fieldName in type.fields.keys) {
      resultMap[fieldName] = decode(typeTable, '$path.$fieldName',
          type.fields[fieldName]!, value[fieldName]);
    }
    return Function.apply(type.createFromFields, [resultMap]);
  } else if (type is String) {
    if (type.endsWith('?')) {
      if (value == null) {
        return null;
      } else {
        return decode(
            typeTable, path, type.substring(0, type.length - 1), value);
      }
    } else if (type.endsWith('[]')) {
      if (value is! List) {
        throw SdkgenTypeException(
            'Invalid Type at \'$path\', expected ${jsonEncode(type)}, got ${jsonEncode(value)}');
      }
      return value
          .asMap()
          .entries
          .map((entry) => decode(typeTable, '$path[${entry.key}]',
              type.substring(0, type.length - 2), entry.value))
          .toList();
    } else {
      switch (type) {
        case 'bytes':
          if (value is! String) {
            throw SdkgenTypeException(
                'Invalid Type at \'$path\', expected ${jsonEncode(type)}, got ${jsonEncode(value)}');
          }
          return Base64Decoder().convert(value);
        case 'bigint':
          if (value is num) {
            return BigInt.from(value);
          } else {
            if ((value is! String || !RegExp(r'^-?[0-9]+$').hasMatch(value))) {
              throw SdkgenTypeException(
                  'Invalid Type at \'$path\', expected ${jsonEncode(type)}, got ${jsonEncode(value)}');
            }
            return BigInt.parse(value);
          }
        case 'date':
          if (value is! String ||
              !RegExp(r'^[0-9]{4}-[01][0-9]-[0123][0-9]$').hasMatch(value)) {
            throw SdkgenTypeException(
                'Invalid Type at \'$path\', expected ${jsonEncode(type)}, got ${jsonEncode(value)}');
          }
          return DateTime.parse('${value}T00:00:00Z');
        case 'datetime':
          if (value is! String ||
              !RegExp(r'^[0-9]{4}-[01][0-9]-[0123][0-9]T[012][0-9]:[0123456][0-9]:[0123456][0-9](\.[0-9]{1,6})?Z?$')
                  .hasMatch(value)) {
            throw SdkgenTypeException(
                'Invalid Type at \'$path\', expected ${jsonEncode(type)}, got ${jsonEncode(value)}');
          }
          return DateTime.parse('${value}Z').toLocal();
        default:
          if (simpleTypes.contains(type)) {
            return simpleEncodeDecode(typeTable, path, type, value);
          } else if (typeTable.containsKey(type)) {
            return decode(typeTable, path, typeTable[type]!, value);
          } else {
            throw SdkgenTypeException(
                'Unknown type \'${jsonEncode(type)}\' at \'$path\'');
          }
      }
    }
  } else {
    throw SdkgenTypeException(
        'Unknown type \'${jsonEncode(type)}\' at \'$path\'');
  }
}