internal object GetValueMatch(Type valueType, int level, Info valueInfo) { if (level > Cache.Limits) { throw new PacketException(PacketError.RecursiveError); } level += 1; switch (valueInfo.To) { case Info.Reader: return(this); case Info.RawReader: return(new PacketRawReader(this)); case Info.Collection: { var inf = Cache.GetConverterOrInfo(converters, valueInfo.ElementType, out var con); if (inf == null) { return(valueInfo.ToCollection(this, con)); } var lst = GetList(); var len = lst.Count; var arr = new object[len]; for (int i = 0; i < len; i++) { arr[i] = lst[i].GetValueMatch(valueInfo.ElementType, level, inf); } var res = valueInfo.ToCollectionCast(arr); return(res); } case Info.Enumerable: { var inf = Cache.GetConverterOrInfo(converters, valueInfo.ElementType, out var con); if (inf == null) { return(valueInfo.ToEnumerable(this, con)); } return(valueInfo.ToEnumerableAdapter(this, level, inf)); } case Info.Dictionary: { var keycon = Cache.GetConverter(converters, valueInfo.IndexType, true); if (keycon == null) { throw PacketException.InvalidKeyType(valueType); } var inf = Cache.GetConverterOrInfo(converters, valueInfo.ElementType, out var con); if (inf == null) { return(valueInfo.ToDictionary(this, keycon, con)); } var max = element.Max; var idx = element.offset; var buf = element.buffer; var keylen = keycon.Length; var len = 0; var lst = new List <object>(); while (true) { var res = max - idx; if (res == 0) { break; } if (keylen > 0) { if (res < keylen) { goto fail; } else { len = keylen; } } else if (buf.MoveNext(max, ref idx, out len) == false) { goto fail; } // Wrap error non-check var key = keycon.GetValueWrap(buf, idx, len); idx += len; if (buf.MoveNext(max, ref idx, out len) == false) { goto fail; } var rea = new PacketReader(buf, idx, len, converters); var val = rea.GetValueMatch(valueInfo.ElementType, level, inf); idx += len; lst.Add(key); lst.Add(val); } return(valueInfo.ToDictionaryCast(lst)); fail: throw PacketException.Overflow(); } default: { var set = Cache.GetSetInfo(valueType); if (set == null) { throw PacketException.InvalidType(valueType); } var arg = set.Arguments; var arr = new object[arg.Length]; for (int i = 0; i < arg.Length; i++) { var rea = GetItem(arg[i].Key, false); var val = rea.GetValue(arg[i].Value, level); arr[i] = val; } var res = set.GetObject(arr); return(res); } } }
private static Item GetItemMatch(ConverterDictionary converters, object value, int level, Info valueInfo) { if (level > Cache.Limits) { throw new PacketException(PacketError.RecursiveError); } level += 1; switch (valueInfo.From) { case Info.Writer: return(((PacketWriter)value).item); case Info.RawWriter: return(new Item(((PacketRawWriter)value).stream)); case Info.Bytes: return(new Item(((ICollection <byte>)value).ToBytes())); case Info.SBytes: return(new Item(((ICollection <sbyte>)value).ToBytes())); case Info.Enumerable: { var ele = valueInfo.ElementType; var inf = Cache.GetConverterOrInfo(converters, ele, out var con); if (inf == null) { return(new Item(valueInfo.FromEnumerable(con, value), con.Length)); } var lst = new List <Item>(); foreach (var i in ((IEnumerable)value)) { lst.Add(GetItemMatch(converters, i, level, inf)); } return(new Item(lst)); } case Info.Dictionary: { var key = Cache.GetConverter(converters, valueInfo.IndexType, true); if (key == null) { throw PacketException.InvalidKeyType(valueInfo.IndexType); } var ele = valueInfo.ElementType; var inf = Cache.GetConverterOrInfo(converters, ele, out var con); if (inf == null) { return(new Item(valueInfo.FromDictionary(key, con, value), key.Length, con.Length)); } var lst = new List <KeyValuePair <byte[], Item> >(); var kvp = valueInfo.FromDictionaryAdapter(key, value); foreach (var i in kvp) { var res = GetItemMatch(converters, i.Value, level, inf); var tmp = new KeyValuePair <byte[], Item>(i.Key, res); lst.Add(tmp); } return(new Item(lst, key.Length)); } case Info.Map: { var dic = (IDictionary <string, object>)value; var lst = new Dictionary <string, PacketWriter>(); foreach (var i in dic) { lst[i.Key] = GetWriter(converters, i.Value, level); } return(new Item(lst)); } default: { var lst = new Dictionary <string, PacketWriter>(); var get = Cache.GetGetInfo(valueInfo.Type); var val = get.GetValues(value); var arg = get.Arguments; for (int i = 0; i < arg.Length; i++) { lst[arg[i].Key] = GetWriter(converters, val[i], level); } return(new Item(lst)); } } }