_rust_url_c_api_rustc_static/lib.rs
1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use std::ffi::{c_char, c_void, CStr, CString};
6use url::Url;
7use zx::Status;
8
9/// Parse a URL, returning success/failure as a status code. On success, `out` will contain a
10/// pointer to the parsed URL.
11///
12/// # Safety
13///
14/// * `input` must be a valid pointer to a null-terminated string. The string must consist solely of
15/// UTF-8 characters but failure to provide UTF-8 will result in defined behavior.
16/// * `out` must be a valid pointer to write to. The pointer written there must be freed with
17/// `rust_url_free`.
18#[no_mangle]
19unsafe extern "C" fn rust_url_parse(input: *const c_char, out: *mut *mut c_void) -> Status {
20 if let Ok(raw_url) = CStr::from_ptr(input).to_str() {
21 match Url::parse(raw_url) {
22 Ok(url) => {
23 *out = Box::into_raw(Box::new(url)) as *mut c_void;
24 Status::OK
25 }
26 Err(_) => Status::INVALID_ARGS,
27 }
28 } else {
29 Status::INVALID_ARGS
30 }
31}
32
33/// Free a URL parsed with `rust_url_parse`.
34///
35/// # Safety
36///
37/// * `url` must have been produced from `rust_url_parse`.
38/// * This function can only be called once per pointer.
39#[no_mangle]
40unsafe extern "C" fn rust_url_free(url: *mut c_void) {
41 drop(Box::from_raw(url as *mut Url));
42}
43
44/// Get the domain from a parsed URL, returning a C-string if available. If no domain is present,
45/// a null pointer is returned.
46///
47/// # Safety
48///
49/// * `url` must have been produced from a successful call to `rust_url_parse`.
50/// * `url` cannot have been freed before calling this function.
51#[no_mangle]
52unsafe extern "C" fn rust_url_get_domain(url: *const c_void) -> *const c_char {
53 let url = &*(url as *const Url);
54
55 if let Some(domain) = url.domain() {
56 CString::new(domain).expect("no null bytes in a valid URL's domain").into_raw()
57 } else {
58 std::ptr::null()
59 }
60}
61
62/// Free a domain returned by `rust_url_get_domain`.
63///
64/// # Safety
65///
66/// * `domain` must be a valid non-null pointer returned by `rust_url_get_domain`.
67/// * This function can only be called once per pointer.
68#[no_mangle]
69unsafe extern "C" fn rust_url_free_domain(domain: *mut c_char) {
70 drop(CString::from_raw(domain));
71}