private static KeyValuePair<RecordKey, RecordUpdate> _decodeRecordFromBlock(BlockAccessor rs)
{
// ..we are ASSUMING that the records starts right here in the stream, it better be true!
// ..TODO: considering adding two separate record start/end markers
// Accumulate the key.
List<byte> keydata = new List<byte>();
bool keydone = false;
while (rs.Position < rs.Length && !keydone) {
byte c = (byte)rs.ReadByte();
switch (c) {
case SegmentBlockBasicEncoder.END_OF_LINE: // end of line
throw new Exception("reached end of line before keyvalue delimiter");
case SegmentBlockBasicEncoder.KEY_VAL_SEP: // key value delimiter
keydone = true;
break;
case SegmentBlockBasicEncoder.ESCAPE_CHAR:
byte nc = (byte)rs.ReadByte();
byte unescaped = (byte)(nc + (byte)SegmentBlockBasicEncoder.ESCAPE_OFFSET);
if (unescaped < SegmentBlockBasicEncoder.FIRST_SPECIAL || unescaped > SegmentBlockBasicEncoder.LAST_SPECIAL) {
throw new Exception("unhandled escape payload 1: " + ((int)nc).ToString());
}
keydata.Add(unescaped);
break;
default:
keydata.Add(c);
break;
}
}
if (!keydone) { throw new Exception("reached end of buffer before keydone!"); }
// accumulate the value
List<byte> valuedata = new List<byte>();
bool valuedone = false;
while (rs.Position < rs.Length && !valuedone) {
byte c = (byte)rs.ReadByte();
switch (c) {
case SegmentBlockBasicEncoder.END_OF_LINE: // end of line
valuedone = true;
break;
case SegmentBlockBasicEncoder.KEY_VAL_SEP: // key value delimiter
throw new Exception("found keyvalue delimiter in value");
case SegmentBlockBasicEncoder.ESCAPE_CHAR:
byte nc = (byte)rs.ReadByte();
byte unescaped = (byte)(nc + SegmentBlockBasicEncoder.ESCAPE_OFFSET);
if (unescaped < SegmentBlockBasicEncoder.FIRST_SPECIAL || unescaped > SegmentBlockBasicEncoder.LAST_SPECIAL) {
throw new Exception("unhandled escape sequence 2: " + unescaped.ToString());
}
valuedata.Add(unescaped);
break;
default:
valuedata.Add(c);
break;
}
}
if (valuedone != true) {
throw new Exception("SegmentBlockBasicDecoder: finished record without reaching END_OF_LINE");
}
RecordKey key = new RecordKey(keydata.ToArray());
RecordUpdate value = RecordUpdate.FromEncodedData(valuedata.ToArray());
// Debug.WriteLine("scanning " + key.ToString() + " : " + value.ToString());
return new KeyValuePair<RecordKey, RecordUpdate>(key, value);
}