1use crate::error::{ClientResultExt, ZeroFsError};
2use crate::session::{FidGuard, Session};
3use crate::types::{Metadata, SetAttrs};
4use std::sync::Arc;
5use std::sync::atomic::{AtomicBool, Ordering};
6
7pub struct File {
10 session: Arc<Session>,
11 guard: FidGuard,
12 closed: AtomicBool,
13 path: String,
14}
15
16impl std::fmt::Debug for File {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 f.debug_struct("File")
19 .field("path", &self.path)
20 .field("closed", &self.closed.load(Ordering::Relaxed))
21 .finish_non_exhaustive()
22 }
23}
24
25impl File {
26 pub(crate) fn new(session: Arc<Session>, guard: FidGuard, path: String) -> Arc<Self> {
27 Arc::new(Self {
28 session,
29 guard,
30 closed: AtomicBool::new(false),
31 path,
32 })
33 }
34
35 fn check(&self) -> Result<u32, ZeroFsError> {
36 if self.closed.load(Ordering::Acquire) {
37 Err(ZeroFsError::Closed)
38 } else {
39 Ok(self.guard.fid())
40 }
41 }
42
43 #[cfg(feature = "tokio-io")]
46 pub(crate) fn max_read_chunk(&self) -> u32 {
47 self.session.client.max_io()
48 }
49
50 pub async fn read_at(&self, offset: u64, len: u32) -> Result<bytes::Bytes, ZeroFsError> {
53 let fid = self.check()?;
54 self.session
55 .client
56 .read_bytes(fid, offset, len)
57 .await
58 .ctx(&self.path)
59 }
60
61 pub async fn write_at(&self, offset: u64, data: &[u8]) -> Result<(), ZeroFsError> {
64 let fid = self.check()?;
65 self.session.write_all(fid, offset, data, &self.path).await
66 }
67
68 pub async fn metadata(&self) -> Result<Metadata, ZeroFsError> {
70 let fid = self.check()?;
71 let stat = self.session.stat_fid(fid, &self.path).await?;
72 Ok(Metadata::from_stat(&stat))
73 }
74
75 pub async fn set_len(&self, size: u64) -> Result<(), ZeroFsError> {
77 let fid = self.check()?;
78 let attrs = SetAttrs {
79 size: Some(size),
80 ..Default::default()
81 };
82 self.session.setattr_fid(fid, &attrs, &self.path).await?;
83 Ok(())
84 }
85
86 pub async fn set_attr(&self, attrs: SetAttrs) -> Result<Metadata, ZeroFsError> {
88 let fid = self.check()?;
89 let stat = self.session.setattr_fid(fid, &attrs, &self.path).await?;
90 Ok(Metadata::from_stat(&stat))
91 }
92
93 pub async fn sync_all(&self) -> Result<(), ZeroFsError> {
95 let fid = self.check()?;
96 self.session.client.fsync(fid, 0).await.ctx(&self.path)
97 }
98
99 pub async fn sync_data(&self) -> Result<(), ZeroFsError> {
101 let fid = self.check()?;
102 self.session.client.fsync(fid, 1).await.ctx(&self.path)
103 }
104
105 pub async fn close(&self) {
109 self.closed.store(true, Ordering::Release);
113 }
114
115 #[cfg(feature = "tokio-io")]
120 pub fn cursor(self: &Arc<File>) -> crate::io::FileCursor {
121 crate::io::FileCursor::new(Arc::clone(self))
122 }
123}