#[cfg(not(feature = "std"))]
use crate::alloc_prelude::*;
use mbedtls_sys::types::raw_types::c_char;
use mbedtls_sys::types::raw_types::{c_int, c_uchar};
use mbedtls_sys::types::size_t;
use crate::error::{Error, HiError, IntoResult, LoError, Result};
pub trait UnsafeFrom<T>
where
Self: Sized,
{
unsafe fn from(_: T) -> Option<Self>;
}
pub fn alloc_vec_repeat<F>(mut f: F, data_at_end: bool) -> Result<Vec<u8>>
where
F: FnMut(*mut c_uchar, size_t) -> c_int,
{
const MAX_VECTOR_ALLOCATION: usize = 4 * 1024 * 1024;
let mut vec = Vec::with_capacity(2048 );
let is_buf_too_small = |e: &Error| match (e.high_level(), e.low_level()) {
(Some(HiError::EcpBufferTooSmall | HiError::SslBufferTooSmall | HiError::X509BufferTooSmall), _)
| (
_,
Some(
LoError::Asn1BufTooSmall
| LoError::Base64BufferTooSmall
| LoError::MpiBufferTooSmall
| LoError::NetBufferTooSmall
| LoError::OidBufTooSmall,
),
) => true,
_ => false,
};
loop {
match f(vec.as_mut_ptr(), vec.capacity()).into_result() {
Err(e) if is_buf_too_small(&e) && vec.capacity() < MAX_VECTOR_ALLOCATION => {
let cap = vec.capacity();
vec.reserve(cap * 2)
}
Err(e) => return Err(e),
Ok(n) => {
if data_at_end {
let len = vec.capacity();
unsafe { vec.set_len(len) };
drop(vec.drain(..len - (n as usize)));
} else {
unsafe { vec.set_len(n as usize) };
}
break;
}
}
}
vec.shrink_to_fit();
Ok(vec)
}
pub fn alloc_string_repeat<F>(mut f: F) -> Result<String>
where
F: FnMut(*mut c_char, size_t) -> c_int,
{
let vec = alloc_vec_repeat(|b, s| f(b as _, s), false)?;
String::from_utf8(vec).map_err(|e| e.utf8_error().into())
}
#[cfg(feature = "std")]
pub unsafe fn cstr_to_slice<'a>(ptr: *const c_char) -> &'a [u8] {
::std::ffi::CStr::from_ptr(ptr).to_bytes()
}
#[cfg(not(feature = "std"))]
pub unsafe fn cstr_to_slice<'a>(ptr: *const c_char) -> &'a [u8] {
extern "C" {
fn strlen(s: *const c_char) -> size_t;
}
::core::slice::from_raw_parts(ptr as *const _, strlen(ptr))
}
#[cfg(feature = "std")]
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
#[cfg(feature = "std")]
#[allow(dead_code)]
pub fn error_to_io_error(e: Error) -> IoError {
IoError::new(IoErrorKind::Other, e.to_string())
}