Skip to content

Commit f3128ea

Browse files
authored
Add a serde feature to wasmparser for its collections (#1569)
Required now that the types here are new types defined in this crate.
1 parent fe250db commit f3128ea

8 files changed

Lines changed: 197 additions & 1 deletion

File tree

.github/workflows/main.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ jobs:
221221
- run: cargo check --no-default-features -p wasmparser --target x86_64-unknown-none
222222
- run: cargo check --no-default-features -p wasmparser --features std
223223
- run: cargo check --no-default-features -p wasmparser --features validate
224+
- run: cargo check --no-default-features -p wasmparser --features no-hash-maps
225+
- run: cargo check --no-default-features -p wasmparser --features serde
226+
- run: cargo check --no-default-features -p wasmparser --features serde,no-hash-maps
224227
- run: cargo check --no-default-features -p wast
225228
- run: cargo check --no-default-features -p wast --features wasm-module
226229
- run: |

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/wasmparser/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ indexmap = { workspace = true, optional = true }
2222
semver = { workspace = true, optional = true }
2323
hashbrown = { workspace = true, optional = true }
2424
ahash = { workspace = true, optional = true }
25+
serde = { workspace = true, optional = true }
2526

2627
[dev-dependencies]
2728
anyhow = { workspace = true }
@@ -39,7 +40,7 @@ name = "benchmark"
3940
harness = false
4041

4142
[features]
42-
default = ['std', 'validate']
43+
default = ['std', 'validate', 'serde']
4344

4445
# A feature which enables implementations of `std::error::Error` as appropriate
4546
# along with other convenience APIs. This additionally uses the standard
@@ -61,3 +62,7 @@ validate = [
6162
'dep:hashbrown',
6263
'dep:ahash',
6364
]
65+
66+
# Enable Serialize/Deserialize implementations for types in
67+
# `wasmparser::collections`
68+
serde = ['dep:serde', 'indexmap/serde', 'hashbrown/serde']

crates/wasmparser/src/collections/index_map.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,3 +603,33 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
603603
}
604604

605605
impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {}
606+
607+
#[cfg(feature = "serde")]
608+
impl<K, V> serde::Serialize for IndexMap<K, V>
609+
where
610+
K: serde::Serialize + Eq + Hash + Ord,
611+
V: serde::Serialize,
612+
{
613+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
614+
where
615+
S: serde::ser::Serializer,
616+
{
617+
serde::Serialize::serialize(&self.inner, serializer)
618+
}
619+
}
620+
621+
#[cfg(feature = "serde")]
622+
impl<'a, K, V> serde::Deserialize<'a> for IndexMap<K, V>
623+
where
624+
K: serde::Deserialize<'a> + Eq + Hash + Ord + Clone,
625+
V: serde::Deserialize<'a>,
626+
{
627+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
628+
where
629+
D: serde::de::Deserializer<'a>,
630+
{
631+
Ok(IndexMap {
632+
inner: serde::Deserialize::deserialize(deserializer)?,
633+
})
634+
}
635+
}

crates/wasmparser/src/collections/index_map/detail.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,3 +1022,73 @@ where
10221022
.finish()
10231023
}
10241024
}
1025+
1026+
#[cfg(feature = "serde")]
1027+
mod serde_impls {
1028+
use super::IndexMap;
1029+
use core::fmt;
1030+
use core::marker::PhantomData;
1031+
use serde::de::{Deserialize, MapAccess, Visitor};
1032+
use serde::ser::{Serialize, SerializeMap, Serializer};
1033+
1034+
impl<K, V> Serialize for IndexMap<K, V>
1035+
where
1036+
K: Serialize + Ord,
1037+
V: Serialize,
1038+
{
1039+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1040+
where
1041+
S: Serializer,
1042+
{
1043+
let mut map = serializer.serialize_map(Some(self.len()))?;
1044+
for (k, v) in self.iter() {
1045+
map.serialize_entry(k, v)?;
1046+
}
1047+
map.end()
1048+
}
1049+
}
1050+
1051+
impl<'a, K, V> Deserialize<'a> for IndexMap<K, V>
1052+
where
1053+
K: Deserialize<'a> + Clone + Ord,
1054+
V: Deserialize<'a>,
1055+
{
1056+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1057+
where
1058+
D: serde::de::Deserializer<'a>,
1059+
{
1060+
deserializer.deserialize_map(IndexMapVisitor {
1061+
_marker: PhantomData,
1062+
})
1063+
}
1064+
}
1065+
1066+
struct IndexMapVisitor<K, V> {
1067+
_marker: PhantomData<fn() -> IndexMap<K, V>>,
1068+
}
1069+
1070+
impl<'de, K, V> Visitor<'de> for IndexMapVisitor<K, V>
1071+
where
1072+
K: Deserialize<'de> + Clone + Ord,
1073+
V: Deserialize<'de>,
1074+
{
1075+
type Value = IndexMap<K, V>;
1076+
1077+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1078+
formatter.write_str("a map")
1079+
}
1080+
1081+
fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
1082+
where
1083+
M: MapAccess<'de>,
1084+
{
1085+
let mut map = IndexMap::with_capacity(access.size_hint().unwrap_or(0));
1086+
1087+
while let Some((key, value)) = access.next_entry()? {
1088+
map.insert(key, value);
1089+
}
1090+
1091+
Ok(map)
1092+
}
1093+
}
1094+
}

crates/wasmparser/src/collections/index_set.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,31 @@ impl<T> ExactSizeIterator for IntoIter<T> {
261261
}
262262

263263
impl<T> FusedIterator for IntoIter<T> {}
264+
265+
#[cfg(feature = "serde")]
266+
impl<T> serde::Serialize for IndexSet<T>
267+
where
268+
T: serde::Serialize + Eq + Hash + Ord,
269+
{
270+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
271+
where
272+
S: serde::ser::Serializer,
273+
{
274+
serde::Serialize::serialize(&self.inner, serializer)
275+
}
276+
}
277+
278+
#[cfg(feature = "serde")]
279+
impl<'a, T> serde::Deserialize<'a> for IndexSet<T>
280+
where
281+
T: serde::Deserialize<'a> + Eq + Hash + Ord + Clone,
282+
{
283+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
284+
where
285+
D: serde::de::Deserializer<'a>,
286+
{
287+
Ok(IndexSet {
288+
inner: serde::Deserialize::deserialize(deserializer)?,
289+
})
290+
}
291+
}

crates/wasmparser/src/collections/map.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,3 +808,33 @@ impl<K, V> ExactSizeIterator for IntoValues<K, V> {
808808
}
809809

810810
impl<K, V> FusedIterator for IntoValues<K, V> where detail::IntoValuesImpl<K, V>: FusedIterator {}
811+
812+
#[cfg(feature = "serde")]
813+
impl<K, V> serde::Serialize for Map<K, V>
814+
where
815+
K: serde::Serialize + Eq + Hash + Ord,
816+
V: serde::Serialize,
817+
{
818+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
819+
where
820+
S: serde::ser::Serializer,
821+
{
822+
serde::Serialize::serialize(&self.inner, serializer)
823+
}
824+
}
825+
826+
#[cfg(feature = "serde")]
827+
impl<'a, K, V> serde::Deserialize<'a> for Map<K, V>
828+
where
829+
K: serde::Deserialize<'a> + Eq + Hash + Ord,
830+
V: serde::Deserialize<'a>,
831+
{
832+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
833+
where
834+
D: serde::de::Deserializer<'a>,
835+
{
836+
Ok(Map {
837+
inner: serde::Deserialize::deserialize(deserializer)?,
838+
})
839+
}
840+
}

crates/wasmparser/src/collections/set.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,3 +630,31 @@ where
630630
detail::UnionImpl<'a, T>: FusedIterator,
631631
{
632632
}
633+
634+
#[cfg(feature = "serde")]
635+
impl<T> serde::Serialize for Set<T>
636+
where
637+
T: serde::Serialize + Eq + Hash + Ord,
638+
{
639+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
640+
where
641+
S: serde::ser::Serializer,
642+
{
643+
serde::Serialize::serialize(&self.inner, serializer)
644+
}
645+
}
646+
647+
#[cfg(feature = "serde")]
648+
impl<'a, T> serde::Deserialize<'a> for Set<T>
649+
where
650+
T: serde::Deserialize<'a> + Eq + Hash + Ord,
651+
{
652+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
653+
where
654+
D: serde::de::Deserializer<'a>,
655+
{
656+
Ok(Set {
657+
inner: serde::Deserialize::deserialize(deserializer)?,
658+
})
659+
}
660+
}

0 commit comments

Comments
 (0)