diff --git a/build.zig b/build.zig index e41d6553..22ebb542 100644 --- a/build.zig +++ b/build.zig @@ -384,6 +384,7 @@ fn addDependencies(b: *Build, mod: *Build.Module, opts: *Build.Step.Options) !vo try buildMbedtls(b, mod); try buildNghttp2(b, mod); try buildCurl(b, mod); + try buildAda(b, mod); switch (target.result.os.tag) { .macos => { @@ -849,3 +850,34 @@ fn buildCurl(b: *Build, m: *Build.Module) !void { }, }); } + +pub fn buildAda(b: *Build, m: *Build.Module) !void { + const ada_dep = b.dependency("ada-singleheader", .{}); + + const ada_mod = b.createModule(.{ + .root_source_file = b.path("vendor/ada/root.zig"), + }); + + const ada_lib = b.addLibrary(.{ + .name = "ada", + .root_module = b.createModule(.{ + .link_libcpp = true, + .target = m.resolved_target, + .optimize = m.optimize, + }), + .linkage = .static, + }); + + ada_lib.addCSourceFile(.{ + .file = ada_dep.path("ada.cpp"), + .flags = &.{ "-std=c++20", "-O3" }, + .language = .cpp, + }); + + ada_lib.installHeader(ada_dep.path("ada_c.h"), "ada_c.h"); + + // Link the library to ada module. + ada_mod.linkLibrary(ada_lib); + // Expose ada module to main module. + m.addImport("ada", ada_mod); +} diff --git a/build.zig.zon b/build.zig.zon index 9d57095f..6e4f544b 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -9,5 +9,9 @@ .hash = "v8-0.0.0-xddH63bVAwBSEobaUok9J0er1FqsvEujCDDVy6ItqKQ5", }, //.v8 = .{ .path = "../zig-v8-fork" } + .@"ada-singleheader" = .{ + .url = "https://github.com/ada-url/ada/releases/download/v3.3.0/singleheader.zip", + .hash = "N-V-__8AAPmhFAAw64ALjlzd5YMtzpSrmZ6KymsT84BKfB4s", + }, }, } diff --git a/vendor/ada/root.zig b/vendor/ada/root.zig new file mode 100644 index 00000000..da281068 --- /dev/null +++ b/vendor/ada/root.zig @@ -0,0 +1,168 @@ +//! Wrappers for ada URL parser. +//! https://github.com/ada-url/ada + +const c = @cImport({ + @cInclude("ada_c.h"); +}); + +pub const URLComponents = c.ada_url_components; +pub const URLOmitted = c.ada_url_omitted; +pub const String = c.ada_string; +pub const OwnedString = c.ada_owned_string; +/// Pointer types. +pub const URL = c.ada_url; +pub const URLSearchParams = c.ada_url_search_params; + +pub const ParseError = error{Invalid}; + +pub fn parse(input: []const u8) ParseError!URL { + const url = c.ada_parse(input.ptr, input.len); + if (!c.ada_is_valid(url)) { + return error.Invalid; + } + + return url; +} + +pub fn parseWithBase(input: []const u8, base: []const u8) ParseError!URL { + const url = c.ada_parse_with_base(input.ptr, input.len, base.ptr, base.len); + if (!c.ada_is_valid(url)) { + return error.Invalid; + } + + return url; +} + +pub inline fn getComponents(url: URL) *const URLComponents { + return c.ada_get_components(url); +} + +pub inline fn free(url: URL) void { + return c.ada_free(url); +} + +pub inline fn freeOwnedString(owned: OwnedString) void { + return c.ada_free_owned_string(owned); +} + +/// Returns true if given URL is valid. +pub inline fn isValid(url: URL) bool { + return c.ada_is_valid(url); +} + +/// Creates a new `URL` from given `URL`. +pub inline fn copy(url: URL) URL { + return c.ada_copy(url); +} + +/// Contrary to other getters, this heap allocates. +pub inline fn getOriginNullable(url: URL) OwnedString { + return c.ada_get_origin(url); +} + +pub inline fn getHrefNullable(url: URL) String { + return c.ada_get_href(url); +} + +pub inline fn getUsernameNullable(url: URL) String { + return c.ada_get_username(url); +} + +pub inline fn getPasswordNullable(url: URL) String { + return c.ada_get_password(url); +} + +pub inline fn getSearchNullable(url: URL) String { + return c.ada_get_search(url); +} + +pub inline fn getPortNullable(url: URL) String { + return c.ada_get_port(url); +} + +pub inline fn getHashNullable(url: URL) String { + return c.ada_get_hash(url); +} + +pub inline fn getHostNullable(url: URL) String { + return c.ada_get_host(url); +} + +pub inline fn getHostnameNullable(url: URL) String { + return c.ada_get_hostname(url); +} + +pub inline fn getPathnameNullable(url: URL) String { + return c.ada_get_pathname(url); +} + +pub inline fn getProtocolNullable(url: URL) String { + return c.ada_get_protocol(url); +} + +pub inline fn setHref(url: URL, input: []const u8) bool { + return c.ada_set_href(url, input.ptr, input.len); +} + +pub inline fn setHost(url: URL, input: []const u8) bool { + return c.ada_set_host(url, input.ptr, input.len); +} + +pub inline fn setHostname(url: URL, input: []const u8) bool { + return c.ada_set_hostname(url, input.ptr, input.len); +} + +pub inline fn setProtocol(url: URL, input: []const u8) bool { + return c.ada_set_protocol(url, input.ptr, input.len); +} + +pub inline fn setUsername(url: URL, input: []const u8) bool { + return c.ada_set_username(url, input.ptr, input.len); +} + +pub inline fn setPassword(url: URL, input: []const u8) bool { + return c.ada_set_password(url, input.ptr, input.len); +} + +pub inline fn setPort(url: URL, input: []const u8) bool { + return c.ada_set_port(url, input.ptr, input.len); +} + +pub inline fn setPathname(url: URL, input: []const u8) bool { + return c.ada_set_pathname(url, input.ptr, input.len); +} + +pub inline fn setSearch(url: URL, input: []const u8) void { + return c.ada_set_search(url, input.ptr, input.len); +} + +pub inline fn setHash(url: URL, input: []const u8) void { + return c.ada_set_hash(url, input.ptr, input.len); +} + +pub inline fn clearHash(url: URL) void { + return c.ada_clear_hash(url); +} + +pub inline fn clearSearch(url: URL) void { + return c.ada_clear_search(url); +} + +pub inline fn clearPort(url: URL) void { + return c.ada_clear_port(url); +} + +pub const Scheme = struct { + pub const http: u8 = 0; + pub const not_special: u8 = 1; + pub const https: u8 = 2; + pub const ws: u8 = 3; + pub const ftp: u8 = 4; + pub const wss: u8 = 5; + pub const file: u8 = 6; +}; + +/// Returns one of the constants defined in `Scheme`. +pub inline fn getSchemeType(url: URL) u8 { + return c.ada_get_scheme_type(url); +}