diff --git a/Cargo.lock b/Cargo.lock index e0b304a..26754f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,7 +95,7 @@ checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "bitflags", "clap_lex", - "indexmap", + "indexmap 1.9.2", "textwrap", ] @@ -201,6 +201,7 @@ dependencies = [ "criterion", "dhcproto-macros", "hex", + "indexmap 2.6.0", "hickory-proto", "ipnet", "rand", @@ -246,6 +247,12 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -318,6 +325,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "heck" version = "0.4.0" @@ -510,7 +523,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 58ac9c8..0352eaf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +indexmap = { version = "2.6.0", features = ["serde"] } thiserror = "1.0" rand = "0.8" serde = { version = "1.0", features = ["derive"], optional = true } diff --git a/src/v4/options.rs b/src/v4/options.rs index 21b41be..aadda4a 100644 --- a/src/v4/options.rs +++ b/src/v4/options.rs @@ -1,4 +1,6 @@ -use std::{borrow::Cow, collections::HashMap, iter, net::Ipv4Addr}; +use std::{borrow::Cow, iter, net::Ipv4Addr}; + +use indexmap::IndexMap; use crate::{ decoder::{Decodable, Decoder}, @@ -155,7 +157,7 @@ dhcproto_macros::declare_codes!( /// ``` #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[derive(Debug, Default, Clone, PartialEq, Eq)] -pub struct DhcpOptions(HashMap); +pub struct DhcpOptions(IndexMap); impl DhcpOptions { /// Create new [`DhcpOptions`] @@ -178,7 +180,7 @@ impl DhcpOptions { } /// remove option pub fn remove(&mut self, code: OptionCode) -> Option { - self.0.remove(&code) + self.0.shift_remove(&code) } /// insert a new [`DhcpOption`] /// @@ -276,7 +278,7 @@ impl DhcpOptions { impl IntoIterator for DhcpOptions { type Item = (OptionCode, DhcpOption); - type IntoIter = std::collections::hash_map::IntoIter; + type IntoIter = indexmap::map::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() @@ -288,21 +290,21 @@ impl FromIterator for DhcpOptions { DhcpOptions( iter.into_iter() .map(|opt| ((&opt).into(), opt)) - .collect::>(), + .collect::>(), ) } } impl FromIterator<(OptionCode, DhcpOption)> for DhcpOptions { fn from_iter>(iter: T) -> Self { - DhcpOptions(iter.into_iter().collect::>()) + DhcpOptions(iter.into_iter().collect::>()) } } impl Decodable for DhcpOptions { fn decode(decoder: &mut Decoder<'_>) -> DecodeResult { // represented as a vector in the actual message - let mut opts = HashMap::new(); + let mut opts = IndexMap::new(); // should we error the whole parser if we fail to parse an // option or just stop parsing options? -- here we will just stop while let Ok(opt) = DhcpOption::decode(decoder) {