blob: 8e6a09ca75a801e62239fb0bf98cd1814ae0300f [file] [log] [blame]
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
use crate::StdString;
extern crate std;
use std::slice;
use cc_std::std::string_view;
use std::string::String;
use std::vec::Vec;
impl StdString {
pub fn as_slice(&self) -> &[u8] {
let len = self.len();
assert!(
len <= isize::MAX as usize,
"The string length does not fit in an `isize`: {}",
len
);
unsafe {
// SAFETY:
//
// * `StdString::data` returns the pointer of the C++ `std::string::data()`,
// which is guaranteed to be non-null and point to a continuous memory region.
// Every byte from `StdString` (i.e., [data, data + len)) is intialized.
// (See https://en.cppreference.com/w/cpp/string/basic_string/data)
// * The data is guaranteed to be not mutated because we don't ever mutate
// data() except when accessed via &mut self, which is blocked by Rust borrow
// checker.
// * `len` is guaranteed to be less than `isize::MAX` because C++
// implementations guarantee in practice that the object won't go past the end
// of the address space.
slice::from_raw_parts(StdString::data(self) as _, len)
}
}
pub fn as_slice_mut(&mut self) -> &mut [u8] {
let len = self.len();
assert!(
len <= isize::MAX as usize,
"The string length does not fit in an `isize`: {}",
len
);
unsafe {
// SAFETY:
//
// * `StdString::data` returns the pointer of the C++ `std::string::data()`,
// which is guaranteed to be non-null and point to a continuous memory region.
// And every byte from `StdString` (i.e., [data, data + len)) is intialized.
// (See https://en.cppreference.com/w/cpp/string/basic_string/data)
// * `len` is guaranteed to be less than `isize::MAX` because C++
// implementations guarantee in practice that the object won't go past the end
// of the address space.
slice::from_raw_parts_mut(StdString::data(self) as _, len)
}
}
pub fn len(&self) -> usize {
unsafe {
// SAFETY: self is a valid reference.
StdString::size(self)
}
}
}
impl From<string_view> for StdString {
fn from(s: string_view) -> Self {
StdString::FromStringView(s)
}
}
impl From<&[u8]> for StdString {
fn from(s: &[u8]) -> Self {
string_view::from(s).into()
}
}
impl From<&String> for StdString {
fn from(s: &String) -> Self {
s.as_bytes().into()
}
}
impl From<&Vec<u8>> for StdString {
fn from(s: &Vec<u8>) -> Self {
s.as_slice().into()
}
}
impl From<&str> for StdString {
fn from(s: &str) -> Self {
s.as_bytes().into()
}
}
impl core::fmt::Debug for StdString {
// TODO(jeanpierreda): format as StdString(b"...")
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "StdString({:?})", self.as_slice())
}
}
impl core::fmt::Display for StdString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", String::from_utf8_lossy(self.as_slice()))
}
}
impl AsRef<[u8]> for StdString {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl AsMut<[u8]> for StdString {
fn as_mut(&mut self) -> &mut [u8] {
self.as_slice_mut()
}
}
impl Clone for StdString {
fn clone(&self) -> Self {
self.as_slice().into()
}
}
impl core::ops::Deref for StdString {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl core::ops::DerefMut for StdString {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_slice_mut()
}
}