private void _moveNext()
{
if(_stack.Count == 0)
{
_state = new SchemaState(PrimitiveSchema.EOF, 255, -1);
return;
}
var parent = _stack.Pop();
if (parent.Schema.Type == Types.ValueType.Option)
{
// we skip option states on the way back up
_moveNext();
}
else if (parent.Schema.Type == Types.ValueType.Sequence)
{
var sequence = (SequenceSchema)parent.Schema;
var newParent = new SchemaState(sequence, parent.Tag, parent.Index + 1);
if (newParent.Index == sequence.Fields.Length)
{
// we have read all of fields
_state = newParent;
}
else
{
// we still have at least 1 field to read
_stack.Push(newParent);
var field = sequence.Fields[newParent.Index];
_state = new SchemaState(field.Type, field.Tag, -1);
}
}
else if (parent.Schema.Type == Types.ValueType.Choice)
{
var choice = (ChoiceSchema)parent.Schema;
_state = new SchemaState(choice, parent.Tag, choice.Fields.Length);
}
else if (parent.Schema.Type == Types.ValueType.Array)
{
var array = (ArraySchema)parent.Schema;
// TODO: Might still need better logic for detecting
// whether we are at the end of the array
if (_reader.EOF())
{
_state = new SchemaState(array, parent.Tag, parent.Index + 1);
}
else if (array.ElementType == PrimitiveSchema.GenericSchema)
{
if (_reader.AtTag(parent.Tag, ApplicationTag.Null))
{
_state = new SchemaState(array, parent.Tag, parent.Index + 1);
}
else
{
var newParent = new SchemaState(array, parent.Tag, parent.Index + 1);
_stack.Push(newParent);
_state = new SchemaState(array.ElementType, 255, -1);
}
}
else
{
var elementExpected = Utils.GetExpectedTag(255, array.ElementType);
if (_reader.AtTag(elementExpected.ContextTag, elementExpected.ApplicationTag))
{
var newParent = new SchemaState(array, parent.Tag, parent.Index + 1);
_stack.Push(newParent);
_state = new SchemaState(array.ElementType, 255, -1);
}
else
{
_state = new SchemaState(array, parent.Tag, parent.Index + 1);
}
}
}
else
throw new Exception("unknown parent schema state, can't move next");
}