all_term 0.1.0

Cross-platform terminal abstraction library
Documentation
use std::{ptr, slice};

use winapi::{
    um::{
        winbase::{
            STD_OUTPUT_HANDLE,
            STD_INPUT_HANDLE,
            FORMAT_MESSAGE_ALLOCATE_BUFFER,
            FORMAT_MESSAGE_FROM_SYSTEM,
            FORMAT_MESSAGE_IGNORE_INSERTS,
            FormatMessageA,
        },
        processenv::GetStdHandle,
        errhandlingapi::GetLastError,
        winnt::{
            HANDLE,
            MAKELANGID,
            LANG_NEUTRAL,
            SUBLANG_DEFAULT,
        },
        handleapi::INVALID_HANDLE_VALUE,
    },
    shared::ntdef::NULL,
};

pub fn get_last_error() -> Option<String> {
    let error = unsafe {
        GetLastError()
    };

    if error == 0 {
        return None;
    }

    let mut raw_buffer: *const u8 = ptr::null();
    let size = unsafe {
        FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) as u32, &mut raw_buffer as *mut _ as *mut _, 0, ptr::null_mut())
    };

    let buffer = unsafe {
        slice::from_raw_parts(raw_buffer, size as usize)
    };
    let message = String::from_utf8_lossy(buffer).into_owned();

    Some(message)
}

pub fn check_win32_error() -> Result<(), String> {
    match get_last_error() {
        Some(error) => Err(error),
        None => Ok(())
    }
}

pub fn get_stdout_handle() -> Result<HANDLE, String> {
    let handle = unsafe {
        GetStdHandle(STD_OUTPUT_HANDLE)
    };

    if handle == INVALID_HANDLE_VALUE {
        check_win32_error()?;
    }

    if handle == NULL {
        return Err("No stdout available".to_string());
    }

    Ok(handle)
}

pub fn get_stdin_handle() -> Result<HANDLE, String> {
    let handle = unsafe {
        GetStdHandle(STD_INPUT_HANDLE)
    };

    if handle == INVALID_HANDLE_VALUE {
        check_win32_error()?;
    }

    if handle == NULL {
        return Err("No stdin available".to_string());
    }

    Ok(handle)
}