-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmod.rs
More file actions
157 lines (137 loc) · 5.34 KB
/
Copy pathmod.rs
File metadata and controls
157 lines (137 loc) · 5.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! Module defining gist hosts.
//!
//! A host is an external (web) service that hosts gists, and allows users to paste snippets
//! of code to share with others. gist.github.com is a prime example; others are the various
//! "pastebins", including the pastebin.com namesake.
mod common;
mod github;
mod bpaste;
mod dpaste_de;
mod hastebin;
mod heypasteit;
mod ix_io;
mod lpaste;
mod mibpaste;
mod mozilla;
mod paste_rs;
mod pastebin;
mod sprunge;
mod thepasteb_in;
use std::collections::HashMap;
use std::io;
use std::sync::Arc;
use super::gist::{self, Gist};
/// Represents a gists' host: a (web) service that hosts gists (code snippets).
/// Examples include gist.github.com.
pub trait Host : Send + Sync {
/// Returns a unique identifier of the gist Host.
fn id(&self) -> &'static str;
/// Returns a user-visible name of the gists' host.
fn name(&self) -> &str;
/// Fetch a current version of the gist if necessary.
///
/// The `mode` parameter specifies in what circumstances the gist will be fetched
/// from the remote host: always, only if new, or when needed.
///
/// If the gist has been downloaded previously,
/// it can also be updated instead (e.g. via pull rather than clone
/// if its a Git repo).
fn fetch_gist(&self, gist: &Gist, mode: FetchMode) -> io::Result<()>;
/// Return a URL to a HTML page that can display the gist.
/// This may involve talking to the remote host.
fn gist_url(&self, gist: &Gist) -> io::Result<String>;
/// Return a structure with information/metadata about the gist.
///
/// Note: The return type for this method is io::Result<Option<Info>>
/// rather than Option<io::Result<Info>> because the availability of
/// gist metadata may be gist-specific (i.e. some gists have it,
/// some don't).
fn gist_info(&self, gist: &Gist) -> io::Result<Option<gist::Info>> {
// This default indicates the host cannot fetch any additional gist metadata
// (beyond what may already have been fetched when resolving gist URL).
Ok(gist.info.clone())
}
/// Return a gist corresponding to the given URL.
/// The URL will typically point to a user-facing HTML page of the gist.
///
/// Note: The return type of this method is an Option (Option<io::Result<Gist>>)
/// because the URL may not be recognized as belonging to this host.
fn resolve_url(&self, _: &str) -> Option<io::Result<Gist>> {
// This default indicates that the URL wasn't recognized
// as pointing to any gist hosted by this host.
None
}
}
macro_attr! {
#[derive(Clone, Debug, PartialEq, Eq, Hash,
IterVariants!(FetchModes))]
pub enum FetchMode {
/// Automatically decide how & whether to fetch the gist.
///
/// This is host-specific, but should typically mean that the gist
/// is only updated periodically, or when it's necessary to do so.
Auto,
/// Always fetch the gist from the remote host.
Always,
/// Only fetch the gist if necessary
/// (i.e. when it hasn't been downloaded before).
New,
}
}
impl Default for FetchMode {
#[inline]
fn default() -> Self { FetchMode::Auto }
}
/// Mapping of gist host identifiers to Host structs.
lazy_static! {
static ref BUILTIN_HOSTS: HashMap<&'static str, Arc<Host>> = hashmap!{
github::ID => Arc::new(github::GitHub::new()) as Arc<Host>,
pastebin::ID => Arc::new(pastebin::create()) as Arc<Host>,
lpaste::ID => Arc::new(lpaste::create()) as Arc<Host>,
heypasteit::ID => Arc::new(heypasteit::create()) as Arc<Host>,
bpaste::ID => Arc::new(bpaste::create()) as Arc<Host>,
mozilla::ID => Arc::new(mozilla::create()) as Arc<Host>,
paste_rs::ID => Arc::new(paste_rs::create()) as Arc<Host>,
hastebin::ID => Arc::new(hastebin::Hastebin::new()) as Arc<Host>,
mibpaste::ID => Arc::new(mibpaste::Mibpaste::new()) as Arc<Host>,
sprunge::ID => Arc::new(sprunge::Sprunge::new()) as Arc<Host>,
dpaste_de::ID => Arc::new(dpaste_de::create()) as Arc<Host>,
thepasteb_in::ID => Arc::new(thepasteb_in::create()) as Arc<Host>,
ix_io::ID => Arc::new(ix_io::Ix::new()) as Arc<Host>,
};
}
#[cfg(not(test))]
lazy_static! {
pub static ref HOSTS: HashMap<&'static str, Arc<Host>> = BUILTIN_HOSTS.clone();
}
#[cfg(test)]
lazy_static! {
pub static ref HOSTS: HashMap<&'static str, Arc<Host>> = {
use testing::{INMEMORY_HOST_DEFAULT_ID, InMemoryHost};
let mut hosts = BUILTIN_HOSTS.clone();
hosts.insert(INMEMORY_HOST_DEFAULT_ID, Arc::new(InMemoryHost::new()) as Arc<Host>);
hosts
};
}
pub const DEFAULT_HOST_ID: &'static str = github::ID;
#[cfg(test)]
mod tests {
use testing::INMEMORY_HOST_DEFAULT_ID;
use super::{DEFAULT_HOST_ID, HOSTS};
#[test]
fn consistent_hosts() {
for (&id, host) in &*HOSTS {
assert_eq!(id, host.id());
}
}
#[test]
fn default_host_id() {
assert!(HOSTS.contains_key(DEFAULT_HOST_ID),
"Default host ID `{}` doesn't occur among known gist hosts", DEFAULT_HOST_ID);
}
#[test]
fn inmemory_host_for_testing() {
assert!(HOSTS.contains_key(INMEMORY_HOST_DEFAULT_ID),
"Test in-memory host ID `{}` doesn't occur among known gist hosts", INMEMORY_HOST_DEFAULT_ID);
}
}