Compiler Error with coercion or type casting...Need Help!

I am having trouble with coercion. I am trying to take a response and parse it.
Here is the code. Please help. Thanks.

const std = @import("std");

fn get(a: []const u8, b: std.mem.Allocator) !void {
    const uri = try std.Uri.parse(a);

    var client = std.http.Client{ .allocator = b };
    defer client.deinit();

    const server_header_buffer: []u8 = try b.alloc(u8, 1024 * 8);
    defer b.free(server_header_buffer);

    var req = try client.open(.GET, uri, .{
        .server_header_buffer = server_header_buffer,
    });
    defer req.deinit();

    try req.send();
    try req.finish();
    try req.wait();

    // 1024 * 8 of memory.
    const body = try req.reader().readAllAlloc(b, 229000 * 8);
    defer b.free(body);
    std.debug.print("{s}", .{body});
    const x = std.mem.splitScalar(u8, body, "er\":\"");
    for (x) |i| {
        const h = std.mem.splitScalar(u8, i, "\"")[0];
        std.debug.print("{s}", .{h});
    }
}
pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();
    try get("https://api.polygon.io/v3/reference/tickers?market=stocks&active=true&order=asc&limit=1000&sort=ticker&apiKey=MY_API_KEY", allocator);
}

Compiler error

test.zig:25:47: error: expected type '[]const []const u8', found '[]u8'
    const x = std.mem.splitScalar([]const u8, body, "er\":\"");
                                              ^~~~
test.zig:25:47: note: pointer type child 'u8' cannot cast into pointer type child '[]const u8'
C:\Users\first cash\zig-windows-x86_64-0.15.0-dev.369+1a2ceb36c\lib\std\mem.zig:2481:46: note: parameter type declared here
pub fn splitScalar(comptime T: type, buffer: []const T, delimiter: T) SplitIterator(T, .scalar) {
                                             ^~~~~~~~~
referenced by:
    main: test.zig:35:12
    WinStartup: C:\Users\first cash\zig-windows-x86_64-0.15.0-dev.369+1a2ceb36c\lib\std\start.zig:671:37
    3 reference(s) hidden; use '-freference-trace=5' to see all references

Thanks again.

It looks like the code does not match the output, so it looks like you maybe just forgot to save.
The code you sent seems to already have fixed the problem shown.

1 Like

I think your problem is here. Split scalar expects a u8 (i.e. ':', '\n', ':' or 8) as the 3rd parameter. I think what you are looking for is either splitAny or splitSequence If you want that specific string, then you want splitSequence.

2 Likes

I tried that it did not work. What I am trying to do this split the string by a string delimiter. Has anyone done this before. I have tried switching the data types but without success. I get the byte string but not the actual string…

The output for the program is. It is the string split in u8 data but I want it in string…

mem.SplitIterator(u8,.sequence){ .buffer = { 123, 34, 114, 101, 115, 117, 108, 116, 115, 34, 58, 91, 123, 34, 116, 105, 99, 107, 101, 114, 34, 58, 34, 65, 34, 44, 34, 110, 97, 109, 101, 34, 58, 34, 65, 103, 105, 108, 101, 110, 116, 32, 84, 101, 99, 104, 110, 111, 108, 111, 103, 105, 101, 115, 32, 73, 110, 99, 46, 34, 44, 34, 109, 97, 114, 107, 101, 116, 34, 58, 34, 115, 116, 111, 99, 107, 115, 34, 44, 34, 108, 111, 99, 97, 108, 101, 34, 58, 34, 117, 115, 34, 44, 34, 112, 114, 105, 109, 97, 114, 121, 95, 101, 120, 99, 104, 97, 110, 103, 101, 34, 58, 34, 88, 78, 89, 83, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 67, 83, 34, 44, 34, 97, 99, 116, 105, 118, 101, 34, 58, 116, 114, 117, 101, 44, 34, 99, 117, 114, 114, 101, 110, 99, 121, 95, 110, 97, 109, 101, 34, 58, 34, 117, 115, 100, 34, 44, 34, 99, 105, 107, 34, 58, 34, 48, 48, 48, 49, 48, 57, 48, 56, 55, 50, 34, 44, 34, 99, 111, 109, 112, 111, 115, 105, 116, 101, 95, 102, 105, 103, 105, 34, 58, 34, 66, 66, 71, 48, 48, 48, 67, 50, 86, 51, 68, 54, 34, 44, 34, 115, 104, 97, 114, 101, 95, 99, 108, 97, 115, 115, 95, 102, 105, 103, 105, 34, 58, 34, 66, 66, 71, 48, 48, 49, 83, 67, 84, 81, 89, 52, 34, 44, 34, 108, 97, 115, 116, 95, 117, 112, 100, 97, 116, 101, 100, 95, 117, 116, 99, 34, 58, 34, 50, 48, 50, 53, 45, 48, 57, 45, 50, 55, 84, 48, 54, 58, 48, 53, 58, 50, 49, 46, 53, 53, 53, 51, 57, 57, 52, 52, 54, 90, 34, 125, 44, 123, 34, 116, 105, 99, 107, 101, 114, 34, 58, 34, 65, 65, 34, 44, 34, 110, 97, 109, 101, 34, 58, 34, 65, 108, 99, 111, 97, 32, 67, 111, 114, 112, 111, 114, 97, 116, 105, 111, 110, 34, 44, 34, 109, 97, 114, 107, 101, 116, 34, 58, 34, 115, 116, 111, 99, 107, 115, 34, 44, 34, 108, 111, 99, 97, 108, 101, 34, 58, 34, 117, 115, 34, 44, 34, 112, 114, 105, 109, 97, 114, 121, 95, 101, 120, 99, 104, 97, 110, 103, 101, 34, 58, 34, 88, 78, 89, 83, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 67, 83, 34, 44, 34, 97, 99, 116, 105, 118, 101, 34, 58, 116, 114, 117, 101, 44, 34, 99, 117, 114, 114, 101, 110, 99, 121, 95, 110, 97, 109, 101, 34, 58, 34, 117, 115, 100, 34, 44, 34, 99, 105, 107, 34, 58, 34, 48, 48, 48, 49, 54, 55, 53, 49, 52, 57, 34, 44, 34, 99, 111, 109, 112, 111, 115, 105, 116, 101, 95, 102, 105, 103, 105, 34, 58, 34, 66, 66, 71, 48, 48, 66, 51, 84, 51, 72, 68, 51, 34, 44, 34, 115, 104, 97, 114, 101, 95, 99, 108, 97, 115, 115, 95, 102, 105, 103, 105, 34, 58, 34, 66, 66, 71, 48, 48, 66, 51, 84, 51, 72, 70, 49, 34, 44, 34, 108, 97, 115, 116, 95, 117, 112, 100, 97, 116, 101, 100, 95, 117, 116, 99, 34, 58, 34, 50, 48, 50, 53, 45, 48, 57, 45, 50, 55, 84, 48, 54, 58, 4

Sounds like you tried to use splitAny (which is wrong if you want a single multi character delimiter), but haven’t used splitSequence.

I don’t understand what you mean with this, can you show some code example with inputs, outputs and what you expect instead?

These methods return an iterator because the length of the sequence is unknown (and returning a slice representing the sequence would cause unnecessary allocation in cases where these elements aren’t needed permanently (for example if many are skipped/discarded)).

You need to use that iterator to get to the individual elements of the sequence. This uses splitSequence: Iterators | zig.guide
Depending on what your code does you may want to use a while loop with the iterator.


I have only read the first part, but it seems like a good post to read if you are unfamiliar with Zig iterators: Zig Iterators

1 Like

I took a look at the API for polygon, and I think you are headed in a more challenging direction. This is a JSON HTTP api, so the body of your response is going to be JSON. Instead of getting the body and trying to haphazardly parse out what you want, I would suggest looking at the standard library JSON parser.

const body = try req.reader().readAllAlloc(b, 229000 * 8);
defer b.free(body);

const parsed = try std.json.parseFromSlice(TickerResponse, b, body, .{
    .ignore_unknown_fields = true, // If your TickerResponse may not define all fields found in the JSON, set true. Otherwise it will return an error if it doesn't match exactly.
});
defer parsed.deinit(b);
const ticker = parsed.value.results[0].ticker;
...

You can type the response with a normal Zig struct.

const TickerResponse = struct {
    const Ticker = struct {
        ticker: []const u8,
        name: []const u8,
        // Other fields go here
    };
    count: usize,
    next_url: []const u8,
    request_id: []const u8,
    // other fields go here
};
3 Likes