예제 #1
0
 public int HomegrownMemorySlice()
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(memTest.Slice(1).Span));
 }
예제 #2
0
 /// <summary>
 /// Reads an int from memory.
 /// </summary>
 /// <param name="address">The zero-based address to read from.</param>
 /// <returns>Returns the int read from memory.</returns>
 public int ReadInt32(int address)
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(Span.Slice(address, 4)));
 }
예제 #3
0
 public virtual unsafe float ReadSingle() => BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(InternalRead(4)));
예제 #4
0
 public static int Read(this ReadOnlySpan <byte> span, out int value)
 {
     value = BinaryPrimitives.ReadInt32LittleEndian(span);
     return(sizeof(int));
 }
예제 #5
0
 public int ReadInt32() => BinaryPrimitives.ReadInt32LittleEndian(ReadBytes(4));
예제 #6
0
        /// <summary>
        /// 解码
        /// </summary>
        /// <param name="bytes">数据</param>
        /// <param name="info">编码信息</param>
        /// <returns></returns>
        public virtual object Decode(byte[] bytes, CodeInfo info)
        {
            switch (info.CodeType)
            {
            case CodeType.binary:
                return(new BitArray(bytes));   //string.Join("", bytes.Select(o => Convert.ToString(o, 2).PadLeft(8, '0')).ToArray();

            case CodeType.boolean:
                return(BitConverter.ToBoolean(bytes));

            case CodeType.@byte:
                return(bytes[0]);

            case CodeType.bytes:
                return(bytes);

            case CodeType.uint16:
                return(Protocol.BigEndian
                        ? BinaryPrimitives.ReadUInt16BigEndian(bytes)
                        : BinaryPrimitives.ReadUInt16LittleEndian(bytes));

            case CodeType.uint32:
                return(Protocol.BigEndian
                        ? BinaryPrimitives.ReadUInt32BigEndian(bytes)
                        : BinaryPrimitives.ReadUInt32LittleEndian(bytes));

            case CodeType.uint64:
                return(Protocol.BigEndian
                        ? BinaryPrimitives.ReadUInt64BigEndian(bytes)
                        : BinaryPrimitives.ReadUInt64LittleEndian(bytes));

            case CodeType.int16:
                return(Protocol.BigEndian
                        ? BinaryPrimitives.ReadInt16BigEndian(bytes)
                        : BinaryPrimitives.ReadInt16LittleEndian(bytes));

            case CodeType.int32:
                return(Protocol.BigEndian
                        ? BinaryPrimitives.ReadInt32BigEndian(bytes)
                        : BinaryPrimitives.ReadInt32LittleEndian(bytes));

            case CodeType.int64:
                return(Protocol.BigEndian
                        ? BinaryPrimitives.ReadInt64BigEndian(bytes)
                        : BinaryPrimitives.ReadInt64LittleEndian(bytes));

            case CodeType.byte_hex:
                return(Convert.ToByte((string)Decode(bytes, new CodeInfo
                {
                    CodeType = CodeType.string_hex
                }), 16));

            case CodeType.int16_hex:
                return(Convert.ToInt16((string)Decode(bytes, new CodeInfo
                {
                    CodeType = CodeType.string_hex
                }), 16));

            case CodeType.int32_hex:
                return(Convert.ToInt32((string)Decode(bytes, new CodeInfo
                {
                    CodeType = CodeType.string_hex
                }), 16));

            case CodeType.int64_hex:
                return(Convert.ToInt64((string)Decode(bytes, new CodeInfo
                {
                    CodeType = CodeType.string_hex
                }), 16));

            case CodeType.uint16_hex:
                return(Convert.ToUInt16((string)Decode(bytes, new CodeInfo
                {
                    CodeType = CodeType.string_hex
                }), 16));

            case CodeType.uint32_hex:
                return(Convert.ToUInt32((string)Decode(bytes, new CodeInfo
                {
                    CodeType = CodeType.string_hex
                }), 16));

            case CodeType.uint64_hex:
                return(Convert.ToUInt64((string)Decode(bytes, new CodeInfo
                {
                    CodeType = CodeType.string_hex
                }), 16));

            case CodeType.uint64_unix:
                return(localDefaultDateTime.AddSeconds((UInt64)Decode(bytes, new CodeInfo
                {
                    CodeType = CodeType.uint64
                })));

            case CodeType.@enum:
                return(Enum.Parse(
                           (string.IsNullOrWhiteSpace(info.Assembly) ?
                            Assembly.GetExecutingAssembly() :
                            Assembly.Load(info.Assembly))
                           .GetType(info.TypeName),
                           GetZHCNEncoding().GetString(bytes.ClearnPadding(GetPadding()))));//.Replace("\0", ""));

            case CodeType.@string:
            default:
                return(GetZHCNEncoding().GetString(bytes.ClearnPadding(GetPadding())));   //.Replace("\0", "");

            case CodeType.string_x_0:
                return(string.Join("", bytes.Select(o => o.ToString("x").PadLeft(2, '0'))));

            case CodeType.@string_x2:
                return(bytes[0].ToString("x2"));

            case CodeType.string_hex:
                return($"0x{string.Join("", bytes.Select(o => o.ToString("x2").PadLeft(2, '0')))}");

            case CodeType.string_ascii:
                return(Encoding.ASCII.GetString(bytes));

            case CodeType.string_bcd8421:
                return(new string((char[])Decode(bytes, new CodeInfo
                {
                    CodeType = CodeType.char_bcd8421
                })));

            case CodeType.char_bcd8421:
                return(bytes.SelectMany(o => new char[]
                {
                    //高4位
                    (char)(48 + (o >> 4 & 0xf)),
                    //低4位
                    (char)(48 + (o & 0xf))
                }).ToArray());

            case CodeType.datetime_bcd8421:
                var charArray = (char[])Decode(bytes, new CodeInfo
                {
                    CodeType = CodeType.char_bcd8421
                });
                return(DateTime.Parse(
                           $"{DateTime.Now.Year / 100 * 100}{charArray[0]:00}" +
                           $"-{charArray[1]:00}" +
                           $"-{charArray[2]:00}" +
                           $" {charArray[3]:00}" +
                           $":{charArray[4]:00}" +
                           $":{charArray[5]:00}"));

            case CodeType.date_bcd8421:
                return(((DateTime)Decode(
                            bytes.Concat(new byte[] { 0, 0, 0 }).ToArray(),
                            new CodeInfo
                {
                    CodeType = CodeType.datetime_bcd8421
                })).Date);

            case CodeType.time_bcd8421:
                return((DateTime)Decode(
                           new byte[]
                {
                    (byte)(DateTime.Now.Year % 100),
                    (byte)(DateTime.Now.Month),
                    (byte)(DateTime.Now.Day),
                }.Concat(bytes).ToArray(),
                           new CodeInfo
                {
                    CodeType = CodeType.datetime_bcd8421
                }));

            case CodeType.data:
                return(string.Join("", bytes));

            case CodeType.data_split:
                return(string.Join(' ', bytes));

            case CodeType.json:
                var jsonString = GetZHCNEncoding().GetString(bytes.ClearnPadding(GetPadding()));    //.Replace("\0", ""));
                if (string.IsNullOrWhiteSpace(info.TypeName))
                {
                    return(JsonConvert.DeserializeObject(jsonString));
                }
                else
                {
                    var jsonType = (string.IsNullOrWhiteSpace(info.Assembly) ?
                                    Assembly.GetExecutingAssembly() :
                                    Assembly.Load(info.Assembly))
                                   .GetType(info.TypeName);
                    return(JsonConvert.DeserializeObject(jsonString, jsonType));
                }
            }
        }
예제 #7
0
 public override int ReadInt32()
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(ReadBytes(4), 0));
 }
예제 #8
0
 /// <summary>
 /// Interprets a subrecord's content as a int.
 /// </summary>
 /// <param name="frame">Frame to read from</param>
 /// <exception cref="System.ArgumentException">Thrown if frame's content is not exactly 4</exception>
 /// <returns>Subrecord's content as a int</returns>
 public static int AsInt32(this SubrecordFrame frame)
 {
     frame.AssertLength(4);
     return(BinaryPrimitives.ReadInt32LittleEndian(frame.Content));
 }
예제 #9
0
 bool GetDataCustom() => _DataLocation.HasValue ? BinaryPrimitives.ReadInt32LittleEndian(HeaderTranslation.ExtractSubrecordMemory(_data, _DataLocation.Value, _package.MetaData.Constants)) != 0 : default;
예제 #10
0
            static void ParseTemporary(MutagenFrame frame, ICellInternal obj)
            {
                var groupMeta = frame.ReadGroup();
                var formKey   = FormKey.Factory(frame.MetaData.MasterReferences !, BinaryPrimitives.ReadUInt32LittleEndian(groupMeta.ContainedRecordTypeData));

                if (formKey != obj.FormKey)
                {
                    throw new ArgumentException("Cell children group did not match the FormID of the parent cell.");
                }
                obj.TemporaryTimestamp        = BinaryPrimitives.ReadInt32LittleEndian(groupMeta.LastModifiedData);
                obj.TemporaryUnknownGroupData = BinaryPrimitives.ReadInt32LittleEndian(groupMeta.HeaderData.Slice(groupMeta.HeaderData.Length - 4));
                var items = ListBinaryTranslation <IPlaced> .Instance.Parse(
                    reader : frame,
                    transl : (MutagenFrame r, RecordType header, out IPlaced placed) =>
                {
                    switch (header.TypeInt)
                    {
                    case RecordTypeInts.ACHR:
                        placed = PlacedNpc.CreateFromBinary(r);
                        return(true);

                    case RecordTypeInts.REFR:
                        placed = PlacedObject.CreateFromBinary(r);
                        return(true);

                    case RecordTypeInts.PARW:
                        placed = PlacedArrow.CreateFromBinary(r);
                        return(true);

                    case RecordTypeInts.PBAR:
                        placed = PlacedBarrier.CreateFromBinary(r);
                        return(true);

                    case RecordTypeInts.PBEA:
                        placed = PlacedBeam.CreateFromBinary(r);
                        return(true);

                    case RecordTypeInts.PCON:
                        placed = PlacedCone.CreateFromBinary(r);
                        return(true);

                    case RecordTypeInts.PFLA:
                        placed = PlacedFlame.CreateFromBinary(r);
                        return(true);

                    case RecordTypeInts.PHZD:
                        placed = PlacedHazard.CreateFromBinary(r);
                        return(true);

                    case RecordTypeInts.PMIS:
                        placed = PlacedMissile.CreateFromBinary(r);
                        return(true);

                    case RecordTypeInts.PGRE:
                        placed = PlacedTrap.CreateFromBinary(r);
                        return(true);

                    default:
                        if (ParseTemporaryOutliers(frame, obj))
                        {
                            placed = null !;
                            return(false);
                        }
                        throw new NotImplementedException();
                    }
                });

                obj.Temporary.SetTo(new ExtendedList <IPlaced>(items));
            }
예제 #11
0
            private static void CustomBinaryEnd(MutagenFrame frame, ICellInternal obj)
            {
                try
                {
                    if (frame.Reader.Complete)
                    {
                        return;
                    }
                    if (!frame.TryGetGroup(out var groupMeta))
                    {
                        return;
                    }
                    var formKey = FormKey.Factory(frame.MetaData.MasterReferences !, BinaryPrimitives.ReadUInt32LittleEndian(groupMeta.ContainedRecordTypeData));
                    if (groupMeta.GroupType == (int)GroupTypeEnum.CellChildren)
                    {
                        obj.Timestamp        = BinaryPrimitives.ReadInt32LittleEndian(groupMeta.LastModifiedData);
                        obj.UnknownGroupData = BinaryPrimitives.ReadInt32LittleEndian(groupMeta.HeaderData.Slice(groupMeta.HeaderData.Length - 4));
                        frame.Position      += groupMeta.HeaderLength;
                        if (formKey != obj.FormKey)
                        {
                            throw new ArgumentException("Cell children group did not match the FormID of the parent cell.");
                        }
                    }
                    else
                    {
                        return;
                    }
                    var subFrame = frame.SpawnWithLength(groupMeta.ContentLength);
                    while (!subFrame.Complete)
                    {
                        var persistGroupMeta = frame.GetGroup();
                        if (!persistGroupMeta.IsGroup)
                        {
                            throw new ArgumentException();
                        }
                        GroupTypeEnum type      = (GroupTypeEnum)persistGroupMeta.GroupType;
                        var           itemFrame = frame.SpawnWithLength(persistGroupMeta.TotalLength);
                        switch (type)
                        {
                        case GroupTypeEnum.CellTemporaryChildren:
                            ParseTemporary(
                                itemFrame,
                                obj);
                            break;

                        case GroupTypeEnum.CellPersistentChildren:
                            ParseTypical(
                                itemFrame,
                                obj);
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw RecordException.Enrich(ex, obj);
                }
            }
예제 #12
0
파일: Ptc.cs 프로젝트: ianuub/Ryujinxxx
        private static unsafe bool Load(string fileName, bool isBackup)
        {
            using (FileStream compressedStream = new(fileName, FileMode.Open))
                using (DeflateStream deflateStream = new(compressedStream, CompressionMode.Decompress, true))
                {
                    Hash128 currentSizeHash = DeserializeStructure <Hash128>(compressedStream);

                    Span <byte> sizeBytes = new byte[sizeof(int)];
                    compressedStream.Read(sizeBytes);
                    Hash128 expectedSizeHash = XXHash128.ComputeHash(sizeBytes);

                    if (currentSizeHash != expectedSizeHash)
                    {
                        InvalidateCompressedStream(compressedStream);

                        return(false);
                    }

                    int size = BinaryPrimitives.ReadInt32LittleEndian(sizeBytes);

                    IntPtr intPtr = IntPtr.Zero;

                    try
                    {
                        intPtr = Marshal.AllocHGlobal(size);

                        using (UnmanagedMemoryStream stream = new((byte *)intPtr.ToPointer(), size, size, FileAccess.ReadWrite))
                        {
                            try
                            {
                                deflateStream.CopyTo(stream);
                            }
                            catch
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            int hashSize = Unsafe.SizeOf <Hash128>();

                            stream.Seek(0L, SeekOrigin.Begin);
                            Hash128 currentHash = DeserializeStructure <Hash128>(stream);

                            ReadOnlySpan <byte> streamBytes  = new(stream.PositionPointer, (int)(stream.Length - stream.Position));
                            Hash128             expectedHash = XXHash128.ComputeHash(streamBytes);

                            if (currentHash != expectedHash)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            stream.Seek((long)hashSize, SeekOrigin.Begin);

                            Header header = ReadHeader(stream);

                            if (header.Magic != _headerMagic)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.CacheFileVersion != InternalVersion)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.Endianness != GetEndianness())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.FeatureInfo != GetFeatureInfo())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.OSPlatform != GetOSPlatform())
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            if (header.InfosLen % InfoEntry.Stride != 0)
                            {
                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            ReadOnlySpan <byte> infosBuf = new(stream.PositionPointer, header.InfosLen);
                            stream.Seek(header.InfosLen, SeekOrigin.Current);

                            ReadOnlySpan <byte> codesBuf = new(stream.PositionPointer, header.CodesLen);
                            stream.Seek(header.CodesLen, SeekOrigin.Current);

                            ReadOnlySpan <byte> relocsBuf = new(stream.PositionPointer, header.RelocsLen);
                            stream.Seek(header.RelocsLen, SeekOrigin.Current);

                            ReadOnlySpan <byte> unwindInfosBuf = new(stream.PositionPointer, header.UnwindInfosLen);
                            stream.Seek(header.UnwindInfosLen, SeekOrigin.Current);

                            try
                            {
                                PtcJumpTable = PtcJumpTable.Deserialize(stream);
                            }
                            catch
                            {
                                PtcJumpTable = new PtcJumpTable();

                                InvalidateCompressedStream(compressedStream);

                                return(false);
                            }

                            _infosStream.Write(infosBuf);
                            _codesStream.Write(codesBuf);
                            _relocsStream.Write(relocsBuf);
                            _unwindInfosStream.Write(unwindInfosBuf);
                        }
                    }
                    finally
                    {
                        if (intPtr != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(intPtr);
                        }
                    }
                }

            long fileSize = new FileInfo(fileName).Length;

            Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetInfosEntriesCount()}).");

            return(true);
        }
예제 #13
0
 public int SpanSliceToSize()
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(arr.AsSpan().Slice(1, 4)));
 }
예제 #14
0
 public int HomegrownMemorySpanSliceToSize()
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(memTest.Span.Slice(1, 4)));
 }
예제 #15
0
 public KerbApOptionsRestriction(KrbAuthorizationData authz)
     : base(authz?.Type ?? 0, AuthorizationDataType.KerbApOptions)
 {
     this.Options = (ApOptions)BinaryPrimitives.ReadInt32LittleEndian(authz.Data.Span);
 }
예제 #16
0
 public static int ReadInt(ReadOnlySpan <byte> span)
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(span));
 }
예제 #17
0
 public static ReadOnlySpan <byte> ReadAndSlice(this ReadOnlySpan <byte> buf, out Int32 obj)
 {
     obj = BinaryPrimitives.ReadInt32LittleEndian(buf);
     return(buf.Slice(4));
 }
예제 #18
0
 public override int GetHashCode()
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(AsSpan().Slice(0, 4)));
 }
예제 #19
0
        private object?DoDeserialize(ReadOnlyMemory <byte> data, uint flags)
        {
            if (flags == RawDataFlag
                // check if unknown flag
                || ((flags & (FlagPrefix + 0xff)) != flags))
            {
                return(data.ToArray());
            }

            var code = (TypeCode)(flags & 0xff);
            var span = data.Span;

#pragma warning disable IDE0049 // readability

            switch (code)
            {
            case TypeCode.Object:
                if (!MemoryMarshal.TryGetArray(data, out var segment))
                {
                    throw new SerializationException("Cannot deserialize object, MemoryMarshal was not able to get the byte[] of the buffer.");                             // TODO dump the first 16-32 bytes into the exception
                }
                using (var ms = new MemoryStream(segment.Array, segment.Offset, segment.Count, false))
                    return(new BinaryFormatter().Deserialize(ms));

            case TypeCode.DBNull: return(null);

            // incrementing a non-existing key then getting it
            // returns as a string, but the flag will be 0
            // so treat all 0 flagged items as string
            // this may help inter-client data management as well
            case TypeCode.Empty:
            case TypeCode.String: return(Utf8NoBom.GetString(span));

            case TypeCode.SByte: return((SByte)span[0]);

            case TypeCode.Byte: return(span[0]);

            case TypeCode.Boolean: return(span[0] != FALSE);

            case TypeCode.Char: return((char)BinaryPrimitives.ReadUInt16LittleEndian(span));

            case TypeCode.Int16: return(BinaryPrimitives.ReadInt16LittleEndian(span));

            case TypeCode.Int32: return(BinaryPrimitives.ReadInt32LittleEndian(span));

            case TypeCode.Int64: return(BinaryPrimitives.ReadInt64LittleEndian(span));

            case TypeCode.UInt16: return(BinaryPrimitives.ReadUInt16LittleEndian(span));

            case TypeCode.UInt32: return(BinaryPrimitives.ReadUInt32LittleEndian(span));

            case TypeCode.UInt64: return(BinaryPrimitives.ReadUInt64LittleEndian(span));

            case TypeCode.DateTime: return(DateTime.FromBinary(BinaryPrimitives.ReadInt64LittleEndian(span)));

            case TypeCode.Single: return(BitConverter.ToSingle(span));

            case TypeCode.Double: return(BitConverter.ToDouble(span));

            case TypeCode.Decimal:

                var bits = new int[4];
                bits[0] = BinaryPrimitives.ReadInt32LittleEndian(span);
                bits[1] = BinaryPrimitives.ReadInt32LittleEndian(span.Slice(sizeof(Int32)));
                bits[2] = BinaryPrimitives.ReadInt32LittleEndian(span.Slice(sizeof(Int32) + sizeof(Int32)));
                bits[3] = BinaryPrimitives.ReadInt32LittleEndian(span.Slice(sizeof(Int32) + sizeof(Int32) + sizeof(Int32)));

                return(new Decimal(bits));
            }
#pragma warning restore IDE0049

            return(data.ToArray());
        }
예제 #20
0
 public override int ReadInt(int offset)
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(this.memory.AsSpan().Slice(offset)));
 }
예제 #21
0
 public override int GetHashCode() => BinaryPrimitives.ReadInt32LittleEndian(this.Value.Slice(0, 4));
예제 #22
0
 public override int GetHashCode()
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(Bytes));
 }
예제 #23
0
        //
        // Assuming the text doesn't look like a normal floating point, we attempt to parse it as one the special floating point values.
        //
        private static bool TryParseAsSpecialFloatingPoint <T>(ReadOnlySpan <byte> source, T positiveInfinity, T negativeInfinity, T nan, out T value, out int bytesConsumed)
        {
            int  srcIndex   = 0;
            int  remaining  = source.Length;
            bool isNegative = false;

            // We need at least 4 characters to process a sign
            if (remaining >= 4)
            {
                byte c = source[srcIndex];

                switch (c)
                {
                case Utf8Constants.Minus:
                {
                    isNegative = true;
                    goto case Utf8Constants.Plus;
                }

                case Utf8Constants.Plus:
                {
                    srcIndex++;
                    remaining--;
                    break;
                }
                }
            }

            // We can efficiently do an ASCII IsLower check by xor'ing with the expected
            // result and validating that it returns either 0 or exactly 0x20 (which is the
            // delta between lowercase and uppercase ASCII characters).

            if (remaining >= 3)
            {
                if ((((source[srcIndex] ^ (byte)('n')) & ~0x20) == 0) &&
                    (((source[srcIndex + 1] ^ (byte)('a')) & ~0x20) == 0) &&
                    (((source[srcIndex + 2] ^ (byte)('n')) & ~0x20) == 0))
                {
                    value         = nan;
                    bytesConsumed = 3 + srcIndex;
                    return(true);
                }

                if (remaining >= 8)
                {
                    const int infi = 0x69666E69;
                    int       diff = (BinaryPrimitives.ReadInt32LittleEndian(source.Slice(srcIndex)) ^ infi);

                    if ((diff & ~0x20202020) == 0)
                    {
                        const int nity = 0x7974696E;
                        diff = (BinaryPrimitives.ReadInt32LittleEndian(source.Slice(srcIndex + 4)) ^ nity);

                        if ((diff & ~0x20202020) == 0)
                        {
                            value         = isNegative ? negativeInfinity : positiveInfinity;
                            bytesConsumed = 8 + srcIndex;
                            return(true);
                        }
                    }
                }
            }

            value         = default;
            bytesConsumed = 0;
            return(false);
        }
예제 #24
0
 internal static unsafe int ReadUnalignedI4(int *p)
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(new ReadOnlySpan <byte>(p, sizeof(int))));
 }
예제 #25
0
        /// <summary>
        /// Given the metadata for an event and an event payload, decode and deserialize the event payload.
        /// </summary>
        internal static object[] DecodePayload(ref EventSource.EventMetadata metadata, ReadOnlySpan <byte> payload)
        {
            ParameterInfo[] parameters    = metadata.Parameters;
            object[]        decodedFields = new object[parameters.Length];
            for (int i = 0; i < parameters.Length; i++)
            {
                // It is possible that an older version of the event was emitted.
                // If this happens, the payload might be missing arguments at the end.
                // We can just leave these unset.
                if (payload.Length <= 0)
                {
                    break;
                }

                Type parameterType = parameters[i].ParameterType;
                Type?enumType      = parameterType.IsEnum ? Enum.GetUnderlyingType(parameterType) : null;
                if (parameterType == typeof(IntPtr))
                {
                    if (IntPtr.Size == 8)
                    {
                        decodedFields[i] = (IntPtr)BinaryPrimitives.ReadInt64LittleEndian(payload);
                    }
                    else
                    {
                        decodedFields[i] = (IntPtr)BinaryPrimitives.ReadInt32LittleEndian(payload);
                    }
                    payload = payload.Slice(IntPtr.Size);
                }
                else if (parameterType == typeof(int) || enumType == typeof(int))
                {
                    decodedFields[i] = BinaryPrimitives.ReadInt32LittleEndian(payload);
                    payload          = payload.Slice(sizeof(int));
                }
                else if (parameterType == typeof(uint) || enumType == typeof(uint))
                {
                    decodedFields[i] = BinaryPrimitives.ReadUInt32LittleEndian(payload);
                    payload          = payload.Slice(sizeof(uint));
                }
                else if (parameterType == typeof(long) || enumType == typeof(long))
                {
                    decodedFields[i] = BinaryPrimitives.ReadInt64LittleEndian(payload);
                    payload          = payload.Slice(sizeof(long));
                }
                else if (parameterType == typeof(ulong) || enumType == typeof(ulong))
                {
                    decodedFields[i] = BinaryPrimitives.ReadUInt64LittleEndian(payload);
                    payload          = payload.Slice(sizeof(ulong));
                }
                else if (parameterType == typeof(byte) || enumType == typeof(byte))
                {
                    decodedFields[i] = MemoryMarshal.Read <byte>(payload);
                    payload          = payload.Slice(sizeof(byte));
                }
                else if (parameterType == typeof(sbyte) || enumType == typeof(sbyte))
                {
                    decodedFields[i] = MemoryMarshal.Read <sbyte>(payload);
                    payload          = payload.Slice(sizeof(sbyte));
                }
                else if (parameterType == typeof(short) || enumType == typeof(short))
                {
                    decodedFields[i] = BinaryPrimitives.ReadInt16LittleEndian(payload);
                    payload          = payload.Slice(sizeof(short));
                }
                else if (parameterType == typeof(ushort) || enumType == typeof(ushort))
                {
                    decodedFields[i] = BinaryPrimitives.ReadUInt16LittleEndian(payload);
                    payload          = payload.Slice(sizeof(ushort));
                }
                else if (parameterType == typeof(float))
                {
                    decodedFields[i] = BitConverter.Int32BitsToSingle(BinaryPrimitives.ReadInt32LittleEndian(payload));
                    payload          = payload.Slice(sizeof(float));
                }
                else if (parameterType == typeof(double))
                {
                    decodedFields[i] = BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(payload));
                    payload          = payload.Slice(sizeof(double));
                }
                else if (parameterType == typeof(bool))
                {
                    // The manifest defines a bool as a 32bit type (WIN32 BOOL), not 1 bit as CLR Does.
                    decodedFields[i] = (BinaryPrimitives.ReadInt32LittleEndian(payload) == 1);
                    payload          = payload.Slice(sizeof(int));
                }
                else if (parameterType == typeof(Guid))
                {
                    const int sizeOfGuid = 16;
                    decodedFields[i] = new Guid(payload.Slice(0, sizeOfGuid));
                    payload          = payload.Slice(sizeOfGuid);
                }
                else if (parameterType == typeof(char))
                {
                    decodedFields[i] = (char)BinaryPrimitives.ReadUInt16LittleEndian(payload);
                    payload          = payload.Slice(sizeof(char));
                }
                else if (parameterType == typeof(string))
                {
                    // Try to find null terminator (0x00) from the byte span
                    // NOTE: we do this by hand instead of using IndexOf because payload may be unaligned due to
                    // mixture of different types being stored in the same buffer. (see eventpipe.cpp:CopyData)
                    int byteCount = -1;
                    for (int j = 1; j < payload.Length; j += 2)
                    {
                        if (payload[j - 1] == (byte)(0) && payload[j] == (byte)(0))
                        {
                            byteCount = j + 1;
                            break;
                        }
                    }

                    ReadOnlySpan <char> charPayload;
                    if (byteCount < 0)
                    {
                        charPayload = MemoryMarshal.Cast <byte, char>(payload);
                        payload     = default;
                    }
                    else
                    {
                        charPayload = MemoryMarshal.Cast <byte, char>(payload.Slice(0, byteCount - 2));
                        payload     = payload.Slice(byteCount);
                    }
                    decodedFields[i] = BitConverter.IsLittleEndian ? new string(charPayload) : Encoding.Unicode.GetString(MemoryMarshal.Cast <char, byte>(charPayload));
                }
                else
                {
                    Debug.Fail($"Unsupported type \"{parameterType}\" encountered.");
                }
            }

            return(decodedFields);
        }
예제 #26
0
        private static bool IsFormatV2OrV3(ReadOnlySpan <byte> buffer, int entrySize, out Endianness endianness)
        {
            endianness = Endianness.Little;

            // Need at least a full entry
            if (buffer.Length < 4 + entrySize)
            {
                return(false);
            }

            var entryCount = BinaryPrimitives.ReadInt32LittleEndian(buffer);

            if (entryCount <= 0 || entryCount > 1024)
            {
                BinaryOperations <int> .Reverse(ref entryCount);

                if (entryCount <= 0 || entryCount > 1024)
                {
                    return(false);
                }

                endianness = Endianness.Big;
            }

            // check if the name field is correct
            if (buffer[4] == 0)
            {
                return(false);
            }

            var nameTerminated = false;

            for (int i = 0; i < (entrySize - 4); i++)
            {
                if (buffer[4 + i] == 0x00)
                {
                    nameTerminated = true;
                }
                else if (nameTerminated)
                {
                    return(false);
                }
            }

            // Data length sanity check
            var length = BinaryPrimitives.ReadInt32LittleEndian(buffer.Slice(4 + entrySize - 4));

            if (length < 0 || length >= MAX_LENGTH_SANITY_VALUE)
            {
                BinaryOperations <int> .Reverse(ref length);

                if (length < 0 || length >= MAX_LENGTH_SANITY_VALUE)
                {
                    return(false);
                }

                endianness = Endianness.Big;
            }

            return(true);
        }
예제 #27
0
 public virtual int ReadInt32() => BinaryPrimitives.ReadInt32LittleEndian(InternalRead(4));
예제 #28
0
        /// <summary>
        /// Reads the <see cref="BmpInfoHeader"/> from the stream.
        /// </summary>
        private void ReadInfoHeader()
        {
#if NETCOREAPP2_1
            Span <byte> buffer = stackalloc byte[BmpInfoHeader.MaxHeaderSize];
#else
            byte[] buffer = new byte[BmpInfoHeader.MaxHeaderSize];
#endif
            this.stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize); // read the header size

            int headerSize = BinaryPrimitives.ReadInt32LittleEndian(buffer);
            if (headerSize < BmpInfoHeader.CoreSize)
            {
                throw new NotSupportedException($"ImageSharp does not support this BMP file. HeaderSize: {headerSize}.");
            }

            int skipAmount = 0;
            if (headerSize > BmpInfoHeader.MaxHeaderSize)
            {
                skipAmount = headerSize - BmpInfoHeader.MaxHeaderSize;
                headerSize = BmpInfoHeader.MaxHeaderSize;
            }

            // read the rest of the header
            this.stream.Read(buffer, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize);

            if (headerSize == BmpInfoHeader.CoreSize)
            {
                // 12 bytes
                this.infoHeader = BmpInfoHeader.ParseCore(buffer);
            }
            else if (headerSize >= BmpInfoHeader.Size)
            {
                // >= 40 bytes
                this.infoHeader = BmpInfoHeader.Parse(buffer);
            }
            else
            {
                throw new NotSupportedException($"ImageSharp does not support this BMP file. HeaderSize: {headerSize}.");
            }

            // Resolution is stored in PPM.
            var meta = new ImageMetaData
            {
                ResolutionUnits = PixelResolutionUnit.PixelsPerMeter
            };
            if (this.infoHeader.XPelsPerMeter > 0 && this.infoHeader.YPelsPerMeter > 0)
            {
                meta.HorizontalResolution = this.infoHeader.XPelsPerMeter;
                meta.VerticalResolution   = this.infoHeader.YPelsPerMeter;
            }
            else
            {
                // Convert default metadata values to PPM.
                meta.HorizontalResolution = Math.Round(UnitConverter.InchToMeter(ImageMetaData.DefaultHorizontalResolution));
                meta.VerticalResolution   = Math.Round(UnitConverter.InchToMeter(ImageMetaData.DefaultVerticalResolution));
            }

            this.metaData = meta;

            short       bitsPerPixel = this.infoHeader.BitsPerPixel;
            BmpMetaData bmpMetaData  = this.metaData.GetFormatMetaData(BmpFormat.Instance);

            // We can only encode at these bit rates so far.
            if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24) ||
                bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel32))
            {
                bmpMetaData.BitsPerPixel = (BmpBitsPerPixel)bitsPerPixel;
            }

            // skip the remaining header because we can't read those parts
            this.stream.Skip(skipAmount);
        }
예제 #29
0
            public static IEnumerable <APerkEffect> ParseEffects(IMutagenReadStream stream)
            {
                while (stream.TryReadSubrecordFrame(RecordTypes.PRKE, out var prkeFrame))
                {
                    var         type     = (Perk.EffectType)prkeFrame.Content[0];
                    var         rank     = prkeFrame.Content[1];
                    var         priority = prkeFrame.Content[2];
                    APerkEffect effect;
                    if (stream.TryReadSubrecordFrame(RecordTypes.DATA, out var dataFrame))
                    {
                        switch (type)
                        {
                        case Perk.EffectType.Quest:
                            effect = new PerkQuestEffect()
                            {
                                Quest   = new FormLink <IQuestGetter>(FormKeyBinaryTranslation.Instance.Parse(dataFrame.Content, stream.MetaData.MasterReferences !)),
                                Stage   = dataFrame.Content[4],
                                Unknown = dataFrame.Content.Slice(5, 3).ToArray(),
                            };
                            effect.Conditions.SetTo(
                                ListBinaryTranslation <PerkCondition> .Instance.Parse(
                                    reader: new MutagenFrame(stream),
                                    transl: (MutagenFrame r, out PerkCondition listSubItem) =>
                            {
                                return(LoquiBinaryTranslation <PerkCondition> .Instance.Parse(
                                           frame: r,
                                           item: out listSubItem !));
                            }));
                            break;

                        case Perk.EffectType.Ability:
                            effect = new PerkAbilityEffect()
                            {
                                Ability = new FormLink <ISpellGetter>(FormKeyBinaryTranslation.Instance.Parse(dataFrame.Content, stream.MetaData.MasterReferences !)),
                            };
                            effect.Conditions.SetTo(
                                ListBinaryTranslation <PerkCondition> .Instance.Parse(
                                    reader: new MutagenFrame(stream),
                                    transl: (MutagenFrame r, out PerkCondition listSubItem) =>
                            {
                                return(LoquiBinaryTranslation <PerkCondition> .Instance.Parse(
                                           frame: r,
                                           item: out listSubItem !));
                            }));
                            break;

                        case Perk.EffectType.EntryPoint:
                            var entryPt    = (APerkEntryPointEffect.EntryType)dataFrame.Content[0];
                            var func       = (APerkEntryPointEffect.FunctionType)dataFrame.Content[1];
                            var tabCount   = dataFrame.Content[2];
                            var conditions = ListBinaryTranslation <PerkCondition> .Instance.Parse(
                                reader : new MutagenFrame(stream),
                                transl : (MutagenFrame r, out PerkCondition listSubItem) =>
                            {
                                return(LoquiBinaryTranslation <PerkCondition> .Instance.Parse(
                                           frame: r,
                                           item: out listSubItem !));
                            })
                                             .ToList();

                            ReadOnlyMemorySlice <byte>?epf2 = null;
                            ReadOnlyMemorySlice <byte>?epf3 = null;
                            ReadOnlyMemorySlice <byte>?epfd = null;
                            ReadOnlyMemorySlice <byte>?epft = null;
                            while (stream.TryReadSubrecordFrame(out var subFrame))
                            {
                                switch (subFrame.RecordTypeInt)
                                {
                                case RecordTypeInts.EPF2:
                                    epf2 = subFrame.Content;
                                    break;

                                case RecordTypeInts.EPF3:
                                    epf3 = subFrame.Content;
                                    break;

                                case RecordTypeInts.EPFD:
                                    epfd = subFrame.Content;
                                    break;

                                case RecordTypeInts.EPFT:
                                    epft = subFrame.Content;
                                    break;

                                default:
                                    stream.Position -= subFrame.Content.Length;
                                    goto searchDone;
                                }
                            }
searchDone:
                            APerkEntryPointEffect entryPointEffect;
                            switch (func)
                            {
                            case APerkEntryPointEffect.FunctionType.SetValue:
                            case APerkEntryPointEffect.FunctionType.AddValue:
                            case APerkEntryPointEffect.FunctionType.MultiplyValue:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                float?f;
                                if (epft == null && epfd == null)
                                {
                                    f = null;
                                }
                                else
                                {
                                    if (!epft.HasValue)
                                    {
                                        throw new ArgumentException($"{nameof(PerkEntryPointModifyValue)} did not have expected EPFT record");
                                    }
                                    if (!epfd.HasValue)
                                    {
                                        throw new ArgumentException($"{nameof(PerkEntryPointModifyValue)} did not have expected EPFD record");
                                    }
                                    if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.Float)
                                    {
                                        throw new ArgumentException($"{nameof(PerkEntryPointModifyValue)} did not have expected parameter type flag: {epft.Value[0]}");
                                    }

                                    f = epfd.Value.Float();
                                }
                                entryPointEffect = new PerkEntryPointModifyValue()
                                {
                                    Value        = f,
                                    Modification = func switch
                                    {
                                        APerkEntryPointEffect.FunctionType.SetValue => PerkEntryPointModifyValue.ModificationType.Set,
                                        APerkEntryPointEffect.FunctionType.MultiplyValue => PerkEntryPointModifyValue.ModificationType.Multiply,
                                        APerkEntryPointEffect.FunctionType.AddValue => PerkEntryPointModifyValue.ModificationType.Add,
                                        _ => throw new ArgumentException(),
                                    }
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.AddRangeToValue:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddRangeToValue)} did not have expected EPFT record");
                                }
                                if (!epfd.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddRangeToValue)} did not have expected EPFD record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.FloatFloat)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddRangeToValue)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointAddRangeToValue()
                                {
                                    From = epfd.Value.Float(),
                                    To   = epfd.Value.Slice(4).Float(),
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.SetToActorValueMult:
                            case APerkEntryPointEffect.FunctionType.MultiplyActorValueMult:
                            case APerkEntryPointEffect.FunctionType.MultiplyOnePlusActorValueMult:
                            case APerkEntryPointEffect.FunctionType.AddActorValueMult:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointModifyActorValue)} did not have expected EPFT record");
                                }
                                if (!epfd.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointModifyActorValue)} did not have expected EPFD record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.FloatFloat)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointModifyActorValue)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointModifyActorValue()
                                {
                                    ActorValue   = (ActorValue)BinaryPrimitives.ReadInt32LittleEndian(epfd.Value),
                                    Value        = epfd.Value.Slice(4).Float(),
                                    Modification = func switch
                                    {
                                        APerkEntryPointEffect.FunctionType.SetToActorValueMult => PerkEntryPointModifyActorValue.ModificationType.SetToAVMult,
                                        APerkEntryPointEffect.FunctionType.AddActorValueMult => PerkEntryPointModifyActorValue.ModificationType.AddAVMult,
                                        APerkEntryPointEffect.FunctionType.MultiplyActorValueMult => PerkEntryPointModifyActorValue.ModificationType.MultiplyAVMult,
                                        APerkEntryPointEffect.FunctionType.MultiplyOnePlusActorValueMult => PerkEntryPointModifyActorValue.ModificationType.MultiplyOnePlusAVMult,
                                        _ => throw new ArgumentException(),
                                    }
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.AbsoluteValue:
                            case APerkEntryPointEffect.FunctionType.NegativeAbsoluteValue:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (epft.HasValue && epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.None)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAbsoluteValue)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointAbsoluteValue()
                                {
                                    Negative = func == APerkEntryPointEffect.FunctionType.NegativeAbsoluteValue
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.AddLeveledList:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddLeveledItem)} did not have expected EPFT record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.LeveledItem)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddLeveledItem)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointAddLeveledItem()
                                {
                                    Item = new FormLink <ILeveledItemGetter>(epfd.HasValue ? FormKeyBinaryTranslation.Instance.Parse(epfd.Value, stream.MetaData.MasterReferences !) : FormKey.Null)
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.AddActivateChoice:
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddActivateChoice)} did not have expected EPFT record");
                                }
                                if (!epf3.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddActivateChoice)} did not have expected EPF3 record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.SpellWithStrings)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointAddActivateChoice)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointAddActivateChoice()
                                {
                                    Spell       = new FormLinkNullable <ISpellGetter>(epfd.HasValue ? FormKeyBinaryTranslation.Instance.Parse(epfd.Value, stream.MetaData.MasterReferences !) : default(FormKey?)),
                                    ButtonLabel = epf2.HasValue ? StringBinaryTranslation.Instance.Parse(epf2.Value, StringsSource.Normal, stream.MetaData.StringsLookup !) : null,
                                    Flags       = new PerkScriptFlag()
                                    {
                                        Flags         = (PerkScriptFlag.Flag)BinaryPrimitives.ReadInt16LittleEndian(epf3.Value),
                                        FragmentIndex = BinaryPrimitives.ReadUInt16LittleEndian(epf3.Value.Slice(2))
                                    },
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.SelectSpell:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSelectSpell)} did not have expected EPFT record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.Spell)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSelectSpell)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointSelectSpell()
                                {
                                    Spell = new FormLink <ISpellGetter>(epfd.HasValue ? FormKeyBinaryTranslation.Instance.Parse(epfd.Value, stream.MetaData.MasterReferences !) : FormKey.Null),
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.SelectText:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSelectText)} did not have expected EPFT record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.String)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSelectText)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointSelectText()
                                {
                                    Text = epfd.HasValue ? BinaryStringUtility.ProcessWholeToZString(epfd.Value) : string.Empty
                                };
                                break;

                            case APerkEntryPointEffect.FunctionType.SetText:
                                if (epf2.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF2, $"{nameof(PerkEntryPointModifyValue)} had EPF2 unexpectedly");
                                }
                                if (epf3.HasValue)
                                {
                                    stream.MetaData.ReportIssue(RecordTypes.EPF3, $"{nameof(PerkEntryPointModifyValue)} had EPF3 unexpectedly");
                                }
                                if (!epft.HasValue)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSetText)} did not have expected EPFT record");
                                }
                                if (epft.Value[0] != (byte)APerkEntryPointEffect.ParameterType.LString)
                                {
                                    throw new ArgumentException($"{nameof(PerkEntryPointSetText)} did not have expected parameter type flag: {epft.Value[0]}");
                                }
                                entryPointEffect = new PerkEntryPointSetText()
                                {
                                    Text = epfd.HasValue ? StringBinaryTranslation.Instance.Parse(epfd.Value, StringsSource.Normal, stream.MetaData.StringsLookup !) : (TranslatedString)string.Empty,
                                };
                                break;

                            default:
                                throw new NotImplementedException();
                            }
                            entryPointEffect.EntryPoint            = entryPt;
                            entryPointEffect.PerkConditionTabCount = tabCount;
                            entryPointEffect.Conditions.SetTo(conditions);
                            effect = entryPointEffect;
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                    }
                    else
                    {
                        effect = type switch
                        {
                            Perk.EffectType.Quest => new PerkQuestEffect(),
                            Perk.EffectType.Ability => new PerkAbilityEffect(),
                            _ => throw new ArgumentException($"Expected DATA subrecord that did not exist."),
                        };
                    }
                    effect.Rank     = rank;
                    effect.Priority = priority;
                    if (stream.TryReadSubrecordFrame(RecordTypes.EPFT, out var epftFrame) &&
                        epftFrame.ContentLength != 1 &&
                        epftFrame.Content[0] != (byte)APerkEntryPointEffect.ParameterType.None)
                    {
                        throw new ArgumentException($"Encountered an unexpected epft frame.");
                    }
                    stream.TryReadSubrecordFrame(RecordTypes.PRKF, out var _);
                    yield return(effect);
                }
            }
예제 #30
0
 public int MemorySpanSlice()
 {
     return(BinaryPrimitives.ReadInt32LittleEndian(mem.Span.Slice(1)));
 }