/src/cargo/ops/tree/format/mod.rs

https://gitlab.com/frewsxcv/cargo · Rust · 135 lines · 120 code · 13 blank · 2 comment · 14 complexity · 3faef1da444136737cc6c02047a481a2 MD5 · raw file

  1. use std::fmt;
  2. use anyhow::{bail, Error};
  3. use self::parse::{Parser, RawChunk};
  4. use super::{Graph, Node};
  5. mod parse;
  6. enum Chunk {
  7. Raw(String),
  8. Package,
  9. License,
  10. Repository,
  11. Features,
  12. LibName,
  13. }
  14. pub struct Pattern(Vec<Chunk>);
  15. impl Pattern {
  16. pub fn new(format: &str) -> Result<Pattern, Error> {
  17. let mut chunks = vec![];
  18. for raw in Parser::new(format) {
  19. let chunk = match raw {
  20. RawChunk::Text(text) => Chunk::Raw(text.to_owned()),
  21. RawChunk::Argument("p") => Chunk::Package,
  22. RawChunk::Argument("l") => Chunk::License,
  23. RawChunk::Argument("r") => Chunk::Repository,
  24. RawChunk::Argument("f") => Chunk::Features,
  25. RawChunk::Argument("lib") => Chunk::LibName,
  26. RawChunk::Argument(a) => {
  27. bail!("unsupported pattern `{}`", a);
  28. }
  29. RawChunk::Error(err) => bail!("{}", err),
  30. };
  31. chunks.push(chunk);
  32. }
  33. Ok(Pattern(chunks))
  34. }
  35. pub fn display<'a>(&'a self, graph: &'a Graph<'a>, node_index: usize) -> Display<'a> {
  36. Display {
  37. pattern: self,
  38. graph,
  39. node_index,
  40. }
  41. }
  42. }
  43. pub struct Display<'a> {
  44. pattern: &'a Pattern,
  45. graph: &'a Graph<'a>,
  46. node_index: usize,
  47. }
  48. impl<'a> fmt::Display for Display<'a> {
  49. fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
  50. let node = self.graph.node(self.node_index);
  51. match node {
  52. Node::Package {
  53. package_id,
  54. features,
  55. ..
  56. } => {
  57. let package = self.graph.package_for_id(*package_id);
  58. for chunk in &self.pattern.0 {
  59. match chunk {
  60. Chunk::Raw(s) => fmt.write_str(s)?,
  61. Chunk::Package => {
  62. let proc_macro_suffix = if package.proc_macro() {
  63. " (proc-macro)"
  64. } else {
  65. ""
  66. };
  67. write!(
  68. fmt,
  69. "{} v{}{}",
  70. package.name(),
  71. package.version(),
  72. proc_macro_suffix
  73. )?;
  74. let source_id = package.package_id().source_id();
  75. if !source_id.is_default_registry() {
  76. write!(fmt, " ({})", source_id)?;
  77. }
  78. }
  79. Chunk::License => {
  80. if let Some(license) = &package.manifest().metadata().license {
  81. write!(fmt, "{}", license)?;
  82. }
  83. }
  84. Chunk::Repository => {
  85. if let Some(repository) = &package.manifest().metadata().repository {
  86. write!(fmt, "{}", repository)?;
  87. }
  88. }
  89. Chunk::Features => {
  90. write!(fmt, "{}", features.join(","))?;
  91. }
  92. Chunk::LibName => {
  93. if let Some(target) = package
  94. .manifest()
  95. .targets()
  96. .iter()
  97. .find(|target| target.is_lib())
  98. {
  99. write!(fmt, "{}", target.crate_name())?;
  100. }
  101. }
  102. }
  103. }
  104. }
  105. Node::Feature { name, node_index } => {
  106. let for_node = self.graph.node(*node_index);
  107. match for_node {
  108. Node::Package { package_id, .. } => {
  109. write!(fmt, "{} feature \"{}\"", package_id.name(), name)?;
  110. if self.graph.is_cli_feature(self.node_index) {
  111. write!(fmt, " (command-line)")?;
  112. }
  113. }
  114. // The node_index in Node::Feature must point to a package
  115. // node, see `add_feature`.
  116. _ => panic!("unexpected feature node {:?}", for_node),
  117. }
  118. }
  119. }
  120. Ok(())
  121. }
  122. }