resources.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright 2019-2022 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use std::path::{Component, Path, PathBuf};
  5. /// Given a path (absolute or relative) to a resource file, returns the
  6. /// relative path from the bundle resources directory where that resource
  7. /// should be stored.
  8. pub fn resource_relpath(path: &Path) -> PathBuf {
  9. let mut dest = PathBuf::new();
  10. for component in path.components() {
  11. match component {
  12. Component::Prefix(_) => {}
  13. Component::RootDir => dest.push("_root_"),
  14. Component::CurDir => {}
  15. Component::ParentDir => dest.push("_up_"),
  16. Component::Normal(string) => dest.push(string),
  17. }
  18. }
  19. dest
  20. }
  21. /// Parses the external binaries to bundle, adding the target triple suffix to each of them.
  22. pub fn external_binaries(external_binaries: &[String], target_triple: &str) -> Vec<String> {
  23. let mut paths = Vec::new();
  24. for curr_path in external_binaries {
  25. paths.push(format!(
  26. "{}-{}{}",
  27. curr_path,
  28. target_triple,
  29. if target_triple.contains("windows") {
  30. ".exe"
  31. } else {
  32. ""
  33. }
  34. ));
  35. }
  36. paths
  37. }
  38. /// A helper to iterate through resources.
  39. pub struct ResourcePaths<'a> {
  40. /// the patterns to iterate.
  41. pattern_iter: std::slice::Iter<'a, String>,
  42. /// the glob iterator if the path from the current iteration is a glob pattern.
  43. glob_iter: Option<glob::Paths>,
  44. /// the walkdir iterator if the path from the current iteration is a directory.
  45. walk_iter: Option<walkdir::IntoIter>,
  46. /// whether the resource paths allows directories or not.
  47. allow_walk: bool,
  48. /// the pattern of the current iteration.
  49. current_pattern: Option<String>,
  50. /// whether the current pattern is valid or not.
  51. current_pattern_is_valid: bool,
  52. }
  53. impl<'a> ResourcePaths<'a> {
  54. /// Creates a new ResourcePaths from a slice of patterns to iterate
  55. pub fn new(patterns: &'a [String], allow_walk: bool) -> ResourcePaths<'a> {
  56. ResourcePaths {
  57. pattern_iter: patterns.iter(),
  58. glob_iter: None,
  59. walk_iter: None,
  60. allow_walk,
  61. current_pattern: None,
  62. current_pattern_is_valid: false,
  63. }
  64. }
  65. }
  66. impl<'a> Iterator for ResourcePaths<'a> {
  67. type Item = crate::Result<PathBuf>;
  68. fn next(&mut self) -> Option<crate::Result<PathBuf>> {
  69. loop {
  70. if let Some(ref mut walk_entries) = self.walk_iter {
  71. if let Some(entry) = walk_entries.next() {
  72. let entry = match entry {
  73. Ok(entry) => entry,
  74. Err(error) => return Some(Err(crate::Error::from(error))),
  75. };
  76. let path = entry.path();
  77. if path.is_dir() {
  78. continue;
  79. }
  80. self.current_pattern_is_valid = true;
  81. return Some(Ok(path.to_path_buf()));
  82. }
  83. }
  84. self.walk_iter = None;
  85. if let Some(ref mut glob_paths) = self.glob_iter {
  86. if let Some(glob_result) = glob_paths.next() {
  87. let path = match glob_result {
  88. Ok(path) => path,
  89. Err(error) => return Some(Err(error.into())),
  90. };
  91. if path.is_dir() {
  92. if self.allow_walk {
  93. let walk = walkdir::WalkDir::new(path);
  94. self.walk_iter = Some(walk.into_iter());
  95. continue;
  96. } else {
  97. return Some(Err(crate::Error::NotAllowedToWalkDir(path)));
  98. }
  99. }
  100. self.current_pattern_is_valid = true;
  101. return Some(Ok(path));
  102. } else if let Some(current_path) = &self.current_pattern {
  103. if !self.current_pattern_is_valid {
  104. self.glob_iter = None;
  105. return Some(Err(crate::Error::GlobPathNotFound(current_path.clone())));
  106. }
  107. }
  108. }
  109. self.glob_iter = None;
  110. if let Some(pattern) = self.pattern_iter.next() {
  111. self.current_pattern = Some(pattern.to_string());
  112. self.current_pattern_is_valid = false;
  113. let glob = match glob::glob(pattern) {
  114. Ok(glob) => glob,
  115. Err(error) => return Some(Err(error.into())),
  116. };
  117. self.glob_iter = Some(glob);
  118. continue;
  119. }
  120. return None;
  121. }
  122. }
  123. }