pub struct Loader<'a> { /* private fields */ }
Expand description
Perform a streaming load of only relevant database tables.
§Example
This example loads just the version_downloads.csv table, in which each row is the download count for a single version of a single crate on a single day. We do not store the rows individually in memory but instead stream from the csv to accumulate just a total count per day across all crates, which requires far less memory.
use chrono::Utc;
use db_dump::Date;
use std::collections::BTreeMap as Map;
fn main() -> db_dump::Result<()> {
let mut downloads = Map::<Date<Utc>, u64>::new();
db_dump::Loader::new()
.version_downloads(|row| {
*downloads.entry(row.date).or_default() += row.downloads;
})
.load("./db-dump.tar.gz")?;
for (date, count) in downloads {
println!("{},{}", date, count);
}
Ok(())
}
Implementations§
Source§impl<'a> Loader<'a>
impl<'a> Loader<'a>
Sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
examples/total-downloads.rs (line 12)
10fn main() -> db_dump::Result<()> {
11 let mut downloads = Map::<Date<Utc>, u64>::new();
12 db_dump::Loader::new()
13 .version_downloads(|row| {
14 *downloads.entry(row.date).or_default() += row.downloads;
15 })
16 .load("./db-dump.tar.gz")?;
17
18 for (date, count) in downloads {
19 println!("{},{}", date, count);
20 }
21
22 Ok(())
23}
More examples
examples/crate-downloads.rs (line 15)
11fn main() -> db_dump::Result<()> {
12 let mut crate_id = None;
13 let mut versions = Vec::new();
14 let mut version_downloads = Vec::new();
15 db_dump::Loader::new()
16 .crates(|row| {
17 if row.name == CRATE {
18 crate_id = Some(row.id);
19 }
20 })
21 .versions(|row| versions.push(row))
22 .version_downloads(|row| version_downloads.push(row))
23 .load("./db-dump.tar.gz")?;
24
25 // Crate id of the crate we care about.
26 let crate_id = crate_id.expect("no such crate");
27
28 // Set of all version ids corresponding to that crate.
29 let mut version_ids = Set::new();
30 for version in versions {
31 if version.crate_id == crate_id {
32 version_ids.insert(version.id);
33 }
34 }
35
36 // Add up downloads across all version of the crate by day.
37 let mut downloads = Map::<Date<Utc>, u64>::new();
38 for stat in version_downloads {
39 if version_ids.contains(&stat.version_id) {
40 *downloads.entry(stat.date).or_default() += stat.downloads;
41 }
42 }
43
44 for (date, count) in downloads {
45 println!("{},{}", date, count);
46 }
47
48 Ok(())
49}
examples/user-downloads.rs (line 23)
18fn main() -> db_dump::Result<()> {
19 let mut user_id = None;
20 let mut crate_owners = Vec::new();
21 let mut versions = Vec::new();
22 let mut version_downloads = Vec::new();
23 db_dump::Loader::new()
24 .users(|row| {
25 if row.gh_login == USER {
26 user_id = Some(row.id);
27 }
28 })
29 .crate_owners(|row| crate_owners.push(row))
30 .versions(|row| versions.push(row))
31 .version_downloads(|row| version_downloads.push(row))
32 .load("./db-dump.tar.gz")?;
33
34 // User id of the crate author we care about.
35 let user_id = user_id.expect("no such user");
36
37 // Set of crate ids currently owned by that user.
38 let mut their_crates = Set::new();
39 for crate_owner in crate_owners {
40 if crate_owner.owner_id == user_id {
41 their_crates.insert(crate_owner.crate_id);
42 }
43 }
44
45 // Set of version ids of all of those crates.
46 let mut their_versions = Set::new();
47 for version in versions {
48 if their_crates.contains(&version.crate_id) {
49 their_versions.insert(version.id);
50 }
51 }
52
53 // Add up downloads across that user's crates, as well as total downloads of
54 // all crates.
55 let mut downloads = Map::<Date<Utc>, Downloads>::new();
56 for stat in version_downloads {
57 let entry = downloads.entry(stat.date).or_default();
58 entry.all += stat.downloads;
59 if their_versions.contains(&stat.version_id) {
60 entry.theirs += stat.downloads;
61 }
62 }
63
64 // Print user's downloads as a fraction of total crates.io downloads by day.
65 for (date, downloads) in downloads {
66 if downloads.theirs > 0 {
67 println!(
68 "{},{}",
69 date,
70 downloads.theirs as f64 / downloads.all as f64,
71 );
72 }
73 }
74
75 Ok(())
76}
examples/user-dependencies.rs (line 19)
11fn main() -> db_dump::Result<()> {
12 // Map of crate id to the most recently published version of that crate.
13 let mut most_recent = Map::new();
14
15 let mut user_id = None;
16 let mut crates = 0;
17 let mut crate_owners = Vec::new();
18 let mut dependencies = Vec::new();
19 db_dump::Loader::new()
20 .users(|row| {
21 if row.gh_login == USER {
22 user_id = Some(row.id);
23 }
24 })
25 .crates(|_row| crates += 1)
26 .crate_owners(|row| crate_owners.push(row))
27 .dependencies(|row| dependencies.push(row))
28 .versions(|row| match most_recent.entry(row.crate_id) {
29 Entry::Vacant(entry) => {
30 entry.insert(row);
31 }
32 Entry::Occupied(mut entry) => {
33 if row.created_at > entry.get().created_at {
34 entry.insert(row);
35 }
36 }
37 })
38 .load("./db-dump.tar.gz")?;
39
40 // User id of the crate author we care about.
41 let user_id = user_id.expect("no such user");
42
43 // Set of crate ids currently owned by that user.
44 let mut their_crates = Set::new();
45 for crate_owner in crate_owners {
46 if crate_owner.owner_id == user_id {
47 their_crates.insert(crate_owner.crate_id);
48 }
49 }
50
51 // Set of version ids which are the most recently published of their crate.
52 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54 // Set of version ids which depend directly on at least one crate by the
55 // user.
56 let mut dep_on_them = Set::new();
57 for dep in dependencies {
58 if their_crates.contains(&dep.crate_id) {
59 dep_on_them.insert(dep.version_id);
60 }
61 }
62
63 // Number of crates whose most recent version depends on at least one crate
64 // by the user.
65 let result = dep_on_them.intersection(&most_recent).count();
66
67 println!(
68 "{} / {} = {:.1}%",
69 result,
70 crates,
71 100.0 * result as f64 / crates as f64,
72 );
73
74 Ok(())
75}
examples/top-crates.rs (line 20)
13fn main() -> db_dump::Result<()> {
14 // Map of crate id to the most recently published version of that crate.
15 let mut most_recent = Map::new();
16
17 let mut crates = Set::new();
18 let mut crate_owners = Vec::new();
19 let mut dependencies = Vec::new();
20 db_dump::Loader::new()
21 .crates(|row| {
22 crates.insert(row);
23 })
24 .crate_owners(|row| crate_owners.push(row))
25 .dependencies(|row| dependencies.push(row))
26 .versions(|row| match most_recent.entry(row.crate_id) {
27 Entry::Vacant(entry) => {
28 entry.insert(row);
29 }
30 Entry::Occupied(mut entry) => {
31 if row.created_at > entry.get().created_at {
32 entry.insert(row);
33 }
34 }
35 })
36 .load("./db-dump.tar.gz")?;
37
38 // Set of version ids which are the most recently published of their crate.
39 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41 // Set of (version id, dependency crate id) pairs to avoid double-counting
42 // cases where a crate has both a normal dependency and dev-dependency or
43 // build-dependency on the same dependency crate.
44 let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46 // Map of crate id to how many other crates' most recent version depends on
47 // that crate.
48 let mut count = Map::<CrateId, usize>::new();
49 for dep in dependencies {
50 if most_recent.contains(&dep.version_id)
51 && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52 {
53 *count.entry(dep.crate_id).or_default() += 1;
54 }
55 }
56
57 // Quickselect and sort the top N crates by reverse dependency count.
58 let mut sort = Vec::from_iter(count);
59 let sort_by_count = |&(_crate, count): &_| Reverse(count);
60 sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61 sort[..N].sort_unstable_by_key(sort_by_count);
62
63 for (id, count) in sort.iter().take(N) {
64 let crate_name = &crates.get(id).unwrap().name;
65 println!("{},{}", crate_name, count);
66 }
67
68 Ok(())
69}
examples/user-dependencies-graph.rs (line 15)
10fn main() -> db_dump::Result<()> {
11 let mut user_id = None;
12 let mut crate_owners = Vec::new();
13 let mut dependencies = Map::new();
14 let mut versions = Vec::new();
15 db_dump::Loader::new()
16 .users(|row| {
17 if row.gh_login == USER {
18 user_id = Some(row.id);
19 }
20 })
21 .crate_owners(|row| crate_owners.push(row))
22 .dependencies(|row| {
23 dependencies
24 .entry(row.version_id)
25 .or_insert_with(Vec::new)
26 .push(row);
27 })
28 .versions(|row| {
29 if !row.yanked {
30 versions.push(row);
31 }
32 })
33 .load("./db-dump.tar.gz")?;
34
35 // User id of the crate author we care about.
36 let user_id = user_id.expect("no such user");
37
38 // Set of crate ids currently owned by that user.
39 let mut their_crates = Set::new();
40 for crate_owner in crate_owners {
41 if crate_owner.owner_id == user_id {
42 their_crates.insert(crate_owner.crate_id);
43 }
44 }
45
46 let mut total_deps = 0usize;
47 let mut their_deps = 0usize;
48 let mut last_printed_ratio = 0.0..=0.0;
49 let mut latest_version = Map::new();
50
51 versions.sort_by_key(|v| v.created_at);
52
53 for version in versions {
54 let no_deps = Vec::new();
55 if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56 for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57 total_deps -= 1;
58 their_deps -= their_crates.contains(&dep.crate_id) as usize;
59 }
60 }
61 for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62 total_deps += 1;
63 their_deps += their_crates.contains(&dep.crate_id) as usize;
64 }
65 if total_deps != 0 {
66 let ratio = their_deps as f64 / total_deps as f64;
67 if !last_printed_ratio.contains(&ratio) {
68 println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69 last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70 }
71 }
72 }
73
74 eprintln!(
75 "{} / {} ({:.02}%)",
76 their_deps,
77 total_deps,
78 (their_deps as f64 / total_deps as f64) * 100.0,
79 );
80 Ok(())
81}
Additional examples can be found in:
pub fn categories(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn crate_downloads(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
Sourcepub fn crate_owners(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn crate_owners(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
Examples found in repository?
examples/user-downloads.rs (line 29)
18fn main() -> db_dump::Result<()> {
19 let mut user_id = None;
20 let mut crate_owners = Vec::new();
21 let mut versions = Vec::new();
22 let mut version_downloads = Vec::new();
23 db_dump::Loader::new()
24 .users(|row| {
25 if row.gh_login == USER {
26 user_id = Some(row.id);
27 }
28 })
29 .crate_owners(|row| crate_owners.push(row))
30 .versions(|row| versions.push(row))
31 .version_downloads(|row| version_downloads.push(row))
32 .load("./db-dump.tar.gz")?;
33
34 // User id of the crate author we care about.
35 let user_id = user_id.expect("no such user");
36
37 // Set of crate ids currently owned by that user.
38 let mut their_crates = Set::new();
39 for crate_owner in crate_owners {
40 if crate_owner.owner_id == user_id {
41 their_crates.insert(crate_owner.crate_id);
42 }
43 }
44
45 // Set of version ids of all of those crates.
46 let mut their_versions = Set::new();
47 for version in versions {
48 if their_crates.contains(&version.crate_id) {
49 their_versions.insert(version.id);
50 }
51 }
52
53 // Add up downloads across that user's crates, as well as total downloads of
54 // all crates.
55 let mut downloads = Map::<Date<Utc>, Downloads>::new();
56 for stat in version_downloads {
57 let entry = downloads.entry(stat.date).or_default();
58 entry.all += stat.downloads;
59 if their_versions.contains(&stat.version_id) {
60 entry.theirs += stat.downloads;
61 }
62 }
63
64 // Print user's downloads as a fraction of total crates.io downloads by day.
65 for (date, downloads) in downloads {
66 if downloads.theirs > 0 {
67 println!(
68 "{},{}",
69 date,
70 downloads.theirs as f64 / downloads.all as f64,
71 );
72 }
73 }
74
75 Ok(())
76}
More examples
examples/user-dependencies.rs (line 26)
11fn main() -> db_dump::Result<()> {
12 // Map of crate id to the most recently published version of that crate.
13 let mut most_recent = Map::new();
14
15 let mut user_id = None;
16 let mut crates = 0;
17 let mut crate_owners = Vec::new();
18 let mut dependencies = Vec::new();
19 db_dump::Loader::new()
20 .users(|row| {
21 if row.gh_login == USER {
22 user_id = Some(row.id);
23 }
24 })
25 .crates(|_row| crates += 1)
26 .crate_owners(|row| crate_owners.push(row))
27 .dependencies(|row| dependencies.push(row))
28 .versions(|row| match most_recent.entry(row.crate_id) {
29 Entry::Vacant(entry) => {
30 entry.insert(row);
31 }
32 Entry::Occupied(mut entry) => {
33 if row.created_at > entry.get().created_at {
34 entry.insert(row);
35 }
36 }
37 })
38 .load("./db-dump.tar.gz")?;
39
40 // User id of the crate author we care about.
41 let user_id = user_id.expect("no such user");
42
43 // Set of crate ids currently owned by that user.
44 let mut their_crates = Set::new();
45 for crate_owner in crate_owners {
46 if crate_owner.owner_id == user_id {
47 their_crates.insert(crate_owner.crate_id);
48 }
49 }
50
51 // Set of version ids which are the most recently published of their crate.
52 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54 // Set of version ids which depend directly on at least one crate by the
55 // user.
56 let mut dep_on_them = Set::new();
57 for dep in dependencies {
58 if their_crates.contains(&dep.crate_id) {
59 dep_on_them.insert(dep.version_id);
60 }
61 }
62
63 // Number of crates whose most recent version depends on at least one crate
64 // by the user.
65 let result = dep_on_them.intersection(&most_recent).count();
66
67 println!(
68 "{} / {} = {:.1}%",
69 result,
70 crates,
71 100.0 * result as f64 / crates as f64,
72 );
73
74 Ok(())
75}
examples/top-crates.rs (line 24)
13fn main() -> db_dump::Result<()> {
14 // Map of crate id to the most recently published version of that crate.
15 let mut most_recent = Map::new();
16
17 let mut crates = Set::new();
18 let mut crate_owners = Vec::new();
19 let mut dependencies = Vec::new();
20 db_dump::Loader::new()
21 .crates(|row| {
22 crates.insert(row);
23 })
24 .crate_owners(|row| crate_owners.push(row))
25 .dependencies(|row| dependencies.push(row))
26 .versions(|row| match most_recent.entry(row.crate_id) {
27 Entry::Vacant(entry) => {
28 entry.insert(row);
29 }
30 Entry::Occupied(mut entry) => {
31 if row.created_at > entry.get().created_at {
32 entry.insert(row);
33 }
34 }
35 })
36 .load("./db-dump.tar.gz")?;
37
38 // Set of version ids which are the most recently published of their crate.
39 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41 // Set of (version id, dependency crate id) pairs to avoid double-counting
42 // cases where a crate has both a normal dependency and dev-dependency or
43 // build-dependency on the same dependency crate.
44 let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46 // Map of crate id to how many other crates' most recent version depends on
47 // that crate.
48 let mut count = Map::<CrateId, usize>::new();
49 for dep in dependencies {
50 if most_recent.contains(&dep.version_id)
51 && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52 {
53 *count.entry(dep.crate_id).or_default() += 1;
54 }
55 }
56
57 // Quickselect and sort the top N crates by reverse dependency count.
58 let mut sort = Vec::from_iter(count);
59 let sort_by_count = |&(_crate, count): &_| Reverse(count);
60 sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61 sort[..N].sort_unstable_by_key(sort_by_count);
62
63 for (id, count) in sort.iter().take(N) {
64 let crate_name = &crates.get(id).unwrap().name;
65 println!("{},{}", crate_name, count);
66 }
67
68 Ok(())
69}
examples/user-dependencies-graph.rs (line 21)
10fn main() -> db_dump::Result<()> {
11 let mut user_id = None;
12 let mut crate_owners = Vec::new();
13 let mut dependencies = Map::new();
14 let mut versions = Vec::new();
15 db_dump::Loader::new()
16 .users(|row| {
17 if row.gh_login == USER {
18 user_id = Some(row.id);
19 }
20 })
21 .crate_owners(|row| crate_owners.push(row))
22 .dependencies(|row| {
23 dependencies
24 .entry(row.version_id)
25 .or_insert_with(Vec::new)
26 .push(row);
27 })
28 .versions(|row| {
29 if !row.yanked {
30 versions.push(row);
31 }
32 })
33 .load("./db-dump.tar.gz")?;
34
35 // User id of the crate author we care about.
36 let user_id = user_id.expect("no such user");
37
38 // Set of crate ids currently owned by that user.
39 let mut their_crates = Set::new();
40 for crate_owner in crate_owners {
41 if crate_owner.owner_id == user_id {
42 their_crates.insert(crate_owner.crate_id);
43 }
44 }
45
46 let mut total_deps = 0usize;
47 let mut their_deps = 0usize;
48 let mut last_printed_ratio = 0.0..=0.0;
49 let mut latest_version = Map::new();
50
51 versions.sort_by_key(|v| v.created_at);
52
53 for version in versions {
54 let no_deps = Vec::new();
55 if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56 for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57 total_deps -= 1;
58 their_deps -= their_crates.contains(&dep.crate_id) as usize;
59 }
60 }
61 for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62 total_deps += 1;
63 their_deps += their_crates.contains(&dep.crate_id) as usize;
64 }
65 if total_deps != 0 {
66 let ratio = their_deps as f64 / total_deps as f64;
67 if !last_printed_ratio.contains(&ratio) {
68 println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69 last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70 }
71 }
72 }
73
74 eprintln!(
75 "{} / {} ({:.02}%)",
76 their_deps,
77 total_deps,
78 (their_deps as f64 / total_deps as f64) * 100.0,
79 );
80 Ok(())
81}
Sourcepub fn crates(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn crates(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
Examples found in repository?
examples/crate-downloads.rs (lines 16-20)
11fn main() -> db_dump::Result<()> {
12 let mut crate_id = None;
13 let mut versions = Vec::new();
14 let mut version_downloads = Vec::new();
15 db_dump::Loader::new()
16 .crates(|row| {
17 if row.name == CRATE {
18 crate_id = Some(row.id);
19 }
20 })
21 .versions(|row| versions.push(row))
22 .version_downloads(|row| version_downloads.push(row))
23 .load("./db-dump.tar.gz")?;
24
25 // Crate id of the crate we care about.
26 let crate_id = crate_id.expect("no such crate");
27
28 // Set of all version ids corresponding to that crate.
29 let mut version_ids = Set::new();
30 for version in versions {
31 if version.crate_id == crate_id {
32 version_ids.insert(version.id);
33 }
34 }
35
36 // Add up downloads across all version of the crate by day.
37 let mut downloads = Map::<Date<Utc>, u64>::new();
38 for stat in version_downloads {
39 if version_ids.contains(&stat.version_id) {
40 *downloads.entry(stat.date).or_default() += stat.downloads;
41 }
42 }
43
44 for (date, count) in downloads {
45 println!("{},{}", date, count);
46 }
47
48 Ok(())
49}
More examples
examples/user-dependencies.rs (line 25)
11fn main() -> db_dump::Result<()> {
12 // Map of crate id to the most recently published version of that crate.
13 let mut most_recent = Map::new();
14
15 let mut user_id = None;
16 let mut crates = 0;
17 let mut crate_owners = Vec::new();
18 let mut dependencies = Vec::new();
19 db_dump::Loader::new()
20 .users(|row| {
21 if row.gh_login == USER {
22 user_id = Some(row.id);
23 }
24 })
25 .crates(|_row| crates += 1)
26 .crate_owners(|row| crate_owners.push(row))
27 .dependencies(|row| dependencies.push(row))
28 .versions(|row| match most_recent.entry(row.crate_id) {
29 Entry::Vacant(entry) => {
30 entry.insert(row);
31 }
32 Entry::Occupied(mut entry) => {
33 if row.created_at > entry.get().created_at {
34 entry.insert(row);
35 }
36 }
37 })
38 .load("./db-dump.tar.gz")?;
39
40 // User id of the crate author we care about.
41 let user_id = user_id.expect("no such user");
42
43 // Set of crate ids currently owned by that user.
44 let mut their_crates = Set::new();
45 for crate_owner in crate_owners {
46 if crate_owner.owner_id == user_id {
47 their_crates.insert(crate_owner.crate_id);
48 }
49 }
50
51 // Set of version ids which are the most recently published of their crate.
52 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54 // Set of version ids which depend directly on at least one crate by the
55 // user.
56 let mut dep_on_them = Set::new();
57 for dep in dependencies {
58 if their_crates.contains(&dep.crate_id) {
59 dep_on_them.insert(dep.version_id);
60 }
61 }
62
63 // Number of crates whose most recent version depends on at least one crate
64 // by the user.
65 let result = dep_on_them.intersection(&most_recent).count();
66
67 println!(
68 "{} / {} = {:.1}%",
69 result,
70 crates,
71 100.0 * result as f64 / crates as f64,
72 );
73
74 Ok(())
75}
examples/top-crates.rs (lines 21-23)
13fn main() -> db_dump::Result<()> {
14 // Map of crate id to the most recently published version of that crate.
15 let mut most_recent = Map::new();
16
17 let mut crates = Set::new();
18 let mut crate_owners = Vec::new();
19 let mut dependencies = Vec::new();
20 db_dump::Loader::new()
21 .crates(|row| {
22 crates.insert(row);
23 })
24 .crate_owners(|row| crate_owners.push(row))
25 .dependencies(|row| dependencies.push(row))
26 .versions(|row| match most_recent.entry(row.crate_id) {
27 Entry::Vacant(entry) => {
28 entry.insert(row);
29 }
30 Entry::Occupied(mut entry) => {
31 if row.created_at > entry.get().created_at {
32 entry.insert(row);
33 }
34 }
35 })
36 .load("./db-dump.tar.gz")?;
37
38 // Set of version ids which are the most recently published of their crate.
39 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41 // Set of (version id, dependency crate id) pairs to avoid double-counting
42 // cases where a crate has both a normal dependency and dev-dependency or
43 // build-dependency on the same dependency crate.
44 let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46 // Map of crate id to how many other crates' most recent version depends on
47 // that crate.
48 let mut count = Map::<CrateId, usize>::new();
49 for dep in dependencies {
50 if most_recent.contains(&dep.version_id)
51 && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52 {
53 *count.entry(dep.crate_id).or_default() += 1;
54 }
55 }
56
57 // Quickselect and sort the top N crates by reverse dependency count.
58 let mut sort = Vec::from_iter(count);
59 let sort_by_count = |&(_crate, count): &_| Reverse(count);
60 sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61 sort[..N].sort_unstable_by_key(sort_by_count);
62
63 for (id, count) in sort.iter().take(N) {
64 let crate_name = &crates.get(id).unwrap().name;
65 println!("{},{}", crate_name, count);
66 }
67
68 Ok(())
69}
examples/industry-coefficient.rs (lines 25-27)
20fn main() -> db_dump::Result<()> {
21 let mut crates: Map<CrateId, String> = Map::new();
22 let mut versions: Map<VersionId, CrateId> = Map::new();
23 let mut version_downloads = Vec::new();
24 db_dump::Loader::new()
25 .crates(|row| {
26 crates.insert(row.id, row.name);
27 })
28 .versions(|row| {
29 versions.insert(row.id, row.crate_id);
30 })
31 .version_downloads(|row| version_downloads.push(row))
32 .load("./db-dump.tar.gz")?;
33
34 let max_date = version_downloads.iter().map(|row| row.date).max().unwrap();
35 let start_date = max_date - TimeDelta::try_weeks(6).unwrap();
36
37 // Add up downloads by crate by date
38 let mut downloads: Map<CrateId, Downloads> = Map::new();
39 for row in version_downloads {
40 // Deliberately cut out the largest date in the db-dump, because the
41 // data is partial.
42 if row.date >= start_date && row.date < max_date {
43 let crate_id = versions[&row.version_id];
44 let downloads = downloads.entry(crate_id).or_insert_with(Downloads::default);
45 match row.date.weekday() {
46 Weekday::Tue | Weekday::Wed | Weekday::Thu => downloads.weekday += row.downloads,
47 Weekday::Sat | Weekday::Sun => downloads.weekend += row.downloads,
48 // Disregard these to reduce some boundary effect from
49 // downloaders not being perfectly aligned with UTC.
50 Weekday::Mon | Weekday::Fri => {}
51 }
52 }
53 }
54
55 let mut downloads_vec = Vec::new();
56 let mut total = Downloads::default();
57 for (crate_id, downloads) in downloads {
58 total.weekday += downloads.weekday;
59 total.weekend += downloads.weekend;
60 let crate_name = &crates[&crate_id];
61 if downloads.weekend > 0
62 && (downloads.weekday + downloads.weekend >= DOWNLOADS_CUTOFF || crate_name == "cxx")
63 {
64 let coefficient = downloads.weekday as f64 / downloads.weekend as f64;
65 downloads_vec.push((crate_name, coefficient));
66 }
67 }
68
69 let mean = total.weekday as f64 / total.weekend as f64;
70 downloads_vec.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
71
72 for (crate_name, coefficient) in downloads_vec {
73 println!("{:>36} {:+.4}", crate_name, coefficient - mean);
74 }
75
76 Ok(())
77}
pub fn crates_categories(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn crates_keywords(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn default_versions(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
Sourcepub fn dependencies(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn dependencies(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
Examples found in repository?
examples/user-dependencies.rs (line 27)
11fn main() -> db_dump::Result<()> {
12 // Map of crate id to the most recently published version of that crate.
13 let mut most_recent = Map::new();
14
15 let mut user_id = None;
16 let mut crates = 0;
17 let mut crate_owners = Vec::new();
18 let mut dependencies = Vec::new();
19 db_dump::Loader::new()
20 .users(|row| {
21 if row.gh_login == USER {
22 user_id = Some(row.id);
23 }
24 })
25 .crates(|_row| crates += 1)
26 .crate_owners(|row| crate_owners.push(row))
27 .dependencies(|row| dependencies.push(row))
28 .versions(|row| match most_recent.entry(row.crate_id) {
29 Entry::Vacant(entry) => {
30 entry.insert(row);
31 }
32 Entry::Occupied(mut entry) => {
33 if row.created_at > entry.get().created_at {
34 entry.insert(row);
35 }
36 }
37 })
38 .load("./db-dump.tar.gz")?;
39
40 // User id of the crate author we care about.
41 let user_id = user_id.expect("no such user");
42
43 // Set of crate ids currently owned by that user.
44 let mut their_crates = Set::new();
45 for crate_owner in crate_owners {
46 if crate_owner.owner_id == user_id {
47 their_crates.insert(crate_owner.crate_id);
48 }
49 }
50
51 // Set of version ids which are the most recently published of their crate.
52 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54 // Set of version ids which depend directly on at least one crate by the
55 // user.
56 let mut dep_on_them = Set::new();
57 for dep in dependencies {
58 if their_crates.contains(&dep.crate_id) {
59 dep_on_them.insert(dep.version_id);
60 }
61 }
62
63 // Number of crates whose most recent version depends on at least one crate
64 // by the user.
65 let result = dep_on_them.intersection(&most_recent).count();
66
67 println!(
68 "{} / {} = {:.1}%",
69 result,
70 crates,
71 100.0 * result as f64 / crates as f64,
72 );
73
74 Ok(())
75}
More examples
examples/top-crates.rs (line 25)
13fn main() -> db_dump::Result<()> {
14 // Map of crate id to the most recently published version of that crate.
15 let mut most_recent = Map::new();
16
17 let mut crates = Set::new();
18 let mut crate_owners = Vec::new();
19 let mut dependencies = Vec::new();
20 db_dump::Loader::new()
21 .crates(|row| {
22 crates.insert(row);
23 })
24 .crate_owners(|row| crate_owners.push(row))
25 .dependencies(|row| dependencies.push(row))
26 .versions(|row| match most_recent.entry(row.crate_id) {
27 Entry::Vacant(entry) => {
28 entry.insert(row);
29 }
30 Entry::Occupied(mut entry) => {
31 if row.created_at > entry.get().created_at {
32 entry.insert(row);
33 }
34 }
35 })
36 .load("./db-dump.tar.gz")?;
37
38 // Set of version ids which are the most recently published of their crate.
39 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41 // Set of (version id, dependency crate id) pairs to avoid double-counting
42 // cases where a crate has both a normal dependency and dev-dependency or
43 // build-dependency on the same dependency crate.
44 let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46 // Map of crate id to how many other crates' most recent version depends on
47 // that crate.
48 let mut count = Map::<CrateId, usize>::new();
49 for dep in dependencies {
50 if most_recent.contains(&dep.version_id)
51 && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52 {
53 *count.entry(dep.crate_id).or_default() += 1;
54 }
55 }
56
57 // Quickselect and sort the top N crates by reverse dependency count.
58 let mut sort = Vec::from_iter(count);
59 let sort_by_count = |&(_crate, count): &_| Reverse(count);
60 sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61 sort[..N].sort_unstable_by_key(sort_by_count);
62
63 for (id, count) in sort.iter().take(N) {
64 let crate_name = &crates.get(id).unwrap().name;
65 println!("{},{}", crate_name, count);
66 }
67
68 Ok(())
69}
examples/user-dependencies-graph.rs (lines 22-27)
10fn main() -> db_dump::Result<()> {
11 let mut user_id = None;
12 let mut crate_owners = Vec::new();
13 let mut dependencies = Map::new();
14 let mut versions = Vec::new();
15 db_dump::Loader::new()
16 .users(|row| {
17 if row.gh_login == USER {
18 user_id = Some(row.id);
19 }
20 })
21 .crate_owners(|row| crate_owners.push(row))
22 .dependencies(|row| {
23 dependencies
24 .entry(row.version_id)
25 .or_insert_with(Vec::new)
26 .push(row);
27 })
28 .versions(|row| {
29 if !row.yanked {
30 versions.push(row);
31 }
32 })
33 .load("./db-dump.tar.gz")?;
34
35 // User id of the crate author we care about.
36 let user_id = user_id.expect("no such user");
37
38 // Set of crate ids currently owned by that user.
39 let mut their_crates = Set::new();
40 for crate_owner in crate_owners {
41 if crate_owner.owner_id == user_id {
42 their_crates.insert(crate_owner.crate_id);
43 }
44 }
45
46 let mut total_deps = 0usize;
47 let mut their_deps = 0usize;
48 let mut last_printed_ratio = 0.0..=0.0;
49 let mut latest_version = Map::new();
50
51 versions.sort_by_key(|v| v.created_at);
52
53 for version in versions {
54 let no_deps = Vec::new();
55 if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56 for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57 total_deps -= 1;
58 their_deps -= their_crates.contains(&dep.crate_id) as usize;
59 }
60 }
61 for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62 total_deps += 1;
63 their_deps += their_crates.contains(&dep.crate_id) as usize;
64 }
65 if total_deps != 0 {
66 let ratio = their_deps as f64 / total_deps as f64;
67 if !last_printed_ratio.contains(&ratio) {
68 println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69 last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70 }
71 }
72 }
73
74 eprintln!(
75 "{} / {} ({:.02}%)",
76 their_deps,
77 total_deps,
78 (their_deps as f64 / total_deps as f64) * 100.0,
79 );
80 Ok(())
81}
pub fn keywords(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn metadata(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn reserved_crate_names(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn teams(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
Sourcepub fn users(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn users(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
Examples found in repository?
examples/user-downloads.rs (lines 24-28)
18fn main() -> db_dump::Result<()> {
19 let mut user_id = None;
20 let mut crate_owners = Vec::new();
21 let mut versions = Vec::new();
22 let mut version_downloads = Vec::new();
23 db_dump::Loader::new()
24 .users(|row| {
25 if row.gh_login == USER {
26 user_id = Some(row.id);
27 }
28 })
29 .crate_owners(|row| crate_owners.push(row))
30 .versions(|row| versions.push(row))
31 .version_downloads(|row| version_downloads.push(row))
32 .load("./db-dump.tar.gz")?;
33
34 // User id of the crate author we care about.
35 let user_id = user_id.expect("no such user");
36
37 // Set of crate ids currently owned by that user.
38 let mut their_crates = Set::new();
39 for crate_owner in crate_owners {
40 if crate_owner.owner_id == user_id {
41 their_crates.insert(crate_owner.crate_id);
42 }
43 }
44
45 // Set of version ids of all of those crates.
46 let mut their_versions = Set::new();
47 for version in versions {
48 if their_crates.contains(&version.crate_id) {
49 their_versions.insert(version.id);
50 }
51 }
52
53 // Add up downloads across that user's crates, as well as total downloads of
54 // all crates.
55 let mut downloads = Map::<Date<Utc>, Downloads>::new();
56 for stat in version_downloads {
57 let entry = downloads.entry(stat.date).or_default();
58 entry.all += stat.downloads;
59 if their_versions.contains(&stat.version_id) {
60 entry.theirs += stat.downloads;
61 }
62 }
63
64 // Print user's downloads as a fraction of total crates.io downloads by day.
65 for (date, downloads) in downloads {
66 if downloads.theirs > 0 {
67 println!(
68 "{},{}",
69 date,
70 downloads.theirs as f64 / downloads.all as f64,
71 );
72 }
73 }
74
75 Ok(())
76}
More examples
examples/user-dependencies.rs (lines 20-24)
11fn main() -> db_dump::Result<()> {
12 // Map of crate id to the most recently published version of that crate.
13 let mut most_recent = Map::new();
14
15 let mut user_id = None;
16 let mut crates = 0;
17 let mut crate_owners = Vec::new();
18 let mut dependencies = Vec::new();
19 db_dump::Loader::new()
20 .users(|row| {
21 if row.gh_login == USER {
22 user_id = Some(row.id);
23 }
24 })
25 .crates(|_row| crates += 1)
26 .crate_owners(|row| crate_owners.push(row))
27 .dependencies(|row| dependencies.push(row))
28 .versions(|row| match most_recent.entry(row.crate_id) {
29 Entry::Vacant(entry) => {
30 entry.insert(row);
31 }
32 Entry::Occupied(mut entry) => {
33 if row.created_at > entry.get().created_at {
34 entry.insert(row);
35 }
36 }
37 })
38 .load("./db-dump.tar.gz")?;
39
40 // User id of the crate author we care about.
41 let user_id = user_id.expect("no such user");
42
43 // Set of crate ids currently owned by that user.
44 let mut their_crates = Set::new();
45 for crate_owner in crate_owners {
46 if crate_owner.owner_id == user_id {
47 their_crates.insert(crate_owner.crate_id);
48 }
49 }
50
51 // Set of version ids which are the most recently published of their crate.
52 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54 // Set of version ids which depend directly on at least one crate by the
55 // user.
56 let mut dep_on_them = Set::new();
57 for dep in dependencies {
58 if their_crates.contains(&dep.crate_id) {
59 dep_on_them.insert(dep.version_id);
60 }
61 }
62
63 // Number of crates whose most recent version depends on at least one crate
64 // by the user.
65 let result = dep_on_them.intersection(&most_recent).count();
66
67 println!(
68 "{} / {} = {:.1}%",
69 result,
70 crates,
71 100.0 * result as f64 / crates as f64,
72 );
73
74 Ok(())
75}
examples/user-dependencies-graph.rs (lines 16-20)
10fn main() -> db_dump::Result<()> {
11 let mut user_id = None;
12 let mut crate_owners = Vec::new();
13 let mut dependencies = Map::new();
14 let mut versions = Vec::new();
15 db_dump::Loader::new()
16 .users(|row| {
17 if row.gh_login == USER {
18 user_id = Some(row.id);
19 }
20 })
21 .crate_owners(|row| crate_owners.push(row))
22 .dependencies(|row| {
23 dependencies
24 .entry(row.version_id)
25 .or_insert_with(Vec::new)
26 .push(row);
27 })
28 .versions(|row| {
29 if !row.yanked {
30 versions.push(row);
31 }
32 })
33 .load("./db-dump.tar.gz")?;
34
35 // User id of the crate author we care about.
36 let user_id = user_id.expect("no such user");
37
38 // Set of crate ids currently owned by that user.
39 let mut their_crates = Set::new();
40 for crate_owner in crate_owners {
41 if crate_owner.owner_id == user_id {
42 their_crates.insert(crate_owner.crate_id);
43 }
44 }
45
46 let mut total_deps = 0usize;
47 let mut their_deps = 0usize;
48 let mut last_printed_ratio = 0.0..=0.0;
49 let mut latest_version = Map::new();
50
51 versions.sort_by_key(|v| v.created_at);
52
53 for version in versions {
54 let no_deps = Vec::new();
55 if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56 for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57 total_deps -= 1;
58 their_deps -= their_crates.contains(&dep.crate_id) as usize;
59 }
60 }
61 for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62 total_deps += 1;
63 their_deps += their_crates.contains(&dep.crate_id) as usize;
64 }
65 if total_deps != 0 {
66 let ratio = their_deps as f64 / total_deps as f64;
67 if !last_printed_ratio.contains(&ratio) {
68 println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69 last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70 }
71 }
72 }
73
74 eprintln!(
75 "{} / {} ({:.02}%)",
76 their_deps,
77 total_deps,
78 (their_deps as f64 / total_deps as f64) * 100.0,
79 );
80 Ok(())
81}
Sourcepub fn version_downloads(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn version_downloads(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
Examples found in repository?
examples/total-downloads.rs (lines 13-15)
10fn main() -> db_dump::Result<()> {
11 let mut downloads = Map::<Date<Utc>, u64>::new();
12 db_dump::Loader::new()
13 .version_downloads(|row| {
14 *downloads.entry(row.date).or_default() += row.downloads;
15 })
16 .load("./db-dump.tar.gz")?;
17
18 for (date, count) in downloads {
19 println!("{},{}", date, count);
20 }
21
22 Ok(())
23}
More examples
examples/crate-downloads.rs (line 22)
11fn main() -> db_dump::Result<()> {
12 let mut crate_id = None;
13 let mut versions = Vec::new();
14 let mut version_downloads = Vec::new();
15 db_dump::Loader::new()
16 .crates(|row| {
17 if row.name == CRATE {
18 crate_id = Some(row.id);
19 }
20 })
21 .versions(|row| versions.push(row))
22 .version_downloads(|row| version_downloads.push(row))
23 .load("./db-dump.tar.gz")?;
24
25 // Crate id of the crate we care about.
26 let crate_id = crate_id.expect("no such crate");
27
28 // Set of all version ids corresponding to that crate.
29 let mut version_ids = Set::new();
30 for version in versions {
31 if version.crate_id == crate_id {
32 version_ids.insert(version.id);
33 }
34 }
35
36 // Add up downloads across all version of the crate by day.
37 let mut downloads = Map::<Date<Utc>, u64>::new();
38 for stat in version_downloads {
39 if version_ids.contains(&stat.version_id) {
40 *downloads.entry(stat.date).or_default() += stat.downloads;
41 }
42 }
43
44 for (date, count) in downloads {
45 println!("{},{}", date, count);
46 }
47
48 Ok(())
49}
examples/user-downloads.rs (line 31)
18fn main() -> db_dump::Result<()> {
19 let mut user_id = None;
20 let mut crate_owners = Vec::new();
21 let mut versions = Vec::new();
22 let mut version_downloads = Vec::new();
23 db_dump::Loader::new()
24 .users(|row| {
25 if row.gh_login == USER {
26 user_id = Some(row.id);
27 }
28 })
29 .crate_owners(|row| crate_owners.push(row))
30 .versions(|row| versions.push(row))
31 .version_downloads(|row| version_downloads.push(row))
32 .load("./db-dump.tar.gz")?;
33
34 // User id of the crate author we care about.
35 let user_id = user_id.expect("no such user");
36
37 // Set of crate ids currently owned by that user.
38 let mut their_crates = Set::new();
39 for crate_owner in crate_owners {
40 if crate_owner.owner_id == user_id {
41 their_crates.insert(crate_owner.crate_id);
42 }
43 }
44
45 // Set of version ids of all of those crates.
46 let mut their_versions = Set::new();
47 for version in versions {
48 if their_crates.contains(&version.crate_id) {
49 their_versions.insert(version.id);
50 }
51 }
52
53 // Add up downloads across that user's crates, as well as total downloads of
54 // all crates.
55 let mut downloads = Map::<Date<Utc>, Downloads>::new();
56 for stat in version_downloads {
57 let entry = downloads.entry(stat.date).or_default();
58 entry.all += stat.downloads;
59 if their_versions.contains(&stat.version_id) {
60 entry.theirs += stat.downloads;
61 }
62 }
63
64 // Print user's downloads as a fraction of total crates.io downloads by day.
65 for (date, downloads) in downloads {
66 if downloads.theirs > 0 {
67 println!(
68 "{},{}",
69 date,
70 downloads.theirs as f64 / downloads.all as f64,
71 );
72 }
73 }
74
75 Ok(())
76}
examples/industry-coefficient.rs (line 31)
20fn main() -> db_dump::Result<()> {
21 let mut crates: Map<CrateId, String> = Map::new();
22 let mut versions: Map<VersionId, CrateId> = Map::new();
23 let mut version_downloads = Vec::new();
24 db_dump::Loader::new()
25 .crates(|row| {
26 crates.insert(row.id, row.name);
27 })
28 .versions(|row| {
29 versions.insert(row.id, row.crate_id);
30 })
31 .version_downloads(|row| version_downloads.push(row))
32 .load("./db-dump.tar.gz")?;
33
34 let max_date = version_downloads.iter().map(|row| row.date).max().unwrap();
35 let start_date = max_date - TimeDelta::try_weeks(6).unwrap();
36
37 // Add up downloads by crate by date
38 let mut downloads: Map<CrateId, Downloads> = Map::new();
39 for row in version_downloads {
40 // Deliberately cut out the largest date in the db-dump, because the
41 // data is partial.
42 if row.date >= start_date && row.date < max_date {
43 let crate_id = versions[&row.version_id];
44 let downloads = downloads.entry(crate_id).or_insert_with(Downloads::default);
45 match row.date.weekday() {
46 Weekday::Tue | Weekday::Wed | Weekday::Thu => downloads.weekday += row.downloads,
47 Weekday::Sat | Weekday::Sun => downloads.weekend += row.downloads,
48 // Disregard these to reduce some boundary effect from
49 // downloaders not being perfectly aligned with UTC.
50 Weekday::Mon | Weekday::Fri => {}
51 }
52 }
53 }
54
55 let mut downloads_vec = Vec::new();
56 let mut total = Downloads::default();
57 for (crate_id, downloads) in downloads {
58 total.weekday += downloads.weekday;
59 total.weekend += downloads.weekend;
60 let crate_name = &crates[&crate_id];
61 if downloads.weekend > 0
62 && (downloads.weekday + downloads.weekend >= DOWNLOADS_CUTOFF || crate_name == "cxx")
63 {
64 let coefficient = downloads.weekday as f64 / downloads.weekend as f64;
65 downloads_vec.push((crate_name, coefficient));
66 }
67 }
68
69 let mean = total.weekday as f64 / total.weekend as f64;
70 downloads_vec.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
71
72 for (crate_name, coefficient) in downloads_vec {
73 println!("{:>36} {:+.4}", crate_name, coefficient - mean);
74 }
75
76 Ok(())
77}
Sourcepub fn versions(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
pub fn versions(&mut self, f: impl FnMut(Row) + 'a) -> &mut Self
Examples found in repository?
examples/crate-downloads.rs (line 21)
11fn main() -> db_dump::Result<()> {
12 let mut crate_id = None;
13 let mut versions = Vec::new();
14 let mut version_downloads = Vec::new();
15 db_dump::Loader::new()
16 .crates(|row| {
17 if row.name == CRATE {
18 crate_id = Some(row.id);
19 }
20 })
21 .versions(|row| versions.push(row))
22 .version_downloads(|row| version_downloads.push(row))
23 .load("./db-dump.tar.gz")?;
24
25 // Crate id of the crate we care about.
26 let crate_id = crate_id.expect("no such crate");
27
28 // Set of all version ids corresponding to that crate.
29 let mut version_ids = Set::new();
30 for version in versions {
31 if version.crate_id == crate_id {
32 version_ids.insert(version.id);
33 }
34 }
35
36 // Add up downloads across all version of the crate by day.
37 let mut downloads = Map::<Date<Utc>, u64>::new();
38 for stat in version_downloads {
39 if version_ids.contains(&stat.version_id) {
40 *downloads.entry(stat.date).or_default() += stat.downloads;
41 }
42 }
43
44 for (date, count) in downloads {
45 println!("{},{}", date, count);
46 }
47
48 Ok(())
49}
More examples
examples/user-downloads.rs (line 30)
18fn main() -> db_dump::Result<()> {
19 let mut user_id = None;
20 let mut crate_owners = Vec::new();
21 let mut versions = Vec::new();
22 let mut version_downloads = Vec::new();
23 db_dump::Loader::new()
24 .users(|row| {
25 if row.gh_login == USER {
26 user_id = Some(row.id);
27 }
28 })
29 .crate_owners(|row| crate_owners.push(row))
30 .versions(|row| versions.push(row))
31 .version_downloads(|row| version_downloads.push(row))
32 .load("./db-dump.tar.gz")?;
33
34 // User id of the crate author we care about.
35 let user_id = user_id.expect("no such user");
36
37 // Set of crate ids currently owned by that user.
38 let mut their_crates = Set::new();
39 for crate_owner in crate_owners {
40 if crate_owner.owner_id == user_id {
41 their_crates.insert(crate_owner.crate_id);
42 }
43 }
44
45 // Set of version ids of all of those crates.
46 let mut their_versions = Set::new();
47 for version in versions {
48 if their_crates.contains(&version.crate_id) {
49 their_versions.insert(version.id);
50 }
51 }
52
53 // Add up downloads across that user's crates, as well as total downloads of
54 // all crates.
55 let mut downloads = Map::<Date<Utc>, Downloads>::new();
56 for stat in version_downloads {
57 let entry = downloads.entry(stat.date).or_default();
58 entry.all += stat.downloads;
59 if their_versions.contains(&stat.version_id) {
60 entry.theirs += stat.downloads;
61 }
62 }
63
64 // Print user's downloads as a fraction of total crates.io downloads by day.
65 for (date, downloads) in downloads {
66 if downloads.theirs > 0 {
67 println!(
68 "{},{}",
69 date,
70 downloads.theirs as f64 / downloads.all as f64,
71 );
72 }
73 }
74
75 Ok(())
76}
examples/user-dependencies.rs (lines 28-37)
11fn main() -> db_dump::Result<()> {
12 // Map of crate id to the most recently published version of that crate.
13 let mut most_recent = Map::new();
14
15 let mut user_id = None;
16 let mut crates = 0;
17 let mut crate_owners = Vec::new();
18 let mut dependencies = Vec::new();
19 db_dump::Loader::new()
20 .users(|row| {
21 if row.gh_login == USER {
22 user_id = Some(row.id);
23 }
24 })
25 .crates(|_row| crates += 1)
26 .crate_owners(|row| crate_owners.push(row))
27 .dependencies(|row| dependencies.push(row))
28 .versions(|row| match most_recent.entry(row.crate_id) {
29 Entry::Vacant(entry) => {
30 entry.insert(row);
31 }
32 Entry::Occupied(mut entry) => {
33 if row.created_at > entry.get().created_at {
34 entry.insert(row);
35 }
36 }
37 })
38 .load("./db-dump.tar.gz")?;
39
40 // User id of the crate author we care about.
41 let user_id = user_id.expect("no such user");
42
43 // Set of crate ids currently owned by that user.
44 let mut their_crates = Set::new();
45 for crate_owner in crate_owners {
46 if crate_owner.owner_id == user_id {
47 their_crates.insert(crate_owner.crate_id);
48 }
49 }
50
51 // Set of version ids which are the most recently published of their crate.
52 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54 // Set of version ids which depend directly on at least one crate by the
55 // user.
56 let mut dep_on_them = Set::new();
57 for dep in dependencies {
58 if their_crates.contains(&dep.crate_id) {
59 dep_on_them.insert(dep.version_id);
60 }
61 }
62
63 // Number of crates whose most recent version depends on at least one crate
64 // by the user.
65 let result = dep_on_them.intersection(&most_recent).count();
66
67 println!(
68 "{} / {} = {:.1}%",
69 result,
70 crates,
71 100.0 * result as f64 / crates as f64,
72 );
73
74 Ok(())
75}
examples/top-crates.rs (lines 26-35)
13fn main() -> db_dump::Result<()> {
14 // Map of crate id to the most recently published version of that crate.
15 let mut most_recent = Map::new();
16
17 let mut crates = Set::new();
18 let mut crate_owners = Vec::new();
19 let mut dependencies = Vec::new();
20 db_dump::Loader::new()
21 .crates(|row| {
22 crates.insert(row);
23 })
24 .crate_owners(|row| crate_owners.push(row))
25 .dependencies(|row| dependencies.push(row))
26 .versions(|row| match most_recent.entry(row.crate_id) {
27 Entry::Vacant(entry) => {
28 entry.insert(row);
29 }
30 Entry::Occupied(mut entry) => {
31 if row.created_at > entry.get().created_at {
32 entry.insert(row);
33 }
34 }
35 })
36 .load("./db-dump.tar.gz")?;
37
38 // Set of version ids which are the most recently published of their crate.
39 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41 // Set of (version id, dependency crate id) pairs to avoid double-counting
42 // cases where a crate has both a normal dependency and dev-dependency or
43 // build-dependency on the same dependency crate.
44 let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46 // Map of crate id to how many other crates' most recent version depends on
47 // that crate.
48 let mut count = Map::<CrateId, usize>::new();
49 for dep in dependencies {
50 if most_recent.contains(&dep.version_id)
51 && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52 {
53 *count.entry(dep.crate_id).or_default() += 1;
54 }
55 }
56
57 // Quickselect and sort the top N crates by reverse dependency count.
58 let mut sort = Vec::from_iter(count);
59 let sort_by_count = |&(_crate, count): &_| Reverse(count);
60 sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61 sort[..N].sort_unstable_by_key(sort_by_count);
62
63 for (id, count) in sort.iter().take(N) {
64 let crate_name = &crates.get(id).unwrap().name;
65 println!("{},{}", crate_name, count);
66 }
67
68 Ok(())
69}
examples/user-dependencies-graph.rs (lines 28-32)
10fn main() -> db_dump::Result<()> {
11 let mut user_id = None;
12 let mut crate_owners = Vec::new();
13 let mut dependencies = Map::new();
14 let mut versions = Vec::new();
15 db_dump::Loader::new()
16 .users(|row| {
17 if row.gh_login == USER {
18 user_id = Some(row.id);
19 }
20 })
21 .crate_owners(|row| crate_owners.push(row))
22 .dependencies(|row| {
23 dependencies
24 .entry(row.version_id)
25 .or_insert_with(Vec::new)
26 .push(row);
27 })
28 .versions(|row| {
29 if !row.yanked {
30 versions.push(row);
31 }
32 })
33 .load("./db-dump.tar.gz")?;
34
35 // User id of the crate author we care about.
36 let user_id = user_id.expect("no such user");
37
38 // Set of crate ids currently owned by that user.
39 let mut their_crates = Set::new();
40 for crate_owner in crate_owners {
41 if crate_owner.owner_id == user_id {
42 their_crates.insert(crate_owner.crate_id);
43 }
44 }
45
46 let mut total_deps = 0usize;
47 let mut their_deps = 0usize;
48 let mut last_printed_ratio = 0.0..=0.0;
49 let mut latest_version = Map::new();
50
51 versions.sort_by_key(|v| v.created_at);
52
53 for version in versions {
54 let no_deps = Vec::new();
55 if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56 for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57 total_deps -= 1;
58 their_deps -= their_crates.contains(&dep.crate_id) as usize;
59 }
60 }
61 for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62 total_deps += 1;
63 their_deps += their_crates.contains(&dep.crate_id) as usize;
64 }
65 if total_deps != 0 {
66 let ratio = their_deps as f64 / total_deps as f64;
67 if !last_printed_ratio.contains(&ratio) {
68 println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69 last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70 }
71 }
72 }
73
74 eprintln!(
75 "{} / {} ({:.02}%)",
76 their_deps,
77 total_deps,
78 (their_deps as f64 / total_deps as f64) * 100.0,
79 );
80 Ok(())
81}
examples/industry-coefficient.rs (lines 28-30)
20fn main() -> db_dump::Result<()> {
21 let mut crates: Map<CrateId, String> = Map::new();
22 let mut versions: Map<VersionId, CrateId> = Map::new();
23 let mut version_downloads = Vec::new();
24 db_dump::Loader::new()
25 .crates(|row| {
26 crates.insert(row.id, row.name);
27 })
28 .versions(|row| {
29 versions.insert(row.id, row.crate_id);
30 })
31 .version_downloads(|row| version_downloads.push(row))
32 .load("./db-dump.tar.gz")?;
33
34 let max_date = version_downloads.iter().map(|row| row.date).max().unwrap();
35 let start_date = max_date - TimeDelta::try_weeks(6).unwrap();
36
37 // Add up downloads by crate by date
38 let mut downloads: Map<CrateId, Downloads> = Map::new();
39 for row in version_downloads {
40 // Deliberately cut out the largest date in the db-dump, because the
41 // data is partial.
42 if row.date >= start_date && row.date < max_date {
43 let crate_id = versions[&row.version_id];
44 let downloads = downloads.entry(crate_id).or_insert_with(Downloads::default);
45 match row.date.weekday() {
46 Weekday::Tue | Weekday::Wed | Weekday::Thu => downloads.weekday += row.downloads,
47 Weekday::Sat | Weekday::Sun => downloads.weekend += row.downloads,
48 // Disregard these to reduce some boundary effect from
49 // downloaders not being perfectly aligned with UTC.
50 Weekday::Mon | Weekday::Fri => {}
51 }
52 }
53 }
54
55 let mut downloads_vec = Vec::new();
56 let mut total = Downloads::default();
57 for (crate_id, downloads) in downloads {
58 total.weekday += downloads.weekday;
59 total.weekend += downloads.weekend;
60 let crate_name = &crates[&crate_id];
61 if downloads.weekend > 0
62 && (downloads.weekday + downloads.weekend >= DOWNLOADS_CUTOFF || crate_name == "cxx")
63 {
64 let coefficient = downloads.weekday as f64 / downloads.weekend as f64;
65 downloads_vec.push((crate_name, coefficient));
66 }
67 }
68
69 let mean = total.weekday as f64 / total.weekend as f64;
70 downloads_vec.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
71
72 for (crate_name, coefficient) in downloads_vec {
73 println!("{:>36} {:+.4}", crate_name, coefficient - mean);
74 }
75
76 Ok(())
77}
Sourcepub fn load(&mut self, path: impl AsRef<Path>) -> Result<()>
pub fn load(&mut self, path: impl AsRef<Path>) -> Result<()>
Examples found in repository?
examples/total-downloads.rs (line 16)
10fn main() -> db_dump::Result<()> {
11 let mut downloads = Map::<Date<Utc>, u64>::new();
12 db_dump::Loader::new()
13 .version_downloads(|row| {
14 *downloads.entry(row.date).or_default() += row.downloads;
15 })
16 .load("./db-dump.tar.gz")?;
17
18 for (date, count) in downloads {
19 println!("{},{}", date, count);
20 }
21
22 Ok(())
23}
More examples
examples/crate-downloads.rs (line 23)
11fn main() -> db_dump::Result<()> {
12 let mut crate_id = None;
13 let mut versions = Vec::new();
14 let mut version_downloads = Vec::new();
15 db_dump::Loader::new()
16 .crates(|row| {
17 if row.name == CRATE {
18 crate_id = Some(row.id);
19 }
20 })
21 .versions(|row| versions.push(row))
22 .version_downloads(|row| version_downloads.push(row))
23 .load("./db-dump.tar.gz")?;
24
25 // Crate id of the crate we care about.
26 let crate_id = crate_id.expect("no such crate");
27
28 // Set of all version ids corresponding to that crate.
29 let mut version_ids = Set::new();
30 for version in versions {
31 if version.crate_id == crate_id {
32 version_ids.insert(version.id);
33 }
34 }
35
36 // Add up downloads across all version of the crate by day.
37 let mut downloads = Map::<Date<Utc>, u64>::new();
38 for stat in version_downloads {
39 if version_ids.contains(&stat.version_id) {
40 *downloads.entry(stat.date).or_default() += stat.downloads;
41 }
42 }
43
44 for (date, count) in downloads {
45 println!("{},{}", date, count);
46 }
47
48 Ok(())
49}
examples/user-downloads.rs (line 32)
18fn main() -> db_dump::Result<()> {
19 let mut user_id = None;
20 let mut crate_owners = Vec::new();
21 let mut versions = Vec::new();
22 let mut version_downloads = Vec::new();
23 db_dump::Loader::new()
24 .users(|row| {
25 if row.gh_login == USER {
26 user_id = Some(row.id);
27 }
28 })
29 .crate_owners(|row| crate_owners.push(row))
30 .versions(|row| versions.push(row))
31 .version_downloads(|row| version_downloads.push(row))
32 .load("./db-dump.tar.gz")?;
33
34 // User id of the crate author we care about.
35 let user_id = user_id.expect("no such user");
36
37 // Set of crate ids currently owned by that user.
38 let mut their_crates = Set::new();
39 for crate_owner in crate_owners {
40 if crate_owner.owner_id == user_id {
41 their_crates.insert(crate_owner.crate_id);
42 }
43 }
44
45 // Set of version ids of all of those crates.
46 let mut their_versions = Set::new();
47 for version in versions {
48 if their_crates.contains(&version.crate_id) {
49 their_versions.insert(version.id);
50 }
51 }
52
53 // Add up downloads across that user's crates, as well as total downloads of
54 // all crates.
55 let mut downloads = Map::<Date<Utc>, Downloads>::new();
56 for stat in version_downloads {
57 let entry = downloads.entry(stat.date).or_default();
58 entry.all += stat.downloads;
59 if their_versions.contains(&stat.version_id) {
60 entry.theirs += stat.downloads;
61 }
62 }
63
64 // Print user's downloads as a fraction of total crates.io downloads by day.
65 for (date, downloads) in downloads {
66 if downloads.theirs > 0 {
67 println!(
68 "{},{}",
69 date,
70 downloads.theirs as f64 / downloads.all as f64,
71 );
72 }
73 }
74
75 Ok(())
76}
examples/user-dependencies.rs (line 38)
11fn main() -> db_dump::Result<()> {
12 // Map of crate id to the most recently published version of that crate.
13 let mut most_recent = Map::new();
14
15 let mut user_id = None;
16 let mut crates = 0;
17 let mut crate_owners = Vec::new();
18 let mut dependencies = Vec::new();
19 db_dump::Loader::new()
20 .users(|row| {
21 if row.gh_login == USER {
22 user_id = Some(row.id);
23 }
24 })
25 .crates(|_row| crates += 1)
26 .crate_owners(|row| crate_owners.push(row))
27 .dependencies(|row| dependencies.push(row))
28 .versions(|row| match most_recent.entry(row.crate_id) {
29 Entry::Vacant(entry) => {
30 entry.insert(row);
31 }
32 Entry::Occupied(mut entry) => {
33 if row.created_at > entry.get().created_at {
34 entry.insert(row);
35 }
36 }
37 })
38 .load("./db-dump.tar.gz")?;
39
40 // User id of the crate author we care about.
41 let user_id = user_id.expect("no such user");
42
43 // Set of crate ids currently owned by that user.
44 let mut their_crates = Set::new();
45 for crate_owner in crate_owners {
46 if crate_owner.owner_id == user_id {
47 their_crates.insert(crate_owner.crate_id);
48 }
49 }
50
51 // Set of version ids which are the most recently published of their crate.
52 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
53
54 // Set of version ids which depend directly on at least one crate by the
55 // user.
56 let mut dep_on_them = Set::new();
57 for dep in dependencies {
58 if their_crates.contains(&dep.crate_id) {
59 dep_on_them.insert(dep.version_id);
60 }
61 }
62
63 // Number of crates whose most recent version depends on at least one crate
64 // by the user.
65 let result = dep_on_them.intersection(&most_recent).count();
66
67 println!(
68 "{} / {} = {:.1}%",
69 result,
70 crates,
71 100.0 * result as f64 / crates as f64,
72 );
73
74 Ok(())
75}
examples/top-crates.rs (line 36)
13fn main() -> db_dump::Result<()> {
14 // Map of crate id to the most recently published version of that crate.
15 let mut most_recent = Map::new();
16
17 let mut crates = Set::new();
18 let mut crate_owners = Vec::new();
19 let mut dependencies = Vec::new();
20 db_dump::Loader::new()
21 .crates(|row| {
22 crates.insert(row);
23 })
24 .crate_owners(|row| crate_owners.push(row))
25 .dependencies(|row| dependencies.push(row))
26 .versions(|row| match most_recent.entry(row.crate_id) {
27 Entry::Vacant(entry) => {
28 entry.insert(row);
29 }
30 Entry::Occupied(mut entry) => {
31 if row.created_at > entry.get().created_at {
32 entry.insert(row);
33 }
34 }
35 })
36 .load("./db-dump.tar.gz")?;
37
38 // Set of version ids which are the most recently published of their crate.
39 let most_recent = Set::from_iter(most_recent.values().map(|version| version.id));
40
41 // Set of (version id, dependency crate id) pairs to avoid double-counting
42 // cases where a crate has both a normal dependency and dev-dependency or
43 // build-dependency on the same dependency crate.
44 let mut unique_dependency_edges = Set::<(VersionId, CrateId)>::new();
45
46 // Map of crate id to how many other crates' most recent version depends on
47 // that crate.
48 let mut count = Map::<CrateId, usize>::new();
49 for dep in dependencies {
50 if most_recent.contains(&dep.version_id)
51 && unique_dependency_edges.insert((dep.version_id, dep.crate_id))
52 {
53 *count.entry(dep.crate_id).or_default() += 1;
54 }
55 }
56
57 // Quickselect and sort the top N crates by reverse dependency count.
58 let mut sort = Vec::from_iter(count);
59 let sort_by_count = |&(_crate, count): &_| Reverse(count);
60 sort.select_nth_unstable_by_key(N - 1, sort_by_count);
61 sort[..N].sort_unstable_by_key(sort_by_count);
62
63 for (id, count) in sort.iter().take(N) {
64 let crate_name = &crates.get(id).unwrap().name;
65 println!("{},{}", crate_name, count);
66 }
67
68 Ok(())
69}
examples/user-dependencies-graph.rs (line 33)
10fn main() -> db_dump::Result<()> {
11 let mut user_id = None;
12 let mut crate_owners = Vec::new();
13 let mut dependencies = Map::new();
14 let mut versions = Vec::new();
15 db_dump::Loader::new()
16 .users(|row| {
17 if row.gh_login == USER {
18 user_id = Some(row.id);
19 }
20 })
21 .crate_owners(|row| crate_owners.push(row))
22 .dependencies(|row| {
23 dependencies
24 .entry(row.version_id)
25 .or_insert_with(Vec::new)
26 .push(row);
27 })
28 .versions(|row| {
29 if !row.yanked {
30 versions.push(row);
31 }
32 })
33 .load("./db-dump.tar.gz")?;
34
35 // User id of the crate author we care about.
36 let user_id = user_id.expect("no such user");
37
38 // Set of crate ids currently owned by that user.
39 let mut their_crates = Set::new();
40 for crate_owner in crate_owners {
41 if crate_owner.owner_id == user_id {
42 their_crates.insert(crate_owner.crate_id);
43 }
44 }
45
46 let mut total_deps = 0usize;
47 let mut their_deps = 0usize;
48 let mut last_printed_ratio = 0.0..=0.0;
49 let mut latest_version = Map::new();
50
51 versions.sort_by_key(|v| v.created_at);
52
53 for version in versions {
54 let no_deps = Vec::new();
55 if let Some(prev) = latest_version.insert(version.crate_id, version.id) {
56 for dep in dependencies.get(&prev).unwrap_or(&no_deps) {
57 total_deps -= 1;
58 their_deps -= their_crates.contains(&dep.crate_id) as usize;
59 }
60 }
61 for dep in dependencies.get(&version.id).unwrap_or(&no_deps) {
62 total_deps += 1;
63 their_deps += their_crates.contains(&dep.crate_id) as usize;
64 }
65 if total_deps != 0 {
66 let ratio = their_deps as f64 / total_deps as f64;
67 if !last_printed_ratio.contains(&ratio) {
68 println!("{},{:.3}", version.created_at.naive_utc(), ratio * 100.0);
69 last_printed_ratio = ratio * 0.99999..=ratio * 1.00001;
70 }
71 }
72 }
73
74 eprintln!(
75 "{} / {} ({:.02}%)",
76 their_deps,
77 total_deps,
78 (their_deps as f64 / total_deps as f64) * 100.0,
79 );
80 Ok(())
81}
Additional examples can be found in:
Trait Implementations§
Auto Trait Implementations§
impl<'a> Freeze for Loader<'a>
impl<'a> !RefUnwindSafe for Loader<'a>
impl<'a> !Send for Loader<'a>
impl<'a> !Sync for Loader<'a>
impl<'a> Unpin for Loader<'a>
impl<'a> !UnwindSafe for Loader<'a>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more