ssh_agent_lib/proto/message/
extension.rs
1use ssh_encoding::{self, CheckedSum, Decode, Encode, Reader, Writer};
4
5use crate::proto::{
6 extension::{KeyConstraintExtension, MessageExtension},
7 Error, Result, Unparsed,
8};
9
10#[derive(Clone, PartialEq, Debug)]
16pub struct Extension {
17 pub name: String,
23
24 pub details: Unparsed,
26}
27
28impl Extension {
29 pub fn new_message<T>(extension: T) -> Result<Self>
32 where
33 T: MessageExtension + Encode,
34 {
35 let mut buffer: Vec<u8> = vec![];
36 extension.encode(&mut buffer)?;
37 Ok(Self {
38 name: T::NAME.into(),
39 details: buffer.into(),
40 })
41 }
42
43 pub fn parse_message<T>(&self) -> std::result::Result<Option<T>, <T as Decode>::Error>
51 where
52 T: MessageExtension + Decode,
53 {
54 if T::NAME == self.name {
55 Ok(Some(self.details.parse::<T>()?))
56 } else {
57 Ok(None)
58 }
59 }
60
61 pub fn new_key_constraint<T>(extension: T) -> Result<Self>
64 where
65 T: KeyConstraintExtension + Encode,
66 {
67 let mut buffer: Vec<u8> = vec![];
68 extension.encode(&mut buffer)?;
69 Ok(Self {
70 name: T::NAME.into(),
71 details: buffer.into(),
72 })
73 }
74
75 pub fn parse_key_constraint<T>(&self) -> std::result::Result<Option<T>, <T as Decode>::Error>
83 where
84 T: KeyConstraintExtension + Decode,
85 {
86 if T::NAME == self.name {
87 Ok(Some(self.details.parse::<T>()?))
88 } else {
89 Ok(None)
90 }
91 }
92}
93
94impl Decode for Extension {
95 type Error = Error;
96
97 fn decode(reader: &mut impl Reader) -> Result<Self> {
98 let name = String::decode(reader)?;
99 let mut details = vec![0; reader.remaining_len()];
100 reader.read(&mut details)?;
101 Ok(Self {
102 name,
103 details: details.into(),
104 })
105 }
106}
107
108impl Encode for Extension {
109 fn encoded_len(&self) -> ssh_encoding::Result<usize> {
110 [self.name.encoded_len()?, self.details.encoded_len()?].checked_sum()
111 }
112
113 fn encode(&self, writer: &mut impl Writer) -> ssh_encoding::Result<()> {
114 self.name.encode(writer)?;
115 self.details.encode(writer)?;
116 Ok(())
117 }
118}