Make the Rust garbage compile again

This commit is contained in:
Yorhel 2021-12-05 18:58:58 +01:00
parent b8dca570a0
commit 4588e67b64
12 changed files with 1348 additions and 1078 deletions

View file

@ -9,7 +9,7 @@ Ironically, documentation about how things work is completely lacking.
- perl: A somewhat recent version (no idea which, due to my XS usage) - perl: A somewhat recent version (no idea which, due to my XS usage)
- postgresql: Also a somewhat recent version - postgresql: Also a somewhat recent version
- rust + cargo (1.13+) - rust: Version who-knows-which
### Web front-end ### Web front-end

2239
indexer/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@ libc = "0.2.39"
libarchive3-sys = "0.1.2" libarchive3-sys = "0.1.2"
encoding = { git = "https://github.com/lifthrasiir/rust-encoding", features = ["no-optimized-legacy-encoding"] } encoding = { git = "https://github.com/lifthrasiir/rust-encoding", features = ["no-optimized-legacy-encoding"] }
ring = "0.14.6" ring = "0.14.6"
postgres = "0.15.2" postgres = "0.17.5"
clap = "2.31.2" clap = "2.31.2"
reqwest = "0.9.17" reqwest = "0.9.17"
url = "1.7.0" url = "1.7.0"

View file

@ -27,12 +27,12 @@ mod sys_rpm;
// Convenience function to get a system id by short-name. Panics if the system doesn't exist. // Convenience function to get a system id by short-name. Panics if the system doesn't exist.
fn sysbyshort(conn: &postgres::GenericConnection, short: &str) -> i32 { fn sysbyshort<T>(conn: &mut T, short: &str) -> i32 where T: postgres::GenericClient {
let r = conn.query("SELECT id FROM systems WHERE short = $1", &[&short]).unwrap(); if let Some(r) = conn.query_opt("SELECT id FROM systems WHERE short = $1", &[&short]).unwrap() {
if r.is_empty() { return r.get(0);
} else {
panic!("Invalid system: {}", short); panic!("Invalid system: {}", short);
} }
r.get(0).get(0)
} }
@ -112,7 +112,7 @@ fn main() {
Ok(x) => x, Ok(x) => x,
Err(_) => { error!("MANNED_PG not set."); return } Err(_) => { error!("MANNED_PG not set."); return }
}; };
let db = match postgres::Connection::connect(&dbhost[..], postgres::TlsMode::None) { let mut db = match postgres::Client::connect(&dbhost[..], postgres::tls::NoTls) {
Ok(x) => x, Ok(x) => x,
Err(x) => { error!("Can't connect to postgres: {}", x); return }, Err(x) => { error!("Can't connect to postgres: {}", x); return },
}; };
@ -125,9 +125,10 @@ fn main() {
"max" => pkg::Date::Max, "max" => pkg::Date::Max,
s => pkg::Date::Known(s), s => pkg::Date::Known(s),
}; };
pkg::pkg(&db, pkg::PkgOpt { let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
pkg::pkg(&mut db, pkg::PkgOpt {
force: matches.is_present("force"), force: matches.is_present("force"),
sys: sysbyshort(&db, matches.value_of("sys").unwrap()), sys: sys,
cat: matches.value_of("cat").unwrap(), cat: matches.value_of("cat").unwrap(),
pkg: matches.value_of("pkg").unwrap(), pkg: matches.value_of("pkg").unwrap(),
ver: matches.value_of("ver").unwrap(), ver: matches.value_of("ver").unwrap(),
@ -138,16 +139,16 @@ fn main() {
} }
if let Some(matches) = arg.subcommand_matches("arch") { if let Some(matches) = arg.subcommand_matches("arch") {
sys_arch::sync(&db, let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
sysbyshort(&db, matches.value_of("sys").unwrap()), sys_arch::sync(&mut db, sys,
matches.value_of("mirror").unwrap(), matches.value_of("mirror").unwrap(),
matches.value_of("repo").unwrap() matches.value_of("repo").unwrap()
); );
} }
if let Some(matches) = arg.subcommand_matches("deb") { if let Some(matches) = arg.subcommand_matches("deb") {
sys_deb::sync(&db, let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
sysbyshort(&db, matches.value_of("sys").unwrap()), sys_deb::sync(&mut db, sys,
matches.value_of("mirror").unwrap(), matches.value_of("mirror").unwrap(),
matches.value_of("contents").map(|e| { open::Path{ path: e, cache: true, canbelocal: true} }), matches.value_of("contents").map(|e| { open::Path{ path: e, cache: true, canbelocal: true} }),
open::Path{ path: matches.value_of("packages").unwrap(), cache: true, canbelocal: true}, open::Path{ path: matches.value_of("packages").unwrap(), cache: true, canbelocal: true},
@ -155,31 +156,31 @@ fn main() {
} }
if let Some(matches) = arg.subcommand_matches("freebsd1") { if let Some(matches) = arg.subcommand_matches("freebsd1") {
sys_freebsd1::sync(&db, let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
sysbyshort(&db, matches.value_of("sys").unwrap()), sys_freebsd1::sync(&mut db, sys,
matches.value_of("arch").unwrap(), matches.value_of("arch").unwrap(),
matches.value_of("mirror").unwrap() matches.value_of("mirror").unwrap()
).unwrap_or_else(|e| error!("{}", e)); ).unwrap_or_else(|e| error!("{}", e));
} }
if let Some(matches) = arg.subcommand_matches("freebsd2") { if let Some(matches) = arg.subcommand_matches("freebsd2") {
sys_freebsd2::sync(&db, let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
sysbyshort(&db, matches.value_of("sys").unwrap()), sys_freebsd2::sync(&mut db, sys,
matches.value_of("mirror").unwrap() matches.value_of("mirror").unwrap()
).unwrap_or_else(|e| error!("{}", e)); ).unwrap_or_else(|e| error!("{}", e));
} }
if let Some(matches) = arg.subcommand_matches("rpmdir") { if let Some(matches) = arg.subcommand_matches("rpmdir") {
sys_rpmdir::sync(&db, let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
sysbyshort(&db, matches.value_of("sys").unwrap()), sys_rpmdir::sync(&mut db, sys,
matches.value_of("cat").unwrap(), matches.value_of("cat").unwrap(),
matches.value_of("mirror").unwrap() matches.value_of("mirror").unwrap()
).unwrap_or_else(|e| error!("{}", e)); ).unwrap_or_else(|e| error!("{}", e));
} }
if let Some(matches) = arg.subcommand_matches("rpm") { if let Some(matches) = arg.subcommand_matches("rpm") {
sys_rpm::sync(&db, let sys = sysbyshort(&mut db, matches.value_of("sys").unwrap());
sysbyshort(&db, matches.value_of("sys").unwrap()), sys_rpm::sync(&mut db, sys,
matches.value_of("cat").unwrap(), matches.value_of("cat").unwrap(),
matches.value_of("mirror").unwrap() matches.value_of("mirror").unwrap()
).unwrap_or_else(|e| error!("{}", e)); ).unwrap_or_else(|e| error!("{}", e));

View file

@ -48,23 +48,23 @@ pub struct PkgOpt<'a> {
} }
fn insert_pkg(tr: &postgres::transaction::Transaction, opt: &PkgOpt) -> Option<i32> { fn insert_pkg(tr: &mut postgres::Transaction, opt: &PkgOpt) -> Option<i32> {
let pkginfo = format!("sys {} / {} / {} - {} @ {:?} @ {}", opt.sys, opt.cat, opt.pkg, opt.ver, opt.date, opt.file.path); let pkginfo = format!("sys {} / {} / {} - {} @ {:?} @ {}", opt.sys, opt.cat, opt.pkg, opt.ver, opt.date, opt.file.path);
// The ON CONFLICT .. DO UPDATE is used instead of DO NOTHING because in that case the // The ON CONFLICT .. DO UPDATE is used instead of DO NOTHING because in that case the
// RETURNING clause wouldn't give us a package id. // RETURNING clause wouldn't give us a package id.
let q = "INSERT INTO packages (system, category, name) VALUES($1, $2, $3) let q = "INSERT INTO packages (system, category, name) VALUES($1, $2, $3)
ON CONFLICT ON CONSTRAINT packages_system_name_category_key DO UPDATE SET name=$3 RETURNING id"; ON CONFLICT ON CONSTRAINT packages_system_name_category_key DO UPDATE SET name=$3 RETURNING id";
let pkgid: i32 = match tr.query(q, &[&opt.sys, &opt.cat, &opt.pkg]) { let pkgid: i32 = match tr.query_one(q, &[&opt.sys, &opt.cat, &opt.pkg]) {
Err(e) => { Err(e) => {
error!("Can't insert package in database: {}", e); error!("Can't insert package in database: {}", e);
return None; return None;
}, },
Ok(r) => r.get(0).get(0), Ok(r) => r.get(0),
}; };
let q = "SELECT id FROM package_versions WHERE package = $1 AND version = $2"; let q = "SELECT id FROM package_versions WHERE package = $1 AND version = $2";
let res = tr.query(q, &[&pkgid, &opt.ver]).unwrap(); let res = tr.query_opt(q, &[&pkgid, &opt.ver]).unwrap();
let verid : i32; let verid : i32;
@ -73,27 +73,27 @@ fn insert_pkg(tr: &postgres::transaction::Transaction, opt: &PkgOpt) -> Option<i
_ => "1980-01-01", // Placeholder _ => "1980-01-01", // Placeholder
}; };
if res.is_empty() { if res.is_none() {
let q = "INSERT INTO package_versions (package, version, released, arch) VALUES($1, $2, $3::text::date, $4) RETURNING id"; let q = "INSERT INTO package_versions (package, version, released, arch) VALUES($1, $2, $3::text::date, $4) RETURNING id";
verid = tr.query(q, &[&pkgid, &opt.ver, &date, &opt.arch]).unwrap().get(0).get(0); verid = tr.query_one(q, &[&pkgid, &opt.ver, &date, &opt.arch]).unwrap().get(0);
info!("New package pkgid {} verid {}, {}", pkgid, verid, pkginfo); info!("New package pkgid {} verid {}, {}", pkgid, verid, pkginfo);
Some(verid) Some(verid)
} else if opt.force { } else if opt.force {
// XXX: Should we update released & arch here? // XXX: Should we update released & arch here?
verid = res.get(0).get(0); verid = res?.get(0);
info!("Overwriting package pkgid {} verid {}, {}", pkgid, verid, pkginfo); info!("Overwriting package pkgid {} verid {}, {}", pkgid, verid, pkginfo);
tr.query("DELETE FROM man WHERE package = $1", &[&verid]).unwrap(); tr.query("DELETE FROM man WHERE package = $1", &[&verid]).unwrap();
Some(verid) Some(verid)
} else { } else {
debug!("Package already in database, pkgid {} verid {}, {}", pkgid, res.get(0).get::<usize,i32>(0), pkginfo); debug!("Package already in database, pkgid {} verid {}, {}", pkgid, res?.get::<usize,i32>(0), pkginfo);
None None
} }
} }
fn insert_man_row(tr: &postgres::GenericConnection, verid: i32, path: &str, enc: &str, hash: &[u8]) { fn insert_man_row<T: postgres::GenericClient>(tr: &mut T, verid: i32, path: &str, enc: &str, hash: &[u8]) {
let (name, sect, locale) = man::parse_path(path).unwrap(); let (name, sect, locale) = man::parse_path(path).unwrap();
let locale = if locale == "" { None } else { Some(locale) }; let locale = if locale == "" { None } else { Some(locale) };
if let Err(e) = tr.execute( if let Err(e) = tr.execute(
@ -107,7 +107,7 @@ fn insert_man_row(tr: &postgres::GenericConnection, verid: i32, path: &str, enc:
} }
fn insert_man(tr: &postgres::GenericConnection, verid: i32, paths: &[&str], ent: &mut Read) { fn insert_man<T: postgres::GenericClient>(tr: &mut T, verid: i32, paths: &[&str], ent: &mut Read) {
let (dig, enc, mut cont) = match man::decode(paths, ent) { let (dig, enc, mut cont) = match man::decode(paths, ent) {
Err(e) => { error!("Error decoding {}: {}", paths[0], e); return }, Err(e) => { error!("Error decoding {}: {}", paths[0], e); return },
Ok(x) => x, Ok(x) => x,
@ -131,14 +131,16 @@ fn insert_man(tr: &postgres::GenericConnection, verid: i32, paths: &[&str], ent:
} }
fn insert_link(tr: &postgres::GenericConnection, verid: i32, src: &str, dest: &str) { fn insert_link<T>(tr: &mut T, verid: i32, src: &str, dest: &str) where T: postgres::GenericClient {
let res = tr.query("SELECT hash, encoding FROM man WHERE package = $1 AND filename = '/'||$2", &[&verid, &dest]).unwrap(); let res = match tr.query_opt("SELECT hash, encoding FROM man WHERE package = $1 AND filename = '/'||$2", &[&verid, &dest]).unwrap() {
if res.is_empty() { /* Can happen if man::decode() failed previously. */ None => { /* Can happen if man::decode() failed previously. */
error!("Link to unindexed man page: {} -> {}", src, dest); error!("Link to unindexed man page: {} -> {}", src, dest);
return; return;
} },
let hash: Vec<u8> = res.get(0).get(0); Some(x) => x
let enc: String = res.get(0).get(1); };
let hash: Vec<u8> = res.get(0);
let enc: String = res.get(1);
insert_man_row(tr, verid, src, &enc, &hash); insert_man_row(tr, verid, src, &enc, &hash);
info!("Inserted man link: {} -> {}", src, dest); info!("Inserted man link: {} -> {}", src, dest);
} }
@ -173,19 +175,20 @@ fn with_pkg<F,T>(opt: &mut PkgOpt, cb: F) -> std::io::Result<T>
} }
fn index_pkg(tr: &postgres::GenericConnection, mut opt: PkgOpt, verid: i32) -> std::io::Result<()> { fn index_pkg<T: postgres::GenericClient>(tr: &mut T, mut opt: PkgOpt, verid: i32) -> std::io::Result<()> {
let indexfunc = |paths: &[&str], ent: &mut ArchiveEntry| {
insert_man(tr, verid, paths, ent);
Ok(()) /* Don't propagate errors, continue handling other man pages */
};
let missed = with_pkg(&mut opt, |e, opt| { let missed = with_pkg(&mut opt, |e, opt| {
archread::FileList::read(e, man::ismanpath, |ent| opt.date.update(ent), &indexfunc) archread::FileList::read(e, man::ismanpath, |ent| opt.date.update(ent), |paths, ent| {
insert_man(tr, verid, paths, ent);
Ok(())
})
})?.links(|src, dest| { insert_link(tr, verid, src, dest) }); })?.links(|src, dest| { insert_link(tr, verid, src, dest) });
if let Some(missed) = missed { if let Some(missed) = missed {
warn!("Some links were missed, reading package again"); warn!("Some links were missed, reading package again");
with_pkg(&mut opt, |e, _| { missed.read(e, indexfunc) })? with_pkg(&mut opt, |e, _| { missed.read(e, |paths, ent| {
insert_man(tr, verid, paths, ent);
Ok(())
}) })?
} }
match opt.date { match opt.date {
@ -201,21 +204,20 @@ fn index_pkg(tr: &postgres::GenericConnection, mut opt: PkgOpt, verid: i32) -> s
} }
pub fn pkg(conn: &postgres::GenericConnection, opt: PkgOpt) { pub fn pkg<T>(conn: &mut T, opt: PkgOpt) where T: postgres::GenericClient {
let tr = conn.transaction().unwrap(); let mut tr = conn.transaction().unwrap();
tr.set_rollback();
let verid = match insert_pkg(&tr, &opt) { Some(x) => x, None => return }; let verid = match insert_pkg(&mut tr, &opt) { Some(x) => x, None => return };
if unsafe { DRY_RUN } { if unsafe { DRY_RUN } {
return; return;
} }
match index_pkg(&tr, opt, verid) { if let Err(e) = index_pkg(&mut tr, opt, verid) {
Err(e) => error!("Error reading package: {}", e), error!("Error reading package: {}", e);
Ok(_) => tr.set_commit() return;
} }
if let Err(e) = tr.finish() { if let Err(e) = tr.commit() {
error!("Error finishing transaction: {}", e); error!("Error finishing transaction: {}", e);
} }
} }

View file

@ -75,7 +75,7 @@ fn read_desc(rd: &mut archive::ArchiveEntry) -> Result<Option<Meta>> {
} }
pub fn sync(pg: &postgres::GenericConnection, sys: i32, mirror: &str, repo: &str) { pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, mirror: &str, repo: &str) {
info!("Reading packages from {} {}", mirror, repo); info!("Reading packages from {} {}", mirror, repo);
let path = format!("{}/{}/os/x86_64/{1:}.files.tar.gz", mirror, repo); let path = format!("{}/{}/os/x86_64/{1:}.files.tar.gz", mirror, repo);

View file

@ -56,7 +56,7 @@ struct Pkg {
} }
fn handlepkg(pg: &postgres::GenericConnection, sys: i32, mirror: &str, manpkgs: &HashSet<String>, pkg: &Pkg) { fn handlepkg<T: postgres::GenericClient>(pg: &mut T, sys: i32, mirror: &str, manpkgs: &HashSet<String>, pkg: &Pkg) {
let name = match pkg.name { Some(ref x) => x, None => return }; let name = match pkg.name { Some(ref x) => x, None => return };
if manpkgs.len() > 0 && !manpkgs.contains(name) { if manpkgs.len() > 0 && !manpkgs.contains(name) {
return return
@ -94,7 +94,7 @@ fn handlepkg(pg: &postgres::GenericConnection, sys: i32, mirror: &str, manpkgs:
} }
pub fn sync(pg: &postgres::GenericConnection, sys: i32, mirror: &str, contents: Option<open::Path>, packages: open::Path) { pub fn sync<T: postgres::GenericClient >(pg: &mut T, sys: i32, mirror: &str, contents: Option<open::Path>, packages: open::Path) {
let manpkgs = match get_contents(contents) { let manpkgs = match get_contents(contents) {
Err(e) => { error!("Can't read {}: {}", contents.unwrap().path, e); return }, Err(e) => { error!("Can't read {}: {}", contents.unwrap().path, e); return },
Ok(x) => x, Ok(x) => x,

View file

@ -26,7 +26,7 @@ use pkg;
// 'pear-PHPUnit version 1.3.3', because there is a 'pear' package in 'Latest' but no // 'pear-PHPUnit version 1.3.3', because there is a 'pear' package in 'Latest' but no
// 'pear-PHPUnit'. This is handled with a static list of package names to add to the 'pkgs' list, // 'pear-PHPUnit'. This is handled with a static list of package names to add to the 'pkgs' list,
// see EXTRA_PKGS below. // see EXTRA_PKGS below.
pub fn sync(pg: &postgres::GenericConnection, sys: i32, arch: &str, mirror: &str) -> Result<()> { pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, arch: &str, mirror: &str) -> Result<()> {
let path = format!("{}Latest/", mirror); let path = format!("{}Latest/", mirror);
let mut pkgs : Vec<String> = open::Path{path: &path, cache: true, canbelocal: false} let mut pkgs : Vec<String> = open::Path{path: &path, cache: true, canbelocal: false}
.dirlist()?.into_iter() .dirlist()?.into_iter()

View file

@ -19,7 +19,7 @@ fn getpkgsite(mut ent: Option<ArchiveEntry>) -> Result<ArchiveEntry> {
} }
pub fn sync(pg: &postgres::GenericConnection, sys: i32, mirror: &str) -> Result<()> { pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, mirror: &str) -> Result<()> {
let path = format!("{}packagesite.txz", mirror); let path = format!("{}packagesite.txz", mirror);
let mut rd = open::Path{path: &path, cache: true, canbelocal: false}.open()?; let mut rd = open::Path{path: &path, cache: true, canbelocal: false}.open()?;

View file

@ -173,7 +173,7 @@ fn repomd(url: String) -> Result<(String,String),Box<Error>> {
} }
pub fn sync(pg: &postgres::GenericConnection, sys: i32, cat: &str, mirror: &str) -> Result<(),Box<Error>> { pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, cat: &str, mirror: &str) -> Result<(),Box<Error>> {
let(primary, filelists) = repomd(format!("{}repodata/repomd.xml", mirror))?; let(primary, filelists) = repomd(format!("{}repodata/repomd.xml", mirror))?;
let mut pkgswithman = HashSet::new(); let mut pkgswithman = HashSet::new();

View file

@ -5,7 +5,7 @@ use postgres;
use open; use open;
use pkg; use pkg;
pub fn sync(pg: &postgres::GenericConnection, sys: i32, cat: &str, mirror: &str) -> Result<()> { pub fn sync<T: postgres::GenericClient>(pg: &mut T, sys: i32, cat: &str, mirror: &str) -> Result<()> {
let pkgs : Vec<String> = open::Path{path: mirror, cache: true, canbelocal: false} let pkgs : Vec<String> = open::Path{path: mirror, cache: true, canbelocal: false}
.dirlist()?.into_iter() .dirlist()?.into_iter()
.filter_map(|(n,d)| if d { None } else { Some(n) }) .filter_map(|(n,d)| if d { None } else { Some(n) })

60
web/Cargo.lock generated
View file

@ -2,74 +2,46 @@
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.3" version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [ dependencies = [
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr",
] ]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.3.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.2.0" version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.1.6" version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [ dependencies = [
"aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "aho-corasick",
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr",
"regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.6" version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ucd-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "utf8-ranges"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]] [[package]]
name = "web" name = "web"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static",
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex",
] ]
[metadata]
"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58"
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"