|
4 | 4 | // SPDX-License-Identifier: AGPL-3.0-only
|
5 | 5 | // Please see LICENSE in the repository root for full details.
|
6 | 6 |
|
7 |
| -use std::{borrow::Cow, collections::HashMap}; |
| 7 | +use std::borrow::Cow; |
8 | 8 |
|
9 | 9 | use chrono::Duration;
|
| 10 | +use indexmap::IndexMap; |
10 | 11 | use language_tags::LanguageTag;
|
11 | 12 | use mas_iana::{
|
12 | 13 | jose::{JsonWebEncryptionAlg, JsonWebEncryptionEnc, JsonWebSignatureAlg},
|
@@ -45,18 +46,18 @@ impl<T> Localized<T> {
|
45 | 46 | }
|
46 | 47 |
|
47 | 48 | fn deserialize(
|
48 |
| - map: &mut HashMap<String, HashMap<Option<LanguageTag>, Value>>, |
| 49 | + map: &mut IndexMap<String, IndexMap<Option<LanguageTag>, Value>>, |
49 | 50 | field_name: &'static str,
|
50 | 51 | ) -> Result<Option<Self>, serde_json::Error>
|
51 | 52 | where
|
52 | 53 | T: DeserializeOwned,
|
53 | 54 | {
|
54 |
| - let Some(map) = map.remove(field_name) else { |
| 55 | + let Some(map) = map.shift_remove(field_name) else { |
55 | 56 | return Ok(None);
|
56 | 57 | };
|
57 | 58 |
|
58 | 59 | let mut non_localized = None;
|
59 |
| - let mut localized = HashMap::with_capacity(map.len() - 1); |
| 60 | + let mut localized = IndexMap::with_capacity(map.len() - 1); |
60 | 61 |
|
61 | 62 | for (k, v) in map {
|
62 | 63 | let value = serde_json::from_value(v)?;
|
@@ -350,8 +351,8 @@ impl<'de> Deserialize<'de> for ClientMetadataLocalizedFields {
|
350 | 351 | where
|
351 | 352 | D: serde::Deserializer<'de>,
|
352 | 353 | {
|
353 |
| - let map = HashMap::<Cow<'de, str>, Value>::deserialize(deserializer)?; |
354 |
| - let mut new_map: HashMap<String, HashMap<Option<LanguageTag>, Value>> = HashMap::new(); |
| 354 | + let map = IndexMap::<Cow<'de, str>, Value>::deserialize(deserializer)?; |
| 355 | + let mut new_map: IndexMap<String, IndexMap<Option<LanguageTag>, Value>> = IndexMap::new(); |
355 | 356 |
|
356 | 357 | for (k, v) in map {
|
357 | 358 | let (prefix, lang) = if let Some((prefix, lang)) = k.split_once('#') {
|
@@ -392,6 +393,8 @@ impl<'de> Deserialize<'de> for ClientMetadataLocalizedFields {
|
392 | 393 |
|
393 | 394 | #[cfg(test)]
|
394 | 395 | mod tests {
|
| 396 | + use insta::assert_yaml_snapshot; |
| 397 | + |
395 | 398 | use super::*;
|
396 | 399 |
|
397 | 400 | #[test]
|
@@ -464,16 +467,28 @@ mod tests {
|
464 | 467 | .validate()
|
465 | 468 | .unwrap();
|
466 | 469 |
|
467 |
| - assert_eq!( |
468 |
| - serde_json::to_value(metadata).unwrap(), |
469 |
| - serde_json::json!({ |
470 |
| - "redirect_uris": ["http://localhost/oidc"], |
471 |
| - "client_name": "Postbox", |
472 |
| - "client_name#fr": "Boîte à lettres", |
473 |
| - "client_uri": "https://localhost/", |
474 |
| - "client_uri#fr": "https://localhost/fr", |
475 |
| - "client_uri#de": "https://localhost/de", |
476 |
| - }) |
477 |
| - ); |
| 470 | + assert_yaml_snapshot!(metadata, @r###" |
| 471 | + redirect_uris: |
| 472 | + - "http://localhost/oidc" |
| 473 | + client_name: Postbox |
| 474 | + "client_name#fr": Boîte à lettres |
| 475 | + client_uri: "https://localhost/" |
| 476 | + "client_uri#fr": "https://localhost/fr" |
| 477 | + "client_uri#de": "https://localhost/de" |
| 478 | + "###); |
| 479 | + |
| 480 | + // Do a roundtrip, we should get the same metadata back with the same order |
| 481 | + let metadata: ClientMetadata = |
| 482 | + serde_json::from_value(serde_json::to_value(metadata).unwrap()).unwrap(); |
| 483 | + let metadata = metadata.validate().unwrap(); |
| 484 | + assert_yaml_snapshot!(metadata, @r###" |
| 485 | + redirect_uris: |
| 486 | + - "http://localhost/oidc" |
| 487 | + client_name: Postbox |
| 488 | + "client_name#fr": Boîte à lettres |
| 489 | + client_uri: "https://localhost/" |
| 490 | + "client_uri#fr": "https://localhost/fr" |
| 491 | + "client_uri#de": "https://localhost/de" |
| 492 | + "###); |
478 | 493 | }
|
479 | 494 | }
|
0 commit comments