1use core::hash::{Hash, Hasher};
2
3use crate::{
4 binding_model::{self},
5 FastIndexMap,
6};
7
8#[derive(Debug, Copy, Clone, PartialEq, Eq)]
10pub enum Origin {
11 Pool,
13 Derived,
15}
16
17#[derive(Debug, Default, Clone, Eq)]
21pub struct EntryMap {
22 inner: FastIndexMap<u32, wgt::BindGroupLayoutEntry>,
25 sorted: bool,
31}
32
33impl PartialEq for EntryMap {
34 fn eq(&self, other: &Self) -> bool {
35 self.assert_sorted();
36 other.assert_sorted();
37
38 self.inner == other.inner
39 }
40}
41
42impl Hash for EntryMap {
43 fn hash<H: Hasher>(&self, state: &mut H) {
44 self.assert_sorted();
45
46 for entry in self.inner.values() {
51 entry.hash(state);
52 }
53 }
54}
55
56impl EntryMap {
57 fn assert_sorted(&self) {
58 assert!(self.sorted);
59 }
60
61 pub fn from_entries(
66 device_limits: &wgt::Limits,
67 entries: &[wgt::BindGroupLayoutEntry],
68 ) -> Result<Self, binding_model::CreateBindGroupLayoutError> {
69 let mut inner = FastIndexMap::with_capacity_and_hasher(entries.len(), Default::default());
70 for entry in entries {
71 if entry.binding >= device_limits.max_bindings_per_bind_group {
72 return Err(
73 binding_model::CreateBindGroupLayoutError::InvalidBindingIndex {
74 binding: entry.binding,
75 maximum: device_limits.max_bindings_per_bind_group,
76 },
77 );
78 }
79 if inner.insert(entry.binding, *entry).is_some() {
80 return Err(binding_model::CreateBindGroupLayoutError::ConflictBinding(
81 entry.binding,
82 ));
83 }
84 }
85 inner.sort_unstable_keys();
86
87 Ok(Self {
88 inner,
89 sorted: true,
90 })
91 }
92
93 pub fn len(&self) -> usize {
95 self.inner.len()
96 }
97
98 pub fn get(&self, binding: u32) -> Option<&wgt::BindGroupLayoutEntry> {
100 self.inner.get(&binding)
101 }
102
103 pub fn indices(&self) -> impl ExactSizeIterator<Item = u32> + '_ {
105 self.inner.keys().copied()
106 }
107
108 pub fn values(&self) -> impl ExactSizeIterator<Item = &wgt::BindGroupLayoutEntry> + '_ {
110 self.inner.values()
111 }
112
113 pub fn iter(&self) -> impl ExactSizeIterator<Item = (&u32, &wgt::BindGroupLayoutEntry)> + '_ {
114 self.inner.iter()
115 }
116
117 pub fn is_empty(&self) -> bool {
118 self.inner.is_empty()
119 }
120
121 pub fn contains_key(&self, key: u32) -> bool {
122 self.inner.contains_key(&key)
123 }
124
125 pub fn entry(&mut self, key: u32) -> indexmap::map::Entry<'_, u32, wgt::BindGroupLayoutEntry> {
126 self.sorted = false;
127 self.inner.entry(key)
128 }
129
130 pub fn sort(&mut self) {
131 self.inner.sort_unstable_keys();
132 self.sorted = true;
133 }
134}