1use rasn::{
4 error::EncodeError,
5 types::{
6 Constraints, FixedOctetString, Identifier, Integer, ObjectIdentifier, OctetString, Oid, Tag,
7 },
8 AsnType, Decode, Encode,
9};
10
11pub const INTERNET: &Oid = Oid::ISO_IDENTIFIED_ORGANISATION_DOD_INTERNET;
12pub const DIRECTORY: &Oid = Oid::ISO_IDENTIFIED_ORGANISATION_DOD_INTERNET_DIRECTORY;
13pub const MGMT: &Oid = Oid::ISO_IDENTIFIED_ORGANISATION_DOD_INTERNET_MGMT;
14pub const EXPERIMENTAL: &Oid = Oid::ISO_IDENTIFIED_ORGANISATION_DOD_INTERNET_EXPERIMENTAL;
15pub const PRIVATE: &Oid = Oid::ISO_IDENTIFIED_ORGANISATION_DOD_INTERNET_PRIVATE;
16pub const ENTERPRISES: &Oid = Oid::ISO_IDENTIFIED_ORGANISATION_DOD_INTERNET_PRIVATE_ENTERPRISES;
17
18pub type ObjectName = ObjectIdentifier;
19
20#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
21#[rasn(choice)]
22pub enum ObjectSyntax {
23 Simple(SimpleSyntax),
24 ApplicationWide(ApplicationSyntax),
25}
26
27#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
28#[rasn(choice)]
29pub enum SimpleSyntax {
30 Number(Integer),
31 String(OctetString),
32 Object(ObjectIdentifier),
33 Empty,
34}
35
36#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
37#[rasn(choice)]
38pub enum ApplicationSyntax {
39 Address(NetworkAddress),
40 Counter(Counter),
41 Gauge(Gauge),
42 Ticks(TimeTicks),
43 Arbitrary(Opaque),
44}
45
46#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
47#[rasn(choice)]
48pub enum NetworkAddress {
49 Internet(IpAddress),
50}
51
52#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
53#[rasn(delegate, tag(application, 0))]
54pub struct IpAddress(pub FixedOctetString<4>);
55
56#[derive(AsnType, Debug, Clone, Copy, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
57#[rasn(delegate, tag(application, 1))]
58pub struct Counter(pub u32);
59
60#[derive(AsnType, Debug, Clone, Copy, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
61#[rasn(delegate, tag(application, 2))]
62pub struct Gauge(pub u32);
63
64#[derive(AsnType, Debug, Clone, Copy, Decode, Encode, PartialEq, PartialOrd, Eq, Ord, Hash)]
65#[rasn(delegate, tag(application, 3))]
66pub struct TimeTicks(pub u32);
67
68#[derive(AsnType, Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
72#[rasn(tag(application, 4))]
73pub struct Opaque(alloc::vec::Vec<u8>);
74
75pub trait ToOpaque {
78 fn to_opaque(&self) -> Result<Opaque, EncodeError>;
79}
80
81impl<T: Encode> ToOpaque for T {
82 fn to_opaque(&self) -> Result<Opaque, EncodeError> {
83 rasn::ber::encode(self).map(Opaque)
84 }
85}
86
87impl AsRef<[u8]> for Opaque {
88 fn as_ref(&self) -> &[u8] {
89 self.0.as_ref()
90 }
91}
92
93impl Decode for Opaque {
94 fn decode_with_tag_and_constraints<D: rasn::Decoder>(
95 decoder: &mut D,
96 tag: Tag,
97 constraints: Constraints,
98 ) -> Result<Self, D::Error> {
99 decoder.decode_octet_string(tag, constraints).map(Self)
100 }
101}
102
103impl Encode for Opaque {
104 fn encode_with_tag_and_constraints<'encoder, EN: rasn::Encoder<'encoder>>(
105 &self,
106 encoder: &mut EN,
107 tag: Tag,
108 constraints: Constraints,
109 identifier: Identifier,
110 ) -> Result<(), EN::Error> {
111 encoder
112 .encode_octet_string(tag, constraints, &self.0, identifier)
113 .map(drop)
114 }
115}
116
117pub struct InvalidVariant;
119
120impl core::fmt::Display for InvalidVariant {
121 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
122 f.write_str("Message was valid SMI but was not the variant we expected")
123 }
124}
125
126from_impls! {
127 impl SimpleSyntax => ObjectSyntax: (value) -> ObjectSyntax::Simple(value);
129 impl ApplicationSyntax => ObjectSyntax: (value) -> ObjectSyntax::ApplicationWide(value);
130 impl Integer => ObjectSyntax: (value) -> SimpleSyntax::Number(value).into();
131 impl u8 => ObjectSyntax: (value) -> SimpleSyntax::Number(value.into()).into();
132 impl u16 => ObjectSyntax: (value) -> SimpleSyntax::Number(value.into()).into();
133 impl u32 => ObjectSyntax: (value) -> SimpleSyntax::Number(value.into()).into();
134 impl u64 => ObjectSyntax: (value) -> SimpleSyntax::Number(value.into()).into();
135 impl u128 => ObjectSyntax: (value) -> SimpleSyntax::Number(value.into()).into();
136 impl i8 => ObjectSyntax: (value) -> SimpleSyntax::Number(value.into()).into();
137 impl i16 => ObjectSyntax: (value) -> SimpleSyntax::Number(value.into()).into();
138 impl i32 => ObjectSyntax: (value) -> SimpleSyntax::Number(value.into()).into();
139 impl i64 => ObjectSyntax: (value) -> SimpleSyntax::Number(value.into()).into();
140 impl i128 => ObjectSyntax: (value) -> SimpleSyntax::Number(value.into()).into();
141 impl OctetString => ObjectSyntax: (value) -> SimpleSyntax::String(value).into();
142 impl ObjectIdentifier => ObjectSyntax: (value) -> SimpleSyntax::Object(value).into();
143 impl NetworkAddress => ObjectSyntax: (value) -> ApplicationSyntax::Address(value).into();
144 impl Counter => ObjectSyntax: (value) -> ApplicationSyntax::Counter(value).into();
145 impl Gauge => ObjectSyntax: (value) -> ApplicationSyntax::Gauge(value).into();
146 impl TimeTicks => ObjectSyntax: (value) -> ApplicationSyntax::Ticks(value).into();
147 impl Opaque => ObjectSyntax: (value) -> ApplicationSyntax::Arbitrary(value).into();
148 impl IpAddress => ObjectSyntax: (value) -> ApplicationSyntax::Address(NetworkAddress::Internet(value)).into();
149 impl Integer => SimpleSyntax: (value) -> SimpleSyntax::Number(value);
151 impl u8 => SimpleSyntax: (value) -> SimpleSyntax::Number(value.into());
152 impl u16 => SimpleSyntax: (value) -> SimpleSyntax::Number(value.into());
153 impl u32 => SimpleSyntax: (value) -> SimpleSyntax::Number(value.into());
154 impl u64 => SimpleSyntax: (value) -> SimpleSyntax::Number(value.into());
155 impl u128 => SimpleSyntax: (value) -> SimpleSyntax::Number(value.into());
156 impl i8 => SimpleSyntax: (value) -> SimpleSyntax::Number(value.into());
157 impl i16 => SimpleSyntax: (value) -> SimpleSyntax::Number(value.into());
158 impl i32 => SimpleSyntax: (value) -> SimpleSyntax::Number(value.into());
159 impl i64 => SimpleSyntax: (value) -> SimpleSyntax::Number(value.into());
160 impl i128 => SimpleSyntax: (value) -> SimpleSyntax::Number(value.into());
161 impl OctetString => SimpleSyntax: (value) -> SimpleSyntax::String(value);
162 impl ObjectIdentifier => SimpleSyntax: (value) -> SimpleSyntax::Object(value);
163 impl NetworkAddress => ApplicationSyntax: (value) -> ApplicationSyntax::Address(value);
165 impl Counter => ApplicationSyntax: (value) -> ApplicationSyntax::Counter(value);
166 impl Gauge => ApplicationSyntax: (value) -> ApplicationSyntax::Gauge(value);
167 impl TimeTicks => ApplicationSyntax: (value) -> ApplicationSyntax::Ticks(value);
168 impl Opaque => ApplicationSyntax: (value) -> ApplicationSyntax::Arbitrary(value);
169 impl IpAddress => ApplicationSyntax: (value) -> ApplicationSyntax::Address(NetworkAddress::Internet(value));
170}
171
172macro_rules! try_from_impls_v1 {
173 ($(impl $name:ty => $pattern:pat => $return:expr);+ $(;)?) => {
174 $(
175 impl core::convert::TryFrom<$crate::v1::ObjectSyntax> for $name {
176 type Error = $crate::v1::InvalidVariant;
177 fn try_from(value: $crate::v1::ObjectSyntax) -> Result<Self, Self::Error> {
178 Ok(match value {
179 $pattern => $return,
180 _ => return Err($crate::v1::InvalidVariant),
181 })
182 }
183 }
184 )+
185 }
186}
187
188try_from_impls_v1! {
189 impl OctetString => ObjectSyntax::Simple(SimpleSyntax::String(value)) => value;
190 impl Integer => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value;
191 impl u8 => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value.try_into().map_err(|_| InvalidVariant)?;
192 impl u16 => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value.try_into().map_err(|_| InvalidVariant)?;
193 impl u32 => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value.try_into().map_err(|_| InvalidVariant)?;
194 impl u64 => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value.try_into().map_err(|_| InvalidVariant)?;
195 impl u128 => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value.try_into().map_err(|_| InvalidVariant)?;
196 impl i8 => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value.try_into().map_err(|_| InvalidVariant)?;
197 impl i16 => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value.try_into().map_err(|_| InvalidVariant)?;
198 impl i32 => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value.try_into().map_err(|_| InvalidVariant)?;
199 impl i64 => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value.try_into().map_err(|_| InvalidVariant)?;
200 impl i128 => ObjectSyntax::Simple(SimpleSyntax::Number(value)) => value.try_into().map_err(|_| InvalidVariant)?;
201 impl ObjectIdentifier => ObjectSyntax::Simple(SimpleSyntax::Object(value)) => value;
202 impl () => ObjectSyntax::Simple(SimpleSyntax::Empty) => ();
203 impl NetworkAddress => ObjectSyntax::ApplicationWide(ApplicationSyntax::Address(value)) => value;
204 impl Counter => ObjectSyntax::ApplicationWide(ApplicationSyntax::Counter(value)) => value;
205 impl Gauge => ObjectSyntax::ApplicationWide(ApplicationSyntax::Gauge(value)) => value;
206 impl TimeTicks => ObjectSyntax::ApplicationWide(ApplicationSyntax::Ticks(value)) => value;
207 impl Opaque => ObjectSyntax::ApplicationWide(ApplicationSyntax::Arbitrary(value)) => value;
208 impl IpAddress => ObjectSyntax::ApplicationWide(ApplicationSyntax::Address(NetworkAddress::Internet(value))) => value;
209}