From 2e4f6fef3be509a8686b2ab81762a659646164b8 Mon Sep 17 00:00:00 2001 From: f3rn0s Date: Thu, 15 Aug 2024 17:37:36 +1000 Subject: [PATCH 1/4] Change HashMap to BTreeMap in order to preserve DHCPOption sorting --- src/v4/options.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/v4/options.rs b/src/v4/options.rs index 6ef0780..d4b3bcc 100644 --- a/src/v4/options.rs +++ b/src/v4/options.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::HashMap, iter, net::Ipv4Addr}; +use std::{borrow::Cow, collections::BTreeMap, iter, net::Ipv4Addr}; use crate::{ decoder::{Decodable, Decoder}, @@ -155,7 +155,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(BTreeMap); impl DhcpOptions { /// Create new [`DhcpOptions`] @@ -276,7 +276,7 @@ impl DhcpOptions { impl IntoIterator for DhcpOptions { type Item = (OptionCode, DhcpOption); - type IntoIter = std::collections::hash_map::IntoIter; + type IntoIter = std::collections::btree_map::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() @@ -288,21 +288,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 = BTreeMap::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) { From 53a2b20d0c69dbc274202aeda9af7ccaee3bb141 Mon Sep 17 00:00:00 2001 From: f3rn0s Date: Thu, 15 Aug 2024 21:28:18 +1000 Subject: [PATCH 2/4] Move BTreeMap -> IndexMap to preserve insertion order --- Cargo.lock | 27 +++++++++++++++++++++++++-- Cargo.toml | 1 + src/v4/options.rs | 14 ++++++++------ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f6e1fb..c126ab7 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.4.0", "ipnet", "rand", "serde", @@ -235,6 +236,12 @@ dependencies = [ "syn", ] +[[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.0.1" @@ -308,6 +315,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "heck" version = "0.4.0" @@ -347,7 +360,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.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +dependencies = [ + "equivalent", + "hashbrown 0.14.5", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d607004..40d51ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ trust-dns-proto = { version = "0.22.0", default-features = false } url = "2.2.2" dhcproto-macros = { path = "./dhcproto-macros", version = "0.1.0" } ipnet = "2.5" +indexmap = "2.4" [features] default = [] diff --git a/src/v4/options.rs b/src/v4/options.rs index d4b3bcc..755bd1f 100644 --- a/src/v4/options.rs +++ b/src/v4/options.rs @@ -1,4 +1,6 @@ -use std::{borrow::Cow, collections::BTreeMap, 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(BTreeMap); +pub struct DhcpOptions(IndexMap); impl DhcpOptions { /// Create new [`DhcpOptions`] @@ -276,7 +278,7 @@ impl DhcpOptions { impl IntoIterator for DhcpOptions { type Item = (OptionCode, DhcpOption); - type IntoIter = std::collections::btree_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 = BTreeMap::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) { From 4d2814d77cd15ac8313400d8b5d43096f4b8c47b Mon Sep 17 00:00:00 2001 From: f3rn0s Date: Thu, 10 Oct 2024 14:52:20 +1000 Subject: [PATCH 3/4] Change remove() to shift_remove() --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- src/v4/options.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c126ab7..f5cff05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,7 +201,7 @@ dependencies = [ "criterion", "dhcproto-macros", "hex", - "indexmap 2.4.0", + "indexmap 2.6.0", "ipnet", "rand", "serde", @@ -317,9 +317,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "heck" @@ -365,12 +365,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 40d51ad..aa7e89a 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 = "2.6.0" thiserror = "1.0" rand = "0.8" serde = { version = "1.0", features = ["derive"], optional = true } @@ -24,7 +25,6 @@ trust-dns-proto = { version = "0.22.0", default-features = false } url = "2.2.2" dhcproto-macros = { path = "./dhcproto-macros", version = "0.1.0" } ipnet = "2.5" -indexmap = "2.4" [features] default = [] diff --git a/src/v4/options.rs b/src/v4/options.rs index 755bd1f..b664314 100644 --- a/src/v4/options.rs +++ b/src/v4/options.rs @@ -180,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`] /// From a2d28036fb575bba462fe778347a1ec0c366edf1 Mon Sep 17 00:00:00 2001 From: f3rn0s Date: Thu, 10 Oct 2024 14:54:59 +1000 Subject: [PATCH 4/4] Make IndexMap have explicit serde support --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index aa7e89a..d9d47e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ license = "MIT" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -indexmap = "2.6.0" +indexmap = { version = "2.6.0", features = ["serde"] } thiserror = "1.0" rand = "0.8" serde = { version = "1.0", features = ["derive"], optional = true }