librqbit_clone_to_owned/
lib.rs

1// These are helpers for objects that can be borrowed, but can be made owned while changing the type.
2// The difference between e.g. Cow and CloneToOwned, is that we can implement it recursively for owned types.
3//
4// E.g. HashMap<&str, &str> can be converted to HashMap<String, String>.
5//
6// This lets us express types like TorrentMetaInfo<&[u8]> for zero-copy metadata about a bencode buffer in memory,
7// but to have one-line conversion for it into TorrentMetaInfo<Vec<u8>> so that we can store it later somewhere.
8
9use bytes::Bytes;
10use std::collections::HashMap;
11
12pub trait CloneToOwned {
13    type Target;
14
15    fn clone_to_owned(&self, within_buffer: Option<&Bytes>) -> Self::Target;
16}
17
18impl<T> CloneToOwned for Option<T>
19where
20    T: CloneToOwned,
21{
22    type Target = Option<<T as CloneToOwned>::Target>;
23
24    fn clone_to_owned(&self, within_buffer: Option<&Bytes>) -> Self::Target {
25        self.as_ref().map(|i| i.clone_to_owned(within_buffer))
26    }
27}
28
29impl<T> CloneToOwned for Vec<T>
30where
31    T: CloneToOwned,
32{
33    type Target = Vec<<T as CloneToOwned>::Target>;
34
35    fn clone_to_owned(&self, within_buffer: Option<&Bytes>) -> Self::Target {
36        self.iter()
37            .map(|i| i.clone_to_owned(within_buffer))
38            .collect()
39    }
40}
41
42impl CloneToOwned for u8 {
43    type Target = u8;
44
45    fn clone_to_owned(&self, _within_buffer: Option<&Bytes>) -> Self::Target {
46        *self
47    }
48}
49
50impl CloneToOwned for u32 {
51    type Target = u32;
52
53    fn clone_to_owned(&self, _within_buffer: Option<&Bytes>) -> Self::Target {
54        *self
55    }
56}
57
58impl<K, V> CloneToOwned for HashMap<K, V>
59where
60    K: CloneToOwned,
61    <K as CloneToOwned>::Target: std::hash::Hash + Eq,
62    V: CloneToOwned,
63{
64    type Target = HashMap<<K as CloneToOwned>::Target, <V as CloneToOwned>::Target>;
65
66    fn clone_to_owned(&self, within_buffer: Option<&Bytes>) -> Self::Target {
67        let mut result = HashMap::with_capacity(self.capacity());
68        for (k, v) in self {
69            result.insert(
70                k.clone_to_owned(within_buffer),
71                v.clone_to_owned(within_buffer),
72            );
73        }
74        result
75    }
76}