1use super::*;
2
3#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
4pub struct Struct {
5 pub def: TypeDef,
6}
7
8impl Struct {
9 pub fn type_name(&self) -> TypeName {
10 self.def.type_name()
11 }
12
13 pub fn write_name(&self, writer: &Writer) -> TokenStream {
14 self.type_name().write(writer, &[])
15 }
16
17 pub fn write(&self, writer: &Writer) -> TokenStream {
18 let name = to_ident(self.def.name());
19
20 let fields: Vec<_> = self
21 .def
22 .fields()
23 .map(|field| (field.name(), field.ty(None)))
24 .collect();
25
26 let is_copyable = fields.iter().all(|(_, ty)| ty.is_copyable());
27
28 let mut derive = DeriveWriter::new(writer, self.type_name());
29 derive.extend(["Clone"]);
30
31 if is_copyable {
32 derive.extend(["Copy"]);
33 }
34
35 if !writer.config.sys {
36 derive.extend(["Default", "Debug", "PartialEq"]);
37 }
38
39 let fields = fields.iter().map(|(name, ty)| {
40 let name = to_ident(name);
41 let ty = ty.write_default(writer);
42 quote! { pub #name: #ty, }
43 });
44
45 let win_traits = if writer.config.sys {
46 quote! {}
47 } else {
48 let type_kind = if is_copyable {
49 quote! { CopyType }
50 } else {
51 quote! { CloneType }
52 };
53
54 let signature = Literal::byte_string(&self.runtime_signature());
55
56 quote! {
57 impl windows_core::TypeKind for #name {
58 type TypeKind = windows_core::#type_kind;
59 }
60 impl windows_core::RuntimeType for #name {
61 const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::from_slice(#signature);
62 }
63 }
64 };
65
66 quote! {
67 #[repr(C)]
68 #derive
69 pub struct #name {
70 #(#fields)*
71 }
72 #win_traits
73 }
74 }
75
76 pub fn runtime_signature(&self) -> String {
77 let mut signature = format!("struct({}", self.def.type_name());
78 for field in self.def.fields() {
79 signature.push(';');
80 signature.push_str(&field.ty(None).runtime_signature());
81 }
82 signature.push(')');
83 signature
84 }
85
86 pub fn dependencies(&self, dependencies: &mut TypeMap) {
87 for field in self.def.fields() {
88 field.ty(None).dependencies(dependencies);
89 }
90 }
91
92 pub fn is_copyable(&self) -> bool {
93 self.def.fields().all(|field| field.ty(None).is_copyable())
94 }
95
96 pub fn size(&self) -> usize {
97 let mut sum = 0;
98 for field in self.def.fields() {
99 let ty = field.ty(None);
100 let size = ty.size();
101 let align = ty.align();
102 sum = (sum + (align - 1)) & !(align - 1);
103 sum += size;
104 }
105 sum
106 }
107
108 pub fn align(&self) -> usize {
109 self.def
110 .fields()
111 .map(|field| field.ty(None).align())
112 .max()
113 .unwrap_or(1)
114 }
115}
116