URLs as functions
Created by: HeroesGrave
Just an idea I'd like to throw in. I have the free time to work on the implementation if you need more contributors.
How about implementing URLs as functions in Rust code, so that if needed, a program can avoid the overhead of URL formatting & parsing, and at the same time maintain consistency and ease-of use for both applications and the user.
The first thing to consider, is the passing of arguments. I propose using some sort of Map<String, String>
structure, which is derived from the query section of the URL (eg: scheme://some/path?key1=value1&key2=value2
).
Arguments
type Arguments = Map<String, String>;
After that, all URL resources implement a trait something like this:
trait UrlFunction {
fn call(&mut self, &Arguments);
}
Example
I'll use the example of the window scheme, because it highlights a few different scenarios while not getting too complex.
The root 'directory' of the window://
scheme would be represented in something like the following structure:
struct WindowRoot {
windows: Vec<Window>, // In practice you'd use a data structure that recycles old IDs, etc.
create: CreateWindow,
}
struct Window {
x: i32,
y: i32,
width: u32,
height: u32,
title: String,
}
struct CreateWindow;
impl UrlFunction for CreateWindow {
fn call(&mut self, args: &Arguments) { // Could probably pass mutably or by-value if needed
let x = args.get("x").and_then(|s| s.parse()).unwrap_or(/* ... */);
let y = args.get("y").and_then(|s| s.parse()).unwrap_or(/* ... */);
let width = args.get("width").and_then(|s| s.parse()).unwrap_or(/* ... */);
let height = args.get("height").and_then(|s| s.parse()).unwrap_or(/* ... */);
let title = args.get("title").unwrap_or(/* ... */);
self.create(x, y, width, height, title);
}
}
impl CreateWindow {
fn create(&mut self, x: i32, y: i32, w: i32, h: i32, title: String) {
// create window
}
// Allows overloading of functionality, etc.
fn create_centred(&mut self, w: i32, h: i32, title: String) {
// create window centred in the screen
}
}
Then to create a window, we can either call the function from within an application:
// schemes.get("window") if the window scheme isn't builtin.
schemes.window.create.create(100, 100, 800, 600, "Window");
Or opening the URL: window://create?x=100&y=100&width=800&height=600&title=Window
(I'm not 100% sure how opening/closing/reading/writing with URLs currently works, but hopefully I'm clsoe enough that you understand)
Or a mix of both:
let args = Arguments::new();
args.insert("x", "100");
args.insert("y", "100");
args.insert("width", "800");
args.insert("height", "600");
args.insert("title", "Window");
schemes.window.create.call(args);
And to get/set the width of the window with the ID 1
, you can do something like:
let w = schemes.window.get(1).unwrap().get_width();
schemes.window.get_mut(1).unwrap().set_width(w + 5);
Because the windowing system needs to know when a value has been changed, you can't access the value directly. Instead a method needs to be called, which will handle the changes, etc.
And using URLs, just read, increment, and write the value from/to
window://1/x
More functions could be added to the root window url like window:/close?id=1
to close windows (although I think this is already handled a different way by closing the window's file descriptor?), window://query?title=Window_Title
to search for a list of windows with the specific title, etc.
A few more notes
-
file://path/to/a/file
probably works the same even with this idea. -
config://hierarchy/of/configs/key
can be read/written from and contains the config value, pretty much the same way that window properties were accessed above.
Obviously the finer details of this are lacking, due to myself only having had a brief look through the codebase, but feel free to comment on why this is/isn't a good idea, if there's something I've missed, or if you've got some ideas for the finer details.