Skip to content

Commit

Permalink
refactor: PlaceholderFile owns blob + remove derives from commands
Browse files Browse the repository at this point in the history
Co-authored-by: ok-nick <nick.libraries@gmail.com>
  • Loading branch information
ho-229 and ok-nick authored May 31, 2024
1 parent 741cbf8 commit 022e30f
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 39 deletions.
6 changes: 3 additions & 3 deletions examples/sftp/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ impl SyncFilter for Filter {

let dirs = self.sftp.readdir(parent).unwrap();
let placeholders = dirs
.iter()
.into_iter()
.filter(|(path, _)| !Path::new(&client_path).join(path).exists())
.map(|(path, stat)| {
println!("path: {:?}, stat {:?}", path, stat);
Expand All @@ -350,11 +350,11 @@ impl SyncFilter for Filter {
)
.overwrite()
// .mark_sync() // need this?
.blob(path.as_os_str().as_encoded_bytes())
.blob(path.into_os_string().into_encoded_bytes())
})
.collect::<Vec<_>>();

ticket.pass_with_placeholder(&placeholders).unwrap();
ticket.pass_with_placeholder(placeholders).unwrap();
}

fn closed(&self, request: Request, info: info::Closed) {
Expand Down
20 changes: 10 additions & 10 deletions src/command/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
};

/// Read data from a placeholder file.
#[derive(Debug, Default)]
#[derive(Debug)]
pub struct Read<'a> {
/// The buffer of data to read into.
pub buffer: &'a mut [u8],
Expand Down Expand Up @@ -54,7 +54,7 @@ impl Command for Read<'_> {
}

/// Write data to a placeholder file.
#[derive(Debug, Clone, Default)]
#[derive(Debug)]
pub struct Write<'a> {
/// The buffer of data to write into the file.
pub buffer: &'a [u8],
Expand Down Expand Up @@ -109,7 +109,7 @@ impl Fallible for Write<'_> {
}

/// Update various properties on a placeholder.
#[derive(Debug, Clone, Default)]
#[derive(Debug)]
pub struct Update<'a> {
/// Whether or not to mark the placeholder as "synced."
pub mark_sync: bool,
Expand Down Expand Up @@ -148,10 +148,10 @@ impl Command for Update<'_> {
}

/// Create placeholder files/directories.
#[derive(Debug, Clone, Default)]
#[derive(Debug)]
pub struct CreatePlaceholders<'a> {
/// The placeholders to create.
pub placeholders: &'a [PlaceholderFile<'a>], // FIXME: placeholder should be mutable
pub placeholders: &'a mut [PlaceholderFile],
/// The total amount of placeholders that are a child of the current directory.
pub total: u64,
}
Expand Down Expand Up @@ -203,7 +203,7 @@ impl Command for CreatePlaceholders<'_> {
}
}

impl<'a> Fallible for CreatePlaceholders<'a> {
impl Fallible for CreatePlaceholders<'_> {
fn fail(
connection_key: RawConnectionKey,
transfer_key: RawTransferKey,
Expand All @@ -228,7 +228,7 @@ impl<'a> Fallible for CreatePlaceholders<'a> {
}

/// Validate the data range in the placeholder file is valid.
#[derive(Debug, Clone, Default)]
#[derive(Debug)]
pub struct Validate {
/// The range of data to validate as "good."
pub range: Range<u64>,
Expand Down Expand Up @@ -276,7 +276,7 @@ impl Fallible for Validate {
}

/// Confirm dehydration of the placeholder file and optionally update its blob.
#[derive(Debug, Clone, Default)]
#[derive(Debug)]
pub struct Dehydrate<'a> {
/// Optional file blob to update.
pub blob: Option<&'a [u8]>,
Expand Down Expand Up @@ -326,7 +326,7 @@ impl Fallible for Dehydrate<'_> {
}

/// Confirm deletion of the placeholder.
#[derive(Debug, Clone, Default)]
#[derive(Debug)]
pub struct Delete;

impl Command for Delete {
Expand Down Expand Up @@ -367,7 +367,7 @@ impl Fallible for Delete {
}

/// Confirm rename/move of the placeholder.
#[derive(Debug, Clone, Default)]
#[derive(Debug)]
pub struct Rename;

impl Command for Rename {
Expand Down
6 changes: 3 additions & 3 deletions src/filter/ticket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ impl FetchPlaceholders {
/// Creates a list of placeholder files/directorys on the file system.
///
/// The value returned is the final [Usn][crate::Usn] (and if they succeeded) after each placeholder is created.
pub fn pass_with_placeholder<'a>(
pub fn pass_with_placeholder(
&self,
placeholders: &'a [PlaceholderFile<'a>],
placeholders: &mut [PlaceholderFile],
) -> core::Result<Vec<core::Result<Usn>>> {
command::CreatePlaceholders {
placeholders,
total: placeholders.len() as _,
placeholders,
}
.execute(self.connection_key, self.transfer_key)
}
Expand Down
12 changes: 11 additions & 1 deletion src/placeholder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ impl Seek for Placeholder {
}

/// Various properties to update a placeholder in batch.
#[derive(Debug, Clone, Default)]
#[derive(Debug)]
pub struct UpdateOptions<'a>(Update<'a>);

impl<'a> UpdateOptions<'a> {
Expand Down Expand Up @@ -303,6 +303,16 @@ impl<'a> UpdateOptions<'a> {
}
}

impl<'a> Default for UpdateOptions<'a> {
fn default() -> Self {
Self(Update {
mark_sync: false,
metadata: None,
blob: None,
})
}
}

// Equivalent to https://docs.microsoft.com/en-us/windows/win32/api/propvarutil/nf-propvarutil-initpropvariantfromuint32
// windows-rs doesn't provide bindings to inlined functions
#[allow(non_snake_case)]
Expand Down
58 changes: 36 additions & 22 deletions src/placeholder_file.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{fs, marker::PhantomData, os::windows::prelude::MetadataExt, path::Path, ptr};
use std::{fs, os::windows::prelude::MetadataExt, path::Path, ptr, slice};

use widestring::U16CString;
use windows::{
Expand All @@ -20,24 +20,21 @@ use crate::usn::Usn;
/// A builder for creating new placeholder files/directories.
#[repr(C)]
#[derive(Debug)]
pub struct PlaceholderFile<'a>(CF_PLACEHOLDER_CREATE_INFO, PhantomData<&'a ()>);
pub struct PlaceholderFile(CF_PLACEHOLDER_CREATE_INFO);

impl<'a> PlaceholderFile<'a> {
impl PlaceholderFile {
/// Creates a new [PlaceholderFile][crate::PlaceholderFile].
pub fn new(relative_path: impl AsRef<Path>) -> Self {
Self(
CF_PLACEHOLDER_CREATE_INFO {
RelativeFileName: PCWSTR(
U16CString::from_os_str(relative_path.as_ref())
.unwrap()
.into_raw(),
),
Flags: CloudFilters::CF_PLACEHOLDER_CREATE_FLAG_NONE,
Result: Foundation::S_OK,
..Default::default()
},
PhantomData,
)
Self(CF_PLACEHOLDER_CREATE_INFO {
RelativeFileName: PCWSTR(
U16CString::from_os_str(relative_path.as_ref())
.unwrap()
.into_raw(),
),
Flags: CloudFilters::CF_PLACEHOLDER_CREATE_FLAG_NONE,
Result: Foundation::S_OK,
..Default::default()
})
}

/// Marks this [PlaceholderFile][crate::PlaceholderFile] as having no child placeholders on
Expand Down Expand Up @@ -93,15 +90,22 @@ impl<'a> PlaceholderFile<'a> {
///
/// The buffer must not exceed
/// [4KiB](https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Storage/CloudFilters/constant.CF_PLACEHOLDER_MAX_FILE_IDENTITY_LENGTH.html).
pub fn blob(mut self, blob: &'a [u8]) -> Self {
pub fn blob(mut self, blob: Vec<u8>) -> Self {
assert!(
blob.len() <= CloudFilters::CF_PLACEHOLDER_MAX_FILE_IDENTITY_LENGTH as usize,
"blob size must not exceed {} bytes, got {} bytes",
CloudFilters::CF_PLACEHOLDER_MAX_FILE_IDENTITY_LENGTH,
blob.len()
);
self.0.FileIdentity = blob.as_ptr() as *mut _;
self.0.FileIdentityLength = blob.len() as u32;

if blob.is_empty() {
return self;
}

let leaked_blob = Box::leak(blob.into_boxed_slice());

self.0.FileIdentity = leaked_blob.as_ptr() as *const _;
self.0.FileIdentityLength = leaked_blob.len() as _;

self
}
Expand Down Expand Up @@ -131,10 +135,20 @@ impl<'a> PlaceholderFile<'a> {
}
}

impl Drop for PlaceholderFile<'_> {
impl Drop for PlaceholderFile {
fn drop(&mut self) {
// Safety: `self.0.RelativeFileName.0` is a valid pointer to a valid UTF-16 string
drop(unsafe { U16CString::from_ptr_str(self.0.RelativeFileName.0) })
drop(unsafe { U16CString::from_ptr_str(self.0.RelativeFileName.0) });

if !self.0.FileIdentity.is_null() {
// Safety: `self.0.FileIdentity` is a valid pointer to a valid slice
drop(unsafe {
Box::from_raw(slice::from_raw_parts_mut(
self.0.FileIdentity as *mut u8,
self.0.FileIdentityLength as _,
))
});
}
}
}

Expand All @@ -143,7 +157,7 @@ pub trait BatchCreate {
fn create<P: AsRef<Path>>(&mut self, path: P) -> core::Result<Vec<core::Result<Usn>>>;
}

impl BatchCreate for [PlaceholderFile<'_>] {
impl BatchCreate for [PlaceholderFile] {
fn create<P: AsRef<Path>>(&mut self, path: P) -> core::Result<Vec<core::Result<Usn>>> {
unsafe {
CfCreatePlaceholders(
Expand Down

0 comments on commit 022e30f

Please sign in to comment.