use libc::c_uint;
use pavao_sys::smbc_dirent;
use crate::utils::char_ptr_to_string;
use crate::SmbError;
#[derive(Debug, Clone)]
pub struct SmbDirent {
type_: SmbDirentType,
comment: String,
name: String,
}
impl SmbDirent {
pub fn get_type(&self) -> SmbDirentType {
self.type_
}
pub fn comment(&self) -> &str {
self.comment.as_str()
}
pub fn name(&self) -> &str {
self.name.as_str()
}
}
impl TryFrom<smbc_dirent> for SmbDirent {
type Error = SmbError;
fn try_from(d: smbc_dirent) -> Result<Self, Self::Error> {
let comment = char_ptr_to_string(d.comment)?;
let name = char_ptr_to_string(d.name.as_slice().as_ptr())?;
Ok(Self {
type_: SmbDirentType::try_from(d.smbc_type)?,
comment,
name,
})
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum SmbDirentType {
Workgroup,
Server,
FileShare,
PrinterShare,
CommsShare,
IpcShare,
Dir,
File,
Link,
}
impl From<SmbDirentType> for c_uint {
fn from(type_: SmbDirentType) -> Self {
match type_ {
SmbDirentType::Workgroup => 1,
SmbDirentType::Server => 2,
SmbDirentType::FileShare => 3,
SmbDirentType::PrinterShare => 4,
SmbDirentType::CommsShare => 5,
SmbDirentType::IpcShare => 6,
SmbDirentType::Dir => 7,
SmbDirentType::File => 8,
SmbDirentType::Link => 9,
}
}
}
impl TryFrom<c_uint> for SmbDirentType {
type Error = SmbError;
fn try_from(value: c_uint) -> Result<Self, Self::Error> {
match value {
1 => Ok(Self::Workgroup),
2 => Ok(Self::Server),
3 => Ok(Self::FileShare),
4 => Ok(Self::PrinterShare),
5 => Ok(Self::CommsShare),
6 => Ok(Self::IpcShare),
7 => Ok(Self::Dir),
8 => Ok(Self::File),
9 => Ok(Self::Link),
_ => Err(Self::Error::BadValue),
}
}
}
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
use super::*;
use crate::utils;
#[test]
fn should_convert_dirent_type_to_uint() {
assert_eq!(c_uint::from(SmbDirentType::Workgroup), 1);
assert_eq!(c_uint::from(SmbDirentType::Server), 2);
assert_eq!(c_uint::from(SmbDirentType::FileShare), 3);
assert_eq!(c_uint::from(SmbDirentType::PrinterShare), 4);
assert_eq!(c_uint::from(SmbDirentType::CommsShare), 5);
assert_eq!(c_uint::from(SmbDirentType::IpcShare), 6);
assert_eq!(c_uint::from(SmbDirentType::Dir), 7);
assert_eq!(c_uint::from(SmbDirentType::File), 8);
assert_eq!(c_uint::from(SmbDirentType::Link), 9);
}
#[test]
fn should_convert_uint_to_dirent_type() {
assert_eq!(
SmbDirentType::try_from(1).unwrap(),
SmbDirentType::Workgroup
);
assert_eq!(SmbDirentType::try_from(2).unwrap(), SmbDirentType::Server);
assert_eq!(
SmbDirentType::try_from(3).unwrap(),
SmbDirentType::FileShare
);
assert_eq!(
SmbDirentType::try_from(4).unwrap(),
SmbDirentType::PrinterShare
);
assert_eq!(
SmbDirentType::try_from(5).unwrap(),
SmbDirentType::CommsShare
);
assert_eq!(SmbDirentType::try_from(6).unwrap(), SmbDirentType::IpcShare);
assert_eq!(SmbDirentType::try_from(7).unwrap(), SmbDirentType::Dir);
assert_eq!(SmbDirentType::try_from(8).unwrap(), SmbDirentType::File);
assert_eq!(SmbDirentType::try_from(9).unwrap(), SmbDirentType::Link);
}
#[test]
fn should_not_convert_bad_dirent_type() {
assert!(SmbDirentType::try_from(100).is_err());
}
#[test]
fn should_convert_dirent_to_smb_dirent() {
let mut dirent = smbc_dirent::default();
let comment = String::from("test");
let comment_ptr = utils::str_to_cstring(comment).unwrap();
dirent.smbc_type = 8;
dirent.comment = comment_ptr.into_raw();
dirent.commentlen = 5;
dirent.name = [0; 1024];
dirent.namelen = 1;
dirent.name[0] = 'h' as libc::c_char;
dirent.name[1] = 'e' as libc::c_char;
dirent.name[2] = 'l' as libc::c_char;
dirent.name[3] = 'l' as libc::c_char;
dirent.name[4] = 'o' as libc::c_char;
let dirent = SmbDirent::try_from(dirent).unwrap();
assert_eq!(dirent.get_type(), SmbDirentType::File);
assert_eq!(dirent.name(), "hello");
assert_eq!(dirent.comment(), "test");
}
#[test]
fn should_fail_conversion_from_smbc_dirent() {
assert!(SmbDirent::try_from(smbc_dirent::default()).is_err());
}
}