wgtk/net/element/
entity.rs1use std::io::{self, Write, Read};
4
5use crate::net::bundle::{BundleElementWriter, TopElementReader, BundleElement, BundleResult};
6use crate::util::io::*;
7
8use super::{ElementLength, ElementIdRange, Element, TopElement};
9
10
11pub trait MethodCall: Sized {
13
14 fn count() -> u16;
16
17 fn index(&self) -> u16;
19
20 fn len(index: u16) -> ElementLength;
22
23 fn encode(&self, write: &mut impl Write) -> io::Result<()>;
25
26 fn decode(read: &mut impl Read, len: usize, index: u16) -> io::Result<Self>;
28
29}
30
31
32pub trait MethodCallExt: TopElement<Config = ()> {
35 const ID_RANGE: ElementIdRange;
36}
37
38
39pub struct MethodCallWrapper<M, P>
43where
44 M: MethodCall,
45 P: MethodCallExt,
46{
47 pub method: M,
49 pub ext: P,
52}
53
54impl<M, P> MethodCallWrapper<M, P>
55where
56 M: MethodCall,
57 P: MethodCallExt,
58{
59
60 pub const DEFAULT_LEN: ElementLength = ElementLength::Callback(|id| {
64
65 if let Some(exposed_id) = P::ID_RANGE.to_exposed_id_checked(M::count(), id) {
70 M::len(exposed_id)
71 } else {
72 ElementLength::Variable16
73 }
74
75 });
76
77 pub fn new(method: M, prefix: P) -> Self {
78 Self { method, ext: prefix }
79 }
80
81 pub fn write(self, mut writer: BundleElementWriter) {
82
83 let (
84 element_id,
85 sub_id
86 ) = P::ID_RANGE.from_exposed_id(M::count(), self.method.index());
87
88 writer.write(element_id, self, &(0, sub_id));
89
90 }
91
92 pub fn read(reader: TopElementReader) -> BundleResult<BundleElement<Self>> {
93 let element_id = reader.id();
94 reader.read::<Self>(&(element_id, None))
95 }
96
97}
98
99impl<M, P> Element for MethodCallWrapper<M, P>
100where
101 M: MethodCall,
102 P: MethodCallExt,
103{
104
105 type Config = (u8, Option<u8>);
109
110 fn encode(&self, write: &mut impl Write, config: &Self::Config) -> io::Result<()> {
111
112 self.ext.encode(write, &())?;
113
114 if let Some(sub_id) = config.1 {
116 write.write_u8(sub_id)?;
117 }
118
119 self.method.encode(write)
120
121 }
122
123 fn decode(read: &mut impl Read, mut len: usize, config: &Self::Config) -> io::Result<Self> {
124
125 let mut prefix_read = IoCounter::new(&mut *read);
127 let prefix = P::decode(&mut prefix_read, len, &())?;
128 len -= prefix_read.count();
129
130 let mut sub_id_err = None;
131 let exposed_id = P::ID_RANGE.to_exposed_id(M::count(), config.0, || {
132 len -= 1;
134 match read.read_u8() {
135 Ok(n) => n,
136 Err(e) => {
137 sub_id_err = Some(e);
138 0 }
140 }
141 });
142
143 if let Some(e) = sub_id_err {
145 return Err(e);
146 }
147
148 M::decode(read, len, exposed_id).map(|method| Self {
149 method,
150 ext: prefix,
151 })
152
153 }
154
155}
156
157impl<M, P> TopElement for MethodCallWrapper<M, P>
158where
159 M: MethodCall,
160 P: MethodCallExt,
161{
162 const LEN: ElementLength = P::LEN;
163}