Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add toBytes and setBytes to std.math.big.int.Managed #10483

Open
NefixEstrada opened this issue Jan 1, 2022 · 2 comments
Open

Add toBytes and setBytes to std.math.big.int.Managed #10483

NefixEstrada opened this issue Jan 1, 2022 · 2 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. standard library This issue involves writing Zig code for the standard library.
Milestone

Comments

@NefixEstrada
Copy link

NefixEstrada commented Jan 1, 2022

Right now, the workaround is to do the following, which is kinda weird. Also, it would be nice to have a function like fillBytes, which would fill a buffer instead of allocating it. What do you think?

fn setBytes(allocator: std.mem.Allocator, int: *std.math.big.int.Managed, buf: []u8) !void {
    var hex = try allocator.alloc(u8, buf.len * 2);
    defer allocator.free(hex);

    const chars = [_]u8{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    for (buf) |b, i| {
        hex[i * 2 + 0] = chars[b >> 4];
        hex[i * 2 + 1] = chars[b & 0x0f];
    }

    try int.setString(16, hex);
}

fn toBytes(allocator: std.mem.Allocator, int: std.math.big.int.Managed) ![]u8 {
    var hex = try int.toString(allocator, 16, .lower);
    defer allocator.free(hex);

    var out: []u8 = undefined;

    if (hex.len & 1 == 0) {
        out = try allocator.alloc(u8, hex.len / 2);
        errdefer allocator.free(out);

        _ = try std.fmt.hexToBytes(out, hex);
    } else {
        out = try allocator.alloc(u8, (hex.len + 1) / 2);
        errdefer allocator.free(out);

        out[0] = try std.fmt.charToDigit(hex[0], 16);
        _ = try std.fmt.hexToBytes(out[1..], hex[1..]);
    }

    return out;
}

Thanks,

Néfix Estrada

@NefixEstrada NefixEstrada added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Jan 1, 2022
@NefixEstrada NefixEstrada changed the title Add toBytes and fromBytes to std.math.big.int.Managed Add toBytes and setBytes to std.math.big.int.Managed Jan 1, 2022
@tiehuis
Copy link
Member

tiehuis commented Jan 5, 2022

There would need to be a few extra parameters required if we wanted this to be a generic platform-independent serialization/deserialization routine. Specifically endian, limb size and potentially internal ordering of the output/input limbs. Can handle sign externally as gmp does.

pub const SerializationOptions = struct {
    endian: enum { host, big, little } = .host,
    limb_order: enum { msb, lsb } = .lsb, // Default internal ordering
    word_size: u8 = @sizeOf(Limb),
};

fn setBytes(allocator: std.mem.Allocator, int: *std.math.big.int.Managed, buf: []u8, options: SerializationOptions) !void

@andrewrk andrewrk added the standard library This issue involves writing Zig code for the standard library. label Feb 2, 2022
@andrewrk andrewrk added this to the 0.11.0 milestone Feb 2, 2022
@topolarity
Copy link
Contributor

topolarity commented Feb 17, 2022

One option would be to implement this on top of readTwosComplement and writeTwosComplement

These write to a provided buffer as if it were backing a big twos-complement integer, so it's independent of the Limb size (and the endianness of the twos-complement number is configurable)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

No branches or pull requests

4 participants