1use wedeo_core::error::Result;
2
3use crate::io::IoContext;
4
5pub trait Protocol: Send + Sync {
7 fn name(&self) -> &'static str;
8 fn open(&self, url: &str, flags: ProtocolFlags) -> Result<Box<dyn IoContext>>;
9}
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct ProtocolFlags {
14 pub read: bool,
15 pub write: bool,
16}
17
18impl ProtocolFlags {
19 pub const READ: Self = Self {
20 read: true,
21 write: false,
22 };
23 pub const WRITE: Self = Self {
24 read: false,
25 write: true,
26 };
27 pub const READ_WRITE: Self = Self {
28 read: true,
29 write: true,
30 };
31}
32
33inventory::collect!(&'static dyn Protocol);
34
35pub fn open_url(url: &str, flags: ProtocolFlags) -> Result<Box<dyn IoContext>> {
37 let scheme = url.find("://").map(|i| &url[..i]).unwrap_or("file");
39
40 for proto in inventory::iter::<&'static dyn Protocol>() {
41 if proto.name() == scheme {
42 return proto.open(url, flags);
43 }
44 }
45
46 if flags.write {
48 Ok(Box::new(crate::io::FileIo::create(url)?))
49 } else {
50 Ok(Box::new(crate::io::FileIo::open(url)?))
51 }
52}