*/
#![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> {
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<T: Read + Seek>(&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::<T>),
+ Some(seek_callback::<T>),
+ );
+
+ let res = dav_store(self.ptr);
+
+ res == 0
+ }
+ }
+
+ pub fn store_with_stream<T: Read>(&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::<T>),
+ None,
+ );
+
+ let res = dav_store(self.ptr);
+
+ res == 0
+ }
+ }
+
+ pub fn get_content<T: Write>(&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::<T>),
+ )
+ };
+
+ result == 0
+ }
+}
+
+
+struct DavSeekableInputStream<'a, T: Read + Seek> {
+ inner: &'a mut T,
+}
+
+struct DavInputStream<'a, T: Read> {
+ inner: &'a mut T,
+}
+
+
+fn do_read<T: 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<T: Read + Seek>(
+ ptr: *const c_void,
+ size: size_t,
+ nmemb: size_t,
+ stream: *mut c_void,
+) -> size_t {
+ unsafe {
+ let stream = &mut *(stream as *mut DavSeekableInputStream<T>);
+ do_read(ptr, size, nmemb, stream.inner)
+ }
+}
+
+extern "C" fn read_callback<T: Read>(
+ ptr: *const c_void,
+ size: size_t,
+ nmemb: size_t,
+ stream: *mut c_void,
+) -> size_t {
+ unsafe {
+ let stream = &mut *(stream as *mut DavInputStream<T>);
+ do_read(ptr, size, nmemb, stream.inner)
+ }
+}
+
+
+extern "C" fn seek_callback<T: Read + Seek>(
+ stream: *mut c_void,
+ offset: c_long,
+ whence: c_int,
+) -> c_int {
+ unsafe {
+ let stream = &mut *(stream as *mut DavSeekableInputStream<T>);
+
+ 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<T: Write> {
+ inner: T,
+}
+
+
+extern "C" fn write_callback<T: Write>(
+ data: *const c_void,
+ size: size_t,
+ nmemb: size_t,
+ stream: *mut c_void,
+) -> size_t {
+ unsafe {
+ let stream = &mut *(stream as *mut DavOutputStream<T>);
+
+ 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,
+ }
}
}
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