| author | |
| committer | |
| log | a70e0061579a4365da0092554470ffeadb4594a4 |
| tree | 654a312e9bea838429c0834e0db97cd97640b78f |
| parent | 5a7dc4b0fae62c8b7ec798043c93e4d90704a638 |
4 files changed, 55 insertions(+), 2 deletions(-)
lib/std/Io/File.zig+4| ... | @@ -784,6 +784,10 @@ pub fn hardLink( | ... | @@ -784,6 +784,10 @@ pub fn hardLink( |
| 784 | return io.vtable.fileHardLink(io.userdata, file, new_dir, new_sub_path, options); | 784 | return io.vtable.fileHardLink(io.userdata, file, new_dir, new_sub_path, options); |
| 785 | } | 785 | } |
| 786 | 786 | ||
| 787 | pub fn createMemoryMap(file: File, io: Io, options: MemoryMap.CreateOptions) MemoryMap.CreateError!MemoryMap { | ||
| 788 | return .create(io, file, options); | ||
| 789 | } | ||
| 790 | |||
| 787 | test { | 791 | test { |
| 788 | _ = Reader; | 792 | _ = Reader; |
| 789 | _ = Writer; | 793 | _ = Writer; |
lib/std/Io/File/MemoryMap.zig+9| ... | @@ -36,7 +36,14 @@ pub const CreateError = error{ | ... | @@ -36,7 +36,14 @@ pub const CreateError = error{ |
| 36 | } || Allocator.Error || File.ReadPositionalError; | 36 | } || Allocator.Error || File.ReadPositionalError; |
| 37 | 37 | ||
| 38 | pub const CreateOptions = struct { | 38 | pub const CreateOptions = struct { |
| 39 | /// When this has read set to false, bytes that are not modified before a | ||
| 40 | /// sync may have the original file contents, or may be set to zero. | ||
| 39 | protection: std.process.MemoryProtection = .{ .read = true, .write = true }, | 41 | protection: std.process.MemoryProtection = .{ .read = true, .write = true }, |
| 42 | /// If set to `true`, allows bytes observed before calling `read` to be | ||
| 43 | /// undefined, and bytes unwritten before calling `write` to write | ||
| 44 | /// undefined memory to the file. | ||
| 45 | undefined_contents: bool = false, | ||
| 46 | /// Prefault the pages. | ||
| 40 | populate: bool = true, | 47 | populate: bool = true, |
| 41 | /// Byte index of file to start from. | 48 | /// Byte index of file to start from. |
| 42 | offset: u64 = 0, | 49 | offset: u64 = 0, |
| ... | @@ -46,6 +53,8 @@ pub const CreateOptions = struct { | ... | @@ -46,6 +53,8 @@ pub const CreateOptions = struct { |
| 46 | len: ?usize = null, | 53 | len: ?usize = null, |
| 47 | }; | 54 | }; |
| 48 | 55 | ||
| 56 | /// To release the resources associated with the returned `MemoryMap`, call | ||
| 57 | /// `destroy`. | ||
| 49 | pub fn create(io: Io, file: File, options: CreateOptions) CreateError!MemoryMap { | 58 | pub fn create(io: Io, file: File, options: CreateOptions) CreateError!MemoryMap { |
| 50 | return io.vtable.fileMemoryMapCreate(io.userdata, file, options); | 59 | return io.vtable.fileMemoryMapCreate(io.userdata, file, options); |
| 51 | } | 60 | } |
lib/std/Io/Threaded.zig+1-2| ... | @@ -16150,8 +16150,7 @@ fn fileMemoryMapCreate( | ... | @@ -16150,8 +16150,7 @@ fn fileMemoryMapCreate( |
| 16150 | }; | 16150 | }; |
| 16151 | errdefer gpa.rawFree(memory, alignment, @returnAddress()); | 16151 | errdefer gpa.rawFree(memory, alignment, @returnAddress()); |
| 16152 | 16152 | ||
| 16153 | // If the mapping does not have read permissions, no need to populate the contents. | 16153 | if (!options.undefined_contents) try mmSyncRead(file, memory, offset); |
| 16154 | if (options.protection.read) try mmSyncRead(file, memory, offset); | ||
| 16155 | 16154 | ||
| 16156 | return .{ | 16155 | return .{ |
| 16157 | .file = file, | 16156 | .file = file, |
lib/std/Io/test.zig+41| ... | @@ -592,3 +592,44 @@ test "randomSecure" { | ... | @@ -592,3 +592,44 @@ test "randomSecure" { |
| 592 | // that two sets of 50 bytes were equal. | 592 | // that two sets of 50 bytes were equal. |
| 593 | try expect(!mem.eql(u8, &buf_a, &buf_b)); | 593 | try expect(!mem.eql(u8, &buf_a, &buf_b)); |
| 594 | } | 594 | } |
| 595 | |||
| 596 | test "memory mapping" { | ||
| 597 | const io = testing.io; | ||
| 598 | |||
| 599 | var tmp = tmpDir(.{}); | ||
| 600 | defer tmp.cleanup(); | ||
| 601 | |||
| 602 | try tmp.dir.writeFile(io, .{ | ||
| 603 | .sub_path = "blah.txt", | ||
| 604 | .data = "this is my data123", | ||
| 605 | }); | ||
| 606 | |||
| 607 | { | ||
| 608 | var file = try tmp.dir.openFile(io, "blah.txt", .{}); | ||
| 609 | defer file.close(io); | ||
| 610 | |||
| 611 | var mm = try file.createMemoryMap(io, .{}); | ||
| 612 | defer mm.destroy(io); | ||
| 613 | |||
| 614 | try expectEqualStrings("this is my data123", mm.memory); | ||
| 615 | mm.memory[5] = '9'; | ||
| 616 | mm.memory[8] = '9'; | ||
| 617 | |||
| 618 | try mm.write(io); | ||
| 619 | } | ||
| 620 | |||
| 621 | var buffer: [100]u8 = undefined; | ||
| 622 | const updated_contents = try tmp.dir.readFile(io, "blah.txt", &buffer); | ||
| 623 | try expectEqualStrings("this9is9my data123", updated_contents); | ||
| 624 | |||
| 625 | var file = try tmp.dir.openFile(io, "blah.txt", .{}); | ||
| 626 | defer file.close(io); | ||
| 627 | |||
| 628 | var mm = try file.createMemoryMap(io, .{ | ||
| 629 | .protection = .{ .read = true }, | ||
| 630 | .offset = 2, | ||
| 631 | }); | ||
| 632 | defer mm.destroy(io); | ||
| 633 | |||
| 634 | try expectEqualStrings("is9is9my data123", mm.memory); | ||
| 635 | } |