Address all the clippy lints (#233)
* Fix literals in vk.rs * Address all the other clippy lints in ash * Module level clippy lint * More lints * Make hashmaps generic for clippy * Remove unused macro import
This commit is contained in:
parent
f935337aa8
commit
855068323d
|
@ -1,4 +1,4 @@
|
||||||
#![allow(dead_code)]
|
#![allow(clippy::trivially_copy_pass_by_ref)]
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::vk;
|
use crate::vk;
|
||||||
use crate::RawPtr;
|
use crate::RawPtr;
|
||||||
|
|
|
@ -13,19 +13,19 @@ use std::ptr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
const LIB_PATH: &'static str = "vulkan-1.dll";
|
const LIB_PATH: &str = "vulkan-1.dll";
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
unix,
|
unix,
|
||||||
not(any(target_os = "macos", target_os = "ios", target_os = "android"))
|
not(any(target_os = "macos", target_os = "ios", target_os = "android"))
|
||||||
))]
|
))]
|
||||||
const LIB_PATH: &'static str = "libvulkan.so.1";
|
const LIB_PATH: &str = "libvulkan.so.1";
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
const LIB_PATH: &'static str = "libvulkan.so";
|
const LIB_PATH: &str = "libvulkan.so";
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
const LIB_PATH: &'static str = "libvulkan.dylib";
|
const LIB_PATH: &str = "libvulkan.dylib";
|
||||||
|
|
||||||
/// Function loader
|
/// Function loader
|
||||||
pub type Entry = EntryCustom<Arc<DynamicLibrary>>;
|
pub type Entry = EntryCustom<Arc<DynamicLibrary>>;
|
||||||
|
@ -126,12 +126,12 @@ pub trait EntryV1_0 {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkGetInstanceProcAddr.html>"]
|
#[doc = "<https://www.khronos.org/registry/vulkan/specs/1.1-extensions/man/html/vkGetInstanceProcAddr.html>"]
|
||||||
fn get_instance_proc_addr(
|
unsafe fn get_instance_proc_addr(
|
||||||
&self,
|
&self,
|
||||||
instance: vk::Instance,
|
instance: vk::Instance,
|
||||||
p_name: *const c_char,
|
p_name: *const c_char,
|
||||||
) -> vk::PFN_vkVoidFunction {
|
) -> vk::PFN_vkVoidFunction {
|
||||||
unsafe { self.static_fn().get_instance_proc_addr(instance, p_name) }
|
self.static_fn().get_instance_proc_addr(instance, p_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ impl EntryCustom<Arc<DynamicLibrary>> {
|
||||||
|| {
|
|| {
|
||||||
DynamicLibrary::open(Some(&Path::new(LIB_PATH)))
|
DynamicLibrary::open(Some(&Path::new(LIB_PATH)))
|
||||||
.map_err(|err| LoadingError::LibraryLoadError(err.clone()))
|
.map_err(|err| LoadingError::LibraryLoadError(err.clone()))
|
||||||
.map(|dl| Arc::new(dl))
|
.map(Arc::new)
|
||||||
},
|
},
|
||||||
|vk_lib, name| unsafe {
|
|vk_lib, name| unsafe {
|
||||||
vk_lib
|
vk_lib
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#![allow(clippy::unreadable_literal)]
|
||||||
|
|
||||||
/*
|
/*
|
||||||
***********************************************************************************************************************
|
***********************************************************************************************************************
|
||||||
*
|
*
|
||||||
|
|
|
@ -15,9 +15,7 @@ impl DebugMarker {
|
||||||
let debug_marker_fn = vk::ExtDebugMarkerFn::load(|name| unsafe {
|
let debug_marker_fn = vk::ExtDebugMarkerFn::load(|name| unsafe {
|
||||||
mem::transmute(instance.get_device_proc_addr(device.handle(), name.as_ptr()))
|
mem::transmute(instance.get_device_proc_addr(device.handle(), name.as_ptr()))
|
||||||
});
|
});
|
||||||
DebugMarker {
|
DebugMarker { debug_marker_fn }
|
||||||
debug_marker_fn: debug_marker_fn,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name() -> &'static CStr {
|
pub fn name() -> &'static CStr {
|
||||||
|
|
|
@ -19,7 +19,7 @@ impl DisplaySwapchain {
|
||||||
});
|
});
|
||||||
DisplaySwapchain {
|
DisplaySwapchain {
|
||||||
handle: device.handle(),
|
handle: device.handle(),
|
||||||
swapchain_fn: swapchain_fn,
|
swapchain_fn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ impl Surface {
|
||||||
});
|
});
|
||||||
Surface {
|
Surface {
|
||||||
handle: instance.handle(),
|
handle: instance.handle(),
|
||||||
surface_fn: surface_fn,
|
surface_fn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ impl Swapchain {
|
||||||
});
|
});
|
||||||
Swapchain {
|
Swapchain {
|
||||||
handle: device.handle(),
|
handle: device.handle(),
|
||||||
swapchain_fn: swapchain_fn,
|
swapchain_fn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![allow(clippy::too_many_arguments)]
|
||||||
//! # Vulkan API
|
//! # Vulkan API
|
||||||
//!
|
//!
|
||||||
//! <https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/index.html>
|
//! <https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/index.html>
|
||||||
|
@ -43,8 +44,8 @@ pub trait RawPtr<T> {
|
||||||
|
|
||||||
impl<'r, T> RawPtr<T> for Option<&'r T> {
|
impl<'r, T> RawPtr<T> for Option<&'r T> {
|
||||||
fn as_raw_ptr(&self) -> *const T {
|
fn as_raw_ptr(&self) -> *const T {
|
||||||
match self {
|
match *self {
|
||||||
&Some(inner) => inner as *const T,
|
Some(inner) => inner as *const T,
|
||||||
|
|
||||||
_ => ::std::ptr::null(),
|
_ => ::std::ptr::null(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,13 +122,13 @@ pub fn read_spv<R: io::Read + io::Seek>(x: &mut R) -> io::Result<Vec<u32>> {
|
||||||
))?;
|
))?;
|
||||||
result.set_len(words);
|
result.set_len(words);
|
||||||
}
|
}
|
||||||
const MAGIC_NUMBER: u32 = 0x07230203;
|
const MAGIC_NUMBER: u32 = 0x0723_0203;
|
||||||
if result.len() > 0 && result[0] == MAGIC_NUMBER.swap_bytes() {
|
if !result.is_empty() && result[0] == MAGIC_NUMBER.swap_bytes() {
|
||||||
for word in &mut result {
|
for word in &mut result {
|
||||||
*word = word.swap_bytes();
|
*word = word.swap_bytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if result.len() == 0 || result[0] != MAGIC_NUMBER {
|
if result.is_empty() || result[0] != MAGIC_NUMBER {
|
||||||
return Err(io::Error::new(
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::InvalidData,
|
io::ErrorKind::InvalidData,
|
||||||
"input missing SPIR-V magic number",
|
"input missing SPIR-V magic number",
|
||||||
|
|
1264
ash/src/vk.rs
1264
ash/src/vk.rs
File diff suppressed because it is too large
Load diff
|
@ -522,7 +522,7 @@ fn main() {
|
||||||
let tex_descriptor = vk::DescriptorImageInfo {
|
let tex_descriptor = vk::DescriptorImageInfo {
|
||||||
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
|
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
|
||||||
image_view: tex_image_view,
|
image_view: tex_image_view,
|
||||||
sampler: sampler,
|
sampler,
|
||||||
};
|
};
|
||||||
|
|
||||||
let write_desc_sets = [
|
let write_desc_sets = [
|
||||||
|
@ -624,7 +624,7 @@ fn main() {
|
||||||
max_depth: 1.0,
|
max_depth: 1.0,
|
||||||
}];
|
}];
|
||||||
let scissors = [vk::Rect2D {
|
let scissors = [vk::Rect2D {
|
||||||
extent: base.surface_resolution.clone(),
|
extent: base.surface_resolution,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}];
|
}];
|
||||||
let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder()
|
let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder()
|
||||||
|
@ -652,8 +652,8 @@ fn main() {
|
||||||
depth_test_enable: 1,
|
depth_test_enable: 1,
|
||||||
depth_write_enable: 1,
|
depth_write_enable: 1,
|
||||||
depth_compare_op: vk::CompareOp::LESS_OR_EQUAL,
|
depth_compare_op: vk::CompareOp::LESS_OR_EQUAL,
|
||||||
front: noop_stencil_state.clone(),
|
front: noop_stencil_state,
|
||||||
back: noop_stencil_state.clone(),
|
back: noop_stencil_state,
|
||||||
max_depth_bounds: 1.0,
|
max_depth_bounds: 1.0,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -729,7 +729,7 @@ fn main() {
|
||||||
.framebuffer(framebuffers[present_index as usize])
|
.framebuffer(framebuffers[present_index as usize])
|
||||||
.render_area(vk::Rect2D {
|
.render_area(vk::Rect2D {
|
||||||
offset: vk::Offset2D { x: 0, y: 0 },
|
offset: vk::Offset2D { x: 0, y: 0 },
|
||||||
extent: base.surface_resolution.clone(),
|
extent: base.surface_resolution,
|
||||||
})
|
})
|
||||||
.clear_values(&clear_values);
|
.clear_values(&clear_values);
|
||||||
|
|
||||||
|
|
|
@ -284,7 +284,7 @@ fn main() {
|
||||||
}];
|
}];
|
||||||
let scissors = [vk::Rect2D {
|
let scissors = [vk::Rect2D {
|
||||||
offset: vk::Offset2D { x: 0, y: 0 },
|
offset: vk::Offset2D { x: 0, y: 0 },
|
||||||
extent: base.surface_resolution.clone(),
|
extent: base.surface_resolution,
|
||||||
}];
|
}];
|
||||||
let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder()
|
let viewport_state_info = vk::PipelineViewportStateCreateInfo::builder()
|
||||||
.scissors(&scissors)
|
.scissors(&scissors)
|
||||||
|
@ -311,8 +311,8 @@ fn main() {
|
||||||
depth_test_enable: 1,
|
depth_test_enable: 1,
|
||||||
depth_write_enable: 1,
|
depth_write_enable: 1,
|
||||||
depth_compare_op: vk::CompareOp::LESS_OR_EQUAL,
|
depth_compare_op: vk::CompareOp::LESS_OR_EQUAL,
|
||||||
front: noop_stencil_state.clone(),
|
front: noop_stencil_state,
|
||||||
back: noop_stencil_state.clone(),
|
back: noop_stencil_state,
|
||||||
max_depth_bounds: 1.0,
|
max_depth_bounds: 1.0,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -387,7 +387,7 @@ fn main() {
|
||||||
.framebuffer(framebuffers[present_index as usize])
|
.framebuffer(framebuffers[present_index as usize])
|
||||||
.render_area(vk::Rect2D {
|
.render_area(vk::Rect2D {
|
||||||
offset: vk::Offset2D { x: 0, y: 0 },
|
offset: vk::Offset2D { x: 0, y: 0 },
|
||||||
extent: base.surface_resolution.clone(),
|
extent: base.surface_resolution,
|
||||||
})
|
})
|
||||||
.clear_values(&clear_values);
|
.clear_values(&clear_values);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#[macro_use]
|
|
||||||
extern crate ash;
|
extern crate ash;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
extern crate winapi;
|
extern crate winapi;
|
||||||
|
@ -170,7 +169,7 @@ unsafe fn create_surface<E: EntryV1_0, I: InstanceV1_0>(
|
||||||
s_type: vk::StructureType::WIN32_SURFACE_CREATE_INFO_KHR,
|
s_type: vk::StructureType::WIN32_SURFACE_CREATE_INFO_KHR,
|
||||||
p_next: ptr::null(),
|
p_next: ptr::null(),
|
||||||
flags: Default::default(),
|
flags: Default::default(),
|
||||||
hinstance: hinstance,
|
hinstance,
|
||||||
hwnd: hwnd as *const c_void,
|
hwnd: hwnd as *const c_void,
|
||||||
};
|
};
|
||||||
let win32_surface_loader = Win32Surface::new(entry, instance);
|
let win32_surface_loader = Win32Surface::new(entry, instance);
|
||||||
|
@ -245,12 +244,10 @@ pub fn find_memorytype_index_f<F: Fn(vk::MemoryPropertyFlags, vk::MemoryProperty
|
||||||
) -> Option<u32> {
|
) -> Option<u32> {
|
||||||
let mut memory_type_bits = memory_req.memory_type_bits;
|
let mut memory_type_bits = memory_req.memory_type_bits;
|
||||||
for (index, ref memory_type) in memory_prop.memory_types.iter().enumerate() {
|
for (index, ref memory_type) in memory_prop.memory_types.iter().enumerate() {
|
||||||
if memory_type_bits & 1 == 1 {
|
if memory_type_bits & 1 == 1 && f(memory_type.property_flags, flags) {
|
||||||
if f(memory_type.property_flags, flags) {
|
|
||||||
return Some(index as u32);
|
return Some(index as u32);
|
||||||
}
|
}
|
||||||
}
|
memory_type_bits >>= 1;
|
||||||
memory_type_bits = memory_type_bits >> 1;
|
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -319,8 +316,8 @@ impl ExampleBase {
|
||||||
let window = winit::WindowBuilder::new()
|
let window = winit::WindowBuilder::new()
|
||||||
.with_title("Ash - Example")
|
.with_title("Ash - Example")
|
||||||
.with_dimensions(winit::dpi::LogicalSize::new(
|
.with_dimensions(winit::dpi::LogicalSize::new(
|
||||||
window_width as f64,
|
f64::from(window_width),
|
||||||
window_height as f64,
|
f64::from(window_height),
|
||||||
))
|
))
|
||||||
.build(&events_loop)
|
.build(&events_loop)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -385,9 +382,10 @@ impl ExampleBase {
|
||||||
surface,
|
surface,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
match supports_graphic_and_surface {
|
if supports_graphic_and_surface {
|
||||||
true => Some((*pdevice, index)),
|
Some((*pdevice, index))
|
||||||
_ => None,
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.nth(0)
|
.nth(0)
|
||||||
|
@ -429,7 +427,7 @@ impl ExampleBase {
|
||||||
format: vk::Format::B8G8R8_UNORM,
|
format: vk::Format::B8G8R8_UNORM,
|
||||||
color_space: sfmt.color_space,
|
color_space: sfmt.color_space,
|
||||||
},
|
},
|
||||||
_ => sfmt.clone(),
|
_ => *sfmt,
|
||||||
})
|
})
|
||||||
.nth(0)
|
.nth(0)
|
||||||
.expect("Unable to find suitable surface format.");
|
.expect("Unable to find suitable surface format.");
|
||||||
|
@ -472,7 +470,7 @@ impl ExampleBase {
|
||||||
.min_image_count(desired_image_count)
|
.min_image_count(desired_image_count)
|
||||||
.image_color_space(surface_format.color_space)
|
.image_color_space(surface_format.color_space)
|
||||||
.image_format(surface_format.format)
|
.image_format(surface_format.format)
|
||||||
.image_extent(surface_resolution.clone())
|
.image_extent(surface_resolution)
|
||||||
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
|
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
|
||||||
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
|
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
|
||||||
.pre_transform(pre_transform)
|
.pre_transform(pre_transform)
|
||||||
|
@ -625,32 +623,32 @@ impl ExampleBase {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
ExampleBase {
|
ExampleBase {
|
||||||
events_loop: RefCell::new(events_loop),
|
events_loop: RefCell::new(events_loop),
|
||||||
entry: entry,
|
entry,
|
||||||
instance: instance,
|
instance,
|
||||||
device: device,
|
device,
|
||||||
queue_family_index: queue_family_index,
|
queue_family_index,
|
||||||
pdevice: pdevice,
|
pdevice,
|
||||||
device_memory_properties: device_memory_properties,
|
device_memory_properties,
|
||||||
window: window,
|
window,
|
||||||
surface_loader: surface_loader,
|
surface_loader,
|
||||||
surface_format: surface_format,
|
surface_format,
|
||||||
present_queue: present_queue,
|
present_queue,
|
||||||
surface_resolution: surface_resolution,
|
surface_resolution,
|
||||||
swapchain_loader: swapchain_loader,
|
swapchain_loader,
|
||||||
swapchain: swapchain,
|
swapchain,
|
||||||
present_images: present_images,
|
present_images,
|
||||||
present_image_views: present_image_views,
|
present_image_views,
|
||||||
pool: pool,
|
pool,
|
||||||
draw_command_buffer: draw_command_buffer,
|
draw_command_buffer,
|
||||||
setup_command_buffer: setup_command_buffer,
|
setup_command_buffer,
|
||||||
depth_image: depth_image,
|
depth_image,
|
||||||
depth_image_view: depth_image_view,
|
depth_image_view,
|
||||||
present_complete_semaphore: present_complete_semaphore,
|
present_complete_semaphore,
|
||||||
rendering_complete_semaphore: rendering_complete_semaphore,
|
rendering_complete_semaphore,
|
||||||
surface: surface,
|
surface,
|
||||||
debug_call_back: debug_call_back,
|
debug_call_back,
|
||||||
debug_report_loader: debug_report_loader,
|
debug_report_loader,
|
||||||
depth_image_memory: depth_image_memory,
|
depth_image_memory,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ use proc_macro2::{Literal, Term};
|
||||||
use quote::Tokens;
|
use quote::Tokens;
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
use std::hash::BuildHasher;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use syn::Ident;
|
use syn::Ident;
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ named!(inverse_number<&str, (CType, String)>,
|
||||||
);
|
);
|
||||||
|
|
||||||
named!(cfloat<&str, f32>,
|
named!(cfloat<&str, f32>,
|
||||||
terminated!(nom::float_s, char!('f'))
|
terminated!(nom::float, char!('f'))
|
||||||
);
|
);
|
||||||
|
|
||||||
fn khronos_link<S: Display>(name: &S) -> Literal {
|
fn khronos_link<S: Display>(name: &S) -> Literal {
|
||||||
|
@ -429,6 +430,22 @@ impl quote::ToTokens for ConstVal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Interleaves a number, for example 100000 => 100_000. Mostly used to make clippy happy
|
||||||
|
fn interleave_number(symbol: char, count: usize, n: &str) -> String {
|
||||||
|
let number: String = n
|
||||||
|
.chars()
|
||||||
|
.rev()
|
||||||
|
.enumerate()
|
||||||
|
.fold(String::new(), |mut acc, (idx, next)| {
|
||||||
|
if idx != 0 && idx % count == 0 {
|
||||||
|
acc.push(symbol);
|
||||||
|
}
|
||||||
|
acc.push(next);
|
||||||
|
acc
|
||||||
|
});
|
||||||
|
number.chars().rev().collect()
|
||||||
|
}
|
||||||
impl Constant {
|
impl Constant {
|
||||||
pub fn value(&self) -> Option<ConstVal> {
|
pub fn value(&self) -> Option<ConstVal> {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -453,11 +470,13 @@ impl Constant {
|
||||||
pub fn to_tokens(&self) -> Tokens {
|
pub fn to_tokens(&self) -> Tokens {
|
||||||
match *self {
|
match *self {
|
||||||
Constant::Number(n) => {
|
Constant::Number(n) => {
|
||||||
let term = Term::intern(&n.to_string());
|
let number = interleave_number('_', 3, &n.to_string());
|
||||||
|
let term = Term::intern(&number);
|
||||||
quote! {#term}
|
quote! {#term}
|
||||||
}
|
}
|
||||||
Constant::Hex(ref s) => {
|
Constant::Hex(ref s) => {
|
||||||
let term = Term::intern(&format!("0x{}", s));
|
let number = interleave_number('_', 4, s);
|
||||||
|
let term = Term::intern(&format!("0x{}", number));
|
||||||
quote! {#term}
|
quote! {#term}
|
||||||
}
|
}
|
||||||
Constant::Text(ref text) => {
|
Constant::Text(ref text) => {
|
||||||
|
@ -470,7 +489,9 @@ impl Constant {
|
||||||
}
|
}
|
||||||
Constant::BitPos(pos) => {
|
Constant::BitPos(pos) => {
|
||||||
let value = 1 << pos;
|
let value = 1 << pos;
|
||||||
let term = Term::intern(&format!("0b{:b}", value));
|
let bit_string = format!("{:b}", value);
|
||||||
|
let bit_string = interleave_number('_', 4, &bit_string);
|
||||||
|
let term = Term::intern(&format!("0b{}", bit_string));
|
||||||
quote! {#term}
|
quote! {#term}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -501,8 +522,14 @@ impl Constant {
|
||||||
|
|
||||||
pub trait FeatureExt {
|
pub trait FeatureExt {
|
||||||
fn version_string(&self) -> String;
|
fn version_string(&self) -> String;
|
||||||
|
fn is_version(&self, major: u32, minor: u32) -> bool;
|
||||||
}
|
}
|
||||||
impl FeatureExt for vkxml::Feature {
|
impl FeatureExt for vkxml::Feature {
|
||||||
|
fn is_version(&self, major: u32, minor: u32) -> bool {
|
||||||
|
let self_major = self.version as u32;
|
||||||
|
let self_minor = (self.version * 10.0) as u32 - self_major;
|
||||||
|
major == self_major && self_minor == minor
|
||||||
|
}
|
||||||
fn version_string(&self) -> String {
|
fn version_string(&self) -> String {
|
||||||
let mut version = format!("{}", self.version);
|
let mut version = format!("{}", self.version);
|
||||||
if version.len() == 1 {
|
if version.len() == 1 {
|
||||||
|
@ -689,7 +716,7 @@ pub type CommandMap<'a> = HashMap<vkxml::Identifier, &'a vkxml::Command>;
|
||||||
fn generate_function_pointers<'a>(
|
fn generate_function_pointers<'a>(
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
commands: &[&'a vkxml::Command],
|
commands: &[&'a vkxml::Command],
|
||||||
fn_cache: &mut HashSet<&'a str>,
|
fn_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||||
) -> quote::Tokens {
|
) -> quote::Tokens {
|
||||||
let names: Vec<_> = commands.iter().map(|cmd| cmd.command_ident()).collect();
|
let names: Vec<_> = commands.iter().map(|cmd| cmd.command_ident()).collect();
|
||||||
let names_ref = &names;
|
let names_ref = &names;
|
||||||
|
@ -711,9 +738,9 @@ fn generate_function_pointers<'a>(
|
||||||
let ident = cmd.name.as_str();
|
let ident = cmd.name.as_str();
|
||||||
if !fn_cache.contains(ident) {
|
if !fn_cache.contains(ident) {
|
||||||
fn_cache.insert(ident);
|
fn_cache.insert(ident);
|
||||||
return true;
|
true
|
||||||
} else {
|
} else {
|
||||||
return false;
|
false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -879,7 +906,7 @@ pub fn generate_extension_constants<'a>(
|
||||||
extension_name: &str,
|
extension_name: &str,
|
||||||
extension_number: i64,
|
extension_number: i64,
|
||||||
extension_items: &'a [vk_parse::ExtensionChild],
|
extension_items: &'a [vk_parse::ExtensionChild],
|
||||||
const_cache: &mut HashSet<&'a str>,
|
const_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||||
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
||||||
) -> quote::Tokens {
|
) -> quote::Tokens {
|
||||||
use vk_parse::EnumSpec;
|
use vk_parse::EnumSpec;
|
||||||
|
@ -944,16 +971,14 @@ pub fn generate_extension_commands<'a>(
|
||||||
extension_name: &str,
|
extension_name: &str,
|
||||||
items: &[vk_parse::ExtensionChild],
|
items: &[vk_parse::ExtensionChild],
|
||||||
cmd_map: &CommandMap<'a>,
|
cmd_map: &CommandMap<'a>,
|
||||||
fn_cache: &mut HashSet<&'a str>,
|
fn_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||||
) -> Tokens {
|
) -> Tokens {
|
||||||
let commands = items
|
let commands = items
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|ext_item| match ext_item {
|
.filter_map(|ext_item| match ext_item {
|
||||||
vk_parse::ExtensionChild::Require { items, .. } => {
|
vk_parse::ExtensionChild::Require { items, .. } => {
|
||||||
Some(items.iter().filter_map(|item| match item {
|
Some(items.iter().filter_map(|item| match item {
|
||||||
vk_parse::InterfaceItem::Command { ref name, .. } => {
|
vk_parse::InterfaceItem::Command { ref name, .. } => cmd_map.get(name).copied(),
|
||||||
cmd_map.get(name).map(|c| *c)
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -983,9 +1008,9 @@ pub fn generate_extension_commands<'a>(
|
||||||
pub fn generate_extension<'a>(
|
pub fn generate_extension<'a>(
|
||||||
extension: &'a vk_parse::Extension,
|
extension: &'a vk_parse::Extension,
|
||||||
cmd_map: &CommandMap<'a>,
|
cmd_map: &CommandMap<'a>,
|
||||||
const_cache: &mut HashSet<&'a str>,
|
const_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||||
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
||||||
fn_cache: &mut HashSet<&'a str>,
|
fn_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||||
) -> Option<quote::Tokens> {
|
) -> Option<quote::Tokens> {
|
||||||
// Okay this is a little bit odd. We need to generate all extensions, even disabled ones,
|
// Okay this is a little bit odd. We need to generate all extensions, even disabled ones,
|
||||||
// because otherwise some StructureTypes won't get generated. But we don't generate extensions
|
// because otherwise some StructureTypes won't get generated. But we don't generate extensions
|
||||||
|
@ -1018,7 +1043,7 @@ pub fn generate_typedef(typedef: &vkxml::Typedef) -> Tokens {
|
||||||
}
|
}
|
||||||
pub fn generate_bitmask(
|
pub fn generate_bitmask(
|
||||||
bitmask: &vkxml::Bitmask,
|
bitmask: &vkxml::Bitmask,
|
||||||
bitflags_cache: &mut HashSet<Ident>,
|
bitflags_cache: &mut HashSet<Ident, impl BuildHasher>,
|
||||||
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
||||||
) -> Option<Tokens> {
|
) -> Option<Tokens> {
|
||||||
// Workaround for empty bitmask
|
// Workaround for empty bitmask
|
||||||
|
@ -1035,8 +1060,8 @@ pub fn generate_bitmask(
|
||||||
if bitflags_cache.contains(&ident) {
|
if bitflags_cache.contains(&ident) {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
bitflags_cache.insert(ident.clone());
|
bitflags_cache.insert(ident);
|
||||||
const_values.insert(ident.clone(), Vec::new());
|
const_values.insert(ident, Vec::new());
|
||||||
let khronos_link = khronos_link(&bitmask.name);
|
let khronos_link = khronos_link(&bitmask.name);
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
@ -1060,7 +1085,7 @@ pub fn variant_ident(enum_name: &str, variant_name: &str) -> Ident {
|
||||||
let vendors = ["_NVX", "_KHR", "_EXT", "_NV", "_AMD", "_ANDROID", "_GOOGLE"];
|
let vendors = ["_NVX", "_KHR", "_EXT", "_NV", "_AMD", "_ANDROID", "_GOOGLE"];
|
||||||
let mut struct_name = _name.to_shouty_snake_case();
|
let mut struct_name = _name.to_shouty_snake_case();
|
||||||
let vendor = vendors
|
let vendor = vendors
|
||||||
.into_iter()
|
.iter()
|
||||||
.find(|&vendor| struct_name.contains(vendor))
|
.find(|&vendor| struct_name.contains(vendor))
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or("");
|
.unwrap_or("");
|
||||||
|
@ -1124,9 +1149,9 @@ pub fn bitflags_impl_block(
|
||||||
|
|
||||||
pub fn generate_enum<'a>(
|
pub fn generate_enum<'a>(
|
||||||
_enum: &'a vkxml::Enumeration,
|
_enum: &'a vkxml::Enumeration,
|
||||||
const_cache: &mut HashSet<&'a str>,
|
const_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||||
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
||||||
bitflags_cache: &mut HashSet<Ident>,
|
bitflags_cache: &mut HashSet<Ident, impl BuildHasher>,
|
||||||
) -> EnumType {
|
) -> EnumType {
|
||||||
let name = &_enum.name[2..];
|
let name = &_enum.name[2..];
|
||||||
let _name = name.replace("FlagBits", "Flags");
|
let _name = name.replace("FlagBits", "Flags");
|
||||||
|
@ -1144,7 +1169,7 @@ pub fn generate_enum<'a>(
|
||||||
const_cache.insert(constant.name.as_str());
|
const_cache.insert(constant.name.as_str());
|
||||||
values.push(constant.variant_ident(&_enum.name));
|
values.push(constant.variant_ident(&_enum.name));
|
||||||
}
|
}
|
||||||
const_values.insert(ident.clone(), values);
|
const_values.insert(ident, values);
|
||||||
|
|
||||||
let khronos_link = khronos_link(&_enum.name);
|
let khronos_link = khronos_link(&_enum.name);
|
||||||
|
|
||||||
|
@ -1154,13 +1179,15 @@ pub fn generate_enum<'a>(
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|constant| Constant::from_constant(constant).value())
|
.filter_map(|constant| Constant::from_constant(constant).value())
|
||||||
.fold(0, |acc, next| acc | next.bits());
|
.fold(0, |acc, next| acc | next.bits());
|
||||||
let all_bits_term = Term::intern(&format!("0b{:b}", all_bits));
|
let bit_string = format!("{:b}", all_bits);
|
||||||
|
let bit_string = interleave_number('_', 4, &bit_string);
|
||||||
|
let all_bits_term = Term::intern(&format!("0b{}", bit_string));
|
||||||
|
|
||||||
let impl_bitflags = bitflags_impl_block(ident, &_enum.name, &constants);
|
let impl_bitflags = bitflags_impl_block(ident, &_enum.name, &constants);
|
||||||
if bitflags_cache.contains(&ident) {
|
if bitflags_cache.contains(&ident) {
|
||||||
EnumType::Bitflags(quote! {})
|
EnumType::Bitflags(quote! {})
|
||||||
} else {
|
} else {
|
||||||
bitflags_cache.insert(ident.clone());
|
bitflags_cache.insert(ident);
|
||||||
let q = quote! {
|
let q = quote! {
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
@ -1344,7 +1371,10 @@ pub fn derive_default(_struct: &vkxml::Struct) -> Option<Tokens> {
|
||||||
};
|
};
|
||||||
Some(q)
|
Some(q)
|
||||||
}
|
}
|
||||||
pub fn derive_debug(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Option<Tokens> {
|
pub fn derive_debug(
|
||||||
|
_struct: &vkxml::Struct,
|
||||||
|
union_types: &HashSet<&str, impl BuildHasher>,
|
||||||
|
) -> Option<Tokens> {
|
||||||
let name = name_to_tokens(&_struct.name);
|
let name = name_to_tokens(&_struct.name);
|
||||||
let members = _struct.elements.iter().filter_map(|elem| match *elem {
|
let members = _struct.elements.iter().filter_map(|elem| match *elem {
|
||||||
vkxml::StructElement::Member(ref field) => Some(field),
|
vkxml::StructElement::Member(ref field) => Some(field),
|
||||||
|
@ -1405,7 +1435,7 @@ pub fn derive_debug(_struct: &vkxml::Struct, union_types: &HashSet<&str>) -> Opt
|
||||||
|
|
||||||
pub fn derive_setters(
|
pub fn derive_setters(
|
||||||
_struct: &vkxml::Struct,
|
_struct: &vkxml::Struct,
|
||||||
root_struct_names: &HashSet<String>,
|
root_struct_names: &HashSet<String, impl BuildHasher>,
|
||||||
) -> Option<Tokens> {
|
) -> Option<Tokens> {
|
||||||
if &_struct.name == "VkBaseInStructure" || &_struct.name == "VkBaseOutStructure" {
|
if &_struct.name == "VkBaseInStructure" || &_struct.name == "VkBaseOutStructure" {
|
||||||
return None;
|
return None;
|
||||||
|
@ -1421,7 +1451,7 @@ pub fn derive_setters(
|
||||||
|
|
||||||
let (has_next, _is_next_const) = match members
|
let (has_next, _is_next_const) = match members
|
||||||
.clone()
|
.clone()
|
||||||
.find(|field| field.param_ident().to_string() == "p_next")
|
.find(|field| field.param_ident().as_ref() == "p_next")
|
||||||
{
|
{
|
||||||
Some(p_next) => {
|
Some(p_next) => {
|
||||||
if p_next.type_tokens(false).to_string().starts_with("*const") {
|
if p_next.type_tokens(false).to_string().starts_with("*const") {
|
||||||
|
@ -1449,7 +1479,7 @@ pub fn derive_setters(
|
||||||
if !array_size.starts_with("latexmath")
|
if !array_size.starts_with("latexmath")
|
||||||
&& !nofilter_count_members
|
&& !nofilter_count_members
|
||||||
.iter()
|
.iter()
|
||||||
.any(|n| *n == &(_struct.name.clone() + "." + field_name))
|
.any(|&n| n == (_struct.name.clone() + "." + field_name))
|
||||||
{
|
{
|
||||||
return Some((*array_size).clone());
|
return Some((*array_size).clone());
|
||||||
}
|
}
|
||||||
|
@ -1561,8 +1591,7 @@ pub fn derive_setters(
|
||||||
let slice_param_ty_tokens = Term::intern(&slice_param_ty_tokens);
|
let slice_param_ty_tokens = Term::intern(&slice_param_ty_tokens);
|
||||||
let ptr = Term::intern(ptr);
|
let ptr = Term::intern(ptr);
|
||||||
|
|
||||||
match array_type {
|
if let vkxml::ArrayType::Dynamic = array_type {
|
||||||
vkxml::ArrayType::Dynamic => {
|
|
||||||
return Some(quote!{
|
return Some(quote!{
|
||||||
pub fn #param_ident_short(mut self, #param_ident_short: #slice_param_ty_tokens) -> #name_builder<'a> {
|
pub fn #param_ident_short(mut self, #param_ident_short: #slice_param_ty_tokens) -> #name_builder<'a> {
|
||||||
self.inner.#array_size_ident = #param_ident_short.len() as _;
|
self.inner.#array_size_ident = #param_ident_short.len() as _;
|
||||||
|
@ -1571,8 +1600,6 @@ pub fn derive_setters(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1618,7 +1645,7 @@ pub fn derive_setters(
|
||||||
.map(|extends| name_to_tokens(&format!("Extends{}", name_to_tokens(&extends))))
|
.map(|extends| name_to_tokens(&format!("Extends{}", name_to_tokens(&extends))))
|
||||||
.collect()
|
.collect()
|
||||||
})
|
})
|
||||||
.unwrap_or(vec![]);
|
.unwrap_or_else(|| vec![]);
|
||||||
|
|
||||||
// We only implement a next methods for root structs with a `pnext` field.
|
// We only implement a next methods for root structs with a `pnext` field.
|
||||||
let next_function = if has_next && root_structs.is_empty() {
|
let next_function = if has_next && root_structs.is_empty() {
|
||||||
|
@ -1735,8 +1762,8 @@ pub fn manual_derives(_struct: &vkxml::Struct) -> Tokens {
|
||||||
}
|
}
|
||||||
pub fn generate_struct(
|
pub fn generate_struct(
|
||||||
_struct: &vkxml::Struct,
|
_struct: &vkxml::Struct,
|
||||||
root_struct_names: &HashSet<String>,
|
root_struct_names: &HashSet<String, impl BuildHasher>,
|
||||||
union_types: &HashSet<&str>,
|
union_types: &HashSet<&str, impl BuildHasher>,
|
||||||
) -> Tokens {
|
) -> Tokens {
|
||||||
let name = name_to_tokens(&_struct.name);
|
let name = name_to_tokens(&_struct.name);
|
||||||
let members = _struct.elements.iter().filter_map(|elem| match *elem {
|
let members = _struct.elements.iter().filter_map(|elem| match *elem {
|
||||||
|
@ -1863,9 +1890,9 @@ pub fn root_struct_names(definitions: &[&vkxml::DefinitionsElement]) -> HashSet<
|
||||||
}
|
}
|
||||||
pub fn generate_definition(
|
pub fn generate_definition(
|
||||||
definition: &vkxml::DefinitionsElement,
|
definition: &vkxml::DefinitionsElement,
|
||||||
union_types: &HashSet<&str>,
|
union_types: &HashSet<&str, impl BuildHasher>,
|
||||||
root_structs: &HashSet<String>,
|
root_structs: &HashSet<String, impl BuildHasher>,
|
||||||
bitflags_cache: &mut HashSet<Ident>,
|
bitflags_cache: &mut HashSet<Ident, impl BuildHasher>,
|
||||||
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
||||||
) -> Option<Tokens> {
|
) -> Option<Tokens> {
|
||||||
match *definition {
|
match *definition {
|
||||||
|
@ -1885,7 +1912,7 @@ pub fn generate_definition(
|
||||||
pub fn generate_feature<'a>(
|
pub fn generate_feature<'a>(
|
||||||
feature: &vkxml::Feature,
|
feature: &vkxml::Feature,
|
||||||
commands: &CommandMap<'a>,
|
commands: &CommandMap<'a>,
|
||||||
fn_cache: &mut HashSet<&'a str>,
|
fn_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||||
) -> quote::Tokens {
|
) -> quote::Tokens {
|
||||||
let (static_commands, entry_commands, device_commands, instance_commands) = feature
|
let (static_commands, entry_commands, device_commands, instance_commands) = feature
|
||||||
.elements
|
.elements
|
||||||
|
@ -1929,7 +1956,7 @@ pub fn generate_feature<'a>(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let version = feature.version_string();
|
let version = feature.version_string();
|
||||||
let static_fn = if feature.version == 1.0 {
|
let static_fn = if feature.is_version(1, 0) {
|
||||||
generate_function_pointers(Ident::from("StaticFn"), &static_commands, fn_cache)
|
generate_function_pointers(Ident::from("StaticFn"), &static_commands, fn_cache)
|
||||||
} else {
|
} else {
|
||||||
quote! {}
|
quote! {}
|
||||||
|
@ -1962,7 +1989,7 @@ pub fn constant_name(name: &str) -> String {
|
||||||
|
|
||||||
pub fn generate_constant<'a>(
|
pub fn generate_constant<'a>(
|
||||||
constant: &'a vkxml::Constant,
|
constant: &'a vkxml::Constant,
|
||||||
cache: &mut HashSet<&'a str>,
|
cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||||
) -> Tokens {
|
) -> Tokens {
|
||||||
cache.insert(constant.name.as_str());
|
cache.insert(constant.name.as_str());
|
||||||
let c = Constant::from_constant(constant);
|
let c = Constant::from_constant(constant);
|
||||||
|
@ -1982,7 +2009,7 @@ pub fn generate_constant<'a>(
|
||||||
|
|
||||||
pub fn generate_feature_extension<'a>(
|
pub fn generate_feature_extension<'a>(
|
||||||
registry: &'a vk_parse::Registry,
|
registry: &'a vk_parse::Registry,
|
||||||
const_cache: &mut HashSet<&'a str>,
|
const_cache: &mut HashSet<&'a str, impl BuildHasher>,
|
||||||
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
const_values: &mut BTreeMap<Ident, Vec<Ident>>,
|
||||||
) -> Tokens {
|
) -> Tokens {
|
||||||
let constants = registry.0.iter().filter_map(|item| match item {
|
let constants = registry.0.iter().filter_map(|item| match item {
|
||||||
|
@ -2000,7 +2027,7 @@ pub fn generate_feature_extension<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_const_debugs<'a>(const_values: &BTreeMap<Ident, Vec<Ident>>) -> Tokens {
|
pub fn generate_const_debugs(const_values: &BTreeMap<Ident, Vec<Ident>>) -> Tokens {
|
||||||
let impls = const_values.iter().map(|(ty, values)| {
|
let impls = const_values.iter().map(|(ty, values)| {
|
||||||
if ty.to_string().contains("Flags") {
|
if ty.to_string().contains("Flags") {
|
||||||
let cases = values.iter().map(|value| {
|
let cases = values.iter().map(|value| {
|
||||||
|
@ -2061,7 +2088,7 @@ pub fn generate_const_debugs<'a>(const_values: &BTreeMap<Ident, Vec<Ident>>) ->
|
||||||
}
|
}
|
||||||
pub fn generate_aliases_of_types<'a>(
|
pub fn generate_aliases_of_types<'a>(
|
||||||
types: &'a vk_parse::Types,
|
types: &'a vk_parse::Types,
|
||||||
ty_cache: &mut HashSet<Ident>,
|
ty_cache: &mut HashSet<Ident, impl BuildHasher>,
|
||||||
) -> Tokens {
|
) -> Tokens {
|
||||||
let aliases = types
|
let aliases = types
|
||||||
.children
|
.children
|
||||||
|
@ -2075,7 +2102,7 @@ pub fn generate_aliases_of_types<'a>(
|
||||||
if ty_cache.contains(&name_ident) {
|
if ty_cache.contains(&name_ident) {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
ty_cache.insert(name_ident.clone());
|
ty_cache.insert(name_ident);
|
||||||
let alias_ident = name_to_tokens(alias);
|
let alias_ident = name_to_tokens(alias);
|
||||||
let tokens = quote! {
|
let tokens = quote! {
|
||||||
pub type #name_ident = #alias_ident;
|
pub type #name_ident = #alias_ident;
|
||||||
|
@ -2239,6 +2266,7 @@ pub fn write_source_code(path: &Path) {
|
||||||
let version_macros = vk_version_macros();
|
let version_macros = vk_version_macros();
|
||||||
let platform_specific_types = platform_specific_types();
|
let platform_specific_types = platform_specific_types();
|
||||||
let source_code = quote! {
|
let source_code = quote! {
|
||||||
|
#![allow(clippy::too_many_arguments, clippy::cognitive_complexity)]
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::os::raw::*;
|
use std::os::raw::*;
|
||||||
/// Iterates through the pointer chain. Includes the item that is passed into the function.
|
/// Iterates through the pointer chain. Includes the item that is passed into the function.
|
||||||
|
@ -2246,10 +2274,9 @@ pub fn write_source_code(path: &Path) {
|
||||||
pub(crate) unsafe fn ptr_chain_iter<T>(
|
pub(crate) unsafe fn ptr_chain_iter<T>(
|
||||||
ptr: &mut T,
|
ptr: &mut T,
|
||||||
) -> impl Iterator<Item = *mut BaseOutStructure> {
|
) -> impl Iterator<Item = *mut BaseOutStructure> {
|
||||||
use std::ptr::null_mut;
|
|
||||||
let ptr: *mut BaseOutStructure = ptr as *mut T as _;
|
let ptr: *mut BaseOutStructure = ptr as *mut T as _;
|
||||||
(0..).scan(ptr, |p_ptr, _| {
|
(0..).scan(ptr, |p_ptr, _| {
|
||||||
if *p_ptr == null_mut() {
|
if p_ptr.is_null() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let n_ptr = (**p_ptr).p_next as *mut BaseOutStructure;
|
let n_ptr = (**p_ptr).p_next as *mut BaseOutStructure;
|
||||||
|
|
Loading…
Reference in a new issue