content: /*
   * Decompiled with CFR 0.153-SNAPSHOT (d6f6758-dirty).
   */
  package com.google.gson;
  
  import com.google.gson.FieldNamingPolicy;
  import com.google.gson.FieldNamingStrategy;
  import com.google.gson.GsonBuilder;
  import com.google.gson.InstanceCreator;
  import com.google.gson.JsonElement;
  import com.google.gson.JsonIOException;
  import com.google.gson.JsonNull;
  import com.google.gson.JsonSyntaxException;
  import com.google.gson.LongSerializationPolicy;
  import com.google.gson.TypeAdapter;
  import com.google.gson.TypeAdapterFactory;
  import com.google.gson.internal.ConstructorConstructor;
  import com.google.gson.internal.Excluder;
  import com.google.gson.internal.Primitives;
  import com.google.gson.internal.Streams;
  import com.google.gson.internal.bind.ArrayTypeAdapter;
  import com.google.gson.internal.bind.CollectionTypeAdapterFactory;
  import com.google.gson.internal.bind.DateTypeAdapter;
  import com.google.gson.internal.bind.JsonAdapterAnnotationTypeAdapterFactory;
  import com.google.gson.internal.bind.JsonTreeReader;
  import com.google.gson.internal.bind.JsonTreeWriter;
  import com.google.gson.internal.bind.MapTypeAdapterFactory;
  import com.google.gson.internal.bind.ObjectTypeAdapter;
  import com.google.gson.internal.bind.ReflectiveTypeAdapterFactory;
  import com.google.gson.internal.bind.SqlDateTypeAdapter;
  import com.google.gson.internal.bind.TimeTypeAdapter;
  import com.google.gson.internal.bind.TypeAdapters;
  import com.google.gson.reflect.TypeToken;
  import com.google.gson.stream.JsonReader;
  import com.google.gson.stream.JsonToken;
  import com.google.gson.stream.JsonWriter;
  import com.google.gson.stream.MalformedJsonException;
  import java.io.EOFException;
  import java.io.IOException;
  import java.io.Reader;
  import java.io.StringReader;
  import java.io.StringWriter;
  import java.io.Writer;
  import java.lang.reflect.Type;
  import java.math.BigDecimal;
  import java.math.BigInteger;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.concurrent.atomic.AtomicLong;
  import java.util.concurrent.atomic.AtomicLongArray;
  
  public final class Gson {
      static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
      static final boolean DEFAULT_LENIENT = false;
      static final boolean DEFAULT_PRETTY_PRINT = false;
      static final boolean DEFAULT_ESCAPE_HTML = true;
      static final boolean DEFAULT_SERIALIZE_NULLS = false;
      static final boolean DEFAULT_COMPLEX_MAP_KEYS = false;
      static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false;
      private static final TypeToken<?> NULL_KEY_SURROGATE = TypeToken.get(Object.class);
      private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
      private final ThreadLocal<Map<TypeToken<?>, FutureTypeAdapter<?>>> calls = new ThreadLocal();
      private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache = new ConcurrentHashMap();
      private final ConstructorConstructor constructorConstructor;
      private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory;
      final List<TypeAdapterFactory> factories;
      final Excluder excluder;
      final FieldNamingStrategy fieldNamingStrategy;
      final Map<Type, InstanceCreator<?>> instanceCreators;
      final boolean serializeNulls;
      final boolean complexMapKeySerialization;
      final boolean generateNonExecutableJson;
      final boolean htmlSafe;
      final boolean prettyPrinting;
      final boolean lenient;
      final boolean serializeSpecialFloatingPointValues;
      final String datePattern;
      final int dateStyle;
      final int timeStyle;
      final LongSerializationPolicy longSerializationPolicy;
      final List<TypeAdapterFactory> builderFactories;
      final List<TypeAdapterFactory> builderHierarchyFactories;
  
      public Gson() {
          this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY, Collections.emptyMap(), false, false, false, true, false, false, false, LongSerializationPolicy.DEFAULT, null, 2, 2, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
      }
  
      Gson(Excluder excluder, FieldNamingStrategy fieldNamingStrategy, Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls, boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle, int timeStyle, List<TypeAdapterFactory> builderFactories, List<TypeAdapterFactory> builderHierarchyFactories, List<TypeAdapterFactory> factoriesToBeAdded) {
          this.excluder = excluder;
          this.fieldNamingStrategy = fieldNamingStrategy;
          this.instanceCreators = instanceCreators;
          this.constructorConstructor = new ConstructorConstructor(instanceCreators);
          this.serializeNulls = serializeNulls;
          this.complexMapKeySerialization = complexMapKeySerialization;
          this.generateNonExecutableJson = generateNonExecutableGson;
          this.htmlSafe = htmlSafe;
          this.prettyPrinting = prettyPrinting;
          this.lenient = lenient;
          this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
          this.longSerializationPolicy = longSerializationPolicy;
          this.datePattern = datePattern;
          this.dateStyle = dateStyle;
          this.timeStyle = timeStyle;
          this.builderFactories = builderFactories;
          this.builderHierarchyFactories = builderHierarchyFactories;
          ArrayList<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();
          factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
          factories.add(ObjectTypeAdapter.FACTORY);
          factories.add(excluder);
          factories.addAll(factoriesToBeAdded);
          factories.add(TypeAdapters.STRING_FACTORY);
          factories.add(TypeAdapters.INTEGER_FACTORY);
          factories.add(TypeAdapters.BOOLEAN_FACTORY);
          factories.add(TypeAdapters.BYTE_FACTORY);
          factories.add(TypeAdapters.SHORT_FACTORY);
          TypeAdapter<Number> longAdapter = Gson.longAdapter(longSerializationPolicy);
          factories.add(TypeAdapters.newFactory(Long.TYPE, Long.class, longAdapter));
          factories.add(TypeAdapters.newFactory(Double.TYPE, Double.class, this.doubleAdapter(serializeSpecialFloatingPointValues)));
          factories.add(TypeAdapters.newFactory(Float.TYPE, Float.class, this.floatAdapter(serializeSpecialFloatingPointValues)));
          factories.add(TypeAdapters.NUMBER_FACTORY);
          factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY);
          factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
          factories.add(TypeAdapters.newFactory(AtomicLong.class, Gson.atomicLongAdapter(longAdapter)));
          factories.add(TypeAdapters.newFactory(AtomicLongArray.class, Gson.atomicLongArrayAdapter(longAdapter)));
          factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY);
          factories.add(TypeAdapters.CHARACTER_FACTORY);
          factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
          factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
          factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
          factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
          factories.add(TypeAdapters.URL_FACTORY);
          factories.add(TypeAdapters.URI_FACTORY);
          factories.add(TypeAdapters.UUID_FACTORY);
          factories.add(TypeAdapters.CURRENCY_FACTORY);
          factories.add(TypeAdapters.LOCALE_FACTORY);
          factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
          factories.add(TypeAdapters.BIT_SET_FACTORY);
          factories.add(DateTypeAdapter.FACTORY);
          factories.add(TypeAdapters.CALENDAR_FACTORY);
          factories.add(TimeTypeAdapter.FACTORY);
          factories.add(SqlDateTypeAdapter.FACTORY);
          factories.add(TypeAdapters.TIMESTAMP_FACTORY);
          factories.add(ArrayTypeAdapter.FACTORY);
          factories.add(TypeAdapters.CLASS_FACTORY);
          factories.add(new CollectionTypeAdapterFactory(this.constructorConstructor));
          factories.add(new MapTypeAdapterFactory(this.constructorConstructor, complexMapKeySerialization));
          this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(this.constructorConstructor);
          factories.add(this.jsonAdapterFactory);
          factories.add(TypeAdapters.ENUM_FACTORY);
          factories.add(new ReflectiveTypeAdapterFactory(this.constructorConstructor, fieldNamingStrategy, excluder, this.jsonAdapterFactory));
          this.factories = Collections.unmodifiableList(factories);
      }
  
      public GsonBuilder newBuilder() {
          return new GsonBuilder(this);
      }
  
      public Excluder excluder() {
          return this.excluder;
      }
  
      public FieldNamingStrategy fieldNamingStrategy() {
          return this.fieldNamingStrategy;
      }
  
      public boolean serializeNulls() {
          return this.serializeNulls;
      }
  
      public boolean htmlSafe() {
          return this.htmlSafe;
      }
  
      private TypeAdapter<Number> doubleAdapter(boolean serializeSpecialFloatingPointValues) {
          if (serializeSpecialFloatingPointValues) {
              return TypeAdapters.DOUBLE;
          }
          return new TypeAdapter<Number>(){
  
              @Override
              public Double read(JsonReader in) throws IOException {
                  if (in.peek() == JsonToken.NULL) {
                      in.nextNull();
                      return null;
                  }
                  return in.nextDouble();
              }
  
              @Override
              public void write(JsonWriter out, Number value) throws IOException {
                  if (value == null) {
                      out.nullValue();
                      return;
                  }
                  double doubleValue = value.doubleValue();
                  Gson.checkValidFloatingPoint(doubleValue);
                  out.value(value);
              }
          };
      }
  
      private TypeAdapter<Number> floatAdapter(boolean serializeSpecialFloatingPointValues) {
          if (serializeSpecialFloatingPointValues) {
              return TypeAdapters.FLOAT;
          }
          return new TypeAdapter<Number>(){
  
              @Override
              public Float read(JsonReader in) throws IOException {
                  if (in.peek() == JsonToken.NULL) {
                      in.nextNull();
                      return null;
                  }
                  return Float.valueOf((float)in.nextDouble());
              }
  
              @Override
              public void write(JsonWriter out, Number value) throws IOException {
                  if (value == null) {
                      out.nullValue();
                      return;
                  }
                  float floatValue = value.floatValue();
                  Gson.checkValidFloatingPoint(floatValue);
                  out.value(value);
              }
          };
      }
  
      static void checkValidFloatingPoint(double value) {
          if (Double.isNaN(value) || Double.isInfinite(value)) {
              throw new IllegalArgumentException(value + " is not a valid double value as per JSON specification. To override this behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method.");
          }
      }
  
      private static TypeAdapter<Number> longAdapter(LongSerializationPolicy longSerializationPolicy) {
          if (longSerializationPolicy == LongSerializationPolicy.DEFAULT) {
              return TypeAdapters.LONG;
          }
          return new TypeAdapter<Number>(){
  
              @Override
              public Number read(JsonReader in) throws IOException {
                  if (in.peek() == JsonToken.NULL) {
                      in.nextNull();
                      return null;
                  }
                  return in.nextLong();
              }
  
              @Override
              public void write(JsonWriter out, Number value) throws IOException {
                  if (value == null) {
                      out.nullValue();
                      return;
                  }
                  out.value(value.toString());
              }
          };
      }
  
      private static TypeAdapter<AtomicLong> atomicLongAdapter(final TypeAdapter<Number> longAdapter) {
          return new TypeAdapter<AtomicLong>(){
  
              @Override
              public void write(JsonWriter out, AtomicLong value) throws IOException {
                  longAdapter.write(out, value.get());
              }
  
              @Override
              public AtomicLong read(JsonReader in) throws IOException {
                  Number value = (Number)longAdapter.read(in);
                  return new AtomicLong(value.longValue());
              }
          }.nullSafe();
      }
  
      private static TypeAdapter<AtomicLongArray> atomicLongArrayAdapter(final TypeAdapter<Number> longAdapter) {
          return new TypeAdapter<AtomicLongArray>(){
  
              @Override
              public void write(JsonWriter out, AtomicLongArray value) throws IOException {
                  out.beginArray();
                  int length = value.length();
                  for (int i = 0; i < length; ++i) {
                      longAdapter.write(out, value.get(i));
                  }
                  out.endArray();
              }
  
              @Override
              public AtomicLongArray read(JsonReader in) throws IOException {
                  ArrayList<Long> list = new ArrayList<Long>();
                  in.beginArray();
                  while (in.hasNext()) {
                      long value = ((Number)longAdapter.read(in)).longValue();
                      list.add(value);
                  }
                  in.endArray();
                  int length = list.size();
                  AtomicLongArray array = new AtomicLongArray(length);
                  for (int i = 0; i < length; ++i) {
                      array.set(i, (Long)list.get(i));
                  }
                  return array;
              }
          }.nullSafe();
      }
  
      public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
          FutureTypeAdapter<?> ongoingCall;
          TypeAdapter<?> cached = this.typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
          if (cached != null) {
              return cached;
          }
          Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = this.calls.get();
          boolean requiresThreadLocalCleanup = false;
          if (threadCalls == null) {
              threadCalls = new HashMap();
              this.calls.set(threadCalls);
              requiresThreadLocalCleanup = true;
          }
          if ((ongoingCall = threadCalls.get(type)) != null) {
              return ongoingCall;
          }
          try {
              FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
              threadCalls.put(type, call);
              for (TypeAdapterFactory factory2 : this.factories) {
                  TypeAdapter<T> candidate = factory2.create(this, type);
                  if (candidate == null) continue;
                  call.setDelegate(candidate);
                  this.typeTokenCache.put(type, candidate);
                  TypeAdapter<T> typeAdapter = candidate;
                  return typeAdapter;
              }
              throw new IllegalArgumentException("GSON (2.8.6) cannot handle " + type);
          } finally {
              threadCalls.remove(type);
              if (requiresThreadLocalCleanup) {
                  this.calls.remove();
              }
          }
      }
  
      public <T> TypeAdapter<T> getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken<T> type) {
          if (!this.factories.contains(skipPast)) {
              skipPast = this.jsonAdapterFactory;
          }
          boolean skipPastFound = false;
          for (TypeAdapterFactory factory2 : this.factories) {
              if (!skipPastFound) {
                  if (factory2 != skipPast) continue;
                  skipPastFound = true;
                  continue;
              }
              TypeAdapter<T> candidate = factory2.create(this, type);
              if (candidate == null) continue;
              return candidate;
          }
          throw new IllegalArgumentException("GSON cannot serialize " + type);
      }
  
      public <T> TypeAdapter<T> getAdapter(Class<T> type) {
          return this.getAdapter(TypeToken.get(type));
      }
  
      public JsonElement toJsonTree(Object src) {
          if (src == null) {
              return JsonNull.INSTANCE;
          }
          return this.toJsonTree(src, src.getClass());
      }
  
      public JsonElement toJsonTree(Object src, Type typeOfSrc) {
          JsonTreeWriter writer = new JsonTreeWriter();
          this.toJson(src, typeOfSrc, writer);
          return writer.get();
      }
  
      public String toJson(Object src) {
          if (src == null) {
              return this.toJson(JsonNull.INSTANCE);
          }
          return this.toJson(src, src.getClass());
      }
  
      public String toJson(Object src, Type typeOfSrc) {
          StringWriter writer = new StringWriter();
          this.toJson(src, typeOfSrc, writer);
          return writer.toString();
      }
  
      public void toJson(Object src, Appendable writer) throws JsonIOException {
          if (src != null) {
              this.toJson(src, src.getClass(), writer);
          } else {
              this.toJson((JsonElement)JsonNull.INSTANCE, writer);
          }
      }
  
      public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
          try {
              JsonWriter jsonWriter = this.newJsonWriter(Streams.writerForAppendable(writer));
              this.toJson(src, typeOfSrc, jsonWriter);
          } catch (IOException e) {
              throw new JsonIOException(e);
          }
      }
  
      public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
          TypeAdapter<?> adapter = this.getAdapter(TypeToken.get(typeOfSrc));
          boolean oldLenient = writer.isLenient();
          writer.setLenient(true);
          boolean oldHtmlSafe = writer.isHtmlSafe();
          writer.setHtmlSafe(this.htmlSafe);
          boolean oldSerializeNulls = writer.getSerializeNulls();
          writer.setSerializeNulls(this.serializeNulls);
          try {
              adapter.write(writer, src);
          } catch (IOException e) {
              throw new JsonIOException(e);
          } catch (AssertionError e) {
              AssertionError error = new AssertionError((Object)("AssertionError (GSON 2.8.6): " + ((Throwable)((Object)e)).getMessage()));
              ((Throwable)((Object)error)).initCause((Throwable)((Object)e));
              throw error;
          } finally {
              writer.setLenient(oldLenient);
              writer.setHtmlSafe(oldHtmlSafe);
              writer.setSerializeNulls(oldSerializeNulls);
          }
      }
  
      public String toJson(JsonElement jsonElement) {
          StringWriter writer = new StringWriter();
          this.toJson(jsonElement, (Appendable)writer);
          return writer.toString();
      }
  
      public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {
          try {
              JsonWriter jsonWriter = this.newJsonWriter(Streams.writerForAppendable(writer));
              this.toJson(jsonElement, jsonWriter);
          } catch (IOException e) {
              throw new JsonIOException(e);
          }
      }
  
      public JsonWriter newJsonWriter(Writer writer) throws IOException {
          if (this.generateNonExecutableJson) {
              writer.write(JSON_NON_EXECUTABLE_PREFIX);
          }
          JsonWriter jsonWriter = new JsonWriter(writer);
          if (this.prettyPrinting) {
              jsonWriter.setIndent("  ");
          }
          jsonWriter.setSerializeNulls(this.serializeNulls);
          return jsonWriter;
      }
  
      public JsonReader newJsonReader(Reader reader) {
          JsonReader jsonReader = new JsonReader(reader);
          jsonReader.setLenient(this.lenient);
          return jsonReader;
      }
  
      public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
          boolean oldLenient = writer.isLenient();
          writer.setLenient(true);
          boolean oldHtmlSafe = writer.isHtmlSafe();
          writer.setHtmlSafe(this.htmlSafe);
          boolean oldSerializeNulls = writer.getSerializeNulls();
          writer.setSerializeNulls(this.serializeNulls);
          try {
              Streams.write(jsonElement, writer);
          } catch (IOException e) {
              throw new JsonIOException(e);
          } catch (AssertionError e) {
              AssertionError error = new AssertionError((Object)("AssertionError (GSON 2.8.6): " + ((Throwable)((Object)e)).getMessage()));
              ((Throwable)((Object)error)).initCause((Throwable)((Object)e));
              throw error;
          } finally {
              writer.setLenient(oldLenient);
              writer.setHtmlSafe(oldHtmlSafe);
              writer.setSerializeNulls(oldSerializeNulls);
          }
      }
  
      public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
          T object = this.fromJson(json, (Type)classOfT);
          return Primitives.wrap(classOfT).cast(object);
      }
  
      public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
          if (json == null) {
              return null;
          }
          StringReader reader = new StringReader(json);
          T target = this.fromJson((Reader)reader, typeOfT);
          return target;
      }
  
      public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {
          JsonReader jsonReader = this.newJsonReader(json);
          T object = this.fromJson(jsonReader, classOfT);
          Gson.assertFullConsumption(object, jsonReader);
          return Primitives.wrap(classOfT).cast(object);
      }
  
      public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
          JsonReader jsonReader = this.newJsonReader(json);
          T object = this.fromJson(jsonReader, typeOfT);
          Gson.assertFullConsumption(object, jsonReader);
          return object;
      }
  
      private static void assertFullConsumption(Object obj, JsonReader reader) {
          try {
              if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) {
                  throw new JsonIOException("JSON document was not fully consumed.");
              }
          } catch (MalformedJsonException e) {
              throw new JsonSyntaxException(e);
          } catch (IOException e) {
              throw new JsonIOException(e);
          }
      }
  
      public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
          boolean isEmpty = true;
          boolean oldLenient = reader.isLenient();
          reader.setLenient(true);
          try {
              Object object;
              reader.peek();
              isEmpty = false;
              TypeToken<?> typeToken = TypeToken.get(typeOfT);
              TypeAdapter<?> typeAdapter = this.getAdapter(typeToken);
              Object obj = object = typeAdapter.read(reader);
              return (T)obj;
          } catch (EOFException e) {
              if (isEmpty) {
                  T typeAdapter = null;
                  return typeAdapter;
              }
              throw new JsonSyntaxException(e);
          } catch (IllegalStateException e) {
              throw new JsonSyntaxException(e);
          } catch (IOException e) {
              throw new JsonSyntaxException(e);
          } catch (AssertionError e) {
              AssertionError error = new AssertionError((Object)("AssertionError (GSON 2.8.6): " + ((Throwable)((Object)e)).getMessage()));
              ((Throwable)((Object)error)).initCause((Throwable)((Object)e));
              throw error;
          } finally {
              reader.setLenient(oldLenient);
          }
      }
  
      public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
          T object = this.fromJson(json, (Type)classOfT);
          return Primitives.wrap(classOfT).cast(object);
      }
  
      public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {
          if (json == null) {
              return null;
          }
          return this.fromJson(new JsonTreeReader(json), typeOfT);
      }
  
      public String toString() {
          return "{serializeNulls:" + this.serializeNulls + ",factories:" + this.factories + ",instanceCreators:" + this.constructorConstructor + "}";
      }
  
      static class FutureTypeAdapter<T>
      extends TypeAdapter<T> {
          private TypeAdapter<T> delegate;
  
          FutureTypeAdapter() {
          }
  
          public void setDelegate(TypeAdapter<T> typeAdapter) {
              if (this.delegate != null) {
                  throw new AssertionError();
              }
              this.delegate = typeAdapter;
          }
  
          @Override
          public T read(JsonReader in) throws IOException {
              if (this.delegate == null) {
                  throw new IllegalStateException();
              }
              return this.delegate.read(in);
          }
  
          @Override
          public void write(JsonWriter out, T value) throws IOException {
              if (this.delegate == null) {
                  throw new IllegalStateException();
              }
              this.delegate.write(out, value);
          }
      }
  }
  
  