valence_nbt/
conv.rs

1//! Zero-cost conversion functions for `valence_nbt`.
2//!
3//! While working with [`Value`], it is often necessary to convert between
4//! collections of signed and unsigned integer types due to API
5//! differences. For instance, you may be given a `&[i8]` from
6//! [`Value::ByteArray`], but functions like [`Write::write_all`] expect to
7//! receive a `&[u8]`.
8//!
9//! This module provides functions to perform conversions between these types
10//! with zero-cost and no `unsafe` code on your part.
11//!
12//! [`Value`]: crate::Value
13//! [`Value::ByteArray`]: crate::Value::ByteArray
14//! [`Write::write_all`]: std::io::Write::write_all
15
16use std::mem::ManuallyDrop;
17
18/// Converts a `Vec<u8>` into a `Vec<i8>` without cloning.
19#[inline]
20pub fn u8_vec_into_i8_vec(vec: Vec<u8>) -> Vec<i8> {
21    // SAFETY: Layouts of u8 and i8 are the same and we're being careful not to drop
22    // the original vec after calling Vec::from_raw_parts.
23    unsafe {
24        let mut vec = ManuallyDrop::new(vec);
25        Vec::from_raw_parts(vec.as_mut_ptr() as *mut i8, vec.len(), vec.capacity())
26    }
27}
28
29/// Converts a `Vec<i8>` into a `Vec<u8>` without cloning.
30#[inline]
31pub fn i8_vec_into_u8_vec(vec: Vec<i8>) -> Vec<u8> {
32    // SAFETY: Layouts of u8 and i8 are the same and we're being careful not to drop
33    // the original vec after calling Vec::from_raw_parts.
34    unsafe {
35        let mut vec = ManuallyDrop::new(vec);
36        Vec::from_raw_parts(vec.as_mut_ptr() as *mut u8, vec.len(), vec.capacity())
37    }
38}
39
40/// Converts a `&[u8]` into a `&[i8]`.
41#[inline]
42pub fn u8_slice_as_i8_slice(slice: &[u8]) -> &[i8] {
43    // SAFETY: i8 has the same layout as u8.
44    unsafe { std::slice::from_raw_parts(slice.as_ptr() as *const i8, slice.len()) }
45}
46
47/// Converts a `&[i8]` into a `&[u8]`.
48#[inline]
49pub fn i8_slice_as_u8_slice(slice: &[i8]) -> &[u8] {
50    // SAFETY: i8 has the same layout as u8.
51    unsafe { std::slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len()) }
52}