Browse Source

Try to map to `General_Error` where possible

gingerBill 1 year ago
parent
commit
def2e2e271

+ 1 - 0
core/os/dir_unix.odin

@@ -3,6 +3,7 @@ package os
 
 import "core:strings"
 
+@(require_results)
 read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
 	dirp := _fdopendir(fd) or_return
 	defer _closedir(dirp)

+ 1 - 0
core/os/dir_windows.odin

@@ -4,6 +4,7 @@ import win32 "core:sys/windows"
 import "core:strings"
 import "base:runtime"
 
+@(require_results)
 read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
 	find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) {
 		// Ignore "." and ".."

+ 3 - 0
core/os/env_windows.odin

@@ -7,6 +7,7 @@ import "base:runtime"
 // If the variable is found in the environment the value (which can be empty) is returned and the boolean is true
 // Otherwise the returned value will be empty and the boolean will be false
 // NOTE: the value will be allocated with the supplied allocator
+@(require_results)
 lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
 	if key == "" {
 		return
@@ -33,6 +34,7 @@ lookup_env :: proc(key: string, allocator := context.allocator) -> (value: strin
 // It returns the value, which will be empty if the variable is not present
 // To distinguish between an empty value and an unset value, use lookup_env
 // NOTE: the value will be allocated with the supplied allocator
+@(require_results)
 get_env :: proc(key: string, allocator := context.allocator) -> (value: string) {
 	value, _ = lookup_env(key, allocator)
 	return
@@ -60,6 +62,7 @@ unset_env :: proc(key: string) -> Errno {
 
 // environ returns a copy of strings representing the environment, in the form "key=value"
 // NOTE: the slice of strings and the strings with be allocated using the supplied allocator
+@(require_results)
 environ :: proc(allocator := context.allocator) -> []string {
 	envs := ([^]win32.WCHAR)(win32.GetEnvironmentStringsW())
 	if envs == nil {

+ 2 - 3
core/os/file_windows.odin

@@ -11,7 +11,7 @@ is_path_separator :: proc(c: byte) -> bool {
 
 open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errno) {
 	if len(path) == 0 {
-		return INVALID_HANDLE, ERROR_FILE_NOT_FOUND
+		return INVALID_HANDLE, General_Error.Not_Exist
 	}
 
 	access: u32
@@ -55,8 +55,7 @@ open :: proc(path: string, mode: int = O_RDONLY, perm: int = 0) -> (Handle, Errn
 		return handle, nil
 	}
 
-	err := get_last_error()
-	return INVALID_HANDLE, err
+	return INVALID_HANDLE, get_last_error()
 }
 
 close :: proc(fd: Handle) -> Errno {

+ 35 - 1
core/os/os.odin

@@ -19,17 +19,51 @@ Platform_Error :: _Platform_Error
 #assert(size_of(Platform_Error) <= 4)
 #assert(intrinsics.type_has_nil(Platform_Error))
 
+General_Error :: enum u32 {
+	None,
+
+	Permission_Denied,
+	Exist,
+	Not_Exist,
+	Closed,
+
+	Timeout,
+
+	Broken_Pipe,
+
+	// Indicates that an attempt to retrieve a file's size was made, but the
+	// file doesn't have a size.
+	No_Size,
+
+	Invalid_File,
+	Invalid_Dir,
+	Invalid_Path,
+	Invalid_Callback,
+
+	Pattern_Has_Separator,
+
+	Unsupported,
+}
+
+
 Errno :: Error // alias for legacy use
 
 Error :: union #shared_nil {
+	General_Error,
 	io.Error,
 	runtime.Allocator_Error,
 	Platform_Error,
 }
-#assert(size_of(Error) <= 8)
+#assert(size_of(Error) == 8)
 
 ERROR_NONE :: Error{}
 
+@(require_results)
+is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) {
+	v := ferr.(Platform_Error) or_else {}
+	return i32(v), i32(v) != 0
+}
+
 write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
 	return write(fd, transmute([]byte)str)
 }

+ 2 - 1
core/os/os2/errors.odin

@@ -42,13 +42,14 @@ Error :: union #shared_nil {
 ERROR_NONE :: Error{}
 
 
-
+@(require_results)
 is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) {
 	v := ferr.(Platform_Error) or_else {}
 	return i32(v), i32(v) != 0
 }
 
 
+@(require_results)
 error_string :: proc(ferr: Error) -> string {
 	if ferr == nil {
 		return ""

+ 12 - 1
core/os/os_linux.odin

@@ -521,7 +521,18 @@ _get_errno :: proc(res: int) -> Errno {
 
 // get errno from libc
 get_last_error :: proc "contextless" () -> Error {
-	return Platform_Error(__errno_location()^)
+	err := Platform_Error(__errno_location()^)
+	#partial switch err {
+	case .NONE:
+		return nil
+	case .EPERM:
+		return .Permission_Denied
+	case .EEXIST:
+		return .Exist
+	case .ENOENT:
+		return .Not_Exist
+	}
+	return err
 }
 
 personality :: proc(persona: u64) -> (Errno) {

+ 47 - 1
core/os/os_windows.odin

@@ -64,7 +64,53 @@ ERROR_NEGATIVE_OFFSET     :: _Platform_Error(1<<29 + 2)
 args := _alloc_command_line_arguments()
 
 get_last_error :: proc "contextless" () -> Error {
-	return Platform_Error(win32.GetLastError())
+	err := win32.GetLastError()
+	if err == 0 {
+		return nil
+	}
+	switch err {
+	case win32.ERROR_ACCESS_DENIED, win32.ERROR_SHARING_VIOLATION:
+		return .Permission_Denied
+
+	case win32.ERROR_FILE_EXISTS, win32.ERROR_ALREADY_EXISTS:
+		return .Exist
+
+	case win32.ERROR_FILE_NOT_FOUND, win32.ERROR_PATH_NOT_FOUND:
+		return .Not_Exist
+
+	case win32.ERROR_NO_DATA:
+		return .Closed
+
+	case win32.ERROR_TIMEOUT, win32.WAIT_TIMEOUT:
+		return .Timeout
+
+	case win32.ERROR_NOT_SUPPORTED:
+		return .Unsupported
+
+	case win32.ERROR_HANDLE_EOF:
+		return .EOF
+
+	case win32.ERROR_INVALID_HANDLE:
+		return .Invalid_File
+
+	case
+		win32.ERROR_BAD_ARGUMENTS,
+		win32.ERROR_INVALID_PARAMETER,
+		win32.ERROR_NOT_ENOUGH_MEMORY,
+		win32.ERROR_NO_MORE_FILES,
+		win32.ERROR_LOCK_VIOLATION,
+		win32.ERROR_BROKEN_PIPE,
+		win32.ERROR_CALL_NOT_IMPLEMENTED,
+		win32.ERROR_INSUFFICIENT_BUFFER,
+		win32.ERROR_INVALID_NAME,
+		win32.ERROR_LOCK_FAILED,
+		win32.ERROR_ENVVAR_NOT_FOUND,
+		win32.ERROR_OPERATION_ABORTED,
+		win32.ERROR_IO_PENDING,
+		win32.ERROR_NO_UNICODE_TRANSLATION:
+		// fallthrough
+	}
+	return Platform_Error(err)
 }