1 // Copyright 2023 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //! Helper traits to convert byte signedness for Java interop 16 17 /// A helper trait to bitcast data to its signed representation 18 pub trait ToSigned { 19 /// The signed version of this type. 20 type Signed; 21 22 /// Bitcast to signed to_signed(self) -> Self::Signed23 fn to_signed(self) -> Self::Signed; 24 } 25 26 impl<'a> ToSigned for &'a [u8] { 27 type Signed = &'a [i8]; 28 29 #[allow(unsafe_code)] to_signed(self) -> Self::Signed30 fn to_signed(self) -> Self::Signed { 31 let len = self.len(); 32 // Safety: 33 // u8 and i8 have the same layout and the lifetime is maintained 34 unsafe { core::slice::from_raw_parts(self.as_ptr() as *const i8, len) } 35 } 36 } 37 38 /// A helper trait to bitcast data to its unsigned representation 39 pub trait ToUnsigned { 40 /// The unsigned version of this type. 41 type Unsigned; 42 43 /// Bitcast to unsigned to_unsigned(self) -> Self::Unsigned44 fn to_unsigned(self) -> Self::Unsigned; 45 } 46 47 impl<'a> ToUnsigned for &'a [i8] { 48 type Unsigned = &'a [u8]; 49 50 #[allow(unsafe_code)] to_unsigned(self) -> Self::Unsigned51 fn to_unsigned(self) -> Self::Unsigned { 52 let len = self.len(); 53 // Safety: 54 // u8 and i8 have the same layout and the lifetime is maintained 55 unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, len) } 56 } 57 } 58 59 #[cfg(test)] 60 mod test { 61 use super::*; 62 63 #[test] test_to_signed()64 fn test_to_signed() { 65 let input: &[u8] = &[1, 2, 3, 0, 0xff, 0xfe]; 66 let expected: &[i8] = &[1, 2, 3, 0, -1, -2]; 67 68 assert_eq!(expected, input.to_signed()); 69 } 70 71 #[test] test_to_unsigned()72 fn test_to_unsigned() { 73 let input: &[i8] = &[1, 2, 3, 0, -1, -2]; 74 let expected: &[u8] = &[1, 2, 3, 0, 0xff, 0xfe]; 75 76 assert_eq!(expected, input.to_unsigned()); 77 } 78 79 #[test] test_roundtrip_unsigned()80 fn test_roundtrip_unsigned() { 81 let case: &[u8] = &[1, 2, 3, 0, 0xff, 0xfe]; 82 assert_eq!(case, case.to_signed().to_unsigned()); 83 } 84 85 #[test] test_roundtrip_signed()86 fn test_roundtrip_signed() { 87 let case: &[i8] = &[1, 2, 3, 0, -1, -2]; 88 assert_eq!(case, case.to_unsigned().to_signed()); 89 } 90 } 91