webparse/http/http2/frame/
priority.rs1use crate::{Http2Error, WebResult};
14use algorithm::buf::{Bt, BtMut};
15
16use super::{frame::Frame, Flag, FrameHeader, StreamIdentifier, MASK_U31};
17
18#[derive(Debug, Eq, PartialEq, Clone)]
19pub struct Priority {
20 stream_id: StreamIdentifier,
21 dependency: StreamDependency,
22}
23
24#[derive(Debug, Eq, PartialEq, Clone)]
25pub struct StreamDependency {
26 dependency_id: StreamIdentifier,
28
29 weight: u8,
33
34 is_exclusive: bool,
36}
37
38impl Priority {
39 pub fn parse<B: Bt>(head: FrameHeader, payload: &mut B) -> WebResult<Self> {
40 let dependency = StreamDependency::load(payload)?;
41
42 if dependency.dependency_id() == head.stream_id() {
43 return Err(Http2Error::InvalidDependencyId.into());
44 }
45
46 Ok(Priority {
47 stream_id: head.stream_id(),
48 dependency,
49 })
50 }
51
52 pub fn into(self) -> (StreamIdentifier, StreamIdentifier, u8) {
53 (
54 self.stream_id,
55 self.dependency.dependency_id,
56 self.dependency.weight,
57 )
58 }
59
60 pub fn stream_id(&self) -> StreamIdentifier {
61 self.stream_id
62 }
63
64 pub fn dependency_id(&self) -> StreamIdentifier {
65 self.dependency.dependency_id
66 }
67
68 pub fn weight(&self) -> u8 {
69 self.dependency.weight
70 }
71
72 pub fn encode<B: Bt + BtMut>(&self, dst: &mut B) -> WebResult<usize> {
73 let head = FrameHeader::new(super::Kind::Priority, Flag::zero(), self.stream_id);
74 let mut size = 0;
75 size += head.encode(dst)?;
76 size += self.dependency.encode(dst)?;
77 log::trace!("HTTP2: 编码优先级信息; len={}", size);
78 Ok(size)
79 }
80}
81
82impl<B> From<Priority> for Frame<B> {
83 fn from(src: Priority) -> Self {
84 Frame::Priority(src)
85 }
86}
87
88impl StreamDependency {
91 pub fn new(dependency_id: StreamIdentifier, weight: u8, is_exclusive: bool) -> Self {
92 StreamDependency {
93 dependency_id,
94 weight,
95 is_exclusive,
96 }
97 }
98
99 pub fn load<B: Bt>(src: &mut B) -> WebResult<Self> {
100 if src.remaining() < 5 {
101 return Err(Http2Error::InvalidPayloadLength.into());
102 }
103
104 let value = src.get_u32();
105 let id = value & MASK_U31;
106 let is_exclusive = value - id != 0;
107
108 let dependency_id = StreamIdentifier(id);
109 let weight = src.get_u8();
110 Ok(StreamDependency::new(dependency_id, weight, is_exclusive))
111 }
112
113 pub fn dependency_id(&self) -> StreamIdentifier {
114 self.dependency_id
115 }
116
117 fn encode<B: Bt + BtMut>(&self, dst: &mut B) -> WebResult<usize> {
118 self.dependency_id.encode(dst)?;
119 dst.put_u8(self.weight);
120 Ok(5)
121 }
122}