1use crate::{
2 Id, ProgramLinkBuilderJsInner, ProgramLinkJs, ProgramLinkJsBuilder, ProgramLinkJsInner,
3};
4use std::fmt::Debug;
5use std::hash::Hash;
6use thiserror::Error;
7use wasm_bindgen::JsValue;
8
9#[derive(Clone, Debug)]
12pub struct ProgramLink<ProgramId: Id, VertexShaderId: Id, FragmentShaderId: Id> {
13 program_id: ProgramId,
14 vertex_shader_id: VertexShaderId,
15 fragment_shader_id: FragmentShaderId,
16 transform_feedback_varyings: Vec<String>,
17}
18
19impl<ProgramId: Id, VertexShaderId: Id, FragmentShaderId: Id>
20 ProgramLink<ProgramId, VertexShaderId, FragmentShaderId>
21{
22 pub fn new(
23 program_id: ProgramId,
24 vertex_shader_id: VertexShaderId,
25 fragment_shader_id: FragmentShaderId,
26 ) -> Self {
27 Self {
28 program_id,
29 vertex_shader_id,
30 fragment_shader_id,
31 transform_feedback_varyings: Default::default(),
32 }
33 }
34
35 pub fn program_id(&self) -> &ProgramId {
36 &self.program_id
37 }
38
39 pub fn vertex_shader_id(&self) -> &VertexShaderId {
40 &self.vertex_shader_id
41 }
42
43 pub fn fragment_shader_id(&self) -> &FragmentShaderId {
44 &self.fragment_shader_id
45 }
46
47 pub fn transform_feedback_varyings(&self) -> &[String] {
48 &self.transform_feedback_varyings
49 }
50
51 pub fn builder() -> ProgramLinkBuilder<ProgramId, VertexShaderId, FragmentShaderId> {
52 ProgramLinkBuilder::default()
53 }
54}
55
56impl<ProgramId: Id, VertexShaderId: Id, FragmentShaderId: Id> Hash
57 for ProgramLink<ProgramId, VertexShaderId, FragmentShaderId>
58{
59 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
60 self.program_id.hash(state);
61 self.vertex_shader_id.hash(state);
62 self.fragment_shader_id.hash(state);
63 }
64}
65
66impl<ProgramId: Id, VertexShaderId: Id, FragmentShaderId: Id> PartialEq
67 for ProgramLink<ProgramId, VertexShaderId, FragmentShaderId>
68{
69 fn eq(&self, other: &Self) -> bool {
70 self.program_id == other.program_id
71 && self.vertex_shader_id == other.vertex_shader_id
72 && self.fragment_shader_id == other.fragment_shader_id
73 }
74}
75
76impl<ProgramId: Id, VertexShaderId: Id, FragmentShaderId: Id> Eq
77 for ProgramLink<ProgramId, VertexShaderId, FragmentShaderId>
78{
79}
80
81impl From<ProgramLink<String, String, String>> for JsValue {
82 fn from(program_link: ProgramLink<String, String, String>) -> Self {
83 let js_program_link: ProgramLinkJs = program_link.into();
84 js_program_link.into()
85 }
86}
87
88#[derive(Error, Debug)]
89pub enum ProgramLinkBuildError {
90 #[error("No VertexShaderId was supplied")]
91 NoVertexShaderId,
92 #[error("No FragmentShaderId was supplied")]
93 NoFragmentShaderId,
94 #[error("No ProgramId was supplied")]
95 NoProgramId,
96}
97
98#[derive(Clone)]
99pub struct ProgramLinkBuilder<ProgramId: Id, VertexShaderId: Id, FragmentShaderId: Id> {
100 program_id: Option<ProgramId>,
101 vertex_shader_id: Option<VertexShaderId>,
102 fragment_shader_id: Option<FragmentShaderId>,
103 transform_feedback_varyings: Vec<String>,
104}
105
106impl<ProgramId: Id, VertexShaderId: Id, FragmentShaderId: Id>
107 ProgramLinkBuilder<ProgramId, VertexShaderId, FragmentShaderId>
108{
109 pub fn new() -> Self {
110 Self::default()
111 }
112
113 pub fn set_program_id(&mut self, program_id: ProgramId) -> &mut Self {
114 self.program_id = Some(program_id);
115 self
116 }
117
118 pub fn set_vertex_shader_id(&mut self, vertex_shader_id: VertexShaderId) -> &mut Self {
119 self.vertex_shader_id = Some(vertex_shader_id);
120 self
121 }
122
123 pub fn set_fragment_shader_id(&mut self, fragment_shader_id: FragmentShaderId) -> &mut Self {
124 self.fragment_shader_id = Some(fragment_shader_id);
125 self
126 }
127
128 pub fn set_transform_feedback_varyings(
129 &mut self,
130 transform_feedback_varyings: impl Into<Vec<String>>,
131 ) -> &mut Self {
132 self.transform_feedback_varyings = transform_feedback_varyings.into();
133 self
134 }
135
136 pub fn build(
137 self,
138 ) -> Result<ProgramLink<ProgramId, VertexShaderId, FragmentShaderId>, ProgramLinkBuildError>
139 {
140 Ok(ProgramLink {
141 program_id: self.program_id.ok_or(ProgramLinkBuildError::NoProgramId)?,
142 vertex_shader_id: self
143 .vertex_shader_id
144 .ok_or(ProgramLinkBuildError::NoVertexShaderId)?,
145 fragment_shader_id: self
146 .fragment_shader_id
147 .ok_or(ProgramLinkBuildError::NoFragmentShaderId)?,
148 transform_feedback_varyings: self.transform_feedback_varyings,
149 })
150 }
151}
152
153impl<ProgramId: Id, VertexShaderId: Id, FragmentShaderId: Id> Default
154 for ProgramLinkBuilder<ProgramId, VertexShaderId, FragmentShaderId>
155{
156 fn default() -> Self {
157 Self {
158 program_id: Default::default(),
159 vertex_shader_id: Default::default(),
160 fragment_shader_id: Default::default(),
161 transform_feedback_varyings: Default::default(),
162 }
163 }
164}
165
166impl<ProgramId: Id, VertexShaderId: Id, FragmentShaderId: Id> Hash
167 for ProgramLinkBuilder<ProgramId, VertexShaderId, FragmentShaderId>
168{
169 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
170 self.program_id.hash(state);
171 self.vertex_shader_id.hash(state);
172 self.fragment_shader_id.hash(state);
173 }
174}
175
176impl<ProgramId: Id, VertexShaderId: Id, FragmentShaderId: Id> PartialEq
177 for ProgramLinkBuilder<ProgramId, VertexShaderId, FragmentShaderId>
178{
179 fn eq(&self, other: &Self) -> bool {
180 self.program_id == other.program_id
181 && self.vertex_shader_id == other.vertex_shader_id
182 && self.fragment_shader_id == other.fragment_shader_id
183 }
184}
185
186impl From<ProgramLinkBuilderJsInner> for JsValue {
187 fn from(program_link_builder: ProgramLinkBuilderJsInner) -> Self {
188 let js_program_link_builder: ProgramLinkJsBuilder = program_link_builder.into();
189 js_program_link_builder.into()
190 }
191}
192
193impl From<ProgramLinkJs> for ProgramLinkJsInner {
194 fn from(js_program_link: ProgramLinkJs) -> Self {
195 js_program_link.into_inner()
196 }
197}