package com.fasterxml.jackson.dataformat.protobuf;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.io.CharTypes;
import com.fasterxml.jackson.core.io.ContentReference;
import com.fasterxml.jackson.dataformat.protobuf.schema.ProtobufField;
import com.fasterxml.jackson.dataformat.protobuf.schema.ProtobufMessage;
Replacement of JsonReadContext
to support features needed to decode nested Protobuf messages. /**
* Replacement of {@link com.fasterxml.jackson.core.json.JsonReadContext}
* to support features needed to decode nested Protobuf messages.
*/
public final class ProtobufReadContext
extends JsonStreamContext
{
Parent context for this context; null for root context.
/**
* Parent context for this context; null for root context.
*/
protected final ProtobufReadContext _parent;
Type of current context.
/**
* Type of current context.
*/
protected ProtobufMessage _messageType;
For array contexts: field that defines type of array values.
/**
* For array contexts: field that defines type of array values.
*/
protected ProtobufField _field;
protected String _currentName;
Since: 2.9
/**
* @since 2.9
*/
protected Object _currentValue;
Offset within input buffer where the message represented
by this context (if message context) ends.
/**
* Offset within input buffer where the message represented
* by this context (if message context) ends.
*/
protected int _endOffset;
/*
/**********************************************************
/* Simple instance reuse slots
/**********************************************************
*/
protected ProtobufReadContext _child = null;
/*
/**********************************************************
/* Instance construction, reuse
/**********************************************************
*/
public ProtobufReadContext(ProtobufReadContext parent,
ProtobufMessage messageType, int type, int endOffset)
{
super();
_parent = parent;
_messageType = messageType;
_type = type;
_endOffset = endOffset;
_index = -1;
}
protected void reset(ProtobufMessage messageType, int type, int endOffset)
{
_messageType = messageType;
_type = type;
_index = -1;
_currentName = null;
_currentValue = null;
_endOffset = endOffset;
}
@Override
public Object getCurrentValue() {
return _currentValue;
}
@Override
public void setCurrentValue(Object v) {
_currentValue = v;
}
// // // Factory methods
public static ProtobufReadContext createRootContext() {
return new ProtobufReadContext(null, null, TYPE_ROOT, Integer.MAX_VALUE);
}
public ProtobufReadContext createChildArrayContext(ProtobufField f)
{
_field = f;
ProtobufReadContext ctxt = _child;
if (ctxt == null) {
_child = ctxt = new ProtobufReadContext(this, _messageType,
TYPE_ARRAY, _endOffset);
} else {
ctxt.reset(_messageType, TYPE_ARRAY, _endOffset);
}
return ctxt;
}
public ProtobufReadContext createChildArrayContext(ProtobufField f, int endOffset)
{
_field = f;
ProtobufReadContext ctxt = _child;
if (ctxt == null) {
_child = ctxt = new ProtobufReadContext(this, _messageType,
TYPE_ARRAY, 0);
} else {
ctxt.reset(_messageType, TYPE_ARRAY, endOffset);
}
ctxt._field = f;
return ctxt;
}
public ProtobufReadContext createChildObjectContext(ProtobufMessage messageType,
ProtobufField f, int endOffset)
{
_field = f;
ProtobufReadContext ctxt = _child;
if (ctxt == null) {
_child = ctxt = new ProtobufReadContext(this, messageType,
TYPE_OBJECT, endOffset);
return ctxt;
}
ctxt.reset(messageType, TYPE_OBJECT, endOffset);
return ctxt;
}
/*
/**********************************************************
/* Abstract method implementations
/**********************************************************
*/
@Override
public String getCurrentName() { return _currentName; }
@Override
public ProtobufReadContext getParent() { return _parent; }
/*
/**********************************************************
/* Extended API
/**********************************************************
*/
Method called when loading more input, or moving existing data;
this requires adjusting relative end offset as well, except for
root context.
/**
* Method called when loading more input, or moving existing data;
* this requires adjusting relative end offset as well, except for
* root context.
*/
public int adjustEnd(int bytesConsumed) {
if (_type == TYPE_ROOT) {
return _endOffset;
}
int newOffset = _endOffset - bytesConsumed;
_endOffset = newOffset;
for (ProtobufReadContext ctxt = _parent; ctxt != null; ctxt = ctxt.getParent()) {
ctxt._adjustEnd(bytesConsumed);
}
// could do sanity check here; but caller should catch it
return newOffset;
}
private void _adjustEnd(int bytesConsumed) {
if (_type != TYPE_ROOT) {
_endOffset -= bytesConsumed;
}
}
public int getEndOffset() { return _endOffset; }
public ProtobufMessage getMessageType() { return _messageType; }
public ProtobufField getField() { return _field; }
public void setMessageType(ProtobufMessage mt) { _messageType = mt; }
Returns: Location pointing to the point where the context
start marker was found
/**
* @return Location pointing to the point where the context
* start marker was found
*/
public JsonLocation startLocation(ContentReference srcRef, long byteOffset) {
// not much we can tell
return new JsonLocation(srcRef, byteOffset, -1, -1);
}
/*
/**********************************************************
/* State changes
/**********************************************************
*/
public void setCurrentName(String name) {
_currentName = name;
}
/*
/**********************************************************
/* Overridden standard methods
/**********************************************************
*/
Overridden to provide developer readable "JsonPath" representation
of the context.
/**
* Overridden to provide developer readable "JsonPath" representation
* of the context.
*/
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(64);
switch (_type) {
case TYPE_ROOT:
sb.append("/");
break;
case TYPE_ARRAY:
sb.append('[');
sb.append(getCurrentIndex());
sb.append(']');
break;
case TYPE_OBJECT:
sb.append('{');
if (_currentName != null) {
sb.append('"');
CharTypes.appendQuoted(sb, _currentName);
sb.append('"');
} else {
sb.append('?');
}
sb.append('}');
break;
}
return sb.toString();
}
}