diff --git a/src/chunks/chunks.odin b/src/chunks/chunks.odin index e3f61ef..a5412ae 100644 --- a/src/chunks/chunks.odin +++ b/src/chunks/chunks.odin @@ -1,6 +1,7 @@ package chunks import "base:runtime" +import "core:fmt" import "core:io" import "core:os" @@ -42,3 +43,27 @@ Error :: union #shared_nil { Read_Error, Write_Error, } + +// ----------------------------------------- + +@(require_results) +format_error :: proc(ferr: Error) -> string { + if ferr == nil do return "" + + switch e in ferr { + case nil: + return "" + case runtime.Allocator_Error: + return fmt.tprintf("allocator: {}", e) + case io.Error: + return fmt.tprintf("io: {}", e) + case os.Error: + return fmt.tprintf("os: {}", e) + case Read_Error: + return fmt.tprintf("chunks: {}", read_error_strings[e]) + case Write_Error: + return fmt.tprintf("chunks: {}", write_error_strings[e]) + } + + return "unknown error" +} diff --git a/src/chunks/read_assets.odin b/src/chunks/read_assets.odin index 7b8fae9..6ed1d12 100644 --- a/src/chunks/read_assets.odin +++ b/src/chunks/read_assets.odin @@ -30,7 +30,6 @@ read_file :: proc( // Check filesystem first, so chunks can be overriden if os.exists(path) { // Open file - fmt.println("searching:", path) file := os.open(path, {.Read}) or_return defer os.close(file) @@ -92,5 +91,6 @@ read_file :: proc( return bytes, nil } - return nil, .File_Not_Exist + fmt.eprintln("asset: ", path) + return nil, .Asset_Not_Exist } diff --git a/src/chunks/reader.odin b/src/chunks/reader.odin index fdc97fd..99e7811 100644 --- a/src/chunks/reader.odin +++ b/src/chunks/reader.odin @@ -14,13 +14,22 @@ Reader :: struct { Read_Error :: enum u8 { None = 0, File_Not_A_Chunk = 1, - File_Not_Exist = 2, + Asset_Not_Exist = 2, Unimplemented = 127, Okay = None, } // ----------------------------------------- +read_error_strings := #sparse[Read_Error]string { // enumerated array + .None = "", + .File_Not_A_Chunk = "file is not a chunk file", + .Asset_Not_Exist = "asset does not exist", + .Unimplemented = "feature is unimplemented", +} + +// ----------------------------------------- + reader_init :: proc( output: ^os.File, allocator := context.allocator, diff --git a/src/chunks/write_assets.odin b/src/chunks/write_assets.odin index dc5915a..bc1102c 100644 --- a/src/chunks/write_assets.odin +++ b/src/chunks/write_assets.odin @@ -26,8 +26,9 @@ write_assets :: proc( number_of_assets := len(entries) if size_per_chunk < w.asset_table.data_offset { - fmt.eprintln( - "error: chunk size too small to hold asset index:", + fmt.eprintf( + "chunk size: {}\nasset index size: {}\n", + size_per_chunk, w.asset_table.data_offset, ) return .Chunk_Size_Too_Small @@ -160,22 +161,13 @@ create_new_chunk :: proc( ) or_return defer delete(chunk_path, allocator) if os.exists(chunk_path) { - rm_err := os.remove(chunk_path) - if rm_err != nil { - fmt.eprintln("error: remove old chunk failed:", rm_err) - return {}, rm_err - } + os.remove(chunk_path) or_return } if w.chunk_file != nil do os.close(w.chunk_file) // close previous // Create new chunk - cf_err: os.Error - w.chunk_file, cf_err = os.create(chunk_path) - if cf_err != nil { - fmt.eprintln("error: create new chunk failed:", cf_err) - return {}, cf_err - } + w.chunk_file = os.create(chunk_path) or_return chunk_stream = os.to_stream(w.chunk_file) @@ -183,34 +175,29 @@ create_new_chunk :: proc( } @(private) -open_asset :: proc(w: ^Writer, path: string) -> (io.Stream, u64, Error) { +open_asset :: proc( + w: ^Writer, + path: string, +) -> ( + asset_stream: io.Stream, + asset_size: u64, + err: Error, +) { if w.asset_file != nil do os.close(w.asset_file) // close previous // Open asset - asset, open_err := os.open(path, {.Read}) - if open_err != nil { - fmt.eprintln("error: asset open failed:", open_err) - return {}, {}, open_err - } + asset := os.open(path, {.Read}) or_return // Asset size - asset_stream := os.to_stream(asset) - asset_size, size_err := io.size(asset_stream) - if size_err != nil { - fmt.eprintln("error: asset size failed:", size_err) - return {}, {}, size_err - } + asset_stream = os.to_stream(asset) + asset_size = cast(u64)io.size(asset_stream) or_return return asset_stream, cast(u64)asset_size, nil } @(private) write_chunk :: proc(dst: io.Stream, src: io.Stream, n: u64) -> Error { - w, err := io.copy_n(dst, src, cast(i64)n) - if err != nil { - fmt.eprintln("error: chunk write error:", err) - return err - } + w := io.copy_n(dst, src, cast(i64)n) or_return return nil } diff --git a/src/chunks/write_metadata.odin b/src/chunks/write_metadata.odin index 3346b86..5a2bd82 100644 --- a/src/chunks/write_metadata.odin +++ b/src/chunks/write_metadata.odin @@ -24,11 +24,7 @@ write_metadata :: proc( chunk_path := compute_chunk_path(output_path, 0, allocator) or_return defer delete(chunk_path, allocator) - chunk_file, err := os.open(chunk_path, {.Read, .Write}) - if err != nil { - fmt.eprintln("error: open chunk failed: ", err) - return err - } + chunk_file := os.open(chunk_path, {.Read, .Write}) or_return defer os.close(chunk_file) write_header(w, chunk_file, number_of_assets, size_per_chunk, compression) @@ -62,11 +58,7 @@ write_header :: proc( // Write header header_bytes := mem.ptr_to_bytes(&header) - n, err := os.write_at(chunk_file, header_bytes, 0) - if err != nil { - fmt.eprintln("error: chunk write error:", err) - return err - } + n := os.write_at(chunk_file, header_bytes, 0) or_return return nil } @@ -91,7 +83,7 @@ write_asset_index :: proc( // TODO: Move to cli validation so it happens sooner path_length := len(f.relpath) if path_length > 512 { - fmt.eprintln("error: path exeeds maximum of 512:", f.relpath) + fmt.eprintf("path: {} ({})\n", f.relpath, path_length) return .Path_Too_Large } @@ -107,15 +99,11 @@ write_asset_index :: proc( assert(len(index_bytes) % size_of(Asset_Index) == 0) // clean multiple // Write asset index - n, err := os.write_at( + n := os.write_at( chunk_file, index_bytes, cast(i64)w.asset_table.asset_index_offset, - ) - if err != nil { - fmt.eprintln("error: chunk write error:", err) - return err - } + ) or_return return nil } diff --git a/src/chunks/writer.odin b/src/chunks/writer.odin index d4a1e4d..b4858b3 100644 --- a/src/chunks/writer.odin +++ b/src/chunks/writer.odin @@ -24,6 +24,15 @@ Write_Error :: enum u8 { // ----------------------------------------- +write_error_strings := #sparse[Write_Error]string { // enumerated array + .None = "", + .Chunk_Size_Too_Small = "chunk size too small to hold asset index", + .Path_Too_Large = "path exeeds maximum of 512", + .Unimplemented = "feature is unimplemented", +} + +// ----------------------------------------- + writer_init :: proc( number_of_assets: u64, allocator := context.allocator, @@ -55,8 +64,8 @@ compute_chunk_path :: proc( chunk_index: int, allocator: runtime.Allocator, ) -> ( - string, - Error, + chunk_path: string, + err: Error, ) { @(static) buf: [20]u8 @@ -65,11 +74,7 @@ compute_chunk_path :: proc( chunk_name := strings.concatenate({CHUNK, chunk_index_str}, allocator) defer delete(chunk_name, allocator) - chunk_path, c_err := os.join_path({output_path, chunk_name}, allocator) - if c_err != nil { - fmt.eprintln("error: chunk join path failed:", c_err) - return {}, c_err - } + chunk_path = os.join_path({output_path, chunk_name}, allocator) or_return return chunk_path, nil // owning string } diff --git a/src/file/file.odin b/src/file/file.odin index 818726d..687ed71 100644 --- a/src/file/file.odin +++ b/src/file/file.odin @@ -17,6 +17,12 @@ File_Error :: enum u8 { Okay = None, } +file_error_strings := #sparse[File_Error]string { // enumerated array + .None = "", + .Not_A_Directory = "path is not a directory", + .Unimplemented = "feature is unimplemented", +} + // ----------------------------------------- get_working_dir :: proc(allocator := context.allocator) -> (string, Error) { @@ -28,3 +34,19 @@ get_working_dir :: proc(allocator := context.allocator) -> (string, Error) { return wd, nil } + +@(require_results) +format_error :: proc(ferr: Error) -> string { + if ferr == nil do return "" + + switch e in ferr { + case nil: + return "" + case os.Error: + return fmt.tprintf("os: {}", e) + case File_Error: + return fmt.tprintf("file: {}", file_error_strings[e]) + } + + return "unknown error" +} diff --git a/src/file/list_dir.odin b/src/file/list_dir.odin index dfbf2f9..d01685c 100644 --- a/src/file/list_dir.odin +++ b/src/file/list_dir.odin @@ -67,7 +67,7 @@ list_dir_recursive_by_path_impl :: proc( Error, ) { if !os.is_dir(path) { - fmt.eprintln("error: path is not a directory:", path) + fmt.eprintln("path:", path) return {}, .Not_A_Directory } @@ -96,18 +96,10 @@ list_dir_queue :: proc( path := pop(queue) defer delete(path, queue^.allocator) - f, open_err := os.open(path, {.Read}) - if open_err != nil { - fmt.eprintln("error: open failed:", open_err) - return open_err - } + f := os.open(path, {.Read}) or_return defer os.close(f) - entries, read_err := os.read_all_directory(f, allocator) - if read_err != nil { - fmt.eprintln("error: read directory failed:", read_err) - return read_err - } + entries := os.read_all_directory(f, allocator) or_return defer os.file_info_slice_delete(entries, allocator) // Reserve space for new entries, minor waste as directories are also counted. diff --git a/src/main.odin b/src/main.odin index 28daff5..46ffa26 100644 --- a/src/main.odin +++ b/src/main.odin @@ -1,5 +1,6 @@ package main +import "core:fmt" import "core:os" import "src:chunks" @@ -28,8 +29,11 @@ main :: proc() { // fmt.println("compression:", opts.compression) // fmt.println("size:", opts.size) - entries, e_err := file.list_dir_recursive(opts.input, working_dir) - if e_err != nil do os.exit(LIST_DIR_ERR) + entries, ld_err := file.list_dir_recursive(opts.input, working_dir) + if ld_err != nil { + fmt.eprintln("error:", file.format_error(ld_err)) + os.exit(LIST_DIR_ERR) + } defer file.delete_entries(&entries) w := chunks.writer_init(cast(u64)len(entries)) @@ -42,7 +46,10 @@ main :: proc() { opts.size, opts.compression, ) - if wa_err != nil do os.exit(WRITE_ASSETS_ERR) + if wa_err != nil { + fmt.eprintln("error:", chunks.format_error(wa_err)) + os.exit(WRITE_ASSETS_ERR) + } wm_err := chunks.write_metadata( &w, @@ -51,7 +58,10 @@ main :: proc() { opts.size, opts.compression, ) - if wm_err != nil do os.exit(WRITE_METADATA_ERR) + if wm_err != nil { + fmt.eprintln("error:", chunks.format_error(wm_err)) + os.exit(WRITE_METADATA_ERR) + } } // TODO: .chunkignore