public void u8() { var storage = new u32ArrayMemory(new u32[42]); var writer = new RawBitWriter <u32ArrayMemory>(storage); u16 v1 = 42; u16 v2 = 666; writer.u16(v1, 16); Assert.AreEqual(16, writer.BitsWritten); writer.u16(v2, 10); writer.Align(); var reader = new RawBitReader <u32ArrayMemory>(storage); var rv1 = reader.u16(16); var rv2 = reader.u16(10); Assert.AreEqual(v1, rv1); Assert.AreEqual(v2, rv2); }
/// <summary> /// Copies data from array. /// </summary> public void CopyFrom(ReadOnlySpan <u8> data) { // may Throw.here as not hot path if (data.Length <= 0) { Throw.Argument("Should be positive", nameof(data.Length)); } if (data.Length > System.UInt16.MaxValue * 4) { Throw.Argument($"Should be less or equal to {System.UInt16.MaxValue * 4}", nameof(data.Length)); } var length = data.Length; Reset(); var step = Unsafe.SizeOf <u32>(); var numChunks = (u16)((length / step) + 1); // TODO: move out this expansion from here if (chunks.Length < numChunks) { Chunks = new u32ArrayMemory(new u32[numChunks]); // call it once to stay expanded forever } // data must be 4 or 8 bytes i64 because 32 and 64 machines https://gafferongames.com/post/reading_and_writing_packets/ // TODO: possible to optimize to avoid copy? some kind of unsafe cast? // TODO: try u64 for performance as most of devices will be 64 bit? // https://github.com/nxrighthere/NetStack/issues/1#issuecomment-475212246 for (u16 i = 0; i < numChunks; i++) { i32 dataIdx = (i32)i * step; u32 chunk = 0; // TODO: ref into data and do block copy of all 4bytes, copy only last 3 bytes by hand // may optimize by calculating variable her and doing zero init of remaining blocks // may reintepret unsafe as uint, and then if less than 3 then only read last as 1 2 3 if (dataIdx < length) { chunk = (u32)data[dataIdx]; } if (dataIdx + 1 < length) { chunk = chunk | (u32)data[dataIdx + 1] << 8; } if (dataIdx + 2 < length) { chunk = chunk | (u32)data[dataIdx + 2] << 16; } if (dataIdx + 3 < length) { chunk = chunk | (u32)data[dataIdx + 3] << 24; } chunks[i] = chunk; } // TODO: write sets 1 bit in the end. so we may read all remaining zeroes, minis 1 bit for flag, and make total less // TODO: should be do that at all? Consoder multiple buffers writing sequenctially or other length indicator (like prefix) // var leadingZeros = BitOperations.LeadingZeroCount(data[length - 1]); // totalNumberBits = 8 * length - leadingZeros - 1; }