Skip to content

Commit d20e4cc

Browse files
KixironJoshua Nelson
authored and
Joshua Nelson
committed
Crate Details
1 parent d5a1127 commit d20e4cc

File tree

3 files changed

+330
-173
lines changed

3 files changed

+330
-173
lines changed

src/web/crate_details.rs

+27-68
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
11
use super::error::Nope;
2-
use super::page::Page;
3-
use super::{
4-
duration_to_str, match_version, redirect_base, render_markdown, MatchSemver, MetaData,
5-
};
6-
use crate::db::Pool;
2+
use super::{match_version, redirect_base, render_markdown, MatchSemver, MetaData};
3+
use crate::{db::Pool, impl_webpage, web::page::WebPage};
74
use chrono::{DateTime, NaiveDateTime, Utc};
85
use iron::prelude::*;
96
use iron::{status, Url};
107
use postgres::Connection;
118
use router::Router;
12-
use serde::{
13-
ser::{SerializeStruct, Serializer},
14-
Serialize,
15-
};
9+
use serde::{ser::Serializer, Serialize};
1610
use serde_json::Value;
1711

1812
// TODO: Add target name and versions
1913

20-
#[derive(Debug, Clone, PartialEq)]
14+
#[derive(Debug, Clone, PartialEq, Serialize)]
2115
pub struct CrateDetails {
2216
name: String,
2317
version: String,
@@ -26,7 +20,9 @@ pub struct CrateDetails {
2620
owners: Vec<(String, String)>,
2721
authors_json: Option<Value>,
2822
dependencies: Option<Value>,
23+
#[serde(serialize_with = "optional_markdown")]
2924
readme: Option<String>,
25+
#[serde(serialize_with = "optional_markdown")]
3026
rustdoc: Option<String>, // this is description_long in database
3127
release_time: DateTime<Utc>,
3228
build_status: bool,
@@ -50,60 +46,16 @@ pub struct CrateDetails {
5046
documentation_url: Option<String>,
5147
}
5248

53-
impl Serialize for CrateDetails {
54-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
55-
where
56-
S: Serializer,
57-
{
58-
// Make sure that the length parameter passed to serde is correct by
59-
// adding the someness of `readme` and `rustdoc` to the total. `true`
60-
// is 1 and `false` is 0, so it increments if the value is some (and therefore
61-
// needs to be serialized)
62-
let mut state = serializer.serialize_struct(
63-
"CrateDetails",
64-
26 + self.readme.is_some() as usize + self.rustdoc.is_some() as usize,
65-
)?;
66-
67-
state.serialize_field("metadata", &self.metadata)?;
68-
state.serialize_field("name", &self.name)?;
69-
state.serialize_field("version", &self.version)?;
70-
state.serialize_field("description", &self.description)?;
71-
state.serialize_field("authors", &self.authors)?;
72-
state.serialize_field("owners", &self.owners)?;
73-
state.serialize_field("authors_json", &self.authors_json)?;
74-
state.serialize_field("dependencies", &self.dependencies)?;
75-
76-
if let Some(ref readme) = self.readme {
77-
state.serialize_field("readme", &render_markdown(&readme))?;
78-
}
79-
80-
if let Some(ref rustdoc) = self.rustdoc {
81-
state.serialize_field("rustdoc", &render_markdown(&rustdoc))?;
82-
}
83-
84-
state.serialize_field("release_time", &duration_to_str(self.release_time))?;
85-
state.serialize_field("build_status", &self.build_status)?;
86-
state.serialize_field("last_successful_build", &self.last_successful_build)?;
87-
state.serialize_field("rustdoc_status", &self.rustdoc_status)?;
88-
state.serialize_field("repository_url", &self.repository_url)?;
89-
state.serialize_field("homepage_url", &self.homepage_url)?;
90-
state.serialize_field("keywords", &self.keywords)?;
91-
state.serialize_field("have_examples", &self.have_examples)?;
92-
state.serialize_field("target_name", &self.target_name)?;
93-
state.serialize_field("releases", &self.releases)?;
94-
state.serialize_field("github", &self.github)?;
95-
state.serialize_field("github_stars", &self.github_stars)?;
96-
state.serialize_field("github_forks", &self.github_forks)?;
97-
state.serialize_field("github_issues", &self.github_issues)?;
98-
state.serialize_field("metadata", &self.metadata)?;
99-
state.serialize_field("is_library", &self.is_library)?;
100-
state.serialize_field("doc_targets", &self.doc_targets)?;
101-
state.serialize_field("yanked", &self.yanked)?;
102-
state.serialize_field("license", &self.license)?;
103-
state.serialize_field("documentation_url", &self.documentation_url)?;
104-
105-
state.end()
49+
fn optional_markdown<S>(markdown: &Option<String>, serializer: S) -> Result<S::Ok, S::Error>
50+
where
51+
S: Serializer,
52+
{
53+
if let Some(ref markdown) = markdown {
54+
Some(render_markdown(&markdown))
55+
} else {
56+
None
10657
}
58+
.serialize(serializer)
10759
}
10860

10961
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
@@ -353,6 +305,15 @@ fn map_to_release(conn: &Connection, crate_id: i32, version: String) -> Release
353305
}
354306
}
355307

308+
#[derive(Debug, Clone, PartialEq, Serialize)]
309+
struct CrateDetailsPage {
310+
details: Option<CrateDetails>,
311+
}
312+
313+
impl_webpage! {
314+
CrateDetailsPage = "crate/details.html",
315+
}
316+
356317
pub fn crate_details_handler(req: &mut Request) -> IronResult<Response> {
357318
let router = extension!(req, Router);
358319
// this handler must always called with a crate name
@@ -365,12 +326,9 @@ pub fn crate_details_handler(req: &mut Request) -> IronResult<Response> {
365326
Some(MatchSemver::Exact((version, _))) => {
366327
let details = CrateDetails::new(&conn, &name, &version);
367328

368-
Page::new(details)
369-
.set_true("show_package_navigation")
370-
.set_true("javascript_highlightjs")
371-
.set_true("package_navigation_crate_tab")
372-
.to_resp("crate_details")
329+
CrateDetailsPage { details }.into_response(req)
373330
}
331+
374332
Some(MatchSemver::Semver((version, _))) => {
375333
let url = ctry!(
376334
req,
@@ -384,6 +342,7 @@ pub fn crate_details_handler(req: &mut Request) -> IronResult<Response> {
384342

385343
Ok(super::redirect(url))
386344
}
345+
387346
None => Err(IronError::new(Nope::CrateNotFound, status::NotFound)),
388347
}
389348
}

templates/crate_details.hbs

-105
This file was deleted.

0 commit comments

Comments
 (0)