// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Autogenerated from Pigeon (v1.0.16), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import
// @dart = 2.12
import 'dart:async';
import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List;
import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer;
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:shared_preferences_ios/messages.g.dart';

class _TestUserDefaultsApiCodec extends StandardMessageCodec {
  const _TestUserDefaultsApiCodec();
}

abstract class TestUserDefaultsApi {
  static const MessageCodec<Object?> codec = _TestUserDefaultsApiCodec();

  void remove(String key);
  void setBool(String key, bool value);
  void setDouble(String key, double value);
  void setValue(String key, Object value);
  Map<String?, Object?> getAll();
  void clear();
  static void setup(TestUserDefaultsApi? api,
      {BinaryMessenger? binaryMessenger}) {
    {
      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
          'dev.flutter.pigeon.UserDefaultsApi.remove', codec,
          binaryMessenger: binaryMessenger);
      if (api == null) {
        channel.setMockMessageHandler(null);
      } else {
        channel.setMockMessageHandler((Object? message) async {
          assert(message != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.remove was null.');
          final List<Object?> args = (message as List<Object?>?)!;
          final String? arg_key = (args[0] as String?);
          assert(arg_key != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.remove was null, expected non-null String.');
          api.remove(arg_key!);
          return <Object?, Object?>{};
        });
      }
    }
    {
      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
          'dev.flutter.pigeon.UserDefaultsApi.setBool', codec,
          binaryMessenger: binaryMessenger);
      if (api == null) {
        channel.setMockMessageHandler(null);
      } else {
        channel.setMockMessageHandler((Object? message) async {
          assert(message != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.setBool was null.');
          final List<Object?> args = (message as List<Object?>?)!;
          final String? arg_key = (args[0] as String?);
          assert(arg_key != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.setBool was null, expected non-null String.');
          final bool? arg_value = (args[1] as bool?);
          assert(arg_value != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.setBool was null, expected non-null bool.');
          api.setBool(arg_key!, arg_value!);
          return <Object?, Object?>{};
        });
      }
    }
    {
      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
          'dev.flutter.pigeon.UserDefaultsApi.setDouble', codec,
          binaryMessenger: binaryMessenger);
      if (api == null) {
        channel.setMockMessageHandler(null);
      } else {
        channel.setMockMessageHandler((Object? message) async {
          assert(message != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.setDouble was null.');
          final List<Object?> args = (message as List<Object?>?)!;
          final String? arg_key = (args[0] as String?);
          assert(arg_key != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.setDouble was null, expected non-null String.');
          final double? arg_value = (args[1] as double?);
          assert(arg_value != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.setDouble was null, expected non-null double.');
          api.setDouble(arg_key!, arg_value!);
          return <Object?, Object?>{};
        });
      }
    }
    {
      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
          'dev.flutter.pigeon.UserDefaultsApi.setValue', codec,
          binaryMessenger: binaryMessenger);
      if (api == null) {
        channel.setMockMessageHandler(null);
      } else {
        channel.setMockMessageHandler((Object? message) async {
          assert(message != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.setValue was null.');
          final List<Object?> args = (message as List<Object?>?)!;
          final String? arg_key = (args[0] as String?);
          assert(arg_key != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.setValue was null, expected non-null String.');
          final Object? arg_value = (args[1] as Object?);
          assert(arg_value != null,
              'Argument for dev.flutter.pigeon.UserDefaultsApi.setValue was null, expected non-null Object.');
          api.setValue(arg_key!, arg_value!);
          return <Object?, Object?>{};
        });
      }
    }
    {
      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
          'dev.flutter.pigeon.UserDefaultsApi.getAll', codec,
          binaryMessenger: binaryMessenger);
      if (api == null) {
        channel.setMockMessageHandler(null);
      } else {
        channel.setMockMessageHandler((Object? message) async {
          // ignore message
          final Map<String?, Object?> output = api.getAll();
          return <Object?, Object?>{'result': output};
        });
      }
    }
    {
      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
          'dev.flutter.pigeon.UserDefaultsApi.clear', codec,
          binaryMessenger: binaryMessenger);
      if (api == null) {
        channel.setMockMessageHandler(null);
      } else {
        channel.setMockMessageHandler((Object? message) async {
          // ignore message
          api.clear();
          return <Object?, Object?>{};
        });
      }
    }
  }
}
