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