578 lines
18 KiB
Rust
578 lines
18 KiB
Rust
use std::ops::{Deref, DerefMut};
|
|
|
|
use ash::vk;
|
|
use bytemuck::{Pod, Zeroable};
|
|
|
|
#[macro_export]
|
|
macro_rules! def_monotonic_id {
|
|
($vis:vis $ty:ident) => {
|
|
#[derive(Copy, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)]
|
|
$vis struct $ty(::core::num::NonZero<u32>);
|
|
|
|
impl $ty {
|
|
pub fn new() -> Self {
|
|
use ::core::sync::atomic::{AtomicU32, Ordering};
|
|
static COUNTER: AtomicU32 = AtomicU32::new(1);
|
|
|
|
let inner = COUNTER.fetch_add(1, Ordering::Relaxed);
|
|
Self(
|
|
::core::num::NonZero::<u32>::new(inner)
|
|
.expect(&format!("integer overwarp for {}", stringify!($ty))),
|
|
)
|
|
}
|
|
|
|
pub fn as_u32(&self) -> u32 {
|
|
self.0.get()
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
pub trait MutexExt<'a, T: 'a> {
|
|
type Guard: Deref<Target = T> + 'a;
|
|
fn lock(&'a self) -> Self::Guard;
|
|
fn with_locked<R, F: FnOnce(&T) -> R>(&'a self, f: F) -> R {
|
|
let lock = MutexExt::lock(self);
|
|
f(&*lock)
|
|
}
|
|
}
|
|
|
|
impl<'a, T: 'a> MutexExt<'a, T> for parking_lot::Mutex<T> {
|
|
type Guard = parking_lot::MutexGuard<'a, T>;
|
|
fn lock(&'a self) -> Self::Guard {
|
|
self.lock()
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub trait FormatExt {
|
|
fn get_component_kind(&self) -> FormatComponentKind;
|
|
fn is_f32(&self) -> bool;
|
|
fn is_u32(&self) -> bool;
|
|
fn is_i32(&self) -> bool;
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
pub enum FormatComponentKind {
|
|
Float,
|
|
UInt,
|
|
SInt,
|
|
}
|
|
|
|
fn format_to_primitive(format: vk::Format) -> FormatComponentKind {
|
|
use FormatComponentKind::*;
|
|
match format {
|
|
vk::Format::BC6H_SFLOAT_BLOCK => Float,
|
|
vk::Format::D32_SFLOAT => Float,
|
|
vk::Format::R16G16B16A16_SFLOAT => Float,
|
|
vk::Format::R16G16B16_SFLOAT => Float,
|
|
vk::Format::R16G16_SFLOAT => Float,
|
|
vk::Format::R16_SFLOAT => Float,
|
|
vk::Format::R32G32B32A32_SFLOAT => Float,
|
|
vk::Format::R32G32B32_SFLOAT => Float,
|
|
vk::Format::R32G32_SFLOAT => Float,
|
|
vk::Format::R32_SFLOAT => Float,
|
|
vk::Format::R64G64B64A64_SFLOAT => Float,
|
|
vk::Format::R64G64B64_SFLOAT => Float,
|
|
vk::Format::R64G64_SFLOAT => Float,
|
|
vk::Format::R64_SFLOAT => Float,
|
|
vk::Format::D32_SFLOAT_S8_UINT => Float,
|
|
vk::Format::A2B10G10R10_SINT_PACK32 => SInt,
|
|
vk::Format::A2R10G10B10_SINT_PACK32 => SInt,
|
|
vk::Format::A8B8G8R8_SINT_PACK32 => SInt,
|
|
vk::Format::B8G8R8A8_SINT => SInt,
|
|
vk::Format::B8G8R8_SINT => SInt,
|
|
vk::Format::R16G16B16A16_SINT => SInt,
|
|
vk::Format::R16G16B16_SINT => SInt,
|
|
vk::Format::R16G16_SINT => SInt,
|
|
vk::Format::R16_SINT => SInt,
|
|
vk::Format::R32G32B32A32_SINT => SInt,
|
|
vk::Format::R32G32B32_SINT => SInt,
|
|
vk::Format::R32G32_SINT => SInt,
|
|
vk::Format::R32_SINT => SInt,
|
|
vk::Format::R64G64B64A64_SINT => SInt,
|
|
vk::Format::R64G64B64_SINT => SInt,
|
|
vk::Format::R64G64_SINT => SInt,
|
|
vk::Format::R64_SINT => SInt,
|
|
vk::Format::R8G8B8A8_SINT => SInt,
|
|
vk::Format::R8G8B8_SINT => SInt,
|
|
vk::Format::R8G8_SINT => SInt,
|
|
vk::Format::R8_SINT => SInt,
|
|
vk::Format::A2B10G10R10_SNORM_PACK32 => Float,
|
|
vk::Format::A2R10G10B10_SNORM_PACK32 => Float,
|
|
vk::Format::A8B8G8R8_SNORM_PACK32 => Float,
|
|
vk::Format::B8G8R8A8_SNORM => Float,
|
|
vk::Format::B8G8R8_SNORM => Float,
|
|
vk::Format::BC4_SNORM_BLOCK => Float,
|
|
vk::Format::BC5_SNORM_BLOCK => Float,
|
|
vk::Format::EAC_R11G11_SNORM_BLOCK => Float,
|
|
vk::Format::EAC_R11_SNORM_BLOCK => Float,
|
|
vk::Format::R16G16B16A16_SNORM => Float,
|
|
vk::Format::R16G16B16_SNORM => Float,
|
|
vk::Format::R16G16_SNORM => Float,
|
|
vk::Format::R16_SNORM => Float,
|
|
vk::Format::R8G8B8A8_SNORM => Float,
|
|
vk::Format::R8G8B8_SNORM => Float,
|
|
vk::Format::R8G8_SNORM => Float,
|
|
vk::Format::R8_SNORM => Float,
|
|
vk::Format::A8B8G8R8_SRGB_PACK32 => Float,
|
|
vk::Format::ASTC_10X10_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_10X5_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_10X6_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_10X8_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_12X10_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_12X12_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_4X4_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_5X4_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_5X5_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_6X5_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_6X6_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_8X5_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_8X6_SRGB_BLOCK => Float,
|
|
vk::Format::ASTC_8X8_SRGB_BLOCK => Float,
|
|
vk::Format::B8G8R8A8_SRGB => Float,
|
|
vk::Format::B8G8R8_SRGB => Float,
|
|
vk::Format::BC1_RGBA_SRGB_BLOCK => Float,
|
|
vk::Format::BC1_RGB_SRGB_BLOCK => Float,
|
|
vk::Format::BC2_SRGB_BLOCK => Float,
|
|
vk::Format::BC3_SRGB_BLOCK => Float,
|
|
vk::Format::BC7_SRGB_BLOCK => Float,
|
|
vk::Format::ETC2_R8G8B8A1_SRGB_BLOCK => Float,
|
|
vk::Format::ETC2_R8G8B8A8_SRGB_BLOCK => Float,
|
|
vk::Format::ETC2_R8G8B8_SRGB_BLOCK => Float,
|
|
vk::Format::R8G8B8A8_SRGB => Float,
|
|
vk::Format::R8G8B8_SRGB => Float,
|
|
vk::Format::R8G8_SRGB => Float,
|
|
vk::Format::R8_SRGB => Float,
|
|
vk::Format::A2B10G10R10_SSCALED_PACK32 => Float,
|
|
vk::Format::A2R10G10B10_SSCALED_PACK32 => Float,
|
|
vk::Format::A8B8G8R8_SSCALED_PACK32 => Float,
|
|
vk::Format::B8G8R8A8_SSCALED => Float,
|
|
vk::Format::B8G8R8_SSCALED => Float,
|
|
vk::Format::R16G16B16A16_SSCALED => Float,
|
|
vk::Format::R16G16B16_SSCALED => Float,
|
|
vk::Format::R16G16_SSCALED => Float,
|
|
vk::Format::R16_SSCALED => Float,
|
|
vk::Format::R8G8B8A8_SSCALED => Float,
|
|
vk::Format::R8G8B8_SSCALED => Float,
|
|
vk::Format::R8G8_SSCALED => Float,
|
|
vk::Format::R8_SSCALED => Float,
|
|
vk::Format::B10G11R11_UFLOAT_PACK32 => Float,
|
|
vk::Format::BC6H_UFLOAT_BLOCK => Float,
|
|
vk::Format::E5B9G9R9_UFLOAT_PACK32 => Float,
|
|
vk::Format::A2B10G10R10_UINT_PACK32 => UInt,
|
|
vk::Format::A2R10G10B10_UINT_PACK32 => UInt,
|
|
vk::Format::A8B8G8R8_UINT_PACK32 => UInt,
|
|
vk::Format::B8G8R8A8_UINT => UInt,
|
|
vk::Format::B8G8R8_UINT => UInt,
|
|
vk::Format::R16G16B16A16_UINT => UInt,
|
|
vk::Format::R16G16B16_UINT => UInt,
|
|
vk::Format::R16G16_UINT => UInt,
|
|
vk::Format::R16_UINT => UInt,
|
|
vk::Format::R32G32B32A32_UINT => UInt,
|
|
vk::Format::R32G32B32_UINT => UInt,
|
|
vk::Format::R32G32_UINT => UInt,
|
|
vk::Format::R32_UINT => UInt,
|
|
vk::Format::R64G64B64A64_UINT => UInt,
|
|
vk::Format::R64G64B64_UINT => UInt,
|
|
vk::Format::R64G64_UINT => UInt,
|
|
vk::Format::R64_UINT => UInt,
|
|
vk::Format::R8G8B8A8_UINT => UInt,
|
|
vk::Format::R8G8B8_UINT => UInt,
|
|
vk::Format::R8G8_UINT => UInt,
|
|
vk::Format::R8_UINT => UInt,
|
|
vk::Format::S8_UINT => UInt,
|
|
vk::Format::A1R5G5B5_UNORM_PACK16 => Float,
|
|
vk::Format::A2B10G10R10_UNORM_PACK32 => Float,
|
|
vk::Format::A2R10G10B10_UNORM_PACK32 => Float,
|
|
vk::Format::A8B8G8R8_UNORM_PACK32 => Float,
|
|
vk::Format::ASTC_10X10_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_10X5_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_10X6_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_10X8_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_12X10_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_12X12_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_4X4_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_5X4_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_5X5_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_6X5_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_6X6_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_8X5_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_8X6_UNORM_BLOCK => Float,
|
|
vk::Format::ASTC_8X8_UNORM_BLOCK => Float,
|
|
vk::Format::B4G4R4A4_UNORM_PACK16 => Float,
|
|
vk::Format::B5G5R5A1_UNORM_PACK16 => Float,
|
|
vk::Format::B5G6R5_UNORM_PACK16 => Float,
|
|
vk::Format::B8G8R8A8_UNORM => Float,
|
|
vk::Format::B8G8R8_UNORM => Float,
|
|
vk::Format::BC1_RGBA_UNORM_BLOCK => Float,
|
|
vk::Format::BC1_RGB_UNORM_BLOCK => Float,
|
|
vk::Format::BC2_UNORM_BLOCK => Float,
|
|
vk::Format::BC3_UNORM_BLOCK => Float,
|
|
vk::Format::BC4_UNORM_BLOCK => Float,
|
|
vk::Format::BC5_UNORM_BLOCK => Float,
|
|
vk::Format::BC7_UNORM_BLOCK => Float,
|
|
vk::Format::D16_UNORM => Float,
|
|
vk::Format::D16_UNORM_S8_UINT => Float,
|
|
vk::Format::D24_UNORM_S8_UINT => Float,
|
|
vk::Format::EAC_R11G11_UNORM_BLOCK => Float,
|
|
vk::Format::EAC_R11_UNORM_BLOCK => Float,
|
|
vk::Format::ETC2_R8G8B8A1_UNORM_BLOCK => Float,
|
|
vk::Format::ETC2_R8G8B8A8_UNORM_BLOCK => Float,
|
|
vk::Format::ETC2_R8G8B8_UNORM_BLOCK => Float,
|
|
vk::Format::R16G16B16A16_UNORM => Float,
|
|
vk::Format::R16G16B16_UNORM => Float,
|
|
vk::Format::R16G16_UNORM => Float,
|
|
vk::Format::R16_UNORM => Float,
|
|
vk::Format::R4G4B4A4_UNORM_PACK16 => Float,
|
|
vk::Format::R4G4_UNORM_PACK8 => Float,
|
|
vk::Format::R5G5B5A1_UNORM_PACK16 => Float,
|
|
vk::Format::R5G6B5_UNORM_PACK16 => Float,
|
|
vk::Format::R8G8B8A8_UNORM => Float,
|
|
vk::Format::R8G8B8_UNORM => Float,
|
|
vk::Format::R8G8_UNORM => Float,
|
|
vk::Format::R8_UNORM => Float,
|
|
vk::Format::X8_D24_UNORM_PACK32 => Float,
|
|
vk::Format::A2B10G10R10_USCALED_PACK32 => Float,
|
|
vk::Format::A2R10G10B10_USCALED_PACK32 => Float,
|
|
vk::Format::A8B8G8R8_USCALED_PACK32 => Float,
|
|
vk::Format::B8G8R8A8_USCALED => Float,
|
|
vk::Format::B8G8R8_USCALED => Float,
|
|
vk::Format::R16G16B16A16_USCALED => Float,
|
|
vk::Format::R16G16B16_USCALED => Float,
|
|
vk::Format::R16G16_USCALED => Float,
|
|
vk::Format::R16_USCALED => Float,
|
|
vk::Format::R8G8B8A8_USCALED => Float,
|
|
vk::Format::R8G8B8_USCALED => Float,
|
|
vk::Format::R8G8_USCALED => Float,
|
|
vk::Format::R8_USCALED => Float,
|
|
_ => unimplemented!(),
|
|
}
|
|
}
|
|
|
|
impl FormatExt for vk::Format {
|
|
fn get_component_kind(&self) -> FormatComponentKind {
|
|
format_to_primitive(*self)
|
|
}
|
|
fn is_f32(&self) -> bool {
|
|
format_to_primitive(*self) == FormatComponentKind::Float
|
|
}
|
|
|
|
fn is_u32(&self) -> bool {
|
|
format_to_primitive(*self) == FormatComponentKind::UInt
|
|
}
|
|
|
|
fn is_i32(&self) -> bool {
|
|
format_to_primitive(*self) == FormatComponentKind::SInt
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)]
|
|
pub struct Rect2D {
|
|
top_left: glam::IVec2,
|
|
bottom_right: glam::IVec2,
|
|
}
|
|
|
|
impl Rect2D {
|
|
pub fn new(left: i32, top: i32, right: i32, bottom: i32) -> Self {
|
|
use glam::ivec2;
|
|
Self {
|
|
top_left: ivec2(left, top),
|
|
bottom_right: ivec2(right, bottom),
|
|
}
|
|
}
|
|
pub fn new_from_size(pos: glam::IVec2, size: glam::IVec2) -> Self {
|
|
Self {
|
|
top_left: pos,
|
|
bottom_right: pos + size,
|
|
}
|
|
}
|
|
|
|
pub fn into_offsets_3d(&self) -> [vk::Offset3D; 2] {
|
|
[
|
|
vk::Offset3D {
|
|
x: self.top_left.x,
|
|
y: self.top_left.y,
|
|
z: 0,
|
|
},
|
|
vk::Offset3D {
|
|
x: self.bottom_right.x,
|
|
y: self.bottom_right.y,
|
|
z: 1,
|
|
},
|
|
]
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn top_left(&self) -> glam::IVec2 {
|
|
self.top_left
|
|
}
|
|
#[allow(dead_code)]
|
|
pub fn size(&self) -> glam::IVec2 {
|
|
self.bottom_right - self.top_left
|
|
}
|
|
#[allow(dead_code)]
|
|
pub fn width(&self) -> i32 {
|
|
self.bottom_right.x - self.top_left.x
|
|
}
|
|
#[allow(dead_code)]
|
|
pub fn height(&self) -> i32 {
|
|
self.bottom_right.y - self.top_left.y
|
|
}
|
|
}
|
|
|
|
pub fn eq_f32(lhs: f32, rhs: f32) -> bool {
|
|
use core::num::FpCategory::*;
|
|
match (lhs.classify(), rhs.classify()) {
|
|
(Zero, Zero) | (Nan, Nan) => true,
|
|
(Infinite, Infinite) => lhs.signum() == rhs.signum(),
|
|
_ => lhs == rhs,
|
|
}
|
|
}
|
|
|
|
pub fn hash_f32<H: std::hash::Hasher>(state: &mut H, f: f32) {
|
|
use std::hash::Hash;
|
|
let classify = f.classify();
|
|
match classify {
|
|
std::num::FpCategory::Nan => (classify as u8).hash(state),
|
|
std::num::FpCategory::Infinite | std::num::FpCategory::Zero => {
|
|
(classify as u8, f.signum() as i8).hash(state)
|
|
}
|
|
std::num::FpCategory::Subnormal | std::num::FpCategory::Normal => f.to_bits().hash(state),
|
|
}
|
|
}
|
|
|
|
pub fn timed<T, F: FnOnce() -> T>(label: &str, f: F) -> T {
|
|
let now = std::time::Instant::now();
|
|
let out = f();
|
|
tracing::info!("{label}: {}ms", now.elapsed().as_micros() as f32 / 1e3);
|
|
|
|
out
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
#[repr(transparent)]
|
|
pub struct Rgba(pub [f32; 4]);
|
|
|
|
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
|
|
#[repr(transparent)]
|
|
pub struct Rgba8(pub [u8; 4]);
|
|
|
|
impl std::hash::Hash for Rgba {
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
self.0.map(|f| hash_f32(state, f));
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
impl Rgba {
|
|
pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
|
|
Self([r, g, b, a])
|
|
}
|
|
pub fn into_u32(&self) -> [u32; 4] {
|
|
self.0.map(|f| (f.clamp(0.0, 1.0) * 255.0) as u32)
|
|
}
|
|
pub fn into_f32(&self) -> [f32; 4] {
|
|
self.0
|
|
}
|
|
pub fn into_u8(&self) -> Rgba8 {
|
|
Rgba8(self.0.map(|f| (f.clamp(0.0, 1.0) * 255.0) as u8))
|
|
}
|
|
pub fn into_snorm(&self) -> [f32; 4] {
|
|
self.0.map(|f| (f - 0.5) * 2.0)
|
|
}
|
|
pub fn into_i32(&self) -> [i32; 4] {
|
|
self.0.map(|f| (f.clamp(0.0, 1.0) * 255.0) as i32 - 128)
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub fn image_aspect_from_format(format: vk::Format) -> vk::ImageAspectFlags {
|
|
use vk::{Format, ImageAspectFlags};
|
|
match format {
|
|
Format::D32_SFLOAT | Format::X8_D24_UNORM_PACK32 | Format::D16_UNORM => {
|
|
ImageAspectFlags::DEPTH
|
|
}
|
|
Format::S8_UINT => ImageAspectFlags::STENCIL,
|
|
Format::D32_SFLOAT_S8_UINT | Format::D16_UNORM_S8_UINT | Format::D24_UNORM_S8_UINT => {
|
|
ImageAspectFlags::DEPTH | ImageAspectFlags::STENCIL
|
|
}
|
|
_ => ImageAspectFlags::COLOR,
|
|
}
|
|
}
|
|
|
|
#[repr(transparent)]
|
|
pub struct WithLifetime<'a, T>(T, std::marker::PhantomData<&'a ()>);
|
|
|
|
impl<T> WithLifetime<'_, T> {
|
|
pub fn new(t: T) -> Self {
|
|
Self(t, std::marker::PhantomData)
|
|
}
|
|
}
|
|
|
|
impl<'a, T: 'a> Deref for WithLifetime<'a, T> {
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
&self.0
|
|
}
|
|
}
|
|
|
|
impl<'a, T: 'a> DerefMut for WithLifetime<'a, T> {
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
&mut self.0
|
|
}
|
|
}
|
|
|
|
bitflags::bitflags! {
|
|
pub struct PipelineAccess: u32 {
|
|
const TRANSFER = 1 << 0;
|
|
const VERTEX_ATTRIBUTE_INPUT = 1 << 1;
|
|
const DRAW_INDIRECT = 1 << 2;
|
|
const VERTEX_INPUT = 1 << 3;
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct BitIter<'a> {
|
|
bits: &'a [u64],
|
|
num_bits: usize,
|
|
bit_offset: usize,
|
|
bit_index: usize,
|
|
}
|
|
|
|
impl<'a> std::fmt::Display for BitIter<'a> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.debug_struct("BitIter")
|
|
.field_with("bits", |f| {
|
|
write!(f, "[")?;
|
|
for bit in self.clone() {
|
|
write!(f, "{bit}, ")?;
|
|
}
|
|
write!(f, " ]")
|
|
})
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
impl<'a> BitIter<'a> {
|
|
pub fn new(bits: &'a [u64], num_bits: usize) -> Self {
|
|
Self {
|
|
bits,
|
|
num_bits,
|
|
bit_index: 0,
|
|
bit_offset: 0,
|
|
}
|
|
}
|
|
|
|
pub fn chunks(self, chunk_size: usize) -> ChunkedBitIter<'a> {
|
|
ChunkedBitIter {
|
|
inner: self,
|
|
chunk_size,
|
|
pos: 0,
|
|
}
|
|
}
|
|
}
|
|
impl Iterator for BitIter<'_> {
|
|
type Item = usize;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
loop {
|
|
if self.bit_index >= self.num_bits {
|
|
return None;
|
|
}
|
|
|
|
let bit_index = self.bit_index + self.bit_offset;
|
|
let byte_idx = bit_index / 64;
|
|
let byte_offset = bit_index % 64;
|
|
self.bit_index += 1;
|
|
|
|
if (self.bits[byte_idx] >> byte_offset) & 1 == 1 {
|
|
return Some(self.bit_index - 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct ChunkedBitIter<'a> {
|
|
inner: BitIter<'a>,
|
|
chunk_size: usize,
|
|
pos: usize,
|
|
}
|
|
|
|
impl<'a> Iterator for ChunkedBitIter<'a> {
|
|
type Item = BitIter<'a>;
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
if self.pos >= self.inner.num_bits {
|
|
return None;
|
|
}
|
|
let bits = (self.inner.num_bits - self.pos).min(self.chunk_size);
|
|
|
|
let iter = BitIter {
|
|
bits: &self.inner.bits[self.pos / 64..],
|
|
bit_offset: self.pos % 64,
|
|
bit_index: 0,
|
|
num_bits: bits,
|
|
};
|
|
self.pos += bits;
|
|
|
|
Some(iter)
|
|
}
|
|
}
|
|
|
|
pub struct RawMutexGuard<'a, T> {
|
|
pub(crate) mutex: &'a parking_lot::RawMutex,
|
|
pub(crate) value: &'a T,
|
|
pub(crate) _pd: std::marker::PhantomData<&'a ()>,
|
|
}
|
|
|
|
impl<'a, T> std::ops::Deref for RawMutexGuard<'a, T> {
|
|
type Target = T;
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
self.value
|
|
}
|
|
}
|
|
|
|
impl<T> Drop for RawMutexGuard<'_, T> {
|
|
fn drop(&mut self) {
|
|
use parking_lot::lock_api::RawMutex;
|
|
unsafe {
|
|
self.mutex.unlock();
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct CStringList {
|
|
pub strings: Box<[*const i8]>,
|
|
#[allow(unused)]
|
|
bytes: Box<[u8]>,
|
|
}
|
|
|
|
impl CStringList {
|
|
pub fn from_iter<I, S>(i: I) -> CStringList
|
|
where
|
|
I: IntoIterator<Item = S>,
|
|
S: AsRef<str>,
|
|
{
|
|
let mut bytes = vec![];
|
|
let mut strings = vec![];
|
|
i.into_iter().for_each(|s| {
|
|
let start = bytes.len();
|
|
bytes.extend_from_slice(s.as_ref().as_bytes());
|
|
bytes.push(0);
|
|
strings.push(start);
|
|
});
|
|
|
|
let bytes = bytes.into_boxed_slice();
|
|
Self {
|
|
strings: strings
|
|
.into_iter()
|
|
.map(|offset| unsafe { bytes.as_ptr().offset(offset as isize) as *const i8 })
|
|
.collect(),
|
|
bytes,
|
|
}
|
|
}
|
|
}
|