1#![warn(rust_2018_idioms, missing_docs)]
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;
27use pb::{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: cid::Error,
50 hidden: (),
52}
53
54impl<'a> From<(usize, pb::PBLink<'a>, cid::Error)> for InvalidCidInLink {
55 fn from((nth, link, source): (usize, pb::PBLink<'a>, cid::Error)) -> Self {
56 let hash = match link.Hash {
57 Some(Cow::Borrowed(x)) if !x.is_empty() => Cow::Owned(x.to_vec()),
58 Some(Cow::Borrowed(_)) | None => Cow::Borrowed(&[][..]),
59 Some(Cow::Owned(x)) => Cow::Owned(x),
60 };
61
62 let name = match link.Name {
63 Some(Cow::Borrowed(x)) if !x.is_empty() => Cow::Owned(x.to_string()),
64 Some(Cow::Borrowed(_)) | None => Cow::Borrowed(""),
65 Some(Cow::Owned(x)) => Cow::Owned(x),
66 };
67
68 InvalidCidInLink {
69 nth,
70 hash,
71 name,
72 source,
73 hidden: (),
74 }
75 }
76}
77
78impl fmt::Display for InvalidCidInLink {
79 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
80 write!(
81 fmt,
82 "failed to convert link #{} ({:?}) to Cid: {}",
83 self.nth, self.name, self.source
84 )
85 }
86}
87
88impl std::error::Error for InvalidCidInLink {
89 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
90 Some(&self.source)
91 }
92}
93
94pub struct UnexpectedNodeType(i32);
97
98impl fmt::Debug for UnexpectedNodeType {
99 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
100 let converted = UnixFsType::from(self.0);
101 if converted == UnixFsType::Raw && self.0 != 0 {
103 write!(fmt, "{} or <unknown>", self.0)
104 } else {
105 write!(fmt, "{} or {:?}", self.0, converted)
106 }
107 }
108}
109
110impl From<UnixFsType> for UnexpectedNodeType {
111 fn from(t: UnixFsType) -> UnexpectedNodeType {
112 UnexpectedNodeType(t.into())
113 }
114}
115
116impl UnexpectedNodeType {
117 pub fn is_directory(&self) -> bool {
119 matches!(
120 UnixFsType::from(self.0),
121 UnixFsType::Directory | UnixFsType::HAMTShard
122 )
123 }
124
125 pub fn is_file(&self) -> bool {
127 matches!(UnixFsType::from(self.0), UnixFsType::File)
128 }
129}
130
131#[derive(Debug, Default, PartialEq, Eq, Clone)]
133pub struct Metadata {
134 mode: Option<u32>,
135 mtime: Option<(i64, u32)>,
136}
137
138impl Metadata {
139 pub fn mode(&self) -> Option<u32> {
148 self.mode
149 }
150
151 pub fn mtime(&self) -> Option<(i64, u32)> {
157 self.mtime
158 }
159
160 #[cfg(feature = "filetime")]
162 pub fn mtime_as_filetime(&self) -> Option<filetime::FileTime> {
163 self.mtime()
164 .map(|(seconds, nanos)| filetime::FileTime::from_unix_time(seconds, nanos))
165 }
166}
167
168impl<'a> From<&'a UnixFs<'_>> for Metadata {
169 fn from(data: &'a UnixFs<'_>) -> Self {
170 let mode = data.mode;
171 let mtime = data
172 .mtime
173 .clone()
174 .map(|ut| (ut.Seconds, ut.FractionalNanoseconds.unwrap_or(0)));
175
176 Metadata { mode, mtime }
177 }
178}