use crate::*;
use crate::alloc::{Allocator, CBoxSized};
use winapi::um::winnt::{SID, PSID, SID_AND_ATTRIBUTES};
use core::mem::{size_of, align_of};
#[track_caller] pub fn assert_valid_ptr_bytes<T, U, A: Allocator>(cbs: &CBoxSized<T, A>, ptr: *const U, min_count: usize) -> usize {
if ptr.is_null() && min_count == 0 { return 0 }
let pbegin = cbs.as_ptr() as usize;
let pend = pbegin + cbs.bytes(); let pbegin = pbegin + size_of::<T>().min(cbs.bytes()); let ptr = ptr as usize;
assert!(ptr % align_of::<U>() == 0, "ptr was not aligned");
assert!(pbegin <= ptr, "ptr not part of `cbs` allocation");
assert!(ptr < pend, "ptr not part of `cbs` allocation");
let bytes_avail = pend - ptr; let count_avail = bytes_avail / size_of::<U>();
assert!(min_count <= count_avail, "ptr valid for at most {count_avail} elements, but was required to be valid for {min_count} elements");
bytes_avail
}
#[track_caller] pub fn assert_valid_sid_or_null<T, A: Allocator>(cbs: &CBoxSized<T, A>, sid: PSID) {
if sid.is_null() { return }
assert_valid_sid(cbs, sid)
}
#[track_caller] pub fn assert_valid_sid<T, A: Allocator>(cbs: &CBoxSized<T, A>, sid: PSID) {
let p = cbs.as_ptr() as usize;
let pend = p + cbs.bytes(); let psid = sid as usize;
assert!(psid % align_of::<SID>() == 0, "sid was expected to have proper alignment");
assert!(p + size_of::<T>() <= psid, "sid was expected to trail the header in the same buffer");
assert!(psid <= pend, "sid was expected to trail the header in the same buffer");
let sid_bytes = pend - psid; let _validate_sid = unsafe { sid::Ptr::from_raw(sid.cast(), sid_bytes) }.expect("sid was truncated or otherwise invalid");
}
#[track_caller] pub fn assert_valid_saa<T, A: Allocator>(cbs: &CBoxSized<T, A>, saa: SID_AND_ATTRIBUTES) {
assert_valid_sid(cbs, saa.Sid);
let _ = saa.Attributes; }
#[track_caller] pub unsafe fn assert_valid_after_header_slice<T, U, A: Allocator>(cbs: &CBoxSized<T, A>, ptr: *const U, count: impl TryInto<usize>, allow_overlap_header: bool) -> &[U] {
let count = count.try_into().map_err(|_| ()).expect("slice count was too large to fit into same buffer");
if ptr.is_null() {
assert!(count == 0, "slice pointer was null with nonzero count");
return &[]
}
let ptr = provenance_addr(cbs.as_ptr(), ptr); let p = cbs.as_ptr() as usize;
let pend = p + cbs.bytes(); let pslice = ptr as usize;
assert!(pslice % align_of::<U>() == 0, "slice was expected to have proper alignment");
assert!(allow_overlap_header || p + size_of::<T>() <= pslice, "slice was expected to trail header in the same buffer, but it started in the header");
assert!(pslice <= pend, "slice was expected to trail header in the same buffer, but it started after the end of the buffer");
let slice_bytes_needed = count.checked_mul(size_of::<U>()).expect("slice size cannot fit in memory");
let slice_bytes_available = pend - pslice; assert!(slice_bytes_available >= slice_bytes_needed, "slice was expected to trail header in the same buffer");
unsafe { core::slice::from_raw_parts(ptr, count) }
}