Skip to content

Commit 9d4a952

Browse files
committed
feat(api): reflection types for hardlink types
1 parent 475c690 commit 9d4a952

5 files changed

Lines changed: 114 additions & 0 deletions

File tree

src/hardlink/hardlink_list.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1+
pub mod reflection;
2+
3+
pub use reflection::Reflection;
4+
15
use crate::{hardlink::LinkPathList, inode::InodeNumber, size};
26
use dashmap::{iter::Iter as DashIter, mapref::multiple::RefMulti, DashMap};
37
use derive_more::{Display, Error};
48
use pipe_trait::Pipe;
59
use std::{fmt::Debug, path::Path};
610

711
/// Storage to be used by [`crate::hook::RecordHardlink`].
12+
///
13+
/// **Serialization and deserialization:** _(feature: `json`)_ `HardlinkList` does not implement
14+
/// `Serialize` and `Deserialize` traits directly, instead, it can be converted into/from a
15+
/// [`Reflection`] which implements these traits.
816
#[derive(Debug, Clone)]
917
pub struct HardlinkList<Size>(
1018
/// Map an inode number to its size and detected paths.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use super::HardlinkList;
2+
use crate::{
3+
hardlink::{link_path_list, LinkPathList},
4+
inode::InodeNumber,
5+
};
6+
use dashmap::DashMap;
7+
use derive_more::{From, Into, IntoIterator};
8+
use pipe_trait::Pipe;
9+
use std::collections::HashMap;
10+
11+
#[cfg(feature = "json")]
12+
use serde::{Deserialize, Serialize};
13+
14+
/// Intermediate format used for construction and inspection of
15+
/// [`HardlinkList`]'s internal content.
16+
///
17+
/// **Serialization and deserialization:** _(feature: `json`)_ `Reflection` implements
18+
/// `Serialize` and `Deserialize` traits, this allows functions in `serde_json` to convert
19+
/// a `Reflection` into/from JSON.
20+
#[derive(Debug, Clone, PartialEq, Eq, From, Into, IntoIterator)]
21+
#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
22+
pub struct Reflection<Size>(pub HashMap<InodeNumber, Value<Size>>);
23+
24+
/// Size and list of link paths corresponding to an [`InodeNumber`] in [`Reflection`].
25+
#[derive(Debug, Clone, PartialEq, Eq)]
26+
#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
27+
pub struct Value<Size> {
28+
pub size: Size,
29+
pub links: link_path_list::Reflection,
30+
}
31+
32+
impl<Size> Value<Size> {
33+
/// Create a new value.
34+
fn new(size: Size, links: LinkPathList) -> Self {
35+
let links = links.into();
36+
Value { size, links }
37+
}
38+
39+
/// Convert the internal [`link_path_list::Reflection`] into a [`LinkPathList`].
40+
fn into_list(self) -> (Size, LinkPathList) {
41+
let Value { size, links } = self;
42+
(size, links.into())
43+
}
44+
}
45+
46+
impl<Size> From<HardlinkList<Size>> for Reflection<Size> {
47+
fn from(value: HardlinkList<Size>) -> Self {
48+
value
49+
.0
50+
.into_iter()
51+
.map(|(ino, (size, links))| (ino, Value::new(size, links)))
52+
.collect::<HashMap<_, _>>()
53+
.pipe(Reflection)
54+
}
55+
}
56+
57+
impl<Size> From<Reflection<Size>> for HardlinkList<Size> {
58+
fn from(value: Reflection<Size>) -> Self {
59+
value
60+
.into_iter()
61+
.map(|(ino, value)| (ino, value.into_list()))
62+
.collect::<DashMap<_, _>>()
63+
.pipe(HardlinkList)
64+
}
65+
}

src/hardlink/link_path_list.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1+
mod reflection;
2+
3+
pub use reflection::Reflection;
4+
15
use pipe_trait::Pipe;
26
use std::{iter::FusedIterator, path::PathBuf, slice};
37

48
/// List of different hardlinks to the same file.
9+
///
10+
/// **Serialization and deserialization:** _(feature: `json`)_ `LinkPathList` does not implement
11+
/// `Serialize` and `Deserialize` traits directly, instead, it can be converted into/from a
12+
/// [`Reflection`] which implements these traits.
513
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
614
pub struct LinkPathList(
715
Vec<PathBuf>, // TODO: benchmark against LinkedList<PathBuf>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use super::LinkPathList;
2+
use derive_more::{From, Into, IntoIterator};
3+
use pipe_trait::Pipe;
4+
use std::{collections::HashSet, path::PathBuf};
5+
6+
#[cfg(feature = "json")]
7+
use serde::{Deserialize, Serialize};
8+
9+
/// Intermediate format used for construction and inspection of
10+
/// [`LinkPathList`]'s internal content.
11+
///
12+
/// **Serialization and deserialization:** _(feature: `json`)_ `Reflection` implements
13+
/// `Serialize` and `Deserialize` traits, this allows functions in `serde_json` to convert
14+
/// a `Reflection` into/from JSON.
15+
#[derive(Debug, Clone, PartialEq, Eq, From, Into, IntoIterator)]
16+
#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
17+
pub struct Reflection(pub HashSet<PathBuf>);
18+
19+
impl From<LinkPathList> for Reflection {
20+
fn from(value: LinkPathList) -> Self {
21+
value.0.into_iter().collect::<HashSet<_>>().pipe(Reflection)
22+
}
23+
}
24+
25+
impl From<Reflection> for LinkPathList {
26+
fn from(value: Reflection) -> Self {
27+
value.0.into_iter().collect::<Vec<_>>().pipe(LinkPathList)
28+
}
29+
}

src/inode.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
use derive_more::{Display, From, Into, LowerHex, Octal, UpperHex};
22

3+
#[cfg(feature = "json")]
4+
use serde::{Deserialize, Serialize};
5+
36
/// The inode number of a file or directory.
47
#[derive(
58
Debug, Display, LowerHex, UpperHex, Octal, Clone, Copy, PartialEq, Eq, Hash, From, Into,
69
)]
10+
#[cfg_attr(feature = "json", derive(Deserialize, Serialize))]
711
pub struct InodeNumber(u64);
812

913
/// POSIX-exclusive functions.

0 commit comments

Comments
 (0)