1pub const CLIENT_PREFACE: &[u8] = b"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
2
3#[derive(Debug, Default)]
4pub struct Prefix(u8);
5
6#[derive(Debug)]
7pub struct Complete(());
8
9#[derive(Debug)]
10pub enum Read {
11 Pending(Prefix),
12 Complete(Complete),
13}
14
15#[derive(Debug)]
16pub struct Mismatch {
17 prefix: Prefix,
18 offset: u8,
19 actual: u8,
20}
21
22impl AsRef<[u8]> for Prefix {
23 fn as_ref(&self) -> &[u8] {
24 &CLIENT_PREFACE[..self.0 as usize]
25 }
26}
27
28impl Prefix {
29 pub fn read(self, bytes: &[u8]) -> Result<(usize, Read), Mismatch> {
30 let offset = self.0 as usize;
31 let expected = &CLIENT_PREFACE[offset..];
32 let count = expected.len().min(bytes.len());
33 for (index, (&expected, &actual)) in expected.iter().zip(bytes).enumerate() {
34 if actual != expected {
35 return Err(Mismatch {
36 prefix: self,
37 offset: (offset + index) as u8,
38 actual,
39 });
40 }
41 }
42 let matched = offset + count;
43 let read = if matched == CLIENT_PREFACE.len() {
44 Read::Complete(Complete(()))
45 } else {
46 Read::Pending(Self(matched as u8))
47 };
48 Ok((count, read))
49 }
50}
51
52impl Mismatch {
53 pub fn into_parts(self) -> (Prefix, usize, u8, u8) {
54 let offset = self.offset as usize;
55 (self.prefix, offset, CLIENT_PREFACE[offset], self.actual)
56 }
57}