1#![warn(rust_2018_idioms)]
2extern crate alloc;
12
13use alloc::borrow::Cow;
14use core::fmt;
15
16pub mod file;
18
19pub mod symlink;
21
22pub mod dir;
24pub use dir::{resolve, LookupError, MaybeResolved, ResolveError};
25
26mod pb;
27pub use pb::{FlatUnixFs, PBLink, PBNode, UnixFs, UnixFsType};
28
29pub mod dagpb;
31
32pub mod walk;
34
35#[cfg(test)]
36pub(crate) mod test_support;
37
38#[derive(Debug)]
40pub struct InvalidCidInLink {
41 pub nth: usize,
43 pub hash: Cow<'static, [u8]>,
45 pub name: Cow<'static, str>,
48 pub source: libipld::cid::Error,
50 #[allow(dead_code)]
52 hidden: (),
53}
54
55impl<'a> From<(usize, pb::PBLink<'a>, libipld::cid::Error)> for InvalidCidInLink {
56 fn from((nth, link, source): (usize, pb::PBLink<'a>, libipld::cid::Error)) -> Self {
57 let hash = match link.Hash {
58 Some(Cow::Borrowed(x)) if !x.is_empty() => Cow::Owned(x.to_vec()),
59 Some(Cow::Borrowed(_)) | None => Cow::Borrowed(&[][..]),
60 Some(Cow::Owned(x)) => Cow::Owned(x),
61 };
62
63 let name = match link.Name {
64 Some(Cow::Borrowed(x)) if !x.is_empty() => Cow::Owned(x.to_string()),
65 Some(Cow::Borrowed(_)) | None => Cow::Borrowed(""),
66 Some(Cow::Owned(x)) => Cow::Owned(x),
67 };
68
69 InvalidCidInLink {
70 nth,
71 hash,
72 name,
73 source,
74 hidden: (),
75 }
76 }
77}
78
79impl fmt::Display for InvalidCidInLink {
80 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
81 write!(
82 fmt,
83 "failed to convert link #{} ({:?}) to Cid: {}",
84 self.nth, self.name, self.source
85 )
86 }
87}
88
89impl std::error::Error for InvalidCidInLink {
90 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
91 Some(&self.source)
92 }
93}
94
95pub struct UnexpectedNodeType(i32);
98
99impl fmt::Debug for UnexpectedNodeType {
100 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
101 let converted = UnixFsType::from(self.0);
102 if converted == UnixFsType::Raw && self.0 != 0 {
104 write!(fmt, "{} or <unknown>", self.0)
105 } else {
106 write!(fmt, "{} or {:?}", self.0, converted)
107 }
108 }
109}
110
111impl From<UnixFsType> for UnexpectedNodeType {
112 fn from(t: UnixFsType) -> UnexpectedNodeType {
113 UnexpectedNodeType(t.into())
114 }
115}
116
117impl UnexpectedNodeType {
118 pub fn is_directory(&self) -> bool {
120 matches!(
121 UnixFsType::from(self.0),
122 UnixFsType::Directory | UnixFsType::HAMTShard
123 )
124 }
125
126 pub fn is_file(&self) -> bool {
128 matches!(UnixFsType::from(self.0), UnixFsType::File)
129 }
130}
131
132#[derive(Debug, Default, PartialEq, Eq, Clone)]
134pub struct Metadata {
135 mode: Option<u32>,
136 mtime: Option<(i64, u32)>,
137}
138
139impl Metadata {
140 pub fn mode(&self) -> Option<u32> {
149 self.mode
150 }
151
152 pub fn mtime(&self) -> Option<(i64, u32)> {
158 self.mtime
159 }
160
161 #[cfg(feature = "filetime")]
163 pub fn mtime_as_filetime(&self) -> Option<filetime::FileTime> {
164 self.mtime()
165 .map(|(seconds, nanos)| filetime::FileTime::from_unix_time(seconds, nanos))
166 }
167}
168
169impl<'a> From<&'a UnixFs<'_>> for Metadata {
170 fn from(data: &'a UnixFs<'_>) -> Self {
171 let mode = data.mode;
172 let mtime = data
173 .mtime
174 .clone()
175 .map(|ut| (ut.Seconds, ut.FractionalNanoseconds.unwrap_or(0)));
176
177 Metadata { mode, mtime }
178 }
179}