Skip to content

aitorvs/url_predictor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

URL Predictor

A small Rust library that decides whether a piece of text from an address bar should be treated as:

  • Navigate → open as a URL
  • Search → send to the search engine

The logic is deterministic and tries to stay minimal so it can be audited and reused across platforms.


Why

Browsers and apps often need to guess what the user meant when typing into the omnibox. For example:

  • example.com → Navigate
  • what is my ip → Search

This crate provides a reference implementation with a configurable Policy struct so each app can tweak behavior.


Features

  • Distinguishes between **Navigate / Search
  • Handles schemes (https://, ftp://, edge://, etc.)
  • Understands hostnames, localhost, IPs, intranet single-labels
  • Optional integration with the Public Suffix List (via the real-psl feature)
  • Cross-platform FFI (Android/iOS/Windows)

Policy

Behavior is tuned via a Policy:

#[derive(Serialize, Deserialize)]
pub struct Policy {
    pub allow_intranet_single_label: bool,
    pub allow_private_suffix: bool,
    pub allowed_schemes: BTreeSet<String>,
}

Example (Rust):

let mut policy = Policy::default();
policy.allow_intranet_single_label = true;

let decision = classify("duck ai translate hello", &policy);

Decisions

pub enum Decision {
    Navigate { url: String },
    Search { query: String },
}

Platform Integration

  • Rust → use classify(&str, &Policy) directly
  • C/FFI → call ddg_up_classify_json, which returns JSON-encoded Decision
  • Android (JNI)UrlPredictor.classify(input) in Kotlin
  • iOS → expose ddg_up_classify_json via a bridging header and wrap it in Swift
  • Windows → link against the .dll and call ddg_up_classify_json

Memory management

ddg_up_classify_json returns a heap-allocated string.
Call ddg_up_free_string(ptr) once you’re done with it to avoid memory leaks.

Example in C:

char* result = ddg_up_classify_json(input, policy_json);
printf("%s\n", result);
ddg_up_free_string(result); // free it!

Building

Default (uses a small demo suffix DB):

cargo build

With real PSL:

cargo build --features real-psl

Building for Platforms

This repo ships helper scripts under scripts/ to cross-compile the Rust core into platform-specific libraries:

  • Android: scripts/build-android.sh
    Produces liburl_predictor.so for all standard ABIs and drops them under android/ddg-url-predictor/src/main/jniLibs.

  • iOS/macOS: scripts/build-ios.sh, scripts/build-macos.sh
    Produces .a / .dylib artifacts for Xcode integration. Requires full Xcode installation (xcode-select).

  • Windows: scripts/build-windows.sh
    Produces url_predictor.dll for MSVC targets.

Outputs land under dist/ by default. These aren’t checked into git — run the scripts yourself.


Tests

Run the Rust test suite:

cargo test

Or run tests using the real PSL:

cargo test --features real-psl

Notes

  • The included DemoSuffixDb is intentionally tiny. For production, enable the real-psl feature and ship a PSL file.
  • The project does not do DNS or network lookups. Everything is local and deterministic.
  • Error cases (like bad policy JSON) fall back to Policy::default().

Example (Kotlin wrapper)

If you’re calling from Android, the Kotlin helper wraps the JNI call and returns a type-safe Decision:

object UrlPredictor {
    init { System.loadLibrary("url_predictor") }

    // JNI call into Rust
    @JvmStatic private external fun ddgClassifyJni(input: String, policyJson: String): String

    // Type-safe API
    @JvmStatic
    fun classify(input: String, policy: DecisionJson.Policy = DecisionJson.Policy()): Decision {
        val policyJson = DecisionJson.encodePolicy(policy)
        val decisionJson = ddgClassifyJni(input, policyJson)
        return DecisionJson.decodeDecision(decisionJson)
    }
}

Usage:

val result = UrlPredictor.classify("duck ai hello world")
when (result) {
    is Decision.Navigate -> println("Navigate to ${result.url}")
    is Decision.Search -> println("Search for ${result.query}")
}

About

Rust library for omnibox input classification (Navigate vs Search).

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published