4 ms·
articles about rust don't have to include a link to "what is Rust" like this one does.
by KnightHawk3 7y ago
articles about rust don't have to include a link to "what is Rust" like this one does.
- FpUser 7y agoFor one thing I do not think you can implement allocator in Rust. This alone would disqualify it as a "low level"/"systems" language in my opinion.
- shepmaster 7y agoYou can implement an allocator in Rust; it's unclear why you think this is not possible. One example: - https://github.com/fitzgen/bumpalo https://github.com/fitzgen/bumpalo
- FpUser 7y agoI said "I do not think". I do not really know Rust. Obviously I was wrong.
- deleted 7y ago[deleted]
- dunkelheit 7y agoWorth noting that support for custom allocators in standard collections is not finalized yet: https://github.com/rust-lang/rust/issues/32838 https://github.com/rust-lang/rust/issues/32838 The (awesome) bumpalo crate that you link to gets around this by providing ported implementations of Vec and String, but if you need e.g. a custom-allocated HashMap, you need to implement it yourself.
- shepmaster 7y agoThanks for the additional points! What you state is true, but somewhat orthogonal to the point that the grandparent post was making (and I sought to refute). Creating an allocator is inherently possible. Using that allocator with the rest of the ecosystem is currently not stable, as you point out. As a sometimes Rust embedded developer, I look forward to both parameterized allocators and fallible allocation.
- yellowapple 7y agoAlso worth noting that this is one thing Zig seems to have gotten quite right already: every standard library function which might need to allocate memory requires the user of that function to pass in an allocator of one's choosing, whether provided with the standard library or provided from scratch. For example, I've been (slowly, given limited free time) working on a SQLite binding for Zig. SQLite has its own allocator, which I've wrapped like so: const std = @import("std"); const Allocator = std.mem.Allocator; const ArrayList = std.ArrayList; // This is all ripped from Zig's C allocator, with adaptations to point to // SQLite's allocator instead. pub const allocator = &allocator_state; var allocator_state = Allocator{ .reallocFn = realloc, .shrinkFn = shrink, }; fn realloc(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 { std.debug.assert(new_align <= @alignOf(c_longdouble)); const old_ptr = if (old_mem.len == 0) null else @ptrCast(*c_void, old_mem.ptr); const buf = sqlite3_realloc64(old_ptr, @intCast(u64, new_size)) orelse return error.OutOfMemory; return @ptrCast([*]u8, buf)[0..new_size]; } fn shrink(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { const old_ptr = @ptrCast(*c_void, old_mem.ptr); const buf = sqlite3_realloc64(old_ptr, @intCast(u64, new_size)) orelse return old_mem[0..new_size]; return @ptrCast([*]u8, buf)[0..new_size]; } And later, to actually open a database (where we need an allocator to add a null byte to a Zig string to satisfy SQLite's expectations for a database name, so we might as well use SQLite's)¹: pub fn open(name: []const u8) !Database { // "allocator" here being the const-defined one above var cstrName = try std.cstr.addNullByte(allocator, name); defer allocator.free(cstrName); var db: Database = undefined; var rc = sqlite3_open(cstrName.ptr, &db); if (rc == SQLITE_OK) { return db; } else { _ = sqlite3_close(db); return errorCode(rc); } } Of course, it'd be even better if such a wrapper actually used SQLite's own support for custom allocators to follow the Zig stdlib convention of allowing the user to supply one's own allocator. Going the other way seemed like a reasonable short-term choice, though, and it was a good enough excuse for me to learn the ropes on custom allocators (even if most of the code ultimately came from Zig's own C allocator). ---- ¹: It turns out that this specific example will apparently be entirely unnecessary in future versions of Zig; the master branch documentation seems to do away with "Zig strings" v. "C strings", instead just making strings null-terminated by default (using what looks to be new support for "sentinel-terminated" pointers/arrays/slices). Looks like I've got some work to do :)
- pjmlp 7y agoYou also cannot fully implement libc in ISO C, without using either language extensions or an external Assembler. So I guess it is not a "low level"/"systems".
- jakear 7y agoThey did when Rust was as mature as Zig is now. Language popularity is a reasonable deciding factor when one is starting a project that has a hiring component; personal projects not so much.