Add one more puzzle-piece for async parsing api
diff --git a/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java b/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java
new file mode 100644
index 0000000..6c67e26
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParser.java
@@ -0,0 +1,220 @@
+package com.fasterxml.jackson.core.json.async;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.core.async.ByteArrayFeeder;
+import com.fasterxml.jackson.core.async.NonBlockingInputFeeder;
+import com.fasterxml.jackson.core.io.IOContext;
+import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer;
+import com.fasterxml.jackson.core.util.VersionUtil;
+
+public class NonBlockingJsonParser
+    extends NonBlockingJsonParserBase
+    implements ByteArrayFeeder
+{
+    /*
+    /**********************************************************************
+    /* Input source config
+    /**********************************************************************
+     */
+
+    /**
+     * This buffer is actually provided via {@link NonBlockingInputFeeder}
+     */
+    protected byte[] _inputBuffer = NO_BYTES;
+
+    /**
+     * In addition to current buffer pointer, and end pointer,
+     * we will also need to know number of bytes originally
+     * contained. This is needed to correctly update location
+     * information when the block has been completed.
+     */
+    protected int _origBufferLen;
+
+    // And from ParserBase:
+//  protected int _inputPtr;
+//  protected int _inputEnd;
+
+    /*
+    /**********************************************************************
+    /* Life-cycle
+    /**********************************************************************
+     */
+
+    public NonBlockingJsonParser(IOContext ctxt, int parserFeatures,
+            ByteQuadsCanonicalizer sym)
+    {
+        super(ctxt, parserFeatures, sym);
+    }
+
+    /*
+    /**********************************************************************
+    /* AsyncInputFeeder impl
+    /**********************************************************************
+     */
+
+    @Override
+    public ByteArrayFeeder getNonBlockingInputFeeder() {
+        return this;
+    }
+
+    @Override
+    public final boolean needMoreInput() {
+        return (_inputPtr >=_inputEnd) && !_endOfInput;
+    }
+
+    @Override
+    public void feedInput(byte[] buf, int start, int end) throws IOException
+    {
+        // Must not have remaining input
+        if (_inputPtr < _inputEnd) {
+            _reportError("Still have %d undecoded bytes, should not call 'feedInput'", _inputEnd - _inputPtr);
+        }
+        if (end < start) {
+            _reportError("Input end (%d) may not be before start (%d)", end, start);
+        }
+        // and shouldn't have been marked as end-of-input
+        if (_endOfInput) {
+            _reportError("Already closed, can not feed more input");
+        }
+        // Time to update pointers first
+        _currInputProcessed += _origBufferLen;
+
+        // And then update buffer settings
+        _inputBuffer = buf;
+        _inputPtr = start;
+        _inputEnd = end;
+        _origBufferLen = end - start;
+    }
+
+    @Override
+    public void endOfInput() {
+        _endOfInput = true;
+    }
+
+    /*
+    /**********************************************************************
+    /* Abstract methods/overrides from JsonParser
+    /**********************************************************************
+     */
+
+    /* Implementing these methods efficiently for non-blocking cases would
+     * be complicated; so for now let's just use the default non-optimized
+     * implementation
+     */
+
+//    public boolean nextFieldName(SerializableString str) throws IOException
+//    public String nextTextValue() throws IOException
+//    public int nextIntValue(int defaultValue) throws IOException
+//    public long nextLongValue(long defaultValue) throws IOException
+//    public Boolean nextBooleanValue() throws IOException
+
+    @Override
+    public int releaseBuffered(OutputStream out) throws IOException {
+        int avail = _inputEnd - _inputPtr;
+        if (avail > 0) {
+            out.write(_inputBuffer, _inputPtr, avail);
+        }
+        return avail;
+    }
+    
+    /*
+    /**********************************************************************
+    /* Main-level decoding
+    /**********************************************************************
+     */
+
+    @Override
+    public JsonToken nextToken() throws IOException
+    {
+        // First: regardless of where we really are, need at least one more byte;
+        // can simplify some of the checks by short-circuiting right away
+        if (_inputPtr >= _inputEnd) {
+            if (_closed) {
+                return null;
+            }
+            // note: if so, do not even bother changing state
+            if (_endOfInput) { // except for this special case
+                return _eofAsNextToken();
+            }
+            return JsonToken.NOT_AVAILABLE;
+        }
+        // in the middle of tokenization?
+        if (_currToken == JsonToken.NOT_AVAILABLE) {
+            return _finishToken();
+        }
+
+        // No: fresh new token; may or may not have existing one
+        _numTypesValid = NR_UNKNOWN;
+//            _tokenInputTotal = _currInputProcessed + _inputPtr;
+        // also: clear any data retained so far
+        _binaryValue = null;
+        int ch = _inputBuffer[_inputPtr++];
+
+        switch (_majorState) {
+        case MAJOR_INITIAL:
+            // TODO: Bootstrapping? BOM?
+
+        case MAJOR_ROOT:
+            return _startValue(ch);
+
+        case MAJOR_OBJECT_FIELD: // field or end-object
+            // expect name
+            return _startFieldName(ch);
+            
+        case MAJOR_OBJECT_VALUE:
+        case MAJOR_ARRAY_ELEMENT: // element or end-array
+            return _startValue(ch);
+
+        default:
+        }
+        VersionUtil.throwInternal();
+        return null;
+    }
+
+    /**
+     * Method called when a (scalar) value type has been detected, but not all of
+     * contents have been decoded due to incomplete input available.
+     */
+    protected final JsonToken _finishToken() throws IOException
+    {
+        // NOTE: caller ensures availability of at least one byte
+
+        switch (_minorState) {
+        }
+        return null;
+    }
+
+    /*
+    /**********************************************************************
+    /* Second-level decoding, root level
+    /**********************************************************************
+     */
+
+    /**
+     * Helper method called to detect type of a value token (at any level), and possibly
+     * decode it if contained in input buffer.
+     * Note that possible header has been ruled out by caller and is not checked here.
+     */
+    private final JsonToken _startValue(int ch) throws IOException
+    {
+        return null;
+    }
+
+    /*
+    /**********************************************************************
+    /* Second-level decoding, Name decoding
+    /**********************************************************************
+     */
+
+    /**
+     * Method that handles initial token type recognition for token
+     * that has to be either FIELD_NAME or END_OBJECT.
+     */
+    protected final JsonToken _startFieldName(int ch) throws IOException
+    {
+        return null;
+    }
+}