#![no_std]
use core::fmt;
use core::result;
use core::str;
pub type Result<T> = result::Result<T, Error>;
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct Error {
    pub errno: i32,
}
impl Error {
    pub const fn new(errno: i32) -> Self {
        Self { errno }
    }
    pub fn last() -> Self {
        Self { errno: errno() }
    }
}
impl Default for Error {
    fn default() -> Self {
        Error::new(-1)
    }
}
impl From<i32> for Error {
    fn from(i32: i32) -> Self {
        Self::new(i32)
    }
}
impl From<Error> for Result<()> {
    fn from(err: Error) -> Self {
        if err.errno == 0 {
            Ok(())
        } else {
            Err(err)
        }
    }
}
const ERRMSG_MAX_SIZE: usize = 64;
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> {
        let mut msg = [0_u8; ERRMSG_MAX_SIZE];
        write!(f, "{}: {}", self.errno, errmsg(self.errno, &mut msg[..]))
    }
}
impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> result::Result<(), fmt::Error> {
        let mut msg = [0_u8; ERRMSG_MAX_SIZE];
        write!(f, "{}: {}", self.errno, errmsg(self.errno, &mut msg[..]))
    }
}
#[cfg(any(unix, all(target_os = "windows", target_env = "gnu")))]
fn format_message_utf8<'a>(input: &[u8], output: &'a mut [u8]) -> &'a str {
    let Ok(s) = str::from_utf8(input) else {
        return get_message(output, 0);
    };
    if input.len() <= output.len() {
        output[..input.len()].copy_from_slice(input);
        return str::from_utf8(&output[..input.len()]).unwrap();
    }
    return truncate_message(s, output);
}
#[cfg(any(unix, all(target_os = "windows", target_env = "gnu")))]
fn truncate_message<'a>(input: &str, output: &'a mut [u8]) -> &'a str {
    let mut pos = 0;
    for c in input.chars() {
        if !put_message(output, &mut pos, c) {
            break;
        }
    }
    get_message(output, pos)
}
fn put_message(output: &mut [u8], pos: &mut usize, c: char) -> bool {
    if *pos + c.len_utf8() <= output.len() {
        c.encode_utf8(&mut output[*pos..]);
        *pos += c.len_utf8();
        return true;
    }
    false
}
fn get_message(output: &[u8], len: usize) -> &str {
    if len > 0 {
        str::from_utf8(&output[..len]).unwrap()
    } else {
        "Unknown error"
    }
}
#[cfg(all(target_os = "windows", not(target_env = "gnu")))]
fn format_message_utf16<'a>(input: &[u16], output: &'a mut [u8]) -> &'a str {
    let mut pos = 0;
    char::decode_utf16(input.iter().copied()).any(|c| {
        let Ok(c) = c else {
            pos = 0;
            return true;
        };
        !put_message(output, &mut pos, c)
    });
    get_message(output, pos)
}
#[cfg(any(unix, all(target_os = "windows", target_env = "gnu")))]
mod unix;
#[cfg(any(unix, all(target_os = "windows", target_env = "gnu")))]
pub use unix::*;
#[cfg(all(target_os = "windows", not(target_env = "gnu")))]
mod windows;
#[cfg(all(target_os = "windows", not(target_env = "gnu")))]
pub use windows::*;
#[cfg(test)]
mod test {
    use super::*;
    extern crate std;
    use std::println;
    #[test]
    fn test_errno() {
        set_errno(100);
        assert_eq!(errno(), 100);
    }
    #[test]
    fn test_print() {
        for n in 0..=102 {
            let err = Error::new(n);
            println!("[{}]\n[{:?}]\n", err, err);
        }
        set_errno(4);
        println!("5: {}", errmsg(5, &mut [0_u8; 7]));
    }
}