Skip to content

Commit 1703482

Browse files
author
Nicklas Warming Jacobsen
committed
Add implementation of from/to TableAttribute for HashMap and BTreeMap
1 parent 646843f commit 1703482

File tree

1 file changed

+160
-1
lines changed

1 file changed

+160
-1
lines changed

src/encrypted_table/table_entry.rs

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use crate::traits::ReadConversionError;
22
use aws_sdk_dynamodb::{primitives::Blob, types::AttributeValue};
3-
use std::collections::HashMap;
3+
use std::{
4+
collections::{BTreeMap, HashMap},
5+
str::FromStr,
6+
};
47

58
// FIXME: Clean this up
69
//#[skip_serializing_none]
@@ -398,6 +401,84 @@ impl From<AttributeValue> for TableAttribute {
398401
}
399402
}
400403

404+
impl<K, V> From<HashMap<K, V>> for TableAttribute
405+
where
406+
K: ToString,
407+
V: Into<TableAttribute>,
408+
{
409+
fn from(map: HashMap<K, V>) -> Self {
410+
TableAttribute::Map(
411+
map.into_iter()
412+
.map(|(k, v)| (k.to_string(), v.into()))
413+
.collect(),
414+
)
415+
}
416+
}
417+
418+
impl<K, V> TryFromTableAttr for HashMap<K, V>
419+
where
420+
K: FromStr + std::hash::Hash + std::cmp::Eq,
421+
V: TryFromTableAttr,
422+
{
423+
fn try_from_table_attr(value: TableAttribute) -> Result<Self, ReadConversionError> {
424+
let TableAttribute::Map(map) = value else {
425+
return Err(ReadConversionError::ConversionFailed(
426+
std::any::type_name::<Self>().to_string(),
427+
));
428+
};
429+
430+
map.into_iter()
431+
.map(|(k, v)| {
432+
let k = k.parse().map_err(|_| {
433+
ReadConversionError::ConversionFailed(std::any::type_name::<Self>().to_string())
434+
})?;
435+
let v = V::try_from_table_attr(v)?;
436+
437+
Ok((k, v))
438+
})
439+
.collect()
440+
}
441+
}
442+
443+
impl<K, V> From<BTreeMap<K, V>> for TableAttribute
444+
where
445+
K: ToString,
446+
V: Into<TableAttribute>,
447+
{
448+
fn from(map: BTreeMap<K, V>) -> Self {
449+
TableAttribute::Map(
450+
map.into_iter()
451+
.map(|(k, v)| (k.to_string(), v.into()))
452+
.collect(),
453+
)
454+
}
455+
}
456+
457+
impl<K, V> TryFromTableAttr for BTreeMap<K, V>
458+
where
459+
K: FromStr + std::cmp::Ord,
460+
V: TryFromTableAttr,
461+
{
462+
fn try_from_table_attr(value: TableAttribute) -> Result<Self, ReadConversionError> {
463+
let TableAttribute::Map(map) = value else {
464+
return Err(ReadConversionError::ConversionFailed(
465+
std::any::type_name::<Self>().to_string(),
466+
));
467+
};
468+
469+
map.into_iter()
470+
.map(|(k, v)| {
471+
let k = k.parse().map_err(|_| {
472+
ReadConversionError::ConversionFailed(std::any::type_name::<Self>().to_string())
473+
})?;
474+
let v = V::try_from_table_attr(v)?;
475+
476+
Ok((k, v))
477+
})
478+
.collect()
479+
}
480+
}
481+
401482
#[cfg(test)]
402483
mod test {
403484
use super::*;
@@ -430,6 +511,38 @@ mod test {
430511
}
431512
}
432513

514+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
515+
enum MapKeys {
516+
A,
517+
B,
518+
C,
519+
}
520+
521+
impl std::fmt::Display for MapKeys {
522+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
523+
let c = match self {
524+
MapKeys::A => "A",
525+
MapKeys::B => "B",
526+
MapKeys::C => "C",
527+
};
528+
529+
write!(f, "{c}")
530+
}
531+
}
532+
533+
impl FromStr for MapKeys {
534+
type Err = ();
535+
536+
fn from_str(s: &str) -> Result<Self, Self::Err> {
537+
match s {
538+
"A" => Ok(MapKeys::A),
539+
"B" => Ok(MapKeys::B),
540+
"C" => Ok(MapKeys::C),
541+
_ => Err(()),
542+
}
543+
}
544+
}
545+
433546
#[test]
434547
fn test_to_and_from_list() {
435548
let test_vec = vec![
@@ -503,4 +616,50 @@ mod test {
503616

504617
assert_eq!(original, test_vec);
505618
}
619+
620+
#[test]
621+
fn test_hashmap() {
622+
let map = [
623+
(MapKeys::A, "Something in A".to_string()),
624+
(MapKeys::A, "Something in B".to_string()),
625+
(MapKeys::A, "Something in C".to_string()),
626+
]
627+
.into_iter()
628+
.collect::<HashMap<_, _>>();
629+
630+
let table_attribute = TableAttribute::from(map.clone());
631+
632+
assert!(matches!(
633+
&table_attribute,
634+
TableAttribute::Map(x)
635+
if x.len() == map.len()
636+
));
637+
638+
let original = HashMap::<MapKeys, String>::try_from_table_attr(table_attribute).unwrap();
639+
640+
assert_eq!(original, map);
641+
}
642+
643+
#[test]
644+
fn test_btreemap() {
645+
let map = [
646+
(MapKeys::A, "Something in A".to_string()),
647+
(MapKeys::A, "Something in B".to_string()),
648+
(MapKeys::A, "Something in C".to_string()),
649+
]
650+
.into_iter()
651+
.collect::<BTreeMap<_, _>>();
652+
653+
let table_attribute = TableAttribute::from(map.clone());
654+
655+
assert!(matches!(
656+
&table_attribute,
657+
TableAttribute::Map(x)
658+
if x.len() == map.len()
659+
));
660+
661+
let original = BTreeMap::<MapKeys, String>::try_from_table_attr(table_attribute).unwrap();
662+
663+
assert_eq!(original, map);
664+
}
506665
}

0 commit comments

Comments
 (0)