From 63780110f4cf3c2b3c9cdd986332d749f49ce278 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 14 Nov 2025 15:57:41 +0000 Subject: [PATCH 1/4] Add `File_Stream` to replace `io.Stream`+`Fstat_Callback` within `os2` --- core/os/os2/file.odin | 61 ++++++++++++++++++++++++++------ core/os/os2/file_linux.odin | 65 +++++++++++++---------------------- core/os/os2/file_posix.odin | 13 ++++--- core/os/os2/file_stream.odin | 64 +++++++++++++++++++++++++++++++++- core/os/os2/file_windows.odin | 32 +++++++---------- core/os/os2/stat.odin | 7 ++-- 6 files changed, 161 insertions(+), 81 deletions(-) diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin index 85ebfcecedf..9e7788c318b 100644 --- a/core/os/os2/file.odin +++ b/core/os/os2/file.odin @@ -22,8 +22,7 @@ import "base:runtime" */ File :: struct { impl: rawptr, - stream: io.Stream, - fstat: Fstat_Callback, + stream: File_Stream, } /* @@ -218,7 +217,11 @@ name :: proc(f: ^File) -> string { */ close :: proc(f: ^File) -> Error { if f != nil { - return io.close(f.stream) + if f.stream.procedure == nil { + return .Unsupported + } + _, err := f.stream.procedure(f, .Close, nil, 0, nil, runtime.nil_allocator()) + return err } return nil } @@ -235,7 +238,10 @@ close :: proc(f: ^File) -> Error { */ seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { if f != nil { - return io.seek(f.stream, offset, whence) + if f.stream.procedure == nil { + return 0, .Unsupported + } + return f.stream.procedure(f, .Seek, nil, offset, whence, runtime.nil_allocator()) } return 0, .Invalid_File } @@ -247,7 +253,12 @@ seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Err */ read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { if f != nil { - return io.read(f.stream, p) + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Read, p, 0, nil, runtime.nil_allocator()) + return int(n64), err } return 0, .Invalid_File } @@ -260,7 +271,12 @@ read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { */ read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { if f != nil { - return io.read_at(f.stream, p, offset) + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Read_At, p, offset, nil, runtime.nil_allocator()) + return int(n64), err } return 0, .Invalid_File } @@ -272,7 +288,12 @@ read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { */ write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { if f != nil { - return io.write(f.stream, p) + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Write, p, 0, nil, runtime.nil_allocator()) + return int(n64), err } return 0, .Invalid_File } @@ -284,7 +305,12 @@ write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { */ write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { if f != nil { - return io.write_at(f.stream, p, offset) + if f.stream.procedure == nil { + return 0, .Unsupported + } + n64: i64 + n64, err = f.stream.procedure(f, .Write_At, p, offset, nil, runtime.nil_allocator()) + return int(n64), err } return 0, .Invalid_File } @@ -294,7 +320,18 @@ write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { */ file_size :: proc(f: ^File) -> (n: i64, err: Error) { if f != nil { - return io.size(f.stream) + if f.stream.procedure == nil { + return 0, .Unsupported + } + n, err = f.stream.procedure(f, .Size, nil, 0, nil, runtime.nil_allocator()) + if err == .Unsupported { + n = 0 + curr := seek(f, 0, .Current) or_return + end := seek(f, 0, .End) or_return + seek(f, curr, .Start) or_return + n = end + } + return } return 0, .Invalid_File } @@ -304,7 +341,11 @@ file_size :: proc(f: ^File) -> (n: i64, err: Error) { */ flush :: proc(f: ^File) -> Error { if f != nil { - return io.flush(f.stream) + if f.stream.procedure == nil { + return .Unsupported + } + _, err := f.stream.procedure(f, .Flush, nil, 0, nil, runtime.nil_allocator()) + return err } return nil } diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin index 6d66ffd7504..fb25ca41112 100644 --- a/core/os/os2/file_linux.odin +++ b/core/os/os2/file_linux.odin @@ -29,19 +29,16 @@ _stdin := File{ stream = { procedure = _file_stream_proc, }, - fstat = _fstat, } _stdout := File{ stream = { procedure = _file_stream_proc, }, - fstat = _fstat, } _stderr := File{ stream = { procedure = _file_stream_proc, }, - fstat = _fstat, } @init @@ -55,7 +52,6 @@ _standard_stream_init :: proc "contextless" () { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -109,7 +105,6 @@ _new_file :: proc(fd: uintptr, _: string, allocator: runtime.Allocator) -> (f: ^ data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file, nil } @@ -476,88 +471,76 @@ _read_entire_pseudo_file_cstring :: proc(name: cstring, allocator: runtime.Alloc } @(private="package") -_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) - ferr: Error switch mode { case .Read: - n, ferr = _read(f, p) - err = error_to_io_error(ferr) + n, err = _read(f, p) return case .Read_At: - n, ferr = _read_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _read_at(f, p, offset) return case .Write: - n, ferr = _write(f, p) - err = error_to_io_error(ferr) + n, err = _write(f, p) return case .Write_At: - n, ferr = _write_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _write_at(f, p, offset) return case .Seek: - n, ferr = _seek(f, offset, whence) - err = error_to_io_error(ferr) + n, err = _seek(f, offset, whence) return case .Size: - n, ferr = _file_size(f) - err = error_to_io_error(ferr) + n, err = _file_size(f) return case .Flush: - ferr = _flush(f) - err = error_to_io_error(ferr) + err = _flush(f) return case .Close, .Destroy: - ferr = _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return } return 0, .Unsupported } @(private="package") -_file_stream_buffered_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_buffered_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) - ferr: Error switch mode { case .Read: - n, ferr = _read(f, p) - err = error_to_io_error(ferr) + n, err = _read(f, p) return case .Read_At: - n, ferr = _read_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _read_at(f, p, offset) return case .Write: - n, ferr = _write(f, p) - err = error_to_io_error(ferr) + n, err = _write(f, p) return case .Write_At: - n, ferr = _write_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _write_at(f, p, offset) return case .Seek: - n, ferr = _seek(f, offset, whence) - err = error_to_io_error(ferr) + n, err = _seek(f, offset, whence) return case .Size: - n, ferr = _file_size(f) - err = error_to_io_error(ferr) + n, err = _file_size(f) return case .Flush: - ferr = _flush(f) - err = error_to_io_error(ferr) + err = _flush(f) return case .Close, .Destroy: - ferr = _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return } return 0, .Unsupported } diff --git a/core/os/os2/file_posix.odin b/core/os/os2/file_posix.odin index f445cb5f46f..874ec7c7dc4 100644 --- a/core/os/os2/file_posix.odin +++ b/core/os/os2/file_posix.odin @@ -36,7 +36,6 @@ init_std_files :: proc "contextless" () { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -110,7 +109,6 @@ __new_file :: proc(handle: posix.FD, allocator: runtime.Allocator) -> ^File { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -371,7 +369,7 @@ _exists :: proc(path: string) -> bool { return posix.access(cpath) == .OK } -_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) fd := f.fd @@ -489,18 +487,19 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, return case .Flush: - ferr := _sync(&f.file) - err = error_to_io_error(ferr) + err = _sync(&f.file) return case .Close, .Destroy: - ferr := _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return case: return 0, .Unsupported } diff --git a/core/os/os2/file_stream.odin b/core/os/os2/file_stream.odin index e1c29a79263..9c03d49094d 100644 --- a/core/os/os2/file_stream.odin +++ b/core/os/os2/file_stream.odin @@ -1,12 +1,47 @@ package os2 +import "base:runtime" import "core:io" +// A subset of the io.Stream_Mode with added File specific modes +File_Stream_Mode :: enum { + Close, + Flush, + Read, + Read_At, + Write, + Write_At, + Seek, + Size, + Destroy, + Query, // query what modes are available + + Fstat, +} + +File_Stream_Proc :: #type proc( + stream_data: rawptr, + mode: File_Stream_Mode, + p: []byte, + offset: i64, + whence: io.Seek_From, + allocator: runtime.Allocator, +) -> (n: i64, err: Error) + +File_Stream :: struct { + procedure: File_Stream_Proc, + data: rawptr, +} + + // Converts a file `f` into an `io.Stream` to_stream :: proc(f: ^File) -> (s: io.Stream) { if f != nil { assert(f.stream.procedure != nil) - s = f.stream + s = { + file_io_stream_proc, + f, + } } return } @@ -24,3 +59,30 @@ to_writer :: to_stream even if it has no logical difference. */ to_reader :: to_stream + + +@(private="package") +file_io_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { + f := (^File)(stream_data) + + file_stream_mode := transmute(File_Stream_Mode)mode + + ferr: Error + n, ferr = f.stream.procedure(f, file_stream_mode, p, offset, whence, runtime.nil_allocator()) + err = error_to_io_error(ferr) + return +} + + + +@(private="package") +file_stream_fstat_utility :: proc(f: ^File_Impl, p: []byte, allocator: runtime.Allocator) -> (err: Error) { + fi: File_Info + if len(p) >= size_of(fi) { + fi, err = _fstat(&f.file, allocator) + runtime.mem_copy_non_overlapping(raw_data(p), &fi, size_of(fi)) + } else { + err = .Short_Buffer + } + return +} \ No newline at end of file diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 03fbc596e62..0d2f2864243 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -65,7 +65,6 @@ init_std_files :: proc "contextless" () { data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file } @@ -185,7 +184,6 @@ _new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) - data = impl, procedure = _file_stream_proc, } - impl.file.fstat = _fstat return &impl.file, nil } @@ -827,44 +825,38 @@ _exists :: proc(path: string) -> bool { } @(private="package") -_file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { +_file_stream_proc :: proc(stream_data: rawptr, mode: File_Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From, allocator: runtime.Allocator) -> (n: i64, err: Error) { f := (^File_Impl)(stream_data) - ferr: Error switch mode { case .Read: - n, ferr = _read(f, p) - err = error_to_io_error(ferr) + n, err = _read(f, p) return case .Read_At: - n, ferr = _read_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _read_at(f, p, offset) return case .Write: - n, ferr = _write(f, p) - err = error_to_io_error(ferr) + n, err = _write(f, p) return case .Write_At: - n, ferr = _write_at(f, p, offset) - err = error_to_io_error(ferr) + n, err = _write_at(f, p, offset) return case .Seek: - n, ferr = _seek(f, offset, whence) - err = error_to_io_error(ferr) + n, err = _seek(f, offset, whence) return case .Size: - n, ferr = _file_size(f) - err = error_to_io_error(ferr) + n, err = _file_size(f) return case .Flush: - ferr = _flush(f) - err = error_to_io_error(ferr) + err = _flush(f) return case .Close, .Destroy: - ferr = _close(f) - err = error_to_io_error(ferr) + err = _close(f) return case .Query: return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query}) + case .Fstat: + err = file_stream_fstat_utility(f, p, allocator) + return } return 0, .Unsupported } diff --git a/core/os/os2/stat.odin b/core/os/os2/stat.odin index f87afc4c920..58df457549f 100644 --- a/core/os/os2/stat.odin +++ b/core/os/os2/stat.odin @@ -46,8 +46,11 @@ file_info_delete :: proc(fi: File_Info, allocator: runtime.Allocator) { fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) { if f == nil { return {}, nil - } else if f.fstat != nil { - return f->fstat(allocator) + } else if f.stream.procedure != nil { + fi: File_Info + data := ([^]byte)(&fi)[:size_of(fi)] + _, err := f.stream.procedure(f, .Fstat, data, 0, nil, allocator) + return fi, err } return {}, .Invalid_Callback } From 8558ab59edbe1e610c389f9de1b7d697f2060d16 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 14 Nov 2025 16:10:11 +0000 Subject: [PATCH 2/4] Added some comments --- core/os/os2/file_stream.odin | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/os/os2/file_stream.odin b/core/os/os2/file_stream.odin index 9c03d49094d..7ab56b8af31 100644 --- a/core/os/os2/file_stream.odin +++ b/core/os/os2/file_stream.odin @@ -16,9 +16,10 @@ File_Stream_Mode :: enum { Destroy, Query, // query what modes are available - Fstat, + Fstat, // File specific (not available on io.Stream) } +// Superset interface of io.Stream_Proc with the added `runtime.Allocator` parameter needed for the Fstat mode File_Stream_Proc :: #type proc( stream_data: rawptr, mode: File_Stream_Mode, @@ -73,8 +74,6 @@ file_io_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte return } - - @(private="package") file_stream_fstat_utility :: proc(f: ^File_Impl, p: []byte, allocator: runtime.Allocator) -> (err: Error) { fi: File_Info From d380b0877dab2dd727d3a572417d5624e7cad826 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 17 Nov 2025 10:03:05 +0000 Subject: [PATCH 3/4] Add `intrinsics.type_is_superset_of` --- base/intrinsics/intrinsics.odin | 3 +- src/check_builtin.cpp | 124 ++++++++++++++++++++++++++++++++ src/checker_builtin_procs.hpp | 2 + 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index d34519f6343..41a1ae1ee3b 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -215,7 +215,8 @@ type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V -- type_is_specialized_polymorphic_record :: proc($T: typeid) -> bool --- type_is_unspecialized_polymorphic_record :: proc($T: typeid) -> bool --- -type_is_subtype_of :: proc($T, $U: typeid) -> bool --- +type_is_subtype_of :: proc($T, $U: typeid) -> bool --- +type_is_superset_of :: proc($Super, $Sub: typeid) -> bool --- type_field_index_of :: proc($T: typeid, $name: string) -> uintptr --- diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index b2d28afc0df..1b3e6912c9f 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -2485,6 +2485,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_min: case BuiltinProc_max: case BuiltinProc_type_is_subtype_of: + case BuiltinProc_type_is_superset_of: case BuiltinProc_objc_send: case BuiltinProc_objc_find_selector: case BuiltinProc_objc_find_class: @@ -7397,6 +7398,129 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As operand->type = t_untyped_bool; } break; + case BuiltinProc_type_is_superset_of: + { + Operand op_super = {}; + Operand op_sub = {}; + + check_expr_or_type(c, &op_super, ce->args[0]); + if (op_super.mode != Addressing_Type) { + gbString e = expr_to_string(op_super.expr); + error(op_super.expr, "'%.*s' expects a type, got %s", LIT(builtin_name), e); + gb_string_free(e); + return false; + } + check_expr_or_type(c, &op_sub, ce->args[1]); + if (op_sub.mode != Addressing_Type) { + gbString e = expr_to_string(op_sub.expr); + error(op_sub.expr, "'%.*s' expects a type, got %s", LIT(builtin_name), e); + gb_string_free(e); + return false; + } + + operand->mode = Addressing_Constant; + operand->type = t_untyped_bool; + + Type *super = op_super.type; + Type *sub = op_sub.type; + if (are_types_identical(super, sub)) { + operand->value = exact_value_bool(true); + return true; + } + + super = base_type(super); + sub = base_type(sub); + if (are_types_identical(super, sub)) { + operand->value = exact_value_bool(true); + return true; + } + + if (super->kind != sub->kind) { + gbString a = type_to_string(op_super.type); + gbString b = type_to_string(op_sub.type); + error(op_super.expr, "'%.*s' expects types of the same kind, got %s vs %s", LIT(builtin_name), a, b); + gb_string_free(b); + gb_string_free(a); + return false; + } + + if (super->kind == Type_Enum) { + if (sub->Enum.fields.count > super->Enum.fields.count) { + operand->value = exact_value_bool(false); + return true; + } + + + Type *base_super = base_enum_type(super); + Type *base_sub = base_enum_type(sub); + if (base_super == base_sub && base_super == nullptr) { + // okay + } else if (!are_types_identical(base_type(base_super), base_type(base_sub))) { + operand->value = exact_value_bool(false); + return true; + } + + for (Entity *f_sub : sub->Enum.fields) { + bool found = false; + + if (f_sub->kind != Entity_Constant) { + continue; + } + + for (Entity *f_super : super->Enum.fields) { + if (f_super->kind != Entity_Constant) { + continue; + } + + if (f_sub->token.string == f_super->token.string) { + if (compare_exact_values(Token_CmpEq, f_sub->Constant.value, f_super->Constant.value)) { + found = true; + break; + } + } + } + + if (!found) { + operand->value = exact_value_bool(false); + return true; + } + } + + operand->value = exact_value_bool(true); + return true; + + } else if (super->kind == Type_Union) { + if (sub->Union.variants.count > super->Union.variants.count) { + operand->value = exact_value_bool(false); + return true; + } + if (sub->Union.kind != super->Union.kind) { + operand->value = exact_value_bool(false); + return true; + } + + for_array(i, sub->Union.variants) { + Type *t_sub = sub->Union.variants[i]; + Type *t_super = super->Union.variants[i]; + if (!are_types_identical(t_sub, t_super)) { + operand->value = exact_value_bool(false); + return true; + } + } + + operand->value = exact_value_bool(true); + return true; + + } + gbString a = type_to_string(op_super.type); + gbString b = type_to_string(op_sub.type); + error(op_super.expr, "'%.*s' expects types of the same kind and either an enum or union, got %s vs %s", LIT(builtin_name), a, b); + gb_string_free(b); + gb_string_free(a); + return false; + } + + case BuiltinProc_type_field_index_of: { Operand op = {}; diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 663274cdc65..5b446cc1ca0 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -336,6 +336,7 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_polymorphic_record_parameter_value, BuiltinProc_type_is_subtype_of, + BuiltinProc_type_is_superset_of, BuiltinProc_type_field_index_of, @@ -708,6 +709,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_polymorphic_record_parameter_value"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_subtype_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_superset_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics }, {STR_LIT("type_field_index_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, From e53bc165ae29d83e55645d1b7af356063ff0f2c9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 17 Nov 2025 10:03:25 +0000 Subject: [PATCH 4/4] Add `#assert(intrinsics.type_is_superset_of(File_Stream_Mode, io.Stream_Mode))` --- core/os/os2/file_stream.odin | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/os/os2/file_stream.odin b/core/os/os2/file_stream.odin index 7ab56b8af31..af6e50921ce 100644 --- a/core/os/os2/file_stream.odin +++ b/core/os/os2/file_stream.odin @@ -1,5 +1,6 @@ package os2 +import "base:intrinsics" import "base:runtime" import "core:io" @@ -14,10 +15,11 @@ File_Stream_Mode :: enum { Seek, Size, Destroy, - Query, // query what modes are available + Query, // query what modes are available on `io.Stream` Fstat, // File specific (not available on io.Stream) } +#assert(intrinsics.type_is_superset_of(File_Stream_Mode, io.Stream_Mode)) // Superset interface of io.Stream_Proc with the added `runtime.Allocator` parameter needed for the Fstat mode File_Stream_Proc :: #type proc(