diff --git a/src/csl/rendering/mod.rs b/src/csl/rendering/mod.rs index 581ee2f..2956074 100644 --- a/src/csl/rendering/mod.rs +++ b/src/csl/rendering/mod.rs @@ -431,10 +431,7 @@ impl RenderCsl for citationberg::Label { }; let depth = ctx.push_elem(citationberg::Formatting::default()); - let plural = match p { - MaybeTyped::Typed(p) => p.is_plural(), - _ => false, - }; + let plural = p.as_typed().map_or(false, |p| p.is_plural()); let content = ctx.term(Term::from(pv), self.label.form, plural).unwrap_or_default(); @@ -496,10 +493,7 @@ impl RenderCsl for citationberg::Label { } NumberOrPageVariable::Page(pv) => { if let Some(p) = ctx.resolve_page_variable(pv) { - let plural = match p { - MaybeTyped::Typed(p) => p.is_plural(), - _ => false, - }; + let plural = p.as_typed().map_or(false, |p| p.is_plural()); ( ctx.term(Term::from(pv), self.label.form, plural).is_some(), UsageInfo::default(), diff --git a/src/csl/taxonomy.rs b/src/csl/taxonomy.rs index fa0f42e..13b4d56 100644 --- a/src/csl/taxonomy.rs +++ b/src/csl/taxonomy.rs @@ -173,6 +173,7 @@ impl EntryLike for Entry { } NumberVariable::PageFirst => self .page_range() + .and_then(MaybeTyped::as_typed) .and_then(PageRanges::first) .map(|r| MaybeTyped::Typed(Cow::Owned(r.clone()))), NumberVariable::PartNumber => self @@ -216,7 +217,7 @@ impl EntryLike for Entry { variable: PageVariable, ) -> Option> { match variable { - PageVariable::Page => self.page_range().map(|r| MaybeTyped::Typed(r.clone())), + PageVariable::Page => self.page_range().cloned(), } } diff --git a/src/interop.rs b/src/interop.rs index 3feb8ae..f44de11 100644 --- a/src/interop.rs +++ b/src/interop.rs @@ -1,7 +1,6 @@ //! Provides conversion methods for BibLaTeX. use std::convert::TryFrom; -use std::str::FromStr; use biblatex as tex; use tex::{ @@ -491,7 +490,7 @@ impl TryFrom<&tex::Entry> for Entry { if let Some(pages) = map_res(entry.pages())? { item.set_page_range(match pages { - PermissiveType::Typed(pages) => PageRanges::new( + PermissiveType::Typed(pages) => MaybeTyped::Typed(PageRanges::new( pages .into_iter() .map(|p| { @@ -505,9 +504,9 @@ impl TryFrom<&tex::Entry> for Entry { } }) .collect(), - ), + )), PermissiveType::Chunks(chunks) => { - PageRanges::from_str(&chunks.format_verbatim()).unwrap() + MaybeTyped::infallible_from_str(&chunks.format_verbatim()) } }); } diff --git a/src/lib.rs b/src/lib.rs index 8514ece..c81eea9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -522,7 +522,7 @@ entry! { /// Published version of an item. "edition" => edition: MaybeTyped, /// The range of pages within the parent this item occupies - "page-range" => page_range: PageRanges, + "page-range" => page_range: MaybeTyped, /// The total number of pages the item has. "page-total" => page_total: Numeric, /// The time range within the parent this item starts and ends at. @@ -982,4 +982,23 @@ mod tests { ["a", "b", "c"] ); } + + #[test] + #[cfg(feature = "biblatex")] + fn test_troublesome_page_ranges() { + use io::from_biblatex_str; + + let bibtex = r#" + @article{b, + title={My page ranges}, + pages={150--es} + } + "#; + + let library = from_biblatex_str(bibtex).unwrap(); + + for entry in library.iter() { + assert!(entry.page_range.is_some()) + } + } } diff --git a/src/types/mod.rs b/src/types/mod.rs index ebabfd6..5fbd5b5 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -304,6 +304,16 @@ pub enum MaybeTyped { String(String), } +impl MaybeTyped { + /// Get the typed value, if it is present. + pub fn as_typed(&self) -> Option<&T> { + match self { + MaybeTyped::Typed(t) => Some(t), + MaybeTyped::String(_) => None, + } + } +} + impl MaybeTyped { /// Wrap the typed value in a [`Cow`]'s borrowed variant. pub fn to_cow(&self) -> MaybeTyped> {