Skip to content
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

Consider adding BitConverter overloads that accept endian option #22839

Closed
stephentoub opened this issue Jul 18, 2017 · 9 comments
Closed

Consider adding BitConverter overloads that accept endian option #22839

stephentoub opened this issue Jul 18, 2017 · 9 comments
Labels
api-needs-work API needs work before it is approved, it is NOT ready for implementation area-System.Runtime
Milestone

Comments

@stephentoub
Copy link
Member

#22803 lists APIs we're planning to add that use Span<byte> instead of byte[]. These and the existing methods also use the current machine's endianness. We should separately consider overloads that accept the endianness to use, rather than always using that of the current machine, e.g.

public static bool TryWriteBytes(Span<byte> destination, long value, bool? littleEndian);
public static long ToInt64(ReadOnlySpan<byte> value, bool? littleEndian);
// null littleEndian means current machine's

or

public enum Endianness
{
    Current,
    Little,
    Big
}

public static bool TryWriteBytes(Span<byte> destination, long value, Endianness endianness);
public static long ToInt64(ReadOnlySpan<byte> value, Endianness endiannes);

cc: @bartonjs

@bartonjs
Copy link
Member

I think the enum makes it clearer to read, but if we're consistent with parameters being either bigEndian or littleEndian then the bool? is accurately capable of describing it (unless we wanted to support Middle-endian, but that doesn't seem terribly likely. Right?)

I'd call the zero-value System or Native instead of Current to indicate that it's really the system-native byte order, and not that the "Current"ness can't be influenced by state.

Wikipedia also makes me wonder if we need the naming to indicate Byte endianness vs Bit endianness. (I do recall back in college and learning about Little Endian and being aghast at how it was really middle-endian, since I was thinking in terms of the bits... the "left-most" "in hardware" being 0x00000008).

Any particular middle-endian byte scheme would need specific descriptions, like PDP would probably be named something terrible like MiddleEndian_01000302 (or, y'know, PDP)).

So I think:

  • I'd go with the enum. It reads better (and it allows flexibility we'll probably never use).
  • I'd rename Current to Native.
  • That (tangentially) I wish I could come up with a name for a parameter to tell Biginteger "this data was unsigned, please don't sniff the sign bit"

@mellinoe
Copy link
Contributor

I strongly prefer the second version, although I know folks will not want to add a new "Endianness" enum into a core namespace. The first option feels like an abuse of the nullable type and looks a bit unpleasant to me. If we use the first option, we should flip the bool? parameter to isBingEndian such that false is a reasonable default (rather than true), given that most/all .NET implementations run on little-endian processors.

@bartonjs
Copy link
Member

I guess an extra cost of the enum (aside from the typedef/Intellisense cost) is that we need to validation on it, or have a convention that says all unmapped values get treated as Native/Current. That said, I still think it enhances legibility.

@jnm2
Copy link
Contributor

jnm2 commented Jul 18, 2017

While I don't particularly agree about abuse of bool?, I do agree about readability.

@jkotas
Copy link
Member

jkotas commented Jul 18, 2017

I guess an extra cost of the enum (aside from the typedef/Intellisense cost) is that we need to validation on it.

Agree. The enum makes the APIs slower than they need to be. What's wrong with having endianness to be part of the API name?

@Clockwork-Muse
Copy link
Contributor

I appreciate the readability of the enum.

(That said, I'm of the opinion that methods shouldn't have boolean parameters, in favor of separate methods or perhaps an enum. Because otherwise "now the method does two things")

@PeterSmithRedmond
Copy link

I like having the tri-state enum. A good goal is to let people fall into the "pit of success" -- can we give Big Endian two different name? I'd love to have an enum like this:
{
0 = systemEndian,
1 = networkEndian
1 = bigEndian # same and networkEndia
2 = littleEndian
}

That way the two most common things people need to do -- convert system to network and network to system -- are super easy. If we can do this without using 'big' versus 'little', that IMHO is a gain.

I've never had to deal with "bit" endian-ness and IMHO adding special options for it (or even mentioning it in documentation) will only confuse our developers.

@Clockwork-Muse
Copy link
Contributor

@PeterSmithRedmond - if we're adding "Network" as an option, does that mean SystemEndian should be HostEndian instead (to match with the NetworkToHost/HostToNetwork methods elsewhere)? Just curious here.

@stephentoub
Copy link
Member Author

This isn't necessary with the BinaryPrimitives APIs being added in dotnet/corefx#24400.

@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 2.1.0 milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-needs-work API needs work before it is approved, it is NOT ready for implementation area-System.Runtime
Projects
None yet
Development

No branches or pull requests

8 participants