use std::mem;
use std::ffi::{CString, CStr};
use std::str;
use libc::size_t;
use traits::Wrappable;
use network::IpAddress;
use system::Time;
use csfml_network_sys as ffi;
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Copy)]
#[repr(i32)]
pub enum TransferMode {
Binary = 0,
Ascii = 1,
Ebcdic = 2
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Copy)]
#[repr(i32)]
pub enum Status {
RestartMarkerReply = ffi::RESTARTMARKERREPLY as i32,
ServiceReadySoon = ffi::SERVICEREADYSOON as i32,
DataConnectionAlreadyOpened = ffi::DATACONNECTIONALREADYOPENED as i32,
OpeningDataConnection = ffi::OPENINGDATACONNECTION as i32,
Ok = ffi::sfFtpOk as i32,
PointlessCommand = ffi::POINTLESSCOMMAND as i32,
SystemStatus = ffi::SYSTEMSTATUS as i32,
DirectoryStatus = ffi::DIRECTORYSTATUS as i32,
FileStatus = ffi::FILESTATUS as i32,
HelpMessage = ffi::HELPMESSAGE as i32,
SystemType = ffi::SYSTEMTYPE as i32,
ServiceReady = ffi::SERVICEREADY as i32,
ClosingConnection = ffi::CLOSINGCONNECTION as i32,
DataConnectionOpened = ffi::DATACONNECTIONOPENED as i32,
ClosingDataConnection = ffi::CLOSINGDATACONNECTION as i32,
EnteringPassiveMode = ffi::ENTERINGPASSIVEMODE as i32,
LoggedIn = ffi::LOGGEDIN as i32,
FileActionOk = ffi::FILEACTIONOK as i32,
DirectoryOk = ffi::DIRECTORYOK as i32,
NeedPassword = ffi::NEEDPASSWORD as i32,
NeedAccountToLogIn = ffi::NEEDACCOUNTTOLOGIN as i32,
NeedInformation = ffi::NEEDINFORMATION as i32,
ServiceUnavailable = ffi::SERVICEUNAVAILABLE as i32,
DataConnectionUnavailable = ffi::DATACONNECTIONUNAVAILABLE as i32,
TransferAborted = ffi::TRANSFERABORTED as i32,
FileActionAborted = ffi::FILEACTIONABORTED as i32,
LocalError = ffi::LOCALERROR as i32,
InsufficientStorageSpace = ffi::INSUFFICIENTSTORAGESPACE as i32,
CommandUnknown = ffi::COMMANDUNKNOWN as i32,
ParametersUnknown = ffi::PARAMETERSUNKNOWN as i32,
CommandNotImplemented = ffi::COMMANDNOTIMPLEMENTED as i32,
BadCommandSequence = ffi::BADCOMMANDSEQUENCE as i32,
ParameterNotImplemented = ffi::PARAMETERNOTIMPLEMENTED as i32,
NotLoggedIn = ffi::NOTLOGGEDIN as i32,
NeedAccountToStore = ffi::NEEDACCOUNTTOSTORE as i32,
FileUnavailable = ffi::FILEUNAVAILABLE as i32,
PageTypeUnknown = ffi::PAGETYPEUNKNOWN as i32,
NotEnoughMemory = ffi::NOTENOUGHMEMORY as i32,
FilenameNotAllowed = ffi::FILENAMENOTALLOWED as i32,
InvalidResponse = ffi::sfFtpInvalidresponse as i32,
ConnectionFailed = ffi::sfFtpConnectionFailed as i32,
ConnectionClosed = ffi::CONNECTIONCLOSED as i32,
InvalidFile = ffi::INVALIDFILE as i32
}
pub struct Ftp {
ftp: *mut ffi::sfFtp
}
pub struct Response {
response: *mut ffi::sfFtpResponse
}
pub struct ListingResponse{
listing_response: *mut ffi::sfFtpListingResponse
}
pub struct DirectoryResponse{
directory_response: *mut ffi::sfFtpDirectoryResponse
}
impl ListingResponse {
pub fn is_ok(&self) -> bool {
unsafe { ffi::sfFtpListingResponse_isOk(self.listing_response) }.to_bool()
}
pub fn get_status(&self) -> Status {
unsafe {
mem::transmute(ffi::sfFtpListingResponse_getStatus(self.listing_response) as i32)
}
}
pub fn get_message(&self) -> String {
unsafe {
let string = ffi::sfFtpListingResponse_getMessage(self.listing_response);
str::from_utf8(CStr::from_ptr(string).to_bytes_with_nul()).unwrap().into()
}
}
pub fn get_count(&self) -> u64 {
unsafe {
ffi::sfFtpListingResponse_getCount(self.listing_response) as u64
}
}
pub fn get_name(&self, index: u64) -> String {
unsafe {
let string = ffi::sfFtpListingResponse_getName(self.listing_response, index as size_t);
str::from_utf8(CStr::from_ptr(string).to_bytes_with_nul()).unwrap().into()
}
}
}
impl Drop for ListingResponse {
fn drop(&mut self) {
unsafe {
ffi::sfFtpListingResponse_destroy(self.listing_response)
}
}
}
impl DirectoryResponse {
pub fn is_ok(&self) -> bool {
unsafe { ffi::sfFtpDirectoryResponse_isOk(self.directory_response) }.to_bool()
}
pub fn get_status(&self) -> Status {
unsafe {
mem::transmute(ffi::sfFtpDirectoryResponse_getStatus(self.directory_response) as i32)
}
}
pub fn get_message(&self) -> String {
unsafe {
let string = ffi::sfFtpDirectoryResponse_getMessage(self.directory_response);
str::from_utf8(CStr::from_ptr(string).to_bytes_with_nul()).unwrap().into()
}
}
pub fn get_directory(&self) -> String {
unsafe {
let string = ffi::sfFtpDirectoryResponse_getDirectory(self.directory_response);
str::from_utf8(CStr::from_ptr(string).to_bytes_with_nul()).unwrap().into()
}
}
}
impl Drop for DirectoryResponse {
fn drop(&mut self) {
unsafe {
ffi::sfFtpDirectoryResponse_destroy(self.directory_response)
}
}
}
impl Response {
pub fn is_ok(&self) -> bool {
unsafe { ffi::sfFtpResponse_isOk(self.response) }.to_bool()
}
pub fn get_status(&self) -> Status {
unsafe {
mem::transmute(ffi::sfFtpResponse_getStatus(self.response) as i32)
}
}
pub fn get_message(&self) -> String {
unsafe {
let string = ffi::sfFtpResponse_getMessage(self.response);
str::from_utf8(CStr::from_ptr(string).to_bytes_with_nul()).unwrap().into()
}
}
}
impl Drop for Response {
fn drop(&mut self) {
unsafe {
ffi::sfFtpResponse_destroy(self.response)
}
}
}
impl Ftp {
pub fn new() -> Option<Ftp> {
let ptr = unsafe { ffi::sfFtp_create() };
if ptr.is_null() {
None
} else {
Some(Ftp {
ftp: ptr
})
}
}
pub fn connect(&self, server: &IpAddress, port: u16, timeout: &Time) -> Response {
Response {
response: unsafe { ffi::sfFtp_connect(self.ftp, server.unwrap(), port, timeout.unwrap()) }
}
}
pub fn login_anonymous(&self) -> Response {
Response {
response: unsafe { ffi::sfFtp_loginAnonymous(self.ftp) }
}
}
pub fn login(&self, user_name: &str, password: &str) -> Response {
let c_user_name = CString::new(user_name.as_bytes()).unwrap().as_ptr();
let c_password = CString::new(password.as_bytes()).unwrap().as_ptr();
Response {
response: unsafe { ffi::sfFtp_login(self.ftp,
c_user_name,
c_password) }
}
}
pub fn disconnect(&self) -> Response {
Response {
response: unsafe { ffi::sfFtp_disconnect(self.ftp) }
}
}
pub fn keep_alive(&self) -> Response {
Response {
response: unsafe { ffi::sfFtp_keepAlive(self.ftp) }
}
}
pub fn get_working_directory(&self) -> DirectoryResponse {
DirectoryResponse {
directory_response: unsafe { ffi::sfFtp_getWorkingDirectory(self.ftp) }
}
}
pub fn get_directory_listing(&self, directory: &str) -> ListingResponse {
let c_directory = CString::new(directory.as_bytes()).unwrap().as_ptr();
ListingResponse {
listing_response: unsafe { ffi::sfFtp_getDirectoryListing(self.ftp,
c_directory) }
}
}
pub fn change_directory(&self, directory: &str) -> Response {
let c_directory = CString::new(directory.as_bytes()).unwrap().as_ptr();
Response {
response: unsafe { ffi::sfFtp_changeDirectory(self.ftp,
c_directory) }
}
}
pub fn parent_directory(&self) -> Response {
Response {
response: unsafe { ffi::sfFtp_parentDirectory(self.ftp) }
}
}
pub fn create_directory(&self, name: &str) -> Response {
let c_name = CString::new(name.as_bytes()).unwrap().as_ptr();
Response {
response: unsafe { ffi::sfFtp_createDirectory(self.ftp,
c_name) }
}
}
pub fn delete_directory(&self, name: &str) -> Response {
let c_name = CString::new(name.as_bytes()).unwrap().as_ptr();
Response {
response: unsafe { ffi::sfFtp_deleteDirectory(self.ftp,
c_name) }
}
}
pub fn rename_file(&self, name: &str, new_name: &str) -> Response {
let c_name = CString::new(name.as_bytes()).unwrap().as_ptr();
let c_new_name = CString::new(new_name.as_bytes()).unwrap().as_ptr();
Response {
response: unsafe { ffi::sfFtp_renameFile(self.ftp,
c_name,
c_new_name) }
}
}
pub fn delete_file(&self, name: &str) -> Response {
let c_name = CString::new(name.as_bytes()).unwrap().as_ptr();
Response {
response: unsafe { ffi::sfFtp_deleteFile(self.ftp,
c_name) }
}
}
pub fn download(&self, distant_file: &str, dest_path: &str, mode: TransferMode) -> Response {
let c_distant_file = CString::new(distant_file.as_bytes()).unwrap().as_ptr();
let c_dest_path = CString::new(dest_path.as_bytes()).unwrap().as_ptr();
Response {
response: unsafe { ffi::sfFtp_download(self.ftp,
c_distant_file,
c_dest_path,
mode as ffi::TransferMode) }
}
}
pub fn upload(&self, local_file: &str, dest_path: &str, mode: TransferMode) -> Response {
let c_local_file = CString::new(local_file.as_bytes()).unwrap().as_ptr();
let c_dest_path = CString::new(dest_path.as_bytes()).unwrap().as_ptr();
Response {
response: unsafe { ffi::sfFtp_upload(self.ftp,
c_local_file,
c_dest_path,
mode as ffi::TransferMode) }
}
}
}
impl Drop for Ftp {
fn drop(&mut self) {
unsafe {
ffi::sfFtp_destroy(self.ftp)
}
}
}