Beispiel #1
0
        public static bool TryParseInfo(BEnc enc, out TorrentFile?file)
        {
            file = default;

            if (!(enc is BDict d))
            {
                return(false);
            }
            var len = d["length"];

            if (len == null)
            {
                return(false);
            }

            if (!(len is BInt lenI))
            {
                return(false);
            }

            var pth = d["path"];

            if (pth == null)
            {
                return(false);
            }

            if (!(pth is BLst pl) || pl.Value.Any(x => !(x is BStr)))
            {
                return(false);
            }

            var elems = pl.Value.OfType <BStr>().ToArray();

            file = new TorrentFile(lenI, elems);

            return(true);
        }
Beispiel #2
0
 public static T Deserialize <T>(BEnc encoded) => (T)Deserialize(encoded, typeof(T));
Beispiel #3
0
        public static object Deserialize(BEnc encoded, Type type)
        {
            if (type.IsInstanceOfType(encoded))
            {
                return(encoded);
            }

            switch (encoded)
            {
            case BStr str: {
                if (type == typeof(string))
                {
                    return(str.Utf8String);
                }
                if (type == typeof(byte[]))
                {
                    return(str.Value.ToArray());
                }
                if (type == typeof(ReadOnlyMemory <byte>))
                {
                    return(str.Value);
                }
                throw new InvalidOperationException($"Can't deserialize a {encoded.Type} to {type}");
            }

            case BInt bint:
                if (type == typeof(int))
                {
                    return(bint.IntValue);
                }

                if (type == typeof(int?))
                {
                    return(bint.IntValue);
                }

                if (type == typeof(uint))
                {
                    return((uint)bint.Value);
                }

                if (type == typeof(uint?))
                {
                    return((uint?)bint.Value);
                }

                if (type == typeof(long))
                {
                    return(bint.Value);
                }

                if (type == typeof(long?))
                {
                    return(bint.Value);
                }

                if (type == typeof(ulong))
                {
                    return((ulong)bint.Value);
                }

                if (type == typeof(ulong?))
                {
                    return((ulong?)bint.Value);
                }

                throw new InvalidOperationException($"Can't deserialize a {encoded.Type} to {type}");

            case BLst lst:
                if (type.IsArray)
                {
                    var elementType = type.GetElementType()
                                      ?? throw new InvalidOperationException($"");
                    var items = lst.Value.Select(v => Deserialize(v, elementType)).ToArray();
                    var arr   = Array.CreateInstance(elementType, items.Length);
                    for (var i = 0; i < items.Length; i++)
                    {
                        arr.SetValue(items[i], i);
                    }
                    return(arr);
                }

                if (type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(List <>))
                {
                    var inst = Activator.CreateInstance(type) as IList;

                    if (inst == null)
                    {
                        throw new InvalidOperationException($"Failed to create type {type}");
                    }

                    foreach (var v in lst.Value.Select(v => Deserialize(v, type.GenericTypeArguments[0])))
                    {
                        inst.Add(v);
                    }
                    return(inst);
                }

                throw new InvalidOperationException($"Can't deserialize a {encoded.Type} to {type}");

            case BDict dict: {
                var dictType = type.GetInterfaces().FirstOrDefault(iface =>
                                                                   iface.IsConstructedGenericType && iface.GetGenericTypeDefinition() == typeof(IDictionary <,>));
                if (dictType != null)
                {
                    var tk   = dictType.GenericTypeArguments[0];
                    var tv   = dictType.GenericTypeArguments[0];
                    var inst = Activator.CreateInstance(type) as IDictionary;

                    if (inst == null)
                    {
                        throw new InvalidOperationException($"Failed to create type {type}");
                    }

                    foreach (var kv in dict.Value)
                    {
                        inst.Add(Deserialize(kv.Key, tk), Deserialize(kv.Value, tv));
                    }

                    return(inst);
                }
                else
                {
                    var inst = Activator.CreateInstance(type);
                    if (inst == null)
                    {
                        throw new InvalidOperationException($"Failed to create type {type}");
                    }

                    var props = type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                .Where(p => p.CanWrite)
                                .ToArray();

                    foreach (var p in props)
                    {
                        var attr =
                            p.GetCustomAttribute(typeof(MetaInfoPropertyAttribute)) as MetaInfoPropertyAttribute;
                        if (attr == null)
                        {
                            continue;
                        }

                        var name = attr.Name ?? p.Name;
                        var val  = dict[name];
                        if (val != null)
                        {
                            p.SetValue(inst, Deserialize(val, p.PropertyType));
                        }
                    }

                    return(inst);
                }

                throw new InvalidOperationException($"Can't deserialize a {encoded.Type} to {type}");
            }

            default:
                throw new InvalidOperationException($"Can't deserialize a {encoded.Type} to {type}");
            }
        }