From: Olaf Wintermann Date: Mon, 22 Jun 2026 19:20:53 +0000 (+0200) Subject: add dav resource methods for loading/storing content X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=1e3c1bdae5575721d39fbdd0541330612a053056;p=note.git add dav resource methods for loading/storing content --- diff --git a/dav-rs/src/dav/ffi.rs b/dav-rs/src/dav/ffi.rs index 93279af..2ac0391 100644 --- a/dav-rs/src/dav/ffi.rs +++ b/dav-rs/src/dav/ffi.rs @@ -26,7 +26,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -use std::ffi::{c_char, c_int, c_void}; +use std::ffi::{c_char, c_int, c_long, c_void}; use libc::time_t; #[repr(C)] @@ -63,3 +63,8 @@ pub struct DavResource { pub iscollection: c_int, pub exists: c_int, } + +pub type DavReadFunc = Option libc::size_t>; +pub type DavWriteFunc = Option libc::size_t>; +pub type DavSeekFunc = Option c_int>; + diff --git a/dav-rs/src/dav/resource.rs b/dav-rs/src/dav/resource.rs index 25b8510..084e5e7 100644 --- a/dav-rs/src/dav/resource.rs +++ b/dav-rs/src/dav/resource.rs @@ -27,11 +27,14 @@ */ #![allow(dead_code)] -use std::ffi::{c_char, c_int, CString}; +use std::ffi::{c_char, c_int, c_long, c_void, CString}; +use std::io::{Read, Seek, SeekFrom, Write}; use std::marker::PhantomData; use std::ops::Deref; +use libc::size_t; use crate::dav::context::DavContext; use crate::dav::ffi; +use crate::dav::ffi::{DavReadFunc, DavSeekFunc, DavWriteFunc}; use crate::dav::session::Session; pub struct Resource<'a> { @@ -111,8 +114,161 @@ impl<'a> ResourceRef<'a> { unsafe { dav_store(self.ptr) == 0 } } - pub fn as_ptr(&self) -> *mut ffi::DavResource { - self.ptr + pub fn store_with_data(&self, data: &[u8]) -> bool { + unsafe { + dav_set_content_data( + self.ptr, + data.as_ptr() as *const c_char, + data.len() as size_t, + ); + + let res = dav_store(self.ptr); + + res == 0 + } + } + + pub fn store_with_seekable_stream(&self, stream: &mut T) -> bool { + let mut wrapper = DavSeekableInputStream { inner: stream }; + + unsafe { + dav_set_content( + self.ptr, + &mut wrapper as *mut _ as *mut c_void, + Some(seekable_read_callback::), + Some(seek_callback::), + ); + + let res = dav_store(self.ptr); + + res == 0 + } + } + + pub fn store_with_stream(&self, stream: &mut T) -> bool { + let mut wrapper = DavInputStream { inner: stream }; + + unsafe { + dav_set_content( + self.ptr, + &mut wrapper as *mut _ as *mut c_void, + Some(read_callback::), + None, + ); + + let res = dav_store(self.ptr); + + res == 0 + } + } + + pub fn get_content(&self, stream: &mut T) -> bool { + let mut wrapper = DavOutputStream { inner: stream }; + + let result = unsafe { + dav_get_content( + self.ptr, + &mut wrapper as *mut _ as *mut c_void, + Some(write_callback::), + ) + }; + + result == 0 + } +} + + +struct DavSeekableInputStream<'a, T: Read + Seek> { + inner: &'a mut T, +} + +struct DavInputStream<'a, T: Read> { + inner: &'a mut T, +} + + +fn do_read( + ptr: *const c_void, + size: size_t, + nmemb: size_t, + stream: &mut T) -> size_t +{ + unsafe { + let len = size * nmemb; + let out = std::slice::from_raw_parts_mut(ptr as *mut u8, len); + + match stream.read(out) { + Ok(n) => n, + Err(_) => 0, + } + } +} + +extern "C" fn seekable_read_callback( + ptr: *const c_void, + size: size_t, + nmemb: size_t, + stream: *mut c_void, +) -> size_t { + unsafe { + let stream = &mut *(stream as *mut DavSeekableInputStream); + do_read(ptr, size, nmemb, stream.inner) + } +} + +extern "C" fn read_callback( + ptr: *const c_void, + size: size_t, + nmemb: size_t, + stream: *mut c_void, +) -> size_t { + unsafe { + let stream = &mut *(stream as *mut DavInputStream); + do_read(ptr, size, nmemb, stream.inner) + } +} + + +extern "C" fn seek_callback( + stream: *mut c_void, + offset: c_long, + whence: c_int, +) -> c_int { + unsafe { + let stream = &mut *(stream as *mut DavSeekableInputStream); + + let pos = match whence { + 0 => SeekFrom::Start(offset as u64), + 1 => SeekFrom::Current(offset as i64), + 2 => SeekFrom::End(offset as i64), + _ => return -1, + }; + + stream.inner.seek(pos).map(|_| 0).unwrap_or(-1) + } +} + +struct DavOutputStream { + inner: T, +} + + +extern "C" fn write_callback( + data: *const c_void, + size: size_t, + nmemb: size_t, + stream: *mut c_void, +) -> size_t { + unsafe { + let stream = &mut *(stream as *mut DavOutputStream); + + let total_bytes = size * nmemb; + let buf = std::slice::from_raw_parts(data as *const u8, total_bytes); + + match stream.inner.write_all(buf) { + Ok(_) => nmemb, // C expects "items written" + Err(_) => 0, + } } } @@ -169,4 +325,8 @@ unsafe extern "C" { fn dav_load(res: *mut ffi::DavResource) -> c_int; fn dav_store(res: *mut ffi::DavResource) -> c_int; + + fn dav_get_content(res: *mut ffi::DavResource, stream: *mut c_void, write_func: DavWriteFunc) -> c_int; + fn dav_set_content(res: *mut ffi::DavResource, stream: *mut c_void, read: DavReadFunc, seek: DavSeekFunc); + fn dav_set_content_data(res: *mut ffi::DavResource, content: *const c_char, length: size_t); } \ No newline at end of file