abi_stable/prefix_type/
pt_metadata.rs1use std::{borrow::Cow, slice};
2
3#[allow(unused_imports)]
4use crate::{
5 std_types::*,
6 type_layout::{
7 TLData, TLDataDiscriminant, TLField, TLFields, TLFieldsIterator, TLPrefixType, TypeLayout,
8 },
9};
10
11use super::accessible_fields::{FieldAccessibility, FieldConditionality, IsAccessible};
12
13#[allow(unused_imports)]
14use core_extensions::SelfOps;
15
16#[doc(hidden)]
17#[derive(Debug, Clone)]
18pub struct __PrefixTypeMetadata {
19 pub prefix_field_count: u8,
22
23 pub accessible_fields: FieldAccessibility,
24
25 pub conditional_prefix_fields: FieldConditionality,
26
27 pub fields: __InitialFieldsOrMut,
28
29 pub layout: &'static TypeLayout,
31}
32
33impl __PrefixTypeMetadata {
34 #[allow(dead_code)]
35 #[cfg(feature = "testing")]
36 pub fn new(layout: &'static TypeLayout) -> Self {
37 match layout.data() {
38 TLData::PrefixType(prefix) => Self::with_prefix_layout(prefix, layout),
39 _ => panic!(
40 "Attempting to construct a __PrefixTypeMetadata from a \
41 TypeLayout of a non-prefix-type.\n\
42 Type:{}\nDataVariant:{:?}\nPackage:{}",
43 layout.full_type(),
44 layout.data_discriminant(),
45 layout.package(),
46 ),
47 }
48 }
49
50 pub(crate) fn with_prefix_layout(prefix: TLPrefixType, layout: &'static TypeLayout) -> Self {
51 Self {
52 fields: __InitialFieldsOrMut::from(prefix.fields),
53 accessible_fields: prefix.accessible_fields,
54 conditional_prefix_fields: prefix.conditional_prefix_fields,
55 prefix_field_count: prefix.first_suffix_field,
56 layout,
57 }
58 }
59
60 #[allow(dead_code)]
71 #[cfg(feature = "testing")]
72 pub fn max(self, other: Self) -> Self {
73 if self.fields.len() < other.fields.len() {
74 other
75 } else {
76 self
77 }
78 }
79 pub(crate) fn min_max(self, other: Self) -> (Self, Self) {
85 if self.fields.len() < other.fields.len() {
86 (self, other)
87 } else {
88 (other, self)
89 }
90 }
91
92 pub(crate) fn combine_fields_from(&mut self, other: &Self) {
101 let mut o_fields = other.fields.iter();
102
103 let min_field_count = o_fields.len().min(self.fields.len());
104
105 for (field_i, (t_acc, o_acc)) in self
106 .accessible_fields
107 .iter()
108 .take(min_field_count)
109 .zip(other.accessible_fields.iter().take(min_field_count))
110 .enumerate()
111 {
112 let o_field = o_fields.next().unwrap();
113 if !t_acc.is_accessible() && o_acc.is_accessible() {
114 let t_fields = self.fields.to_mut();
115
116 t_fields[field_i] = o_field.into_owned();
117 }
118 }
119
120 if min_field_count == self.fields.len() {
121 let t_fields = self.fields.to_mut();
122
123 for (i, o_field) in o_fields.enumerate() {
124 let field_i = i + min_field_count;
125
126 t_fields.push(o_field.into_owned());
127 self.accessible_fields = self.accessible_fields.set(field_i, IsAccessible::Yes);
128 }
129 }
130 }
131}
132
133#[doc(hidden)]
136#[derive(Debug, Clone)]
137pub enum __InitialFieldsOrMut {
138 TLFields(TLFields),
139 Mutable(Vec<TLField>),
140}
141
142impl From<TLFields> for __InitialFieldsOrMut {
143 fn from(this: TLFields) -> Self {
144 __InitialFieldsOrMut::TLFields(this)
145 }
146}
147
148impl __InitialFieldsOrMut {
149 pub fn to_mut(&mut self) -> &mut Vec<TLField> {
150 match self {
151 __InitialFieldsOrMut::Mutable(x) => x,
152 this => {
153 let list = this.iter().map(Cow::into_owned).collect::<Vec<TLField>>();
154 *this = __InitialFieldsOrMut::Mutable(list);
155 match this {
156 __InitialFieldsOrMut::Mutable(x) => x,
157 _ => unreachable!(),
158 }
159 }
160 }
161 }
162 pub fn iter(&self) -> IFOMIter<'_> {
163 match self {
164 __InitialFieldsOrMut::TLFields(x) => IFOMIter::TLFields(x.iter()),
165 __InitialFieldsOrMut::Mutable(x) => IFOMIter::Slice(x.iter()),
166 }
167 }
168 pub fn len(&self) -> usize {
169 match self {
170 __InitialFieldsOrMut::TLFields(x) => x.len(),
171 __InitialFieldsOrMut::Mutable(x) => x.len(),
172 }
173 }
174}
175
176#[repr(C)]
177#[derive(Clone, Debug)]
178pub enum IFOMIter<'a> {
179 TLFields(TLFieldsIterator),
180 Slice(slice::Iter<'a, TLField>),
181}
182
183impl<'a> Iterator for IFOMIter<'a> {
184 type Item = Cow<'a, TLField>;
185
186 fn next(&mut self) -> Option<Cow<'a, TLField>> {
187 match self {
188 IFOMIter::TLFields(iter) => iter.next().map(Cow::Owned),
189 IFOMIter::Slice(iter) => iter.next().map(Cow::Borrowed),
190 }
191 }
192
193 fn size_hint(&self) -> (usize, Option<usize>) {
194 match self {
195 IFOMIter::TLFields(iter) => iter.size_hint(),
196 IFOMIter::Slice(iter) => iter.size_hint(),
197 }
198 }
199 fn count(self) -> usize {
200 match self {
201 IFOMIter::TLFields(iter) => iter.count(),
202 IFOMIter::Slice(iter) => iter.count(),
203 }
204 }
205}
206
207impl<'a> std::iter::ExactSizeIterator for IFOMIter<'a> {}