Skip to content

as_ne_bytes for primitive types #64464

Closed
@hch12907

Description

@hch12907
Contributor

Recently I've encountered a problem, when I wanted to return a slice of bytes in an integer:

fn to_bytes(num: &u32) -> &[u8] {
    &u32::to_le_bytes(*num)
}

(This is an oversimplification of the original code, which is generic over every integer type along with other stuff)

Obviously, since to_le_bytes(*num) is dropped when the function returns, this piece of code failed the borrow check. Hence my need for as_le_bytes(num), as num is actually alive all this time!

Activity

added
C-feature-requestCategory: A feature request, i.e: not implemented / a PR.
T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.
on Sep 14, 2019
Mark-Simulacrum

Mark-Simulacrum commented on Sep 14, 2019

@Mark-Simulacrum
Member

In this case I believe you can do this via a cast, e.g. unsafe { slice::from_raw_parts(num as *const u32 as *const u8, 4) } but I'm not sure if that's entirely well-defined, in particular, the u8 slice would then I believe be over-aligned.

It does seem viable that we could provide something like this, though.

ExpHP

ExpHP commented on Sep 16, 2019

@ExpHP
Contributor

The only method that can possibly be implemented is as_ne_bytes. (native endian)

as_le_bytes would be impossible to implement on BE systems, for precisely the same reasons that you cannot write your own function. Sure, num may be alive, but that would not matter because the memory associated with num would not contain those bytes in little-endian order. (and rust slices always have a stride of +1; you can't have a "backwards" slice)

but I'm not sure if that's entirely well-defined, in particular, the u8 slice would then I believe be over-aligned.

I daresay I've never heard anyone mention over-alignment before as a concern to even think about! (except in the context of deallocation, which doesn't matter here)

hch12907

hch12907 commented on Sep 22, 2019

@hch12907
ContributorAuthor

It is possible to workaround that by creating a struct, which is a reversed iterator, and return that struct instead for non-ne functions.

That might seem to be too much work for such a simple function though... Or we can just implement as_ne_bytes only.

ExpHP

ExpHP commented on Sep 22, 2019

@ExpHP
Contributor

I think the benefits of an iterator over the existing to_{b,l}e_bytes methods seem nebulous. That is to say, in whatever use case motivates this feature request (where the author needs a slice instead of an array), I can't imagine how an iterator would help.

changed the title [-]as_*e_bytes for primitive types[/-] [+]as_ne_bytes for primitive types[/+] on Sep 11, 2020
hch12907

hch12907 commented on Sep 11, 2020

@hch12907
ContributorAuthor

Implemented in #76610 for both floats and integers, under the feature gate int_as_bytes and float_as_bytes respectively.

added a commit that references this issue on Oct 4, 2020

Auto merge of rust-lang#76610 - hch12907:master, r=LukasKalbertodt

SimonSapin

SimonSapin commented on Oct 8, 2020

@SimonSapin
Contributor

Why is a borrow useful? Can’t the calling code assign the result of to_*e_bytes to a local variable and borrow that?

hch12907

hch12907 commented on Oct 11, 2020

@hch12907
ContributorAuthor

It gets problematic when generics are involved:

trait NumberAsBytes {
    fn as_bytes(&self) -> &[u8];
}

// fn as_bytes(&self) -> &[u8] { self.as_ne_bytes() }
impl_num_as_bytes!(i8, u8, /* ... */, i64, u64);

A ToBytes trait is also not doable (at least not in stable AFAIK), since different-sized integers give off a different [u8; N].

SimonSapin

SimonSapin commented on Oct 11, 2020

@SimonSapin
Contributor

If a library wants to be general-purpose enough to expose such a trait, can’t it afford to do the unsafe conversion by itself? Does this really need to be in the standard library?

2 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-feature-requestCategory: A feature request, i.e: not implemented / a PR.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @SimonSapin@ExpHP@jonas-schievink@Mark-Simulacrum@hch12907

      Issue actions

        as_ne_bytes for primitive types · Issue #64464 · rust-lang/rust