-
Notifications
You must be signed in to change notification settings - Fork 1
Add BinaryReaderExtensions and BinaryWriterExtensions #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
59d9cae
51b5f4d
7043ef0
e314ae7
7983663
e8a4e4d
7cab462
f45cd92
167c9a7
005dfd1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| using System; | ||
| using System.IO; | ||
| using System.Text; | ||
| using FluentAssertions; | ||
| using PowerKit.Extensions; | ||
| using Xunit; | ||
|
|
||
| namespace PowerKit.Tests; | ||
|
|
||
| public class BinaryReaderExtensionsTests | ||
| { | ||
| [Fact] | ||
| public void SkipZeroes_NonSeekableStream_Test() | ||
| { | ||
| // Arrange | ||
| var data = new byte[] { 0, 0, 1, 2 }; | ||
| using var stream = new NonSeekableStream(data); | ||
| using var reader = new BinaryReader(stream); | ||
|
|
||
| // Act & assert | ||
| var act = () => reader.SkipZeroes(); | ||
| act.Should().Throw<InvalidOperationException>(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void SkipZeroes_Test() | ||
| { | ||
| // Arrange | ||
| var data = new byte[] { 0, 0, 0, 1, 2, 3 }; | ||
| using var stream = new MemoryStream(data); | ||
| using var reader = new BinaryReader(stream); | ||
|
|
||
| // Act | ||
| reader.SkipZeroes(); | ||
|
|
||
| // Assert | ||
| stream.Position.Should().Be(3); | ||
| reader.ReadByte().Should().Be(1); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void SkipZeroes_WithMaxLength_Test() | ||
| { | ||
| // Arrange | ||
| var data = new byte[] { 0, 0, 0, 0, 1, 2, 3 }; | ||
| using var stream = new MemoryStream(data); | ||
| using var reader = new BinaryReader(stream); | ||
|
|
||
| // Act | ||
| reader.SkipZeroes(maxSkipLength: 2); | ||
|
|
||
| // Assert | ||
| stream.Position.Should().Be(2); | ||
| reader.ReadByte().Should().Be(0); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void SkipZeroes_AllZeroes_Test() | ||
| { | ||
| // Arrange | ||
| var data = new byte[] { 0, 0, 0 }; | ||
| using var stream = new MemoryStream(data); | ||
| using var reader = new BinaryReader(stream); | ||
|
|
||
| // Act | ||
| reader.SkipZeroes(); | ||
|
|
||
| // Assert | ||
| stream.Position.Should().Be(3); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void ReadNullTerminatedString_Test() | ||
| { | ||
| // Arrange | ||
| var data = Encoding.ASCII.GetBytes("hello\0"); | ||
| using var stream = new MemoryStream(data); | ||
| using var reader = new BinaryReader(stream, Encoding.ASCII); | ||
|
|
||
| // Act | ||
| var result = reader.ReadNullTerminatedString(); | ||
|
|
||
| // Assert | ||
| result.Should().Be("hello"); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void ReadNullTerminatedString_Empty_Test() | ||
| { | ||
| // Arrange | ||
| var data = new byte[] { 0 }; | ||
| using var stream = new MemoryStream(data); | ||
| using var reader = new BinaryReader(stream, Encoding.ASCII); | ||
|
|
||
| // Act | ||
| var result = reader.ReadNullTerminatedString(); | ||
|
|
||
| // Assert | ||
| result.Should().Be(""); | ||
| } | ||
| } | ||
|
|
||
| file class NonSeekableStream(byte[] data) : MemoryStream(data) | ||
| { | ||
| public override bool CanSeek => false; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| using System.IO; | ||
| using System.Text; | ||
| using FluentAssertions; | ||
| using PowerKit.Extensions; | ||
| using Xunit; | ||
|
|
||
| namespace PowerKit.Tests; | ||
|
|
||
| public class BinaryWriterExtensionsTests | ||
| { | ||
| [Fact] | ||
| public void WriteNullTerminatedString_Test() | ||
| { | ||
| // Arrange | ||
| using var stream = new MemoryStream(); | ||
| using var writer = new BinaryWriter(stream, Encoding.ASCII); | ||
|
|
||
| // Act | ||
| writer.WriteNullTerminatedString("hello"); | ||
|
|
||
| // Assert | ||
| stream.ToArray().Should().Equal((byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o', 0); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void WriteNullTerminatedString_Empty_Test() | ||
| { | ||
| // Arrange | ||
| using var stream = new MemoryStream(); | ||
| using var writer = new BinaryWriter(stream, Encoding.ASCII); | ||
|
|
||
| // Act | ||
| writer.WriteNullTerminatedString(""); | ||
|
|
||
| // Assert | ||
| stream.ToArray().Should().Equal(0); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| using System; | ||
| using System.IO; | ||
| using System.Text; | ||
|
|
||
| namespace PowerKit.Extensions; | ||
|
|
||
| internal static class BinaryReaderExtensions | ||
| { | ||
| extension(BinaryReader reader) | ||
| { | ||
| /// <summary> | ||
| /// Skips zero bytes in the stream, up to the specified maximum length. | ||
| /// </summary> | ||
| public void SkipZeroes(long? maxSkipLength = null) | ||
| { | ||
| if (!reader.BaseStream.CanSeek) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done in 7cab462. |
||
| { | ||
| throw new InvalidOperationException("The underlying stream must be seekable."); | ||
| } | ||
|
|
||
| var endPosition = maxSkipLength is not null | ||
| ? Math.Min(reader.BaseStream.Position + maxSkipLength.Value, reader.BaseStream.Length) | ||
| : reader.BaseStream.Length; | ||
|
|
||
| while (reader.BaseStream.Position < endPosition) | ||
| { | ||
| if (reader.ReadByte() != 0) | ||
| { | ||
| // Go back to non-zero byte | ||
| reader.BaseStream.Seek(-1, SeekOrigin.Current); | ||
| return; | ||
|
Tyrrrz marked this conversation as resolved.
Outdated
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Reads a null-terminated string from the binary reader. | ||
| /// </summary> | ||
| public string ReadNullTerminatedString() | ||
| { | ||
| var buffer = new StringBuilder(); | ||
|
|
||
| while (true) | ||
| { | ||
| var ch = reader.ReadChar(); | ||
| if (ch == '\0') | ||
| { | ||
| break; | ||
| } | ||
|
|
||
| buffer.Append(ch); | ||
| } | ||
|
|
||
| return buffer.ToString(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| using System.IO; | ||
| using System.Text; | ||
|
|
||
| namespace PowerKit.Extensions; | ||
|
|
||
| internal static class BinaryWriterExtensions | ||
| { | ||
| extension(BinaryWriter writer) | ||
| { | ||
| /// <summary> | ||
| /// Writes a null-terminated string to the binary writer. | ||
| /// </summary> | ||
| public void WriteNullTerminatedString(string value) | ||
| { | ||
| writer.Write(Encoding.UTF8.GetBytes(value)); | ||
| writer.Write((byte)0); | ||
| } | ||
|
Tyrrrz marked this conversation as resolved.
|
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use an u8 string here? @copilot
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in f45cd92. The assertion now uses
"hello\0"u8.ToArray().