Change the output of format bits to big endian instead of native endian (#16435)

Currently the command ouputs in native endian. That is unlike any other
tool that I've used that shows bits (windows calculator comes to mind).
Moreover, if you paste the output of `format bits` as a number you won't
get the same output:

```nushell
~> 258 | format bits
00000010 00000001
~> 0b00000010_00000001
513
```

In order to get a roundtrip, you need to reverse the bytes:

```nushell
~> 0b00000001_00000010
258
~> 258 | format bits | split words | str join | $"0b($in)" | into int
513
~> 258 | format bits | split words | reverse | str join | $"0b($in)" | into int # Added `reverse`
258
```

The goal of this PR is to get rid of this weirdness (and as a bonus get
a platform-independent behavior, without depending on what the native
endianness is).

## Release notes summary - What our users need to know
### Change the output of `format bits` to big endian instead of native
endian

This is what most people expect when formatting numbers and other
primtives in binary. However, until now, if you were in a little endian
system, you would get:
```nushell
~> 258 | format bits
00000010 00000001
```
If you copied and pasted that as a number, you would get a surprising
result:
```nushell
~> 0b00000010_00000001
513
```
Now, `format bits` always formats in big endian:
```nushell
~> 258 | format bits
00000001 00000010
```
This commit is contained in:
andoalon
2025-08-21 16:27:39 +02:00
committed by GitHub
parent f7c131443f
commit ac3f93ff05

View File

@@ -75,6 +75,11 @@ impl Command for FormatBits {
example: "1 | format bits",
result: Some(Value::string("00000001", Span::test_data())),
},
Example {
description: "convert an int into a string, padded to 8 places with 0s (big endian)",
example: "258 | format bits",
result: Some(Value::string("00000001 00000010", Span::test_data())),
},
Example {
description: "convert a filesize value into a string, padded to 8 places with 0s",
example: "1b | format bits",
@@ -158,28 +163,28 @@ fn byte_stream_to_bits(stream: ByteStream, head: Span) -> ByteStream {
fn convert_to_smallest_number_type(num: i64, span: Span) -> Value {
if let Some(v) = num.to_i8() {
let bytes = v.to_ne_bytes();
let bytes = v.to_be_bytes();
let mut raw_string = "".to_string();
for ch in bytes {
raw_string.push_str(&format!("{ch:08b} "));
}
Value::string(raw_string.trim(), span)
} else if let Some(v) = num.to_i16() {
let bytes = v.to_ne_bytes();
let bytes = v.to_be_bytes();
let mut raw_string = "".to_string();
for ch in bytes {
raw_string.push_str(&format!("{ch:08b} "));
}
Value::string(raw_string.trim(), span)
} else if let Some(v) = num.to_i32() {
let bytes = v.to_ne_bytes();
let bytes = v.to_be_bytes();
let mut raw_string = "".to_string();
for ch in bytes {
raw_string.push_str(&format!("{ch:08b} "));
}
Value::string(raw_string.trim(), span)
} else {
let bytes = num.to_ne_bytes();
let bytes = num.to_be_bytes();
let mut raw_string = "".to_string();
for ch in bytes {
raw_string.push_str(&format!("{ch:08b} "));