Extract some logic to a separate function, to reduce binary size overhead of read_cbor_map.
This commit is contained in:
@@ -12,6 +12,11 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
use crate::values::{KeyType, Value};
|
||||||
|
use alloc::collections::btree_map;
|
||||||
|
use core::cmp::Ordering;
|
||||||
|
use core::iter::Peekable;
|
||||||
|
|
||||||
/// This macro generates code to extract multiple values from a `BTreeMap<KeyType, Value>` at once
|
/// This macro generates code to extract multiple values from a `BTreeMap<KeyType, Value>` at once
|
||||||
/// in an optimized manner, consuming the input map.
|
/// in an optimized manner, consuming the input map.
|
||||||
///
|
///
|
||||||
@@ -65,37 +70,45 @@ macro_rules! read_cbor_map {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
test_ordered_keys!($( $key, )+);
|
test_ordered_keys!($( $key, )+);
|
||||||
|
|
||||||
use $crate::values::{IntoCborKey, KeyType, Value};
|
use $crate::values::{IntoCborKey, Value};
|
||||||
use ::core::cmp::Ordering;
|
use $crate::macros::read_cbor_map_peek_value;
|
||||||
use ::core::iter::Peekable;
|
|
||||||
use ::alloc::collections::btree_map::IntoIter;
|
|
||||||
|
|
||||||
let mut it: Peekable<IntoIter<KeyType, Value>> = $map.into_iter().peekable();
|
let mut it = $map.into_iter().peekable();
|
||||||
$(
|
$(
|
||||||
let $variable: Option<Value> = {
|
let $variable: Option<Value> = read_cbor_map_peek_value(&mut it, $key.into_cbor_key());
|
||||||
let needle: KeyType = $key.into_cbor_key();
|
)+
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function is an internal detail of the `read_cbor_map!` macro, but has public visibility so
|
||||||
|
/// that users of the macro can use it.
|
||||||
|
///
|
||||||
|
/// The logic is separated into its own function to reduce binary size, as otherwise the logic
|
||||||
|
/// would be inlined for every use case. As of June 2020, this saves ~40KB of binary size for the
|
||||||
|
/// CTAP2 application of OpenSK.
|
||||||
|
pub fn read_cbor_map_peek_value(
|
||||||
|
it: &mut Peekable<btree_map::IntoIter<KeyType, Value>>,
|
||||||
|
needle: KeyType,
|
||||||
|
) -> Option<Value> {
|
||||||
loop {
|
loop {
|
||||||
match it.peek() {
|
match it.peek() {
|
||||||
None => break None,
|
None => return None,
|
||||||
Some(item) => {
|
Some(item) => {
|
||||||
let key: &KeyType = &item.0;
|
let key: &KeyType = &item.0;
|
||||||
match key.cmp(&needle) {
|
match key.cmp(&needle) {
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
it.next();
|
it.next();
|
||||||
continue
|
continue;
|
||||||
},
|
}
|
||||||
Ordering::Equal => {
|
Ordering::Equal => {
|
||||||
let value: Value = it.next().unwrap().1;
|
let value: Value = it.next().unwrap().1;
|
||||||
break Some(value)
|
return Some(value);
|
||||||
},
|
}
|
||||||
Ordering::Greater => break None,
|
Ordering::Greater => return None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
)+
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|||||||
Reference in New Issue
Block a user