1use alloc::format;
2use core::fmt;
3
4use ironrdp_core::{
5 cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, unsupported_value_err, Decode, DecodeError,
6 DecodeResult, Encode, EncodeResult, ReadCursor, WriteCursor,
7};
8use ironrdp_pdu::utils::{
9 checked_sum, encoded_str_len, read_string_from_cursor, strict_sum, write_string_to_cursor, CharacterSet,
10};
11use ironrdp_svc::SvcEncode;
12
13use crate::{DynamicChannelId, String, Vec};
14
15#[derive(Debug, PartialEq)]
17pub enum DrdynvcDataPdu {
18 DataFirst(DataFirstPdu),
19 Data(DataPdu),
20}
21
22impl DrdynvcDataPdu {
23 pub const MAX_DATA_SIZE: usize = 1590;
25
26 pub fn channel_id(&self) -> DynamicChannelId {
27 match self {
28 DrdynvcDataPdu::DataFirst(pdu) => pdu.channel_id,
29 DrdynvcDataPdu::Data(pdu) => pdu.channel_id,
30 }
31 }
32}
33
34impl Encode for DrdynvcDataPdu {
35 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
36 match self {
37 DrdynvcDataPdu::DataFirst(pdu) => pdu.encode(dst),
38 DrdynvcDataPdu::Data(pdu) => pdu.encode(dst),
39 }
40 }
41
42 fn name(&self) -> &'static str {
43 match self {
44 DrdynvcDataPdu::DataFirst(_) => DataFirstPdu::name(),
45 DrdynvcDataPdu::Data(_) => DataPdu::name(),
46 }
47 }
48
49 fn size(&self) -> usize {
50 match self {
51 DrdynvcDataPdu::DataFirst(pdu) => pdu.size(),
52 DrdynvcDataPdu::Data(pdu) => pdu.size(),
53 }
54 }
55}
56
57#[derive(Debug, PartialEq)]
59pub enum DrdynvcClientPdu {
60 Capabilities(CapabilitiesResponsePdu),
61 Create(CreateResponsePdu),
62 Close(ClosePdu),
63 Data(DrdynvcDataPdu),
64}
65
66impl Encode for DrdynvcClientPdu {
67 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
68 match self {
69 DrdynvcClientPdu::Capabilities(pdu) => pdu.encode(dst),
70 DrdynvcClientPdu::Create(pdu) => pdu.encode(dst),
71 DrdynvcClientPdu::Data(pdu) => pdu.encode(dst),
72 DrdynvcClientPdu::Close(pdu) => pdu.encode(dst),
73 }
74 }
75
76 fn name(&self) -> &'static str {
77 match self {
78 DrdynvcClientPdu::Capabilities(_) => CapabilitiesResponsePdu::name(),
79 DrdynvcClientPdu::Create(_) => CreateResponsePdu::name(),
80 DrdynvcClientPdu::Data(pdu) => pdu.name(),
81 DrdynvcClientPdu::Close(_) => ClosePdu::name(),
82 }
83 }
84
85 fn size(&self) -> usize {
86 match self {
87 DrdynvcClientPdu::Capabilities(_) => CapabilitiesResponsePdu::size(),
88 DrdynvcClientPdu::Create(pdu) => pdu.size(),
89 DrdynvcClientPdu::Data(pdu) => pdu.size(),
90 DrdynvcClientPdu::Close(pdu) => pdu.size(),
91 }
92 }
93}
94
95impl Decode<'_> for DrdynvcClientPdu {
96 fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
97 let header = Header::decode(src)?;
98 match header.cmd {
99 Cmd::Create => Ok(Self::Create(CreateResponsePdu::decode(header, src)?)),
100 Cmd::DataFirst => Ok(Self::Data(DrdynvcDataPdu::DataFirst(DataFirstPdu::decode(
101 header, src,
102 )?))),
103 Cmd::Data => Ok(Self::Data(DrdynvcDataPdu::Data(DataPdu::decode(header, src)?))),
104 Cmd::Close => Ok(Self::Close(ClosePdu::decode(header, src)?)),
105 Cmd::Capability => Ok(Self::Capabilities(CapabilitiesResponsePdu::decode(header, src)?)),
106 _ => Err(unsupported_value_err!("Cmd", header.cmd.into())),
107 }
108 }
109}
110
111#[derive(Debug, PartialEq)]
113pub enum DrdynvcServerPdu {
114 Capabilities(CapabilitiesRequestPdu),
115 Create(CreateRequestPdu),
116 Close(ClosePdu),
117 Data(DrdynvcDataPdu),
118}
119
120impl Encode for DrdynvcServerPdu {
121 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
122 match self {
123 DrdynvcServerPdu::Data(pdu) => pdu.encode(dst),
124 DrdynvcServerPdu::Capabilities(pdu) => pdu.encode(dst),
125 DrdynvcServerPdu::Create(pdu) => pdu.encode(dst),
126 DrdynvcServerPdu::Close(pdu) => pdu.encode(dst),
127 }
128 }
129
130 fn name(&self) -> &'static str {
131 match self {
132 DrdynvcServerPdu::Data(pdu) => pdu.name(),
133 DrdynvcServerPdu::Capabilities(pdu) => pdu.name(),
134 DrdynvcServerPdu::Create(_) => CreateRequestPdu::name(),
135 DrdynvcServerPdu::Close(_) => ClosePdu::name(),
136 }
137 }
138
139 fn size(&self) -> usize {
140 match self {
141 DrdynvcServerPdu::Data(pdu) => pdu.size(),
142 DrdynvcServerPdu::Capabilities(pdu) => pdu.size(),
143 DrdynvcServerPdu::Create(pdu) => pdu.size(),
144 DrdynvcServerPdu::Close(pdu) => pdu.size(),
145 }
146 }
147}
148
149impl Decode<'_> for DrdynvcServerPdu {
150 fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
151 let header = Header::decode(src)?;
152 match header.cmd {
153 Cmd::Create => Ok(Self::Create(CreateRequestPdu::decode(header, src)?)),
154 Cmd::DataFirst => Ok(Self::Data(DrdynvcDataPdu::DataFirst(DataFirstPdu::decode(
155 header, src,
156 )?))),
157 Cmd::Data => Ok(Self::Data(DrdynvcDataPdu::Data(DataPdu::decode(header, src)?))),
158 Cmd::Close => Ok(Self::Close(ClosePdu::decode(header, src)?)),
159 Cmd::Capability => Ok(Self::Capabilities(CapabilitiesRequestPdu::decode(header, src)?)),
160 _ => Err(unsupported_value_err!("Cmd", header.cmd.into())),
161 }
162 }
163}
164
165impl SvcEncode for DrdynvcDataPdu {}
167impl SvcEncode for DrdynvcClientPdu {}
168impl SvcEncode for DrdynvcServerPdu {}
169
170#[derive(Debug, PartialEq)]
174pub struct Header {
175 cb_id: FieldType, sp: FieldType, cmd: Cmd, }
179
180impl Header {
181 pub const FIXED_PART_SIZE: usize = 1;
182 fn new(cb_id_val: u32, sp_val: u32, cmd: Cmd) -> Self {
186 Self {
187 cb_id: FieldType::for_val(cb_id_val),
188 sp: FieldType::for_val(sp_val),
189 cmd,
190 }
191 }
192
193 fn with_cb_id(self, cb_id: FieldType) -> Self {
194 Self { cb_id, ..self }
195 }
196
197 fn with_sp(self, sp: FieldType) -> Self {
198 Self { sp, ..self }
199 }
200
201 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
202 ensure_fixed_part_size!(in: dst);
203 dst.write_u8(((self.cmd as u8) << 4) | (Into::<u8>::into(self.sp) << 2) | Into::<u8>::into(self.cb_id));
204 Ok(())
205 }
206
207 fn decode(src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
208 ensure_size!(in: src, size: Self::size());
209 let byte = src.read_u8();
210 let cmd = Cmd::try_from(byte >> 4)?;
211 let sp = FieldType::from((byte >> 2) & 0b11);
212 let cb_id = FieldType::from(byte & 0b11);
213 Ok(Self { cb_id, sp, cmd })
214 }
215
216 fn size() -> usize {
217 Self::FIXED_PART_SIZE
218 }
219}
220
221#[repr(u8)]
225#[derive(Debug, Copy, Clone, PartialEq)]
226enum Cmd {
227 Create = 0x01,
228 DataFirst = 0x02,
229 Data = 0x03,
230 Close = 0x04,
231 Capability = 0x05,
232 DataFirstCompressed = 0x06,
233 DataCompressed = 0x07,
234 SoftSyncRequest = 0x08,
235 SoftSyncResponse = 0x09,
236}
237
238impl TryFrom<u8> for Cmd {
239 type Error = DecodeError;
240
241 fn try_from(byte: u8) -> Result<Self, Self::Error> {
242 match byte {
243 0x01 => Ok(Self::Create),
244 0x02 => Ok(Self::DataFirst),
245 0x03 => Ok(Self::Data),
246 0x04 => Ok(Self::Close),
247 0x05 => Ok(Self::Capability),
248 0x06 => Ok(Self::DataFirstCompressed),
249 0x07 => Ok(Self::DataCompressed),
250 0x08 => Ok(Self::SoftSyncRequest),
251 0x09 => Ok(Self::SoftSyncResponse),
252 _ => Err(invalid_field_err!("Cmd", "invalid cmd")),
253 }
254 }
255}
256
257impl fmt::Display for Cmd {
258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259 f.write_str(match self {
260 Cmd::Create => "Create",
261 Cmd::DataFirst => "DataFirst",
262 Cmd::Data => "Data",
263 Cmd::Close => "Close",
264 Cmd::Capability => "Capability",
265 Cmd::DataFirstCompressed => "DataFirstCompressed",
266 Cmd::DataCompressed => "DataCompressed",
267 Cmd::SoftSyncRequest => "SoftSyncRequest",
268 Cmd::SoftSyncResponse => "SoftSyncResponse",
269 })
270 }
271}
272
273impl From<Cmd> for String {
274 fn from(cmd: Cmd) -> Self {
275 format!("{cmd:?}")
276 }
277}
278
279#[derive(Debug, PartialEq)]
283pub struct DataFirstPdu {
284 header: Header,
285 pub channel_id: DynamicChannelId,
286 pub length: u32,
289 pub data: Vec<u8>,
291}
292
293impl DataFirstPdu {
294 pub fn new(channel_id: DynamicChannelId, total_length: u32, data: Vec<u8>) -> Self {
301 Self {
302 header: Header::new(channel_id, total_length, Cmd::DataFirst),
303 channel_id,
304 length: total_length,
305 data,
306 }
307 }
308
309 #[must_use]
310 pub fn with_cb_id_type(self, cb_id: FieldType) -> Self {
311 Self {
312 header: self.header.with_cb_id(cb_id),
313 ..self
314 }
315 }
316
317 #[must_use]
318 pub fn with_sp_type(self, sp: FieldType) -> Self {
319 Self {
320 header: self.header.with_sp(sp),
321 ..self
322 }
323 }
324
325 fn decode(header: Header, src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
326 let fixed_part_size = checked_sum(&[header.cb_id.size_of_val(), header.sp.size_of_val()])?;
327 ensure_size!(in: src, size: fixed_part_size);
328 let channel_id = header.cb_id.decode_val(src)?;
329 let length = header.sp.decode_val(src)?;
330 let data = src.read_remaining().to_vec();
331 Ok(Self {
332 header,
333 channel_id,
334 length,
335 data,
336 })
337 }
338
339 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
340 ensure_size!(in: dst, size: self.size());
341 self.header.encode(dst)?;
342 self.header.cb_id.encode_val(self.channel_id, dst)?;
343 self.header
344 .sp
345 .encode_val(cast_length!("DataFirstPdu::Length", self.length)?, dst)?;
346 dst.write_slice(&self.data);
347 Ok(())
348 }
349
350 fn name() -> &'static str {
351 "DYNVC_DATA_FIRST"
352 }
353
354 fn size(&self) -> usize {
355 strict_sum(&[
356 Header::size(),
357 self.header.cb_id.size_of_val(),
358 self.header.sp.size_of_val(),
359 self.data.len(),
360 ])
361 }
362}
363
364#[derive(Debug, Copy, Clone, PartialEq, Eq)]
365pub struct FieldType(u8);
366
367impl FieldType {
368 pub const U8: Self = Self(0x00);
369 pub const U16: Self = Self(0x01);
370 pub const U32: Self = Self(0x02);
371
372 fn encode_val(&self, value: u32, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
373 ensure_size!(in: dst, size: self.size_of_val());
374 match *self {
375 FieldType::U8 => dst.write_u8(cast_length!("FieldType::encode", value)?),
376 FieldType::U16 => dst.write_u16(cast_length!("FieldType::encode", value)?),
377 FieldType::U32 => dst.write_u32(value),
378 _ => return Err(invalid_field_err!("FieldType", "invalid field type")),
379 };
380 Ok(())
381 }
382
383 fn decode_val(&self, src: &mut ReadCursor<'_>) -> DecodeResult<u32> {
384 ensure_size!(in: src, size: self.size_of_val());
385 match *self {
386 FieldType::U8 => Ok(u32::from(src.read_u8())),
387 FieldType::U16 => Ok(u32::from(src.read_u16())),
388 FieldType::U32 => Ok(src.read_u32()),
389 _ => Err(invalid_field_err!("FieldType", "invalid field type")),
390 }
391 }
392
393 fn size_of_val(&self) -> usize {
395 match *self {
396 FieldType::U8 => 1,
397 FieldType::U16 => 2,
398 FieldType::U32 => 4,
399 _ => 0,
400 }
401 }
402
403 fn for_val(value: u32) -> Self {
404 if u8::try_from(value).is_ok() {
405 FieldType::U8
406 } else if u16::try_from(value).is_ok() {
407 FieldType::U16
408 } else {
409 FieldType::U32
410 }
411 }
412}
413
414impl From<u8> for FieldType {
415 fn from(byte: u8) -> Self {
416 match byte {
417 0x00 => Self::U8,
418 0x01 => Self::U16,
419 0x02 => Self::U32,
420 _ => Self(byte),
421 }
422 }
423}
424
425impl From<FieldType> for u8 {
426 fn from(field_type: FieldType) -> Self {
427 field_type.0
428 }
429}
430
431#[derive(Debug, PartialEq)]
435pub struct DataPdu {
436 header: Header,
437 pub channel_id: DynamicChannelId,
438 pub data: Vec<u8>,
439}
440
441impl DataPdu {
442 pub fn new(channel_id: DynamicChannelId, data: Vec<u8>) -> Self {
443 Self {
444 header: Header::new(channel_id, 0, Cmd::Data),
445 channel_id,
446 data,
447 }
448 }
449
450 fn decode(header: Header, src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
451 ensure_size!(in: src, size: header.cb_id.size_of_val());
452 let channel_id = header.cb_id.decode_val(src)?;
453 let data = src.read_remaining().to_vec();
454 Ok(Self {
455 header,
456 channel_id,
457 data,
458 })
459 }
460
461 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
462 ensure_size!(in: dst, size: self.size());
463 self.header.encode(dst)?;
464 self.header.cb_id.encode_val(self.channel_id, dst)?;
465 dst.write_slice(&self.data);
466 Ok(())
467 }
468
469 fn name() -> &'static str {
470 "DYNVC_DATA"
471 }
472
473 fn size(&self) -> usize {
474 strict_sum(&[
475 Header::size(),
476 self.header.cb_id.size_of_val(), self.data.len(), ])
479 }
480}
481
482#[derive(Debug, PartialEq)]
486pub struct CreateResponsePdu {
487 header: Header,
488 pub channel_id: DynamicChannelId,
489 pub creation_status: CreationStatus,
490}
491
492impl CreateResponsePdu {
493 pub fn new(channel_id: DynamicChannelId, creation_status: CreationStatus) -> Self {
494 Self {
495 header: Header::new(channel_id, 0, Cmd::Create),
496 channel_id,
497 creation_status,
498 }
499 }
500
501 fn name() -> &'static str {
502 "DYNVC_CREATE_RSP"
503 }
504
505 fn decode(header: Header, src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
506 ensure_size!(in: src, size: Self::headerless_size(&header));
507 let channel_id = header.cb_id.decode_val(src)?;
508 let creation_status = CreationStatus(src.read_u32());
509 Ok(Self {
510 header,
511 channel_id,
512 creation_status,
513 })
514 }
515
516 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
517 ensure_size!(in: dst, size: self.size());
518 self.header.encode(dst)?;
519 self.header.cb_id.encode_val(self.channel_id, dst)?;
520 self.creation_status.encode(dst)?;
521 Ok(())
522 }
523
524 fn headerless_size(header: &Header) -> usize {
525 strict_sum(&[
526 header.cb_id.size_of_val(), CreationStatus::size(), ])
529 }
530
531 fn size(&self) -> usize {
532 strict_sum(&[Header::size(), Self::headerless_size(&self.header)])
533 }
534}
535
536#[derive(Debug, Copy, Clone, PartialEq)]
537pub struct CreationStatus(u32);
538
539impl CreationStatus {
540 pub const OK: Self = Self(0x00000000);
541 pub const NOT_FOUND: Self = Self(0xC0000225);
542 pub const NO_LISTENER: Self = Self(0xC0000001);
543
544 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
545 ensure_size!(in: dst, size: Self::size());
546 dst.write_u32(self.0);
547 Ok(())
548 }
549
550 fn size() -> usize {
551 4
552 }
553}
554
555impl From<CreationStatus> for u32 {
556 fn from(val: CreationStatus) -> Self {
557 val.0
558 }
559}
560
561#[derive(Debug, PartialEq)]
565pub struct ClosePdu {
566 header: Header,
567 pub channel_id: DynamicChannelId,
568}
569
570impl ClosePdu {
571 pub fn new(channel_id: DynamicChannelId) -> Self {
572 Self {
573 header: Header::new(channel_id, 0, Cmd::Close),
574 channel_id,
575 }
576 }
577
578 #[must_use]
579 pub fn with_cb_id_type(self, cb_id: FieldType) -> Self {
580 Self {
581 header: self.header.with_cb_id(cb_id),
582 ..self
583 }
584 }
585
586 fn decode(header: Header, src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
587 ensure_size!(in: src, size: Self::headerless_size(&header));
588 let channel_id = header.cb_id.decode_val(src)?;
589 Ok(Self { header, channel_id })
590 }
591
592 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
593 ensure_size!(in: dst, size: self.size());
594 self.header.encode(dst)?;
595 self.header.cb_id.encode_val(self.channel_id, dst)?;
596 Ok(())
597 }
598
599 fn name() -> &'static str {
600 "DYNVC_CLOSE"
601 }
602
603 fn headerless_size(header: &Header) -> usize {
604 header.cb_id.size_of_val()
605 }
606
607 fn size(&self) -> usize {
608 strict_sum(&[Header::size(), Self::headerless_size(&self.header)])
609 }
610}
611
612#[derive(Debug, PartialEq)]
616pub struct CapabilitiesResponsePdu {
617 header: Header,
618 version: CapsVersion,
619}
620
621impl CapabilitiesResponsePdu {
622 const HEADERLESS_FIXED_PART_SIZE: usize = 1 + CapsVersion::FIXED_PART_SIZE ;
623 const FIXED_PART_SIZE: usize = Header::FIXED_PART_SIZE + Self::HEADERLESS_FIXED_PART_SIZE;
624
625 pub fn new(version: CapsVersion) -> Self {
626 Self {
627 header: Header::new(0, 0, Cmd::Capability),
628 version,
629 }
630 }
631
632 fn decode(header: Header, src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
633 ensure_size!(in: src, size: Self::HEADERLESS_FIXED_PART_SIZE);
634 let _pad = src.read_u8();
635 let version = CapsVersion::try_from(src.read_u16())?;
636 Ok(Self { header, version })
637 }
638
639 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
640 ensure_size!(in: dst, size: Self::size());
641 self.header.encode(dst)?;
642 dst.write_u8(0x00); self.version.encode(dst)?;
644 Ok(())
645 }
646
647 fn name() -> &'static str {
648 "DYNVC_CAPS_RSP"
649 }
650
651 fn size() -> usize {
652 Self::FIXED_PART_SIZE
653 }
654}
655
656#[repr(u16)]
657#[derive(Debug, Copy, Clone, PartialEq)]
658pub enum CapsVersion {
659 V1 = 0x0001,
660 V2 = 0x0002,
661 V3 = 0x0003,
662}
663
664impl CapsVersion {
665 const FIXED_PART_SIZE: usize = 2;
666
667 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
668 ensure_size!(in: dst, size: Self::size());
669 dst.write_u16(*self as u16);
670 Ok(())
671 }
672
673 fn size() -> usize {
674 Self::FIXED_PART_SIZE
675 }
676}
677
678impl TryFrom<u16> for CapsVersion {
679 type Error = DecodeError;
680
681 fn try_from(value: u16) -> Result<Self, Self::Error> {
682 match value {
683 0x0001 => Ok(Self::V1),
684 0x0002 => Ok(Self::V2),
685 0x0003 => Ok(Self::V3),
686 _ => Err(invalid_field_err!("CapsVersion", "invalid version")),
687 }
688 }
689}
690
691impl From<CapsVersion> for u16 {
692 fn from(version: CapsVersion) -> Self {
693 version as u16
694 }
695}
696
697#[derive(Debug, PartialEq)]
701pub enum CapabilitiesRequestPdu {
702 V1 {
703 header: Header,
704 },
705 V2 {
706 header: Header,
707 charges: [u16; CapabilitiesRequestPdu::PRIORITY_CHARGE_COUNT],
708 },
709 V3 {
710 header: Header,
711 charges: [u16; CapabilitiesRequestPdu::PRIORITY_CHARGE_COUNT],
712 },
713}
714
715impl CapabilitiesRequestPdu {
716 const HEADERLESS_FIXED_PART_SIZE: usize = 1 + 2 ;
717 const FIXED_PART_SIZE: usize = Header::FIXED_PART_SIZE + Self::HEADERLESS_FIXED_PART_SIZE;
718 const PRIORITY_CHARGE_SIZE: usize = 2; const PRIORITY_CHARGE_COUNT: usize = 4; const PRIORITY_CHARGES_SIZE: usize = Self::PRIORITY_CHARGE_COUNT * Self::PRIORITY_CHARGE_SIZE;
721
722 pub fn new(version: CapsVersion, charges: Option<[u16; Self::PRIORITY_CHARGE_COUNT]>) -> Self {
723 let header = Header::new(0, 0, Cmd::Capability);
724 let charges = charges.unwrap_or([0; Self::PRIORITY_CHARGE_COUNT]);
725
726 match version {
727 CapsVersion::V1 => Self::V1 { header },
728 CapsVersion::V2 => Self::V2 { header, charges },
729 CapsVersion::V3 => Self::V3 { header, charges },
730 }
731 }
732
733 fn decode(header: Header, src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
734 ensure_size!(in: src, size: Self::HEADERLESS_FIXED_PART_SIZE);
735 let _pad = src.read_u8();
736 let version = CapsVersion::try_from(src.read_u16())?;
737 match version {
738 CapsVersion::V1 => Ok(Self::V1 { header }),
739 _ => {
740 ensure_size!(in: src, size: Self::PRIORITY_CHARGES_SIZE);
741 let mut charges = [0u16; Self::PRIORITY_CHARGE_COUNT];
742 for charge in charges.iter_mut() {
743 *charge = src.read_u16();
744 }
745
746 match version {
747 CapsVersion::V2 => Ok(Self::V2 { header, charges }),
748 CapsVersion::V3 => Ok(Self::V3 { header, charges }),
749 _ => unreachable!(),
750 }
751 }
752 }
753 }
754
755 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
756 ensure_size!(in: dst, size: self.size());
757 match self {
758 CapabilitiesRequestPdu::V1 { header }
759 | CapabilitiesRequestPdu::V2 { header, .. }
760 | CapabilitiesRequestPdu::V3 { header, .. } => header.encode(dst)?,
761 };
762 dst.write_u8(0x00); match self {
764 CapabilitiesRequestPdu::V1 { .. } => dst.write_u16(CapsVersion::V1.into()),
765 CapabilitiesRequestPdu::V2 { .. } => dst.write_u16(CapsVersion::V2.into()),
766 CapabilitiesRequestPdu::V3 { .. } => dst.write_u16(CapsVersion::V3.into()),
767 }
768 match self {
769 CapabilitiesRequestPdu::V1 { .. } => {}
770 CapabilitiesRequestPdu::V2 { charges, .. } | CapabilitiesRequestPdu::V3 { charges, .. } => {
771 for charge in charges.iter() {
772 dst.write_u16(*charge);
773 }
774 }
775 }
776 Ok(())
777 }
778
779 fn size(&self) -> usize {
780 match self {
781 Self::V1 { .. } => Self::FIXED_PART_SIZE,
782 _ => Self::FIXED_PART_SIZE + Self::PRIORITY_CHARGES_SIZE,
783 }
784 }
785
786 fn name(&self) -> &'static str {
787 match self {
788 Self::V1 { .. } => "DYNVC_CAPS_VERSION1",
789 Self::V2 { .. } => "DYNVC_CAPS_VERSION2",
790 Self::V3 { .. } => "DYNVC_CAPS_VERSION3",
791 }
792 }
793}
794
795#[derive(Debug, PartialEq)]
799pub struct CreateRequestPdu {
800 header: Header,
801 pub channel_id: DynamicChannelId,
802 pub channel_name: String,
803}
804
805impl CreateRequestPdu {
806 pub fn new(channel_id: DynamicChannelId, channel_name: String) -> Self {
807 Self {
808 header: Header::new(channel_id, 0, Cmd::Create),
809 channel_id,
810 channel_name,
811 }
812 }
813
814 fn decode(header: Header, src: &mut ReadCursor<'_>) -> DecodeResult<Self> {
815 ensure_size!(in: src, size: Self::headerless_fixed_part_size(&header));
816 let channel_id = header.cb_id.decode_val(src)?;
817 let channel_name = read_string_from_cursor(src, CharacterSet::Ansi, true)?;
818 Ok(Self {
819 header,
820 channel_id,
821 channel_name,
822 })
823 }
824
825 fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
826 ensure_size!(in: dst, size: self.size());
827 self.header.encode(dst)?;
828 self.header.cb_id.encode_val(self.channel_id, dst)?;
829 write_string_to_cursor(dst, &self.channel_name, CharacterSet::Ansi, true)?;
830 Ok(())
831 }
832
833 fn name() -> &'static str {
834 "DYNVC_CREATE_REQ"
835 }
836
837 fn headerless_fixed_part_size(header: &Header) -> usize {
838 header.cb_id.size_of_val() }
840
841 fn size(&self) -> usize {
842 strict_sum(&[
843 Header::size(),
844 Self::headerless_fixed_part_size(&self.header), encoded_str_len(&self.channel_name, CharacterSet::Ansi, true), ])
847 }
848}