// Generated from jackson-core which is licensed under the Apache License 2.0.
// The following copyright from the original authors applies.
// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
//
// Copyright (c) 2007 - The Jackson Project Authors
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Autogenerated by jnigen. DO NOT EDIT!

// ignore_for_file: annotate_overrides
// ignore_for_file: camel_case_extensions
// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: doc_directive_unknown
// ignore_for_file: file_names
// ignore_for_file: lines_longer_than_80_chars
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: overridden_fields
// ignore_for_file: unnecessary_cast
// ignore_for_file: unused_element
// ignore_for_file: unused_field
// ignore_for_file: unused_import
// ignore_for_file: unused_local_variable
// ignore_for_file: unused_shown_name
// ignore_for_file: use_super_parameters

import "dart:isolate" show ReceivePort;
import "dart:ffi" as ffi;
import "package:jni/internal_helpers_for_jnigen.dart";
import "package:jni/jni.dart" as jni;

import "JsonToken.dart" as jsontoken_;
import "../../../../_init.dart";

/// from: com.fasterxml.jackson.core.JsonParser$Feature
///
/// Enumeration that defines all on/off features for parsers.
class JsonParser_Feature extends jni.JObject {
  @override
  late final jni.JObjType<JsonParser_Feature> $type = type;

  JsonParser_Feature.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $JsonParser_FeatureType();
  static final _values =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "JsonParser_Feature__values")
          .asFunction<jni.JniResult Function()>();

  /// from: static public com.fasterxml.jackson.core.JsonParser.Feature[] values()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<JsonParser_Feature> values() {
    return _values().object(const jni.JArrayType($JsonParser_FeatureType()));
  }

  static final _valueOf = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "JsonParser_Feature__valueOf")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public com.fasterxml.jackson.core.JsonParser.Feature valueOf(java.lang.String name)
  /// The returned object must be released after use, by calling the [release] method.
  static JsonParser_Feature valueOf(
    jni.JString name,
  ) {
    return _valueOf(name.reference.pointer)
        .object(const $JsonParser_FeatureType());
  }

  static final _collectDefaults =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "JsonParser_Feature__collectDefaults")
          .asFunction<jni.JniResult Function()>();

  /// from: static public int collectDefaults()
  ///
  /// Method that calculates bit set (flags) of all features that
  /// are enabled by default.
  ///@return Bit mask of all features that are enabled by default
  static int collectDefaults() {
    return _collectDefaults().integer;
  }

  static final _enabledByDefault = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser_Feature__enabledByDefault")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean enabledByDefault()
  bool enabledByDefault() {
    return _enabledByDefault(reference.pointer).boolean;
  }

  static final _enabledIn = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("JsonParser_Feature__enabledIn")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public boolean enabledIn(int flags)
  bool enabledIn(
    int flags,
  ) {
    return _enabledIn(reference.pointer, flags).boolean;
  }

  static final _getMask = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser_Feature__getMask")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int getMask()
  int getMask() {
    return _getMask(reference.pointer).integer;
  }
}

final class $JsonParser_FeatureType extends jni.JObjType<JsonParser_Feature> {
  const $JsonParser_FeatureType();

  @override
  String get signature => r"Lcom/fasterxml/jackson/core/JsonParser$Feature;";

  @override
  JsonParser_Feature fromReference(jni.JReference reference) =>
      JsonParser_Feature.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($JsonParser_FeatureType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($JsonParser_FeatureType) &&
        other is $JsonParser_FeatureType;
  }
}

/// from: com.fasterxml.jackson.core.JsonParser$NumberType
///
/// Enumeration of possible "native" (optimal) types that can be
/// used for numbers.
class JsonParser_NumberType extends jni.JObject {
  @override
  late final jni.JObjType<JsonParser_NumberType> $type = type;

  JsonParser_NumberType.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $JsonParser_NumberTypeType();
  static final _values =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "JsonParser_NumberType__values")
          .asFunction<jni.JniResult Function()>();

  /// from: static public com.fasterxml.jackson.core.JsonParser.NumberType[] values()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<JsonParser_NumberType> values() {
    return _values().object(const jni.JArrayType($JsonParser_NumberTypeType()));
  }

  static final _valueOf = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "JsonParser_NumberType__valueOf")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public com.fasterxml.jackson.core.JsonParser.NumberType valueOf(java.lang.String name)
  /// The returned object must be released after use, by calling the [release] method.
  static JsonParser_NumberType valueOf(
    jni.JString name,
  ) {
    return _valueOf(name.reference.pointer)
        .object(const $JsonParser_NumberTypeType());
  }
}

final class $JsonParser_NumberTypeType
    extends jni.JObjType<JsonParser_NumberType> {
  const $JsonParser_NumberTypeType();

  @override
  String get signature => r"Lcom/fasterxml/jackson/core/JsonParser$NumberType;";

  @override
  JsonParser_NumberType fromReference(jni.JReference reference) =>
      JsonParser_NumberType.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($JsonParser_NumberTypeType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($JsonParser_NumberTypeType) &&
        other is $JsonParser_NumberTypeType;
  }
}

/// from: com.fasterxml.jackson.core.JsonParser
///
/// Base class that defines public API for reading JSON content.
/// Instances are created using factory methods of
/// a JsonFactory instance.
///@author Tatu Saloranta
class JsonParser extends jni.JObject {
  @override
  late final jni.JObjType<JsonParser> $type = type;

  JsonParser.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $JsonParserType();
  static final _get_DEFAULT_READ_CAPABILITIES =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_JsonParser__DEFAULT_READ_CAPABILITIES")
          .asFunction<jni.JniResult Function()>();

  /// from: static protected final com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamReadCapability> DEFAULT_READ_CAPABILITIES
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Default set of StreamReadCapabilityies that may be used as
  /// basis for format-specific readers (or as bogus instance if non-null
  /// set needs to be passed).
  ///@since 2.12
  static jni.JObject get DEFAULT_READ_CAPABILITIES =>
      _get_DEFAULT_READ_CAPABILITIES().object(const jni.JObjectType());

  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "JsonParser__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: protected void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory JsonParser() {
    return JsonParser.fromReference(_new0().reference);
  }

  static final _new1 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
              "JsonParser__new1")
          .asFunction<jni.JniResult Function(int)>();

  /// from: protected void <init>(int features)
  /// The returned object must be released after use, by calling the [release] method.
  factory JsonParser.new1(
    int features,
  ) {
    return JsonParser.fromReference(_new1(features).reference);
  }

  static final _getCodec = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getCodec")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.ObjectCodec getCodec()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Accessor for ObjectCodec associated with this
  /// parser, if any. Codec is used by \#readValueAs(Class)
  /// method (and its variants).
  ///@return Codec assigned to this parser, if any; {@code null} if none
  jni.JObject getCodec() {
    return _getCodec(reference.pointer).object(const jni.JObjectType());
  }

  static final _setCodec = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__setCodec")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract void setCodec(com.fasterxml.jackson.core.ObjectCodec oc)
  ///
  /// Setter that allows defining ObjectCodec associated with this
  /// parser, if any. Codec is used by \#readValueAs(Class)
  /// method (and its variants).
  ///@param oc Codec to assign, if any; {@code null} if none
  void setCodec(
    jni.JObject oc,
  ) {
    _setCodec(reference.pointer, oc.reference.pointer).check();
  }

  static final _getInputSource = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getInputSource")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Object getInputSource()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be used to get access to object that is used
  /// to access input being parsed; this is usually either
  /// InputStream or Reader, depending on what
  /// parser was constructed with.
  /// Note that returned value may be null in some cases; including
  /// case where parser implementation does not want to exposed raw
  /// source to caller.
  /// In cases where input has been decorated, object returned here
  /// is the decorated version; this allows some level of interaction
  /// between users of parser and decorator object.
  ///
  /// In general use of this accessor should be considered as
  /// "last effort", i.e. only used if no other mechanism is applicable.
  ///@return Input source this parser was configured with
  jni.JObject getInputSource() {
    return _getInputSource(reference.pointer).object(const jni.JObjectType());
  }

  static final _setRequestPayloadOnError = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "JsonParser__setRequestPayloadOnError")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void setRequestPayloadOnError(com.fasterxml.jackson.core.util.RequestPayload payload)
  ///
  /// Sets the payload to be passed if JsonParseException is thrown.
  ///@param payload Payload to pass
  ///@since 2.8
  void setRequestPayloadOnError(
    jni.JObject payload,
  ) {
    _setRequestPayloadOnError(reference.pointer, payload.reference.pointer)
        .check();
  }

  static final _setRequestPayloadOnError1 = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(ffi.Pointer<ffi.Void>,
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "JsonParser__setRequestPayloadOnError1")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public void setRequestPayloadOnError(byte[] payload, java.lang.String charset)
  ///
  /// Sets the byte[] request payload and the charset
  ///@param payload Payload to pass
  ///@param charset Character encoding for (lazily) decoding payload
  ///@since 2.8
  void setRequestPayloadOnError1(
    jni.JArray<jni.jbyte> payload,
    jni.JString charset,
  ) {
    _setRequestPayloadOnError1(reference.pointer, payload.reference.pointer,
            charset.reference.pointer)
        .check();
  }

  static final _setRequestPayloadOnError2 = jniLookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>>(
          "JsonParser__setRequestPayloadOnError2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void setRequestPayloadOnError(java.lang.String payload)
  ///
  /// Sets the String request payload
  ///@param payload Payload to pass
  ///@since 2.8
  void setRequestPayloadOnError2(
    jni.JString payload,
  ) {
    _setRequestPayloadOnError2(reference.pointer, payload.reference.pointer)
        .check();
  }

  static final _setSchema = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__setSchema")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void setSchema(com.fasterxml.jackson.core.FormatSchema schema)
  ///
  /// Method to call to make this parser use specified schema. Method must
  /// be called before trying to parse any content, right after parser instance
  /// has been created.
  /// Note that not all parsers support schemas; and those that do usually only
  /// accept specific types of schemas: ones defined for data format parser can read.
  ///
  /// If parser does not support specified schema, UnsupportedOperationException
  /// is thrown.
  ///@param schema Schema to use
  ///@throws UnsupportedOperationException if parser does not support schema
  void setSchema(
    jni.JObject schema,
  ) {
    _setSchema(reference.pointer, schema.reference.pointer).check();
  }

  static final _getSchema = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getSchema")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.FormatSchema getSchema()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for accessing Schema that this parser uses, if any.
  /// Default implementation returns null.
  ///@return Schema in use by this parser, if any; {@code null} if none
  ///@since 2.1
  jni.JObject getSchema() {
    return _getSchema(reference.pointer).object(const jni.JObjectType());
  }

  static final _canUseSchema = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__canUseSchema")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean canUseSchema(com.fasterxml.jackson.core.FormatSchema schema)
  ///
  /// Method that can be used to verify that given schema can be used with
  /// this parser (using \#setSchema).
  ///@param schema Schema to check
  ///@return True if this parser can use given schema; false if not
  bool canUseSchema(
    jni.JObject schema,
  ) {
    return _canUseSchema(reference.pointer, schema.reference.pointer).boolean;
  }

  static final _requiresCustomCodec = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__requiresCustomCodec")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean requiresCustomCodec()
  ///
  /// Method that can be called to determine if a custom
  /// ObjectCodec is needed for binding data parsed
  /// using JsonParser constructed by this factory
  /// (which typically also implies the same for serialization
  /// with JsonGenerator).
  ///@return True if format-specific codec is needed with this parser; false if a general
  ///   ObjectCodec is enough
  ///@since 2.1
  bool requiresCustomCodec() {
    return _requiresCustomCodec(reference.pointer).boolean;
  }

  static final _canParseAsync = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__canParseAsync")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean canParseAsync()
  ///
  /// Method that can be called to determine if this parser instance
  /// uses non-blocking ("asynchronous") input access for decoding or not.
  /// Access mode is determined by earlier calls via JsonFactory;
  /// it may not be changed after construction.
  ///
  /// If non-blocking decoding is (@code true}, it is possible to call
  /// \#getNonBlockingInputFeeder() to obtain object to use
  /// for feeding input; otherwise (<code>false</code> returned)
  /// input is read by blocking
  ///@return True if this is a non-blocking ("asynchronous") parser
  ///@since 2.9
  bool canParseAsync() {
    return _canParseAsync(reference.pointer).boolean;
  }

  static final _getNonBlockingInputFeeder = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getNonBlockingInputFeeder")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.async.NonBlockingInputFeeder getNonBlockingInputFeeder()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that will either return a feeder instance (if parser uses
  /// non-blocking, aka asynchronous access); or <code>null</code> for
  /// parsers that use blocking I/O.
  ///@return Input feeder to use with non-blocking (async) parsing
  ///@since 2.9
  jni.JObject getNonBlockingInputFeeder() {
    return _getNonBlockingInputFeeder(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _getReadCapabilities = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getReadCapabilities")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamReadCapability> getReadCapabilities()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Accessor for getting metadata on capabilities of this parser, based on
  /// underlying data format being read (directly or indirectly).
  ///@return Set of read capabilities for content to read via this parser
  ///@since 2.12
  jni.JObject getReadCapabilities() {
    return _getReadCapabilities(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _version = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__version")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.Version version()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Accessor for getting version of the core package, given a parser instance.
  /// Left for sub-classes to implement.
  ///@return Version of this generator (derived from version declared for
  ///   {@code jackson-core} jar that contains the class
  jni.JObject version() {
    return _version(reference.pointer).object(const jni.JObjectType());
  }

  static final _close = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__close")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract void close()
  ///
  /// Closes the parser so that no further iteration or data access
  /// can be made; will also close the underlying input source
  /// if parser either __owns__ the input source, or feature
  /// Feature\#AUTO_CLOSE_SOURCE is enabled.
  /// Whether parser owns the input source depends on factory
  /// method that was used to construct instance (so check
  /// com.fasterxml.jackson.core.JsonFactory for details,
  /// but the general
  /// idea is that if caller passes in closable resource (such
  /// as InputStream or Reader) parser does NOT
  /// own the source; but if it passes a reference (such as
  /// java.io.File or java.net.URL and creates
  /// stream or reader it does own them.
  ///@throws IOException if there is either an underlying I/O problem
  void close() {
    _close(reference.pointer).check();
  }

  static final _isClosed = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__isClosed")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract boolean isClosed()
  ///
  /// Method that can be called to determine whether this parser
  /// is closed or not. If it is closed, no new tokens can be
  /// retrieved by calling \#nextToken (and the underlying
  /// stream may be closed). Closing may be due to an explicit
  /// call to \#close or because parser has encountered
  /// end of input.
  ///@return {@code True} if this parser instance has been closed
  bool isClosed() {
    return _isClosed(reference.pointer).boolean;
  }

  static final _getParsingContext = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getParsingContext")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.JsonStreamContext getParsingContext()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be used to access current parsing context reader
  /// is in. There are 3 different types: root, array and object contexts,
  /// with slightly different available information. Contexts are
  /// hierarchically nested, and can be used for example for figuring
  /// out part of the input document that correspond to specific
  /// array or object (for highlighting purposes, or error reporting).
  /// Contexts can also be used for simple xpath-like matching of
  /// input, if so desired.
  ///@return Stream input context (JsonStreamContext) associated with this parser
  jni.JObject getParsingContext() {
    return _getParsingContext(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _currentLocation = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__currentLocation")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.JsonLocation currentLocation()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that returns location of the last processed input unit (character
  /// or byte) from the input;
  /// usually for error reporting purposes.
  ///
  /// Note that the location is not guaranteed to be accurate (although most
  /// implementation will try their best): some implementations may only
  /// report specific boundary locations (start or end locations of tokens)
  /// and others only return JsonLocation\#NA due to not having access
  /// to input location information (when delegating actual decoding work
  /// to other library)
  ///@return Location of the last processed input unit (byte or character)
  ///@since 2.13
  jni.JObject currentLocation() {
    return _currentLocation(reference.pointer).object(const jni.JObjectType());
  }

  static final _currentTokenLocation = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__currentTokenLocation")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.JsonLocation currentTokenLocation()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that return the __starting__ location of the current
  /// (most recently returned)
  /// token; that is, the position of the first input unit (character or byte) from input
  /// that starts the current token.
  ///
  /// Note that the location is not guaranteed to be accurate (although most
  /// implementation will try their best): some implementations may only
  /// return JsonLocation\#NA due to not having access
  /// to input location information (when delegating actual decoding work
  /// to other library)
  ///@return Starting location of the token parser currently points to
  ///@since 2.13 (will eventually replace \#getTokenLocation)
  jni.JObject currentTokenLocation() {
    return _currentTokenLocation(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _getCurrentLocation = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getCurrentLocation")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.JsonLocation getCurrentLocation()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Alias for \#currentLocation(), to be deprecated in later
  /// Jackson 2.x versions (and removed from Jackson 3.0).
  ///@return Location of the last processed input unit (byte or character)
  jni.JObject getCurrentLocation() {
    return _getCurrentLocation(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _getTokenLocation = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getTokenLocation")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.JsonLocation getTokenLocation()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Alias for \#currentTokenLocation(), to be deprecated in later
  /// Jackson 2.x versions (and removed from Jackson 3.0).
  ///@return Starting location of the token parser currently points to
  jni.JObject getTokenLocation() {
    return _getTokenLocation(reference.pointer).object(const jni.JObjectType());
  }

  static final _currentValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__currentValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Object currentValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Helper method, usually equivalent to:
  ///<code>
  ///   getParsingContext().getCurrentValue();
  ///</code>
  ///
  /// Note that "current value" is NOT populated (or used) by Streaming parser;
  /// it is only used by higher-level data-binding functionality.
  /// The reason it is included here is that it can be stored and accessed hierarchically,
  /// and gets passed through data-binding.
  ///@return "Current value" associated with the current input context (state) of this parser
  ///@since 2.13 (added as replacement for older \#getCurrentValue()
  jni.JObject currentValue() {
    return _currentValue(reference.pointer).object(const jni.JObjectType());
  }

  static final _assignCurrentValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__assignCurrentValue")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void assignCurrentValue(java.lang.Object v)
  ///
  /// Helper method, usually equivalent to:
  ///<code>
  ///   getParsingContext().setCurrentValue(v);
  ///</code>
  ///@param v Current value to assign for the current input context of this parser
  ///@since 2.13 (added as replacement for older \#setCurrentValue
  void assignCurrentValue(
    jni.JObject v,
  ) {
    _assignCurrentValue(reference.pointer, v.reference.pointer).check();
  }

  static final _getCurrentValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getCurrentValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Object getCurrentValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Alias for \#currentValue(), to be deprecated in later
  /// Jackson 2.x versions (and removed from Jackson 3.0).
  ///@return Location of the last processed input unit (byte or character)
  jni.JObject getCurrentValue() {
    return _getCurrentValue(reference.pointer).object(const jni.JObjectType());
  }

  static final _setCurrentValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__setCurrentValue")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public void setCurrentValue(java.lang.Object v)
  ///
  /// Alias for \#assignCurrentValue, to be deprecated in later
  /// Jackson 2.x versions (and removed from Jackson 3.0).
  ///@param v Current value to assign for the current input context of this parser
  void setCurrentValue(
    jni.JObject v,
  ) {
    _setCurrentValue(reference.pointer, v.reference.pointer).check();
  }

  static final _releaseBuffered = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__releaseBuffered")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public int releaseBuffered(java.io.OutputStream out)
  ///
  /// Method that can be called to push back any content that
  /// has been read but not consumed by the parser. This is usually
  /// done after reading all content of interest using parser.
  /// Content is released by writing it to given stream if possible;
  /// if underlying input is byte-based it can released, if not (char-based)
  /// it can not.
  ///@param out OutputStream to which buffered, undecoded content is written to
  ///@return -1 if the underlying content source is not byte based
  ///    (that is, input can not be sent to OutputStream;
  ///    otherwise number of bytes released (0 if there was nothing to release)
  ///@throws IOException if write to stream threw exception
  int releaseBuffered(
    jni.JObject out,
  ) {
    return _releaseBuffered(reference.pointer, out.reference.pointer).integer;
  }

  static final _releaseBuffered1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__releaseBuffered1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public int releaseBuffered(java.io.Writer w)
  ///
  /// Method that can be called to push back any content that
  /// has been read but not consumed by the parser.
  /// This is usually
  /// done after reading all content of interest using parser.
  /// Content is released by writing it to given writer if possible;
  /// if underlying input is char-based it can released, if not (byte-based)
  /// it can not.
  ///@param w Writer to which buffered but unprocessed content is written to
  ///@return -1 if the underlying content source is not char-based
  ///    (that is, input can not be sent to Writer;
  ///    otherwise number of chars released (0 if there was nothing to release)
  ///@throws IOException if write using Writer threw exception
  int releaseBuffered1(
    jni.JObject w,
  ) {
    return _releaseBuffered1(reference.pointer, w.reference.pointer).integer;
  }

  static final _enable = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__enable")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser enable(com.fasterxml.jackson.core.JsonParser.Feature f)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for enabling specified parser feature
  /// (check Feature for list of features)
  ///@param f Feature to enable
  ///@return This parser, to allow call chaining
  JsonParser enable(
    JsonParser_Feature f,
  ) {
    return _enable(reference.pointer, f.reference.pointer)
        .object(const $JsonParserType());
  }

  static final _disable = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__disable")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser disable(com.fasterxml.jackson.core.JsonParser.Feature f)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for disabling specified  feature
  /// (check Feature for list of features)
  ///@param f Feature to disable
  ///@return This parser, to allow call chaining
  JsonParser disable(
    JsonParser_Feature f,
  ) {
    return _disable(reference.pointer, f.reference.pointer)
        .object(const $JsonParserType());
  }

  static final _configure = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>, ffi.Uint8)>>("JsonParser__configure")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();

  /// from: public com.fasterxml.jackson.core.JsonParser configure(com.fasterxml.jackson.core.JsonParser.Feature f, boolean state)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for enabling or disabling specified feature
  /// (check Feature for list of features)
  ///@param f Feature to enable or disable
  ///@param state Whether to enable feature ({@code true}) or disable ({@code false})
  ///@return This parser, to allow call chaining
  JsonParser configure(
    JsonParser_Feature f,
    bool state,
  ) {
    return _configure(reference.pointer, f.reference.pointer, state ? 1 : 0)
        .object(const $JsonParserType());
  }

  static final _isEnabled = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__isEnabled")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean isEnabled(com.fasterxml.jackson.core.JsonParser.Feature f)
  ///
  /// Method for checking whether specified Feature is enabled.
  ///@param f Feature to check
  ///@return {@code True} if feature is enabled; {@code false} otherwise
  bool isEnabled(
    JsonParser_Feature f,
  ) {
    return _isEnabled(reference.pointer, f.reference.pointer).boolean;
  }

  static final _isEnabled1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__isEnabled1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean isEnabled(com.fasterxml.jackson.core.StreamReadFeature f)
  ///
  /// Method for checking whether specified Feature is enabled.
  ///@param f Feature to check
  ///@return {@code True} if feature is enabled; {@code false} otherwise
  ///@since 2.10
  bool isEnabled1(
    jni.JObject f,
  ) {
    return _isEnabled1(reference.pointer, f.reference.pointer).boolean;
  }

  static final _getFeatureMask = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getFeatureMask")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int getFeatureMask()
  ///
  /// Bulk access method for getting state of all standard Features.
  ///@return Bit mask that defines current states of all standard Features.
  ///@since 2.3
  int getFeatureMask() {
    return _getFeatureMask(reference.pointer).integer;
  }

  static final _setFeatureMask = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("JsonParser__setFeatureMask")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public com.fasterxml.jackson.core.JsonParser setFeatureMask(int mask)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Bulk set method for (re)setting states of all standard Features
  ///@param mask Bit mask that defines set of features to enable
  ///@return This parser, to allow call chaining
  ///@since 2.3
  ///@deprecated Since 2.7, use \#overrideStdFeatures(int, int) instead
  JsonParser setFeatureMask(
    int mask,
  ) {
    return _setFeatureMask(reference.pointer, mask)
        .object(const $JsonParserType());
  }

  static final _overrideStdFeatures = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Int32,
                  ffi.Int32)>>("JsonParser__overrideStdFeatures")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int, int)>();

  /// from: public com.fasterxml.jackson.core.JsonParser overrideStdFeatures(int values, int mask)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Bulk set method for (re)setting states of features specified by <code>mask</code>.
  /// Functionally equivalent to
  ///<code>
  ///    int oldState = getFeatureMask();
  ///    int newState = (oldState &amp; ~mask) | (values &amp; mask);
  ///    setFeatureMask(newState);
  ///</code>
  /// but preferred as this lets caller more efficiently specify actual changes made.
  ///@param values Bit mask of set/clear state for features to change
  ///@param mask Bit mask of features to change
  ///@return This parser, to allow call chaining
  ///@since 2.6
  JsonParser overrideStdFeatures(
    int values,
    int mask,
  ) {
    return _overrideStdFeatures(reference.pointer, values, mask)
        .object(const $JsonParserType());
  }

  static final _getFormatFeatures = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getFormatFeatures")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int getFormatFeatures()
  ///
  /// Bulk access method for getting state of all FormatFeatures, format-specific
  /// on/off configuration settings.
  ///@return Bit mask that defines current states of all standard FormatFeatures.
  ///@since 2.6
  int getFormatFeatures() {
    return _getFormatFeatures(reference.pointer).integer;
  }

  static final _overrideFormatFeatures = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Int32,
                  ffi.Int32)>>("JsonParser__overrideFormatFeatures")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int, int)>();

  /// from: public com.fasterxml.jackson.core.JsonParser overrideFormatFeatures(int values, int mask)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Bulk set method for (re)setting states of FormatFeatures,
  /// by specifying values (set / clear) along with a mask, to determine
  /// which features to change, if any.
  ///
  /// Default implementation will simply throw an exception to indicate that
  /// the parser implementation does not support any FormatFeatures.
  ///@param values Bit mask of set/clear state for features to change
  ///@param mask Bit mask of features to change
  ///@return This parser, to allow call chaining
  ///@since 2.6
  JsonParser overrideFormatFeatures(
    int values,
    int mask,
  ) {
    return _overrideFormatFeatures(reference.pointer, values, mask)
        .object(const $JsonParserType());
  }

  static final _nextToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__nextToken")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.JsonToken nextToken()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Main iteration method, which will advance stream enough
  /// to determine type of the next token, if any. If none
  /// remaining (stream has no content other than possible
  /// white space before ending), null will be returned.
  ///@return Next token from the stream, if any found, or null
  ///   to indicate end-of-input
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jsontoken_.JsonToken nextToken() {
    return _nextToken(reference.pointer)
        .object(const jsontoken_.$JsonTokenType());
  }

  static final _nextValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__nextValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.JsonToken nextValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Iteration method that will advance stream enough
  /// to determine type of the next token that is a value type
  /// (including JSON Array and Object start/end markers).
  /// Or put another way, nextToken() will be called once,
  /// and if JsonToken\#FIELD_NAME is returned, another
  /// time to get the value for the field.
  /// Method is most useful for iterating over value entries
  /// of JSON objects; field name will still be available
  /// by calling \#getCurrentName when parser points to
  /// the value.
  ///@return Next non-field-name token from the stream, if any found,
  ///   or null to indicate end-of-input (or, for non-blocking
  ///   parsers, JsonToken\#NOT_AVAILABLE if no tokens were
  ///   available yet)
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jsontoken_.JsonToken nextValue() {
    return _nextValue(reference.pointer)
        .object(const jsontoken_.$JsonTokenType());
  }

  static final _nextFieldName = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__nextFieldName")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean nextFieldName(com.fasterxml.jackson.core.SerializableString str)
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// verifies whether it is JsonToken\#FIELD_NAME with specified name
  /// and returns result of that comparison.
  /// It is functionally equivalent to:
  ///<pre>
  ///  return (nextToken() == JsonToken.FIELD_NAME) &amp;&amp; str.getValue().equals(getCurrentName());
  ///</pre>
  /// but may be faster for parser to verify, and can therefore be used if caller
  /// expects to get such a property name from input next.
  ///@param str Property name to compare next token to (if next token is
  ///   <code>JsonToken.FIELD_NAME</code>)
  ///@return {@code True} if parser advanced to {@code JsonToken.FIELD_NAME} with
  ///    specified name; {@code false} otherwise (different token or non-matching name)
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  bool nextFieldName(
    jni.JObject str,
  ) {
    return _nextFieldName(reference.pointer, str.reference.pointer).boolean;
  }

  static final _nextFieldName1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__nextFieldName1")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.String nextFieldName()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// verifies whether it is JsonToken\#FIELD_NAME; if it is,
  /// returns same as \#getCurrentName(), otherwise null.
  ///@return Name of the the {@code JsonToken.FIELD_NAME} parser advanced to, if any;
  ///   {@code null} if next token is of some other type
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.5
  jni.JString nextFieldName1() {
    return _nextFieldName1(reference.pointer).object(const jni.JStringType());
  }

  static final _nextTextValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__nextTextValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.String nextTextValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// if it is JsonToken\#VALUE_STRING returns contained String value;
  /// otherwise returns null.
  /// It is functionally equivalent to:
  ///<pre>
  ///  return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null;
  ///</pre>
  /// but may be faster for parser to process, and can therefore be used if caller
  /// expects to get a String value next from input.
  ///@return Text value of the {@code JsonToken.VALUE_STRING} token parser advanced
  ///   to; or {@code null} if next token is of some other type
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JString nextTextValue() {
    return _nextTextValue(reference.pointer).object(const jni.JStringType());
  }

  static final _nextIntValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("JsonParser__nextIntValue")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public int nextIntValue(int defaultValue)
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// if it is JsonToken\#VALUE_NUMBER_INT returns 32-bit int value;
  /// otherwise returns specified default value
  /// It is functionally equivalent to:
  ///<pre>
  ///  return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getIntValue() : defaultValue;
  ///</pre>
  /// but may be faster for parser to process, and can therefore be used if caller
  /// expects to get an int value next from input.
  ///
  /// NOTE: value checks are performed similar to \#getIntValue()
  ///@param defaultValue Value to return if next token is NOT of type {@code JsonToken.VALUE_NUMBER_INT}
  ///@return Integer ({@code int}) value of the {@code JsonToken.VALUE_NUMBER_INT} token parser advanced
  ///   to; or {@code defaultValue} if next token is of some other type
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@throws InputCoercionException if integer number does not fit in Java {@code int}
  int nextIntValue(
    int defaultValue,
  ) {
    return _nextIntValue(reference.pointer, defaultValue).integer;
  }

  static final _nextLongValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int64)>>("JsonParser__nextLongValue")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public long nextLongValue(long defaultValue)
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// if it is JsonToken\#VALUE_NUMBER_INT returns 64-bit long value;
  /// otherwise returns specified default value
  /// It is functionally equivalent to:
  ///<pre>
  ///  return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getLongValue() : defaultValue;
  ///</pre>
  /// but may be faster for parser to process, and can therefore be used if caller
  /// expects to get a long value next from input.
  ///
  /// NOTE: value checks are performed similar to \#getLongValue()
  ///@param defaultValue Value to return if next token is NOT of type {@code JsonToken.VALUE_NUMBER_INT}
  ///@return {@code long} value of the {@code JsonToken.VALUE_NUMBER_INT} token parser advanced
  ///   to; or {@code defaultValue} if next token is of some other type
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@throws InputCoercionException if integer number does not fit in Java {@code long}
  int nextLongValue(
    int defaultValue,
  ) {
    return _nextLongValue(reference.pointer, defaultValue).long;
  }

  static final _nextBooleanValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__nextBooleanValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Boolean nextBooleanValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// if it is JsonToken\#VALUE_TRUE or JsonToken\#VALUE_FALSE
  /// returns matching Boolean value; otherwise return null.
  /// It is functionally equivalent to:
  ///<pre>
  ///  JsonToken t = nextToken();
  ///  if (t == JsonToken.VALUE_TRUE) return Boolean.TRUE;
  ///  if (t == JsonToken.VALUE_FALSE) return Boolean.FALSE;
  ///  return null;
  ///</pre>
  /// but may be faster for parser to process, and can therefore be used if caller
  /// expects to get a Boolean value next from input.
  ///@return {@code Boolean} value of the {@code JsonToken.VALUE_TRUE} or {@code JsonToken.VALUE_FALSE}
  ///   token parser advanced to; or {@code null} if next token is of some other type
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JBoolean nextBooleanValue() {
    return _nextBooleanValue(reference.pointer)
        .object(const jni.JBooleanType());
  }

  static final _skipChildren = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__skipChildren")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.JsonParser skipChildren()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that will skip all child tokens of an array or
  /// object token that the parser currently points to,
  /// iff stream points to
  /// JsonToken\#START_OBJECT or JsonToken\#START_ARRAY.
  /// If not, it will do nothing.
  /// After skipping, stream will point to __matching__
  /// JsonToken\#END_OBJECT or JsonToken\#END_ARRAY
  /// (possibly skipping nested pairs of START/END OBJECT/ARRAY tokens
  /// as well as value tokens).
  /// The idea is that after calling this method, application
  /// will call \#nextToken to point to the next
  /// available token, if any.
  ///@return This parser, to allow call chaining
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  JsonParser skipChildren() {
    return _skipChildren(reference.pointer).object(const $JsonParserType());
  }

  static final _finishToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__finishToken")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public void finishToken()
  ///
  /// Method that may be used to force full handling of the current token
  /// so that even if lazy processing is enabled, the whole contents are
  /// read for possible retrieval. This is usually used to ensure that
  /// the token end location is available, as well as token contents
  /// (similar to what calling, say \#getTextCharacters(), would
  /// achieve).
  ///
  /// Note that for many dataformat implementations this method
  /// will not do anything; this is the default implementation unless
  /// overridden by sub-classes.
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.8
  void finishToken() {
    _finishToken(reference.pointer).check();
  }

  static final _currentToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__currentToken")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.JsonToken currentToken()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Accessor to find which token parser currently points to, if any;
  /// null will be returned if none.
  /// If return value is non-null, data associated with the token
  /// is available via other accessor methods.
  ///@return Type of the token this parser currently points to,
  ///   if any: null before any tokens have been read, and
  ///   after end-of-input has been encountered, as well as
  ///   if the current token has been explicitly cleared.
  ///@since 2.8
  jsontoken_.JsonToken currentToken() {
    return _currentToken(reference.pointer)
        .object(const jsontoken_.$JsonTokenType());
  }

  static final _currentTokenId = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__currentTokenId")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int currentTokenId()
  ///
  /// Method similar to \#getCurrentToken() but that returns an
  /// <code>int</code> instead of JsonToken (enum value).
  ///
  /// Use of int directly is typically more efficient on switch statements,
  /// so this method may be useful when building low-overhead codecs.
  /// Note, however, that effect may not be big enough to matter: make sure
  /// to profile performance before deciding to use this method.
  ///@since 2.8
  ///@return {@code int} matching one of constants from JsonTokenId.
  int currentTokenId() {
    return _currentTokenId(reference.pointer).integer;
  }

  static final _getCurrentToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getCurrentToken")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.JsonToken getCurrentToken()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Alias for \#currentToken(), may be deprecated sometime after
  /// Jackson 2.13 (will be removed from 3.0).
  ///@return Type of the token this parser currently points to,
  ///   if any: null before any tokens have been read, and
  jsontoken_.JsonToken getCurrentToken() {
    return _getCurrentToken(reference.pointer)
        .object(const jsontoken_.$JsonTokenType());
  }

  static final _getCurrentTokenId = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getCurrentTokenId")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract int getCurrentTokenId()
  ///
  /// Deprecated alias for \#currentTokenId().
  ///@return {@code int} matching one of constants from JsonTokenId.
  ///@deprecated Since 2.12 use \#currentTokenId instead
  int getCurrentTokenId() {
    return _getCurrentTokenId(reference.pointer).integer;
  }

  static final _hasCurrentToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__hasCurrentToken")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract boolean hasCurrentToken()
  ///
  /// Method for checking whether parser currently points to
  /// a token (and data for that token is available).
  /// Equivalent to check for <code>parser.getCurrentToken() != null</code>.
  ///@return True if the parser just returned a valid
  ///   token via \#nextToken; false otherwise (parser
  ///   was just constructed, encountered end-of-input
  ///   and returned null from \#nextToken, or the token
  ///   has been consumed)
  bool hasCurrentToken() {
    return _hasCurrentToken(reference.pointer).boolean;
  }

  static final _hasTokenId = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>, ffi.Int32)>>("JsonParser__hasTokenId")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public abstract boolean hasTokenId(int id)
  ///
  /// Method that is functionally equivalent to:
  ///<code>
  ///  return currentTokenId() == id
  ///</code>
  /// but may be more efficiently implemented.
  ///
  /// Note that no traversal or conversion is performed; so in some
  /// cases calling method like \#isExpectedStartArrayToken()
  /// is necessary instead.
  ///@param id Token id to match (from (@link JsonTokenId})
  ///@return {@code True} if the parser current points to specified token
  ///@since 2.5
  bool hasTokenId(
    int id,
  ) {
    return _hasTokenId(reference.pointer, id).boolean;
  }

  static final _hasToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__hasToken")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract boolean hasToken(com.fasterxml.jackson.core.JsonToken t)
  ///
  /// Method that is functionally equivalent to:
  ///<code>
  ///  return currentToken() == t
  ///</code>
  /// but may be more efficiently implemented.
  ///
  /// Note that no traversal or conversion is performed; so in some
  /// cases calling method like \#isExpectedStartArrayToken()
  /// is necessary instead.
  ///@param t Token to match
  ///@return {@code True} if the parser current points to specified token
  ///@since 2.6
  bool hasToken(
    jsontoken_.JsonToken t,
  ) {
    return _hasToken(reference.pointer, t.reference.pointer).boolean;
  }

  static final _isExpectedStartArrayToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__isExpectedStartArrayToken")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean isExpectedStartArrayToken()
  ///
  /// Specialized accessor that can be used to verify that the current
  /// token indicates start array (usually meaning that current token
  /// is JsonToken\#START_ARRAY) when start array is expected.
  /// For some specialized parsers this can return true for other cases
  /// as well; this is usually done to emulate arrays in cases underlying
  /// format is ambiguous (XML, for example, has no format-level difference
  /// between Objects and Arrays; it just has elements).
  ///
  /// Default implementation is equivalent to:
  ///<pre>
  ///   currentToken() == JsonToken.START_ARRAY
  ///</pre>
  /// but may be overridden by custom parser implementations.
  ///@return True if the current token can be considered as a
  ///   start-array marker (such JsonToken\#START_ARRAY);
  ///   {@code false} if not
  bool isExpectedStartArrayToken() {
    return _isExpectedStartArrayToken(reference.pointer).boolean;
  }

  static final _isExpectedStartObjectToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__isExpectedStartObjectToken")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean isExpectedStartObjectToken()
  ///
  /// Similar to \#isExpectedStartArrayToken(), but checks whether stream
  /// currently points to JsonToken\#START_OBJECT.
  ///@return True if the current token can be considered as a
  ///   start-array marker (such JsonToken\#START_OBJECT);
  ///   {@code false} if not
  ///@since 2.5
  bool isExpectedStartObjectToken() {
    return _isExpectedStartObjectToken(reference.pointer).boolean;
  }

  static final _isExpectedNumberIntToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__isExpectedNumberIntToken")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean isExpectedNumberIntToken()
  ///
  /// Similar to \#isExpectedStartArrayToken(), but checks whether stream
  /// currently points to JsonToken\#VALUE_NUMBER_INT.
  ///
  /// The initial use case is for XML backend to efficiently (attempt to) coerce
  /// textual content into numbers.
  ///@return True if the current token can be considered as a
  ///   start-array marker (such JsonToken\#VALUE_NUMBER_INT);
  ///   {@code false} if not
  ///@since 2.12
  bool isExpectedNumberIntToken() {
    return _isExpectedNumberIntToken(reference.pointer).boolean;
  }

  static final _isNaN = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__isNaN")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean isNaN()
  ///
  /// Access for checking whether current token is a numeric value token, but
  /// one that is of "not-a-number" (NaN) variety (including both "NaN" AND
  /// positive/negative infinity!): not supported by all formats,
  /// but often supported for JsonToken\#VALUE_NUMBER_FLOAT.
  /// NOTE: roughly equivalent to calling <code>!Double.isFinite()</code>
  /// on value you would get from calling \#getDoubleValue().
  ///@return {@code True} if the current token is of type JsonToken\#VALUE_NUMBER_FLOAT
  ///   but represents a "Not a Number"; {@code false} for other tokens and regular
  ///   floating-point numbers
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.9
  bool isNaN() {
    return _isNaN(reference.pointer).boolean;
  }

  static final _clearCurrentToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__clearCurrentToken")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract void clearCurrentToken()
  ///
  /// Method called to "consume" the current token by effectively
  /// removing it so that \#hasCurrentToken returns false, and
  /// \#getCurrentToken null).
  /// Cleared token value can still be accessed by calling
  /// \#getLastClearedToken (if absolutely needed), but
  /// usually isn't.
  ///
  /// Method was added to be used by the optional data binder, since
  /// it has to be able to consume last token used for binding (so that
  /// it will not be used again).
  void clearCurrentToken() {
    _clearCurrentToken(reference.pointer).check();
  }

  static final _getLastClearedToken = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getLastClearedToken")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.JsonToken getLastClearedToken()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be called to get the last token that was
  /// cleared using \#clearCurrentToken. This is not necessarily
  /// the latest token read.
  /// Will return null if no tokens have been cleared,
  /// or if parser has been closed.
  ///@return Last cleared token, if any; {@code null} otherwise
  jsontoken_.JsonToken getLastClearedToken() {
    return _getLastClearedToken(reference.pointer)
        .object(const jsontoken_.$JsonTokenType());
  }

  static final _overrideCurrentName = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__overrideCurrentName")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract void overrideCurrentName(java.lang.String name)
  ///
  /// Method that can be used to change what is considered to be
  /// the current (field) name.
  /// May be needed to support non-JSON data formats or unusual binding
  /// conventions; not needed for typical processing.
  ///
  /// Note that use of this method should only be done as sort of last
  /// resort, as it is a work-around for regular operation.
  ///@param name Name to use as the current name; may be null.
  void overrideCurrentName(
    jni.JString name,
  ) {
    _overrideCurrentName(reference.pointer, name.reference.pointer).check();
  }

  static final _getCurrentName = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getCurrentName")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract java.lang.String getCurrentName()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Alias of \#currentName().
  ///@return Name of the current field in the parsing context
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JString getCurrentName() {
    return _getCurrentName(reference.pointer).object(const jni.JStringType());
  }

  static final _currentName = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__currentName")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.String currentName()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be called to get the name associated with
  /// the current token: for JsonToken\#FIELD_NAMEs it will
  /// be the same as what \#getText returns;
  /// for field values it will be preceding field name;
  /// and for others (array values, root-level values) null.
  ///@return Name of the current field in the parsing context
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.10
  jni.JString currentName() {
    return _currentName(reference.pointer).object(const jni.JStringType());
  }

  static final _getText = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getText")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract java.lang.String getText()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for accessing textual representation of the current token;
  /// if no current token (before first call to \#nextToken, or
  /// after encountering end-of-input), returns null.
  /// Method can be called for any token type.
  ///@return Textual value associated with the current token (one returned
  ///   by \#nextToken() or other iteration methods)
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JString getText() {
    return _getText(reference.pointer).object(const jni.JStringType());
  }

  static final _getText1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__getText1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public int getText(java.io.Writer writer)
  ///
  /// Method to read the textual representation of the current token in chunks and
  /// pass it to the given Writer.
  /// Conceptually same as calling:
  ///<pre>
  ///  writer.write(parser.getText());
  ///</pre>
  /// but should typically be more efficient as longer content does need to
  /// be combined into a single <code>String</code> to return, and write
  /// can occur directly from intermediate buffers Jackson uses.
  ///@param writer Writer to write textual content to
  ///@return The number of characters written to the Writer
  ///@throws IOException for low-level read issues or writes using passed
  ///   {@code writer}, or
  ///   JsonParseException for decoding problems
  ///@since 2.8
  int getText1(
    jni.JObject writer,
  ) {
    return _getText1(reference.pointer, writer.reference.pointer).integer;
  }

  static final _getTextCharacters = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getTextCharacters")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract char[] getTextCharacters()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method similar to \#getText, but that will return
  /// underlying (unmodifiable) character array that contains
  /// textual value, instead of constructing a String object
  /// to contain this information.
  /// Note, however, that:
  ///<ul>
  /// <li>Textual contents are not guaranteed to start at
  ///   index 0 (rather, call \#getTextOffset) to
  ///   know the actual offset
  ///  </li>
  /// <li>Length of textual contents may be less than the
  ///  length of returned buffer: call \#getTextLength
  ///  for actual length of returned content.
  ///  </li>
  /// </ul>
  ///
  /// Note that caller __MUST NOT__ modify the returned
  /// character array in any way -- doing so may corrupt
  /// current parser state and render parser instance useless.
  ///
  /// The only reason to call this method (over \#getText)
  /// is to avoid construction of a String object (which
  /// will make a copy of contents).
  ///@return Buffer that contains the current textual value (but not necessarily
  ///    at offset 0, and not necessarily until the end of buffer)
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JArray<jni.jchar> getTextCharacters() {
    return _getTextCharacters(reference.pointer)
        .object(const jni.JArrayType(jni.jcharType()));
  }

  static final _getTextLength = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getTextLength")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract int getTextLength()
  ///
  /// Accessor used with \#getTextCharacters, to know length
  /// of String stored in returned buffer.
  ///@return Number of characters within buffer returned
  ///   by \#getTextCharacters that are part of
  ///   textual content of the current token.
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getTextLength() {
    return _getTextLength(reference.pointer).integer;
  }

  static final _getTextOffset = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getTextOffset")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract int getTextOffset()
  ///
  /// Accessor used with \#getTextCharacters, to know offset
  /// of the first text content character within buffer.
  ///@return Offset of the first character within buffer returned
  ///   by \#getTextCharacters that is part of
  ///   textual content of the current token.
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getTextOffset() {
    return _getTextOffset(reference.pointer).integer;
  }

  static final _hasTextCharacters = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__hasTextCharacters")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract boolean hasTextCharacters()
  ///
  /// Method that can be used to determine whether calling of
  /// \#getTextCharacters would be the most efficient
  /// way to access textual content for the event parser currently
  /// points to.
  ///
  /// Default implementation simply returns false since only actual
  /// implementation class has knowledge of its internal buffering
  /// state.
  /// Implementations are strongly encouraged to properly override
  /// this method, to allow efficient copying of content by other
  /// code.
  ///@return True if parser currently has character array that can
  ///   be efficiently returned via \#getTextCharacters; false
  ///   means that it may or may not exist
  bool hasTextCharacters() {
    return _hasTextCharacters(reference.pointer).boolean;
  }

  static final _getNumberValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getNumberValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract java.lang.Number getNumberValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Generic number value accessor method that will work for
  /// all kinds of numeric values. It will return the optimal
  /// (simplest/smallest possible) wrapper object that can
  /// express the numeric value just parsed.
  ///@return Numeric value of the current token in its most optimal
  ///   representation
  ///@throws IOException Problem with access: JsonParseException if
  ///    the current token is not numeric, or if decoding of the value fails
  ///    (invalid format for numbers); plain IOException if underlying
  ///    content read fails (possible if values are extracted lazily)
  jni.JNumber getNumberValue() {
    return _getNumberValue(reference.pointer).object(const jni.JNumberType());
  }

  static final _getNumberValueExact = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getNumberValueExact")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Number getNumberValueExact()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method similar to \#getNumberValue with the difference that
  /// for floating-point numbers value returned may be BigDecimal
  /// if the underlying format does not store floating-point numbers using
  /// native representation: for example, textual formats represent numbers
  /// as Strings (which are 10-based), and conversion to java.lang.Double
  /// is potentially lossy operation.
  ///
  /// Default implementation simply returns \#getNumberValue()
  ///@return Numeric value of the current token using most accurate representation
  ///@throws IOException Problem with access: JsonParseException if
  ///    the current token is not numeric, or if decoding of the value fails
  ///    (invalid format for numbers); plain IOException if underlying
  ///    content read fails (possible if values are extracted lazily)
  ///@since 2.12
  jni.JNumber getNumberValueExact() {
    return _getNumberValueExact(reference.pointer)
        .object(const jni.JNumberType());
  }

  static final _getNumberType = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getNumberType")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract com.fasterxml.jackson.core.JsonParser.NumberType getNumberType()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// If current token is of type
  /// JsonToken\#VALUE_NUMBER_INT or
  /// JsonToken\#VALUE_NUMBER_FLOAT, returns
  /// one of NumberType constants; otherwise returns null.
  ///@return Type of current number, if parser points to numeric token; {@code null} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  JsonParser_NumberType getNumberType() {
    return _getNumberType(reference.pointer)
        .object(const $JsonParser_NumberTypeType());
  }

  static final _getByteValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getByteValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public byte getByteValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_INT and
  /// it can be expressed as a value of Java byte primitive type.
  /// Note that in addition to "natural" input range of {@code [-128, 127]},
  /// this also allows "unsigned 8-bit byte" values {@code [128, 255]}:
  /// but for this range value will be translated by truncation, leading
  /// to sign change.
  ///
  /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
  /// if so, it is equivalent to calling \#getDoubleValue
  /// and then casting; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the resulting integer value falls outside range of
  /// {@code [-128, 255]},
  /// a InputCoercionException
  /// will be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code byte} (if numeric token within
  ///   range of {@code [-128, 255]}); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getByteValue() {
    return _getByteValue(reference.pointer).byte;
  }

  static final _getShortValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getShortValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public short getShortValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_INT and
  /// it can be expressed as a value of Java short primitive type.
  /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
  /// if so, it is equivalent to calling \#getDoubleValue
  /// and then casting; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the resulting integer value falls outside range of
  /// Java short, a InputCoercionException
  /// will be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code short} (if numeric token within
  ///   Java 16-bit signed {@code short} range); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getShortValue() {
    return _getShortValue(reference.pointer).short;
  }

  static final _getIntValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getIntValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract int getIntValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_INT and
  /// it can be expressed as a value of Java int primitive type.
  /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
  /// if so, it is equivalent to calling \#getDoubleValue
  /// and then casting; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the resulting integer value falls outside range of
  /// Java {@code int}, a InputCoercionException
  /// may be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code int} (if numeric token within
  ///   Java 32-bit signed {@code int} range); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getIntValue() {
    return _getIntValue(reference.pointer).integer;
  }

  static final _getLongValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getLongValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract long getLongValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_INT and
  /// it can be expressed as a Java long primitive type.
  /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
  /// if so, it is equivalent to calling \#getDoubleValue
  /// and then casting to int; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the token is an integer, but its value falls
  /// outside of range of Java long, a InputCoercionException
  /// may be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code long} (if numeric token within
  ///   Java 32-bit signed {@code long} range); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getLongValue() {
    return _getLongValue(reference.pointer).long;
  }

  static final _getBigIntegerValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getBigIntegerValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract java.math.BigInteger getBigIntegerValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_INT and
  /// it can not be used as a Java long primitive type due to its
  /// magnitude.
  /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
  /// if so, it is equivalent to calling \#getDecimalValue
  /// and then constructing a BigInteger from that value.
  ///@return Current number value as BigInteger (if numeric token);
  ///     otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JObject getBigIntegerValue() {
    return _getBigIntegerValue(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _getFloatValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getFloatValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract float getFloatValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_FLOAT and
  /// it can be expressed as a Java float primitive type.
  /// It can also be called for JsonToken\#VALUE_NUMBER_INT;
  /// if so, it is equivalent to calling \#getLongValue
  /// and then casting; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the value falls
  /// outside of range of Java float, a InputCoercionException
  /// will be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code float} (if numeric token within
  ///   Java {@code float} range); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  double getFloatValue() {
    return _getFloatValue(reference.pointer).float;
  }

  static final _getDoubleValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getDoubleValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract double getDoubleValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_FLOAT and
  /// it can be expressed as a Java double primitive type.
  /// It can also be called for JsonToken\#VALUE_NUMBER_INT;
  /// if so, it is equivalent to calling \#getLongValue
  /// and then casting; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the value falls
  /// outside of range of Java double, a InputCoercionException
  /// will be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code double} (if numeric token within
  ///   Java {@code double} range); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  double getDoubleValue() {
    return _getDoubleValue(reference.pointer).doubleFloat;
  }

  static final _getDecimalValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getDecimalValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public abstract java.math.BigDecimal getDecimalValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_FLOAT or
  /// JsonToken\#VALUE_NUMBER_INT. No under/overflow exceptions
  /// are ever thrown.
  ///@return Current number value as BigDecimal (if numeric token);
  ///   otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JObject getDecimalValue() {
    return _getDecimalValue(reference.pointer).object(const jni.JObjectType());
  }

  static final _getBooleanValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getBooleanValue")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean getBooleanValue()
  ///
  /// Convenience accessor that can be called when the current
  /// token is JsonToken\#VALUE_TRUE or
  /// JsonToken\#VALUE_FALSE, to return matching {@code boolean}
  /// value.
  /// If the current token is of some other type, JsonParseException
  /// will be thrown
  ///@return {@code True} if current token is {@code JsonToken.VALUE_TRUE},
  ///   {@code false} if current token is {@code JsonToken.VALUE_FALSE};
  ///   otherwise throws JsonParseException
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  bool getBooleanValue() {
    return _getBooleanValue(reference.pointer).boolean;
  }

  static final _getEmbeddedObject = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getEmbeddedObject")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Object getEmbeddedObject()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Accessor that can be called if (and only if) the current token
  /// is JsonToken\#VALUE_EMBEDDED_OBJECT. For other token types,
  /// null is returned.
  ///
  /// Note: only some specialized parser implementations support
  /// embedding of objects (usually ones that are facades on top
  /// of non-streaming sources, such as object trees). One exception
  /// is access to binary content (whether via base64 encoding or not)
  /// which typically is accessible using this method, as well as
  /// \#getBinaryValue().
  ///@return Embedded value (usually of "native" type supported by format)
  ///   for the current token, if any; {@code null otherwise}
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JObject getEmbeddedObject() {
    return _getEmbeddedObject(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _getBinaryValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__getBinaryValue")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract byte[] getBinaryValue(com.fasterxml.jackson.core.Base64Variant bv)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be used to read (and consume -- results
  /// may not be accessible using other methods after the call)
  /// base64-encoded binary data
  /// included in the current textual JSON value.
  /// It works similar to getting String value via \#getText
  /// and decoding result (except for decoding part),
  /// but should be significantly more performant.
  ///
  /// Note that non-decoded textual contents of the current token
  /// are not guaranteed to be accessible after this method
  /// is called. Current implementation, for example, clears up
  /// textual content during decoding.
  /// Decoded binary content, however, will be retained until
  /// parser is advanced to the next event.
  ///@param bv Expected variant of base64 encoded
  ///   content (see Base64Variants for definitions
  ///   of "standard" variants).
  ///@return Decoded binary data
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JArray<jni.jbyte> getBinaryValue(
    jni.JObject bv,
  ) {
    return _getBinaryValue(reference.pointer, bv.reference.pointer)
        .object(const jni.JArrayType(jni.jbyteType()));
  }

  static final _getBinaryValue1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getBinaryValue1")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public byte[] getBinaryValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Convenience alternative to \#getBinaryValue(Base64Variant)
  /// that defaults to using
  /// Base64Variants\#getDefaultVariant as the default encoding.
  ///@return Decoded binary data
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JArray<jni.jbyte> getBinaryValue1() {
    return _getBinaryValue1(reference.pointer)
        .object(const jni.JArrayType(jni.jbyteType()));
  }

  static final _readBinaryValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__readBinaryValue")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public int readBinaryValue(java.io.OutputStream out)
  ///
  /// Method that can be used as an alternative to \#getBigIntegerValue(),
  /// especially when value can be large. The main difference (beyond method
  /// of returning content using OutputStream instead of as byte array)
  /// is that content will NOT remain accessible after method returns: any content
  /// processed will be consumed and is not buffered in any way. If caller needs
  /// buffering, it has to implement it.
  ///@param out Output stream to use for passing decoded binary data
  ///@return Number of bytes that were decoded and written via OutputStream
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.1
  int readBinaryValue(
    jni.JObject out,
  ) {
    return _readBinaryValue(reference.pointer, out.reference.pointer).integer;
  }

  static final _readBinaryValue1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__readBinaryValue1")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public int readBinaryValue(com.fasterxml.jackson.core.Base64Variant bv, java.io.OutputStream out)
  ///
  /// Similar to \#readBinaryValue(OutputStream) but allows explicitly
  /// specifying base64 variant to use.
  ///@param bv base64 variant to use
  ///@param out Output stream to use for passing decoded binary data
  ///@return Number of bytes that were decoded and written via OutputStream
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.1
  int readBinaryValue1(
    jni.JObject bv,
    jni.JObject out,
  ) {
    return _readBinaryValue1(
            reference.pointer, bv.reference.pointer, out.reference.pointer)
        .integer;
  }

  static final _getValueAsInt = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getValueAsInt")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int getValueAsInt()
  ///
  /// Method that will try to convert value of current token to a
  /// Java {@code int} value.
  /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
  /// and 1 (true), and Strings are parsed using default Java language integer
  /// parsing rules.
  ///
  /// If representation can not be converted to an int (including structured type
  /// markers like start/end Object/Array)
  /// default value of __0__ will be returned; no exceptions are thrown.
  ///@return {@code int} value current token is converted to, if possible; exception thrown
  ///    otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getValueAsInt() {
    return _getValueAsInt(reference.pointer).integer;
  }

  static final _getValueAsInt1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("JsonParser__getValueAsInt1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public int getValueAsInt(int def)
  ///
  /// Method that will try to convert value of current token to a
  /// __int__.
  /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
  /// and 1 (true), and Strings are parsed using default Java language integer
  /// parsing rules.
  ///
  /// If representation can not be converted to an int (including structured type
  /// markers like start/end Object/Array)
  /// specified __def__ will be returned; no exceptions are thrown.
  ///@param def Default value to return if conversion to {@code int} is not possible
  ///@return {@code int} value current token is converted to, if possible; {@code def} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getValueAsInt1(
    int def,
  ) {
    return _getValueAsInt1(reference.pointer, def).integer;
  }

  static final _getValueAsLong = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getValueAsLong")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public long getValueAsLong()
  ///
  /// Method that will try to convert value of current token to a
  /// __long__.
  /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
  /// and 1 (true), and Strings are parsed using default Java language integer
  /// parsing rules.
  ///
  /// If representation can not be converted to a long (including structured type
  /// markers like start/end Object/Array)
  /// default value of __0L__ will be returned; no exceptions are thrown.
  ///@return {@code long} value current token is converted to, if possible; exception thrown
  ///    otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getValueAsLong() {
    return _getValueAsLong(reference.pointer).long;
  }

  static final _getValueAsLong1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int64)>>("JsonParser__getValueAsLong1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public long getValueAsLong(long def)
  ///
  /// Method that will try to convert value of current token to a
  /// __long__.
  /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
  /// and 1 (true), and Strings are parsed using default Java language integer
  /// parsing rules.
  ///
  /// If representation can not be converted to a long (including structured type
  /// markers like start/end Object/Array)
  /// specified __def__ will be returned; no exceptions are thrown.
  ///@param def Default value to return if conversion to {@code long} is not possible
  ///@return {@code long} value current token is converted to, if possible; {@code def} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getValueAsLong1(
    int def,
  ) {
    return _getValueAsLong1(reference.pointer, def).long;
  }

  static final _getValueAsDouble = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getValueAsDouble")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public double getValueAsDouble()
  ///
  /// Method that will try to convert value of current token to a Java
  /// __double__.
  /// Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
  /// and 1.0 (true), and Strings are parsed using default Java language floating
  /// point parsing rules.
  ///
  /// If representation can not be converted to a double (including structured types
  /// like Objects and Arrays),
  /// default value of __0.0__ will be returned; no exceptions are thrown.
  ///@return {@code double} value current token is converted to, if possible; exception thrown
  ///    otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  double getValueAsDouble() {
    return _getValueAsDouble(reference.pointer).doubleFloat;
  }

  static final _getValueAsDouble1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Double)>>("JsonParser__getValueAsDouble1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, double)>();

  /// from: public double getValueAsDouble(double def)
  ///
  /// Method that will try to convert value of current token to a
  /// Java __double__.
  /// Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
  /// and 1.0 (true), and Strings are parsed using default Java language floating
  /// point parsing rules.
  ///
  /// If representation can not be converted to a double (including structured types
  /// like Objects and Arrays),
  /// specified __def__ will be returned; no exceptions are thrown.
  ///@param def Default value to return if conversion to {@code double} is not possible
  ///@return {@code double} value current token is converted to, if possible; {@code def} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  double getValueAsDouble1(
    double def,
  ) {
    return _getValueAsDouble1(reference.pointer, def).doubleFloat;
  }

  static final _getValueAsBoolean = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getValueAsBoolean")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean getValueAsBoolean()
  ///
  /// Method that will try to convert value of current token to a
  /// __boolean__.
  /// JSON booleans map naturally; integer numbers other than 0 map to true, and
  /// 0 maps to false
  /// and Strings 'true' and 'false' map to corresponding values.
  ///
  /// If representation can not be converted to a boolean value (including structured types
  /// like Objects and Arrays),
  /// default value of __false__ will be returned; no exceptions are thrown.
  ///@return {@code boolean} value current token is converted to, if possible; exception thrown
  ///    otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  bool getValueAsBoolean() {
    return _getValueAsBoolean(reference.pointer).boolean;
  }

  static final _getValueAsBoolean1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Uint8)>>("JsonParser__getValueAsBoolean1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public boolean getValueAsBoolean(boolean def)
  ///
  /// Method that will try to convert value of current token to a
  /// __boolean__.
  /// JSON booleans map naturally; integer numbers other than 0 map to true, and
  /// 0 maps to false
  /// and Strings 'true' and 'false' map to corresponding values.
  ///
  /// If representation can not be converted to a boolean value (including structured types
  /// like Objects and Arrays),
  /// specified __def__ will be returned; no exceptions are thrown.
  ///@param def Default value to return if conversion to {@code boolean} is not possible
  ///@return {@code boolean} value current token is converted to, if possible; {@code def} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  bool getValueAsBoolean1(
    bool def,
  ) {
    return _getValueAsBoolean1(reference.pointer, def ? 1 : 0).boolean;
  }

  static final _getValueAsString = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getValueAsString")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.String getValueAsString()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that will try to convert value of current token to a
  /// java.lang.String.
  /// JSON Strings map naturally; scalar values get converted to
  /// their textual representation.
  /// If representation can not be converted to a String value (including structured types
  /// like Objects and Arrays and {@code null} token), default value of
  /// __null__ will be returned; no exceptions are thrown.
  ///@return String value current token is converted to, if possible; {@code null} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.1
  jni.JString getValueAsString() {
    return _getValueAsString(reference.pointer).object(const jni.JStringType());
  }

  static final _getValueAsString1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__getValueAsString1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public abstract java.lang.String getValueAsString(java.lang.String def)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that will try to convert value of current token to a
  /// java.lang.String.
  /// JSON Strings map naturally; scalar values get converted to
  /// their textual representation.
  /// If representation can not be converted to a String value (including structured types
  /// like Objects and Arrays and {@code null} token), specified default value
  /// will be returned; no exceptions are thrown.
  ///@param def Default value to return if conversion to {@code String} is not possible
  ///@return String value current token is converted to, if possible; {@code def} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.1
  jni.JString getValueAsString1(
    jni.JString def,
  ) {
    return _getValueAsString1(reference.pointer, def.reference.pointer)
        .object(const jni.JStringType());
  }

  static final _canReadObjectId = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__canReadObjectId")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean canReadObjectId()
  ///
  /// Introspection method that may be called to see if the underlying
  /// data format supports some kind of Object Ids natively (many do not;
  /// for example, JSON doesn't).
  ///
  /// Default implementation returns true; overridden by data formats
  /// that do support native Object Ids. Caller is expected to either
  /// use a non-native notation (explicit property or such), or fail,
  /// in case it can not use native object ids.
  ///@return {@code True} if the format being read supports native Object Ids;
  ///    {@code false} if not
  ///@since 2.3
  bool canReadObjectId() {
    return _canReadObjectId(reference.pointer).boolean;
  }

  static final _canReadTypeId = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__canReadTypeId")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean canReadTypeId()
  ///
  /// Introspection method that may be called to see if the underlying
  /// data format supports some kind of Type Ids natively (many do not;
  /// for example, JSON doesn't).
  ///
  /// Default implementation returns true; overridden by data formats
  /// that do support native Type Ids. Caller is expected to either
  /// use a non-native notation (explicit property or such), or fail,
  /// in case it can not use native type ids.
  ///@return {@code True} if the format being read supports native Type Ids;
  ///    {@code false} if not
  ///@since 2.3
  bool canReadTypeId() {
    return _canReadTypeId(reference.pointer).boolean;
  }

  static final _getObjectId = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getObjectId")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Object getObjectId()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be called to check whether current token
  /// (one that was just read) has an associated Object id, and if
  /// so, return it.
  /// Note that while typically caller should check with \#canReadObjectId
  /// first, it is not illegal to call this method even if that method returns
  /// true; but if so, it will return null. This may be used to simplify calling
  /// code.
  ///
  /// Default implementation will simply return null.
  ///@return Native Object id associated with the current token, if any; {@code null} if none
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.3
  jni.JObject getObjectId() {
    return _getObjectId(reference.pointer).object(const jni.JObjectType());
  }

  static final _getTypeId = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__getTypeId")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Object getTypeId()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be called to check whether current token
  /// (one that was just read) has an associated type id, and if
  /// so, return it.
  /// Note that while typically caller should check with \#canReadTypeId
  /// first, it is not illegal to call this method even if that method returns
  /// true; but if so, it will return null. This may be used to simplify calling
  /// code.
  ///
  /// Default implementation will simply return null.
  ///@return Native Type Id associated with the current token, if any; {@code null} if none
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.3
  jni.JObject getTypeId() {
    return _getTypeId(reference.pointer).object(const jni.JObjectType());
  }

  static final _readValueAs = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__readValueAs")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public T readValueAs(java.lang.Class<T> valueType)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method to deserialize JSON content into a non-container
  /// type (it can be an array type, however): typically a bean, array
  /// or a wrapper type (like java.lang.Boolean).
  /// __Note__: method can only be called if the parser has
  /// an object codec assigned; this is true for parsers constructed
  /// by <code>MappingJsonFactory</code> (from "jackson-databind" jar)
  /// but not for JsonFactory (unless its <code>setCodec</code>
  /// method has been explicitly called).
  ///
  /// This method may advance the event stream, for structured types
  /// the current token will be the closing end marker (END_ARRAY,
  /// END_OBJECT) of the bound structure. For non-structured Json types
  /// (and for JsonToken\#VALUE_EMBEDDED_OBJECT)
  /// stream is not advanced.
  ///
  /// Note: this method should NOT be used if the result type is a
  /// container (java.util.Collection or java.util.Map.
  /// The reason is that due to type erasure, key and value types
  /// can not be introspected when using this method.
  ///@param <T> Nominal type parameter for value type
  ///@param valueType Java type to read content as (passed to ObjectCodec that
  ///    deserializes content)
  ///@return Java value read from content
  ///@throws IOException if there is either an underlying I/O problem or decoding
  ///    issue at format layer
  $T readValueAs<$T extends jni.JObject>(
    jni.JObject valueType, {
    required jni.JObjType<$T> T,
  }) {
    return _readValueAs(reference.pointer, valueType.reference.pointer)
        .object(T);
  }

  static final _readValueAs1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__readValueAs1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public T readValueAs(com.fasterxml.jackson.core.type.TypeReference<?> valueTypeRef)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method to deserialize JSON content into a Java type, reference
  /// to which is passed as argument. Type is passed using so-called
  /// "super type token"
  /// and specifically needs to be used if the root type is a
  /// parameterized (generic) container type.
  /// __Note__: method can only be called if the parser has
  /// an object codec assigned; this is true for parsers constructed
  /// by <code>MappingJsonFactory</code> (defined in 'jackson-databind' bundle)
  /// but not for JsonFactory (unless its <code>setCodec</code>
  /// method has been explicitly called).
  ///
  /// This method may advance the event stream, for structured types
  /// the current token will be the closing end marker (END_ARRAY,
  /// END_OBJECT) of the bound structure. For non-structured Json types
  /// (and for JsonToken\#VALUE_EMBEDDED_OBJECT)
  /// stream is not advanced.
  ///@param <T> Nominal type parameter for value type
  ///@param valueTypeRef Java type to read content as (passed to ObjectCodec that
  ///    deserializes content)
  ///@return Java value read from content
  ///@throws IOException if there is either an underlying I/O problem or decoding
  ///    issue at format layer
  $T readValueAs1<$T extends jni.JObject>(
    jni.JObject valueTypeRef, {
    required jni.JObjType<$T> T,
  }) {
    return _readValueAs1(reference.pointer, valueTypeRef.reference.pointer)
        .object(T);
  }

  static final _readValuesAs = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__readValuesAs")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public java.util.Iterator<T> readValuesAs(java.lang.Class<T> valueType)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for reading sequence of Objects from parser stream,
  /// all with same specified value type.
  ///@param <T> Nominal type parameter for value type
  ///@param valueType Java type to read content as (passed to ObjectCodec that
  ///    deserializes content)
  ///@return Iterator for reading multiple Java values from content
  ///@throws IOException if there is either an underlying I/O problem or decoding
  ///    issue at format layer
  jni.JIterator<$T> readValuesAs<$T extends jni.JObject>(
    jni.JObject valueType, {
    required jni.JObjType<$T> T,
  }) {
    return _readValuesAs(reference.pointer, valueType.reference.pointer)
        .object(jni.JIteratorType(T));
  }

  static final _readValuesAs1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonParser__readValuesAs1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public java.util.Iterator<T> readValuesAs(com.fasterxml.jackson.core.type.TypeReference<T> valueTypeRef)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for reading sequence of Objects from parser stream,
  /// all with same specified value type.
  ///@param <T> Nominal type parameter for value type
  ///@param valueTypeRef Java type to read content as (passed to ObjectCodec that
  ///    deserializes content)
  ///@return Iterator for reading multiple Java values from content
  ///@throws IOException if there is either an underlying I/O problem or decoding
  ///    issue at format layer
  jni.JIterator<$T> readValuesAs1<$T extends jni.JObject>(
    jni.JObject valueTypeRef, {
    required jni.JObjType<$T> T,
  }) {
    return _readValuesAs1(reference.pointer, valueTypeRef.reference.pointer)
        .object(jni.JIteratorType(T));
  }

  static final _readValueAsTree = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonParser__readValueAsTree")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public T readValueAsTree()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method to deserialize JSON content into equivalent "tree model",
  /// represented by root TreeNode of resulting model.
  /// For JSON Arrays it will an array node (with child nodes),
  /// for objects object node (with child nodes), and for other types
  /// matching leaf node type. Empty or whitespace documents are null.
  ///@param <T> Nominal type parameter for result node type (to reduce need for casting)
  ///@return root of the document, or null if empty or whitespace.
  ///@throws IOException if there is either an underlying I/O problem or decoding
  ///    issue at format layer
  $T readValueAsTree<$T extends jni.JObject>({
    required jni.JObjType<$T> T,
  }) {
    return _readValueAsTree(reference.pointer).object(T);
  }
}

final class $JsonParserType extends jni.JObjType<JsonParser> {
  const $JsonParserType();

  @override
  String get signature => r"Lcom/fasterxml/jackson/core/JsonParser;";

  @override
  JsonParser fromReference(jni.JReference reference) =>
      JsonParser.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($JsonParserType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($JsonParserType) && other is $JsonParserType;
  }
}
