1use crate::{
4 property::{DictRef, ValueRef},
5 util, Tag,
6};
7use core::ops::Add;
8use der::{
9 asn1::Ia5StringRef, Decode, Encode, EncodeValue, FixedTag, Length, Reader, Tagged, Writer,
10};
11#[cfg(any(feature = "alloc", test))]
12use {
13 crate::property::{Dict, Value},
14 alloc::collections::BTreeMap,
15 der::referenced::{OwnedToRef, RefToOwned},
16};
17
18#[derive(Clone, Debug)]
20#[cfg_attr(test, derive(Eq, PartialEq))]
21pub struct RestoreInfoRef<'a>(DictRef<'a>);
22
23impl<'a> RestoreInfoRef<'a> {
24 pub fn decode_after_magic<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
29 Ok(Self(DictRef::decode(decoder)?))
30 }
31
32 pub fn decode_boot_nonce(&self) -> der::Result<Option<u64>> {
45 for result in self.0.iter()? {
46 let (tag, value) = result?;
47
48 if tag != Tag::from_bytes(*b"BNCN") {
49 continue;
50 }
51
52 let ValueRef::Integer(nonce) = value else {
53 return Err(der::Error::new(
54 der::ErrorKind::TagUnexpected {
55 expected: Some(der::Tag::Integer),
56 actual: value.tag(),
57 },
58 Length::ZERO,
59 ));
60 };
61
62 return Ok(Some(nonce));
63 }
64
65 Ok(None)
66 }
67
68 #[cfg(any(feature = "alloc", test))]
73 pub fn decode_owned(&self) -> der::Result<BTreeMap<Tag, Value>> {
74 self.0.decode_owned()
75 }
76}
77
78impl<'a> Decode<'a> for RestoreInfoRef<'a> {
79 fn decode<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
80 decoder.sequence(|nested_decoder| {
81 util::decode_and_check_magic(nested_decoder, b"IM4R")?;
82 Self::decode_after_magic(nested_decoder)
83 })
84 }
85}
86
87impl EncodeValue for RestoreInfoRef<'_> {
88 fn value_len(&self) -> der::Result<Length> {
89 Ia5StringRef::new(&b"IM4R")?
90 .encoded_len()?
91 .add(self.0.encoded_len()?)
92 }
93
94 fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
95 Ia5StringRef::new(&b"IM4R")?.encode(encoder)?;
96 self.0.encode(encoder)
97 }
98}
99
100impl FixedTag for RestoreInfoRef<'_> {
101 const TAG: der::Tag = der::Tag::Sequence;
102}
103
104#[cfg(any(feature = "alloc", test))]
105impl<'a> RefToOwned<'a> for RestoreInfoRef<'a> {
106 type Owned = RestoreInfo;
107
108 fn ref_to_owned(&self) -> Self::Owned {
109 RestoreInfo(self.0.ref_to_owned())
110 }
111}
112
113#[derive(Clone, Debug)]
115#[cfg_attr(test, derive(Eq, PartialEq))]
116#[cfg(any(feature = "alloc", test))]
117pub struct RestoreInfo(Dict);
118
119#[cfg(any(feature = "alloc", test))]
120impl RestoreInfo {
121 pub fn with_boot_nonce(nonce: u64) -> der::Result<Self> {
123 let mut map = BTreeMap::new();
124 map.insert(Tag::from_bytes(*b"BNCN"), Value::Integer(nonce));
125
126 Self::encode_from(&map)
127 }
128
129 pub fn encode_from(value: &BTreeMap<Tag, Value>) -> der::Result<Self> {
132 Dict::encode_from(value).map(Self)
133 }
134
135 pub fn as_bytes(&self) -> &[u8] {
137 self.0.as_bytes()
138 }
139
140 pub fn into_dict(self) -> Dict {
142 self.0
143 }
144
145 pub fn as_dict_ref(&self) -> DictRef<'_> {
147 self.0.owned_to_ref()
148 }
149}
150
151#[cfg(any(feature = "alloc", test))]
152impl From<Dict> for RestoreInfo {
153 fn from(value: Dict) -> Self {
154 Self(value)
155 }
156}
157
158#[cfg(any(feature = "alloc", test))]
159impl From<&'_ DictRef<'_>> for RestoreInfo {
160 fn from(value: &'_ DictRef<'_>) -> Self {
161 Self(value.into())
162 }
163}
164
165#[cfg(any(feature = "alloc", test))]
166impl From<DictRef<'_>> for RestoreInfo {
167 fn from(value: DictRef<'_>) -> Self {
168 Self(value.into())
169 }
170}
171
172#[cfg(any(feature = "alloc", test))]
173impl From<RestoreInfo> for Dict {
174 fn from(value: RestoreInfo) -> Self {
175 value.0
176 }
177}
178
179#[cfg(any(feature = "alloc", test))]
180impl<'a> Decode<'a> for RestoreInfo {
181 fn decode<R: Reader<'a>>(decoder: &mut R) -> der::Result<Self> {
182 Dict::decode(decoder).map(Self)
183 }
184}
185
186#[cfg(any(feature = "alloc", test))]
187impl Encode for RestoreInfo {
188 fn encoded_len(&self) -> der::Result<Length> {
189 self.owned_to_ref().encoded_len()
190 }
191
192 fn encode(&self, encoder: &mut impl Writer) -> der::Result<()> {
193 self.owned_to_ref().encode(encoder)
194 }
195}
196
197#[cfg(any(feature = "alloc", test))]
198impl OwnedToRef for RestoreInfo {
199 type Borrowed<'a> = RestoreInfoRef<'a>;
200
201 fn owned_to_ref(&self) -> Self::Borrowed<'_> {
202 RestoreInfoRef(self.0.owned_to_ref())
203 }
204}