// public static StateMap<T> Deserialize(IReader reader, Path? path = null) { public static StateMap <T> Deserialize(IReader reader, Path path = null) { // path ??= Path.Root; path = path ?? Path.Root; var entries = new Dictionary <UInt32, T>(); while (!reader.EndOfStream()) { var tag = reader.ReadUInt32(); entries[tag] = reader.ReadValue <T>(path, tag); } return(new StateMap <T>(path, entries)); }
// public static StateList<T> Deserialize(IReader reader, Path? path = null) { public static StateList <T> Deserialize(IReader reader, Path path = null) { // path ??= Path.Root; path = path ?? Path.Root; var items = new List <T>(); var tag = 0U; while (!reader.EndOfStream()) { items.Add(reader.ReadValue <T>(path, tag++)); } return(new StateList <T>(path, items)); }
// public static Vector<T> Deserialize(IReader reader, Path? path = null) { public static Vector <T> Deserialize(IReader reader, Path path = null) { // path ??= Path.Root; path = path ?? Path.Root; var items = new List <T>(); var tag = 0U; while (!reader.EndOfStream()) { // Though Vector doesn't support nested states, passing tags to its children is still helpful. items.Add(reader.ReadValue <T>(path, tag++)); } return(new Vector <T>(path, items)); }
// public static StateMap<T> Deserialize(IReader reader, Path? path = null) { public static StateMap <T> Deserialize(IReader reader, Path path = null) { // path ??= Path.Root; path = path ?? Path.Root; var entries = new Dictionary <UInt32, T>(); while (!reader.EndOfStream()) { var tag = reader.ReadKey().Tag; // TODO: Wire type should be considered here. entries[tag] = reader.ReadValue <T>(path, tag); } return(new StateMap <T>(path, entries)); }
public static void Replace(this IState state, IReader reader, bool shouldNotify = true) { if (state is IEnumState) { var variant = reader.ReadUInt32(); state.ReplaceAt(variant, WireType.Sized, reader, shouldNotify); return; } while (!reader.EndOfStream()) { var(tag, wireType) = reader.ReadKey(); var expectedWireType = state.GetWireType(tag); var fieldReader = wireType == WireType.Sized ? reader.GetNested() : reader; // `expectedWireType` being `null` means that `state` either: // (1) doesn't recognize this field; // (2) has no clear expectation for the field's wire type (e.g. there are multiple valid wire types); or // (3) doesn't support update operations. // // An exception is expected to be thrown in case (3). // So, if we skip the field here, that would cause an exception leak // and make the program continue functioning with undefined behavior. // // That's why we leave to `state.ReplaceAt()` to handle instead, // since `state` knows best which case will happen. // // `state.ReplaceAt()` will then handle the cases as below: // * Case (1): It skips the unrecognized field. // * Case (2) or when wire types match: It reads the field based on passed `wireType`. // * Case (3): It throws an exception. // // On the other hand, if `expectedWireType` is clearly defined but doesn't match with `wireType`, // we don't hesitate to skip the field right here. if (expectedWireType != null && wireType != expectedWireType) { var path = state.Path.GetNested(tag); Console.Error.WriteLine("Expected wire type {0} for path {1}, got {2}.", expectedWireType, path, wireType); fieldReader.SkipField(wireType); continue; } state.ReplaceAt(tag, wireType, fieldReader, shouldNotify); } }