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

Array::from_slice deprecated #114

Open
F8RZD opened this issue Jan 20, 2025 · 5 comments
Open

Array::from_slice deprecated #114

F8RZD opened this issue Jan 20, 2025 · 5 comments

Comments

@F8RZD
Copy link

F8RZD commented Jan 20, 2025

Array::from_slice is deprecated it's suggested to use Array::try_from but try::from &[u8] is not satisfied.

I encountered frustration using ml-kem crate trying to serialize and deserialize encapsulation key and the cipher_text

I was unable to find any standard way to achieve that so I just turned off the warning by adding #[allow(deprecated)]

@newpavlov
Copy link
Member

Please show a code snippet demonstrating the issue.

@F8RZD
Copy link
Author

F8RZD commented Jan 20, 2025

I'm sorry I'm half wrong about what I said but there is still a some points in my issue

let's take this code as an example:

use ml_kem::array::Array;
use ml_kem::{
    kem::{Encapsulate, EncapsulationKey},
    Encoded, EncodedSizeUser, KemCore as _, MlKem1024, MlKem1024Params,
};

// using ml-kem = "0.2.1"

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut rng = rand::thread_rng();
    let (dk, ek): (_, EncapsulationKey<MlKem1024Params>) = MlKem1024::generate(&mut rng);
    let ek_as_bytes: Array<u8, _> = ek.as_bytes(); // rust-analyzer unable to deduct Array's second generic argument it's show as Array<u8, {unknow}>
    let ek_as_u8_vec: Vec<u8> = ek_as_bytes.to_vec();
    // send ek_as_u8_vec over internet to client
    {
        // client side code
        let encoded_ek = Encoded::<EncapsulationKey<MlKem1024Params>>::try_from(&ek_as_u8_vec)?; // Error
        let encoded_ek = Encoded::<EncapsulationKey<MlKem1024Params>>::try_from(ek_as_u8_vec)?; // Error
        let encoded_ek =
            Encoded::<EncapsulationKey<MlKem1024Params>>::try_from(ek_as_u8_vec.as_slice())?; // Good

        let ek = EncapsulationKey::<MlKem1024Params>::from_bytes(&ek_as_u8_vec.try_into()?); // Error

        let ek = EncapsulationKey::<MlKem1024Params>::from_bytes(&encoded_ek); // Good
        let ek =
            EncapsulationKey::<MlKem1024Params>::from_bytes(ek_as_u8_vec.as_slice().try_into()?); // Good
        let ek =
            EncapsulationKey::<MlKem1024Params>::from_bytes(&ek_as_u8_vec.as_slice().try_into()?); // Good

        let (cipher_text, shared_key) = ek.encapsulate(&mut rng).unwrap();
        let cipher_text_vec = cipher_text.to_vec();
        // send cipher_text_back_to server
        cipher_text_vec
    };

    // the rest of logic

    Ok(())
}

I expect this code to compile

there are 2 main problems

  • TryFrom::<Vec<u8>>::try_from is not satisfied for Array type
  • Compiler is unable to deref coerce &Vec<u8> into &[u8] which is odd, making &Vec<u8> invalid input for Array::try_from()

I'm on rust 1.84.0 stable

@newpavlov
Copy link
Member

Unfortunately, it's not possible to provide a genericTryFrom<& impl AsRef<[T]>> for Array<T, U> implementation because of conflicting trait implementations. We could provide separate implementations for Vec<T>, but we generally follow implementations which exist for built-in arrays and as you can see there are no vector-specific implementations for [u8; N].

It's unfortunate that the compiler fails to apply deref in this case, while it works for built-in arrays:

use hybrid_array::{Array, sizes::U4};
let vec: Vec<u8> = vec![1, 2, 3, 4];

// works
let key1: [u8; 4] = vec.try_into().unwrap();
// fails
let key2: Array<u8, U4> = vec.try_into().unwrap();

I am not exactly sure what exactly causes this difference (probably the From implementations for built-in arrays), but I don't think we should add new implementations to just work around this. So I would recommended to just use .as_slice().

// rust-analyzer unable to deduct Array's second generic argument it's show as Array<u8, {unknow}>

It's an expected behavior. The same would happen with built-in arrays.

@F8RZD
Copy link
Author

F8RZD commented Jan 20, 2025

but I don't think we should add new implementations to just work around this. So I would recommended to just use .as_slice()

I would still argue that most people think &Vec<_> is just the same as Vec::as_slice() so if I try &Vec and get no good result I won't try as_slice.
At least that's the pit I fell into.

Plus I would always just write try_into() when ever my types are not matching and hope it fixes it self (which it should in this case).

Since compiler isn't able to recognize &Vec<T> as &[T] I'd say adding new implementations could prove beneficial.

Or maybe just adding a How to get Array from Vec<T> section to the documentation could be enough

@tarcieri
Copy link
Member

We can definitely add a section to the documentation about alternatives to from_slice.

In a future release we could also potentially consider adding back a from_slice method which doesn't panic but would allow for deref coercion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants