cache.rs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. use std::fs;
  2. use std::fs::File;
  3. use std::io;
  4. use std::io::Read;
  5. use std::path::Path;
  6. use std::path::PathBuf;
  7. use crate::authentication::Credentials;
  8. use crate::spotify_id::FileId;
  9. use crate::volume::Volume;
  10. #[derive(Clone)]
  11. pub struct Cache {
  12. audio_root: PathBuf,
  13. system_root: PathBuf,
  14. use_audio_cache: bool,
  15. }
  16. fn mkdir_existing(path: &Path) -> io::Result<()> {
  17. fs::create_dir(path).or_else(|err| {
  18. if err.kind() == io::ErrorKind::AlreadyExists {
  19. Ok(())
  20. } else {
  21. Err(err)
  22. }
  23. })
  24. }
  25. impl Cache {
  26. pub fn new(audio_location: PathBuf, system_location: PathBuf, use_audio_cache: bool) -> Cache {
  27. if use_audio_cache == true {
  28. mkdir_existing(&audio_location).unwrap();
  29. mkdir_existing(&audio_location.join("files")).unwrap();
  30. }
  31. mkdir_existing(&system_location).unwrap();
  32. Cache {
  33. audio_root: audio_location,
  34. system_root: system_location,
  35. use_audio_cache: use_audio_cache,
  36. }
  37. }
  38. }
  39. impl Cache {
  40. fn credentials_path(&self) -> PathBuf {
  41. self.system_root.join("credentials.json")
  42. }
  43. pub fn credentials(&self) -> Option<Credentials> {
  44. let path = self.credentials_path();
  45. Credentials::from_file(path)
  46. }
  47. pub fn save_credentials(&self, cred: &Credentials) {
  48. let path = self.credentials_path();
  49. cred.save_to_file(&path);
  50. }
  51. }
  52. // cache volume to system_root/volume
  53. impl Cache {
  54. fn volume_path(&self) -> PathBuf {
  55. self.system_root.join("volume")
  56. }
  57. pub fn volume(&self) -> Option<u16> {
  58. let path = self.volume_path();
  59. Volume::from_file(path)
  60. }
  61. pub fn save_volume(&self, volume: Volume) {
  62. let path = self.volume_path();
  63. volume.save_to_file(&path);
  64. }
  65. }
  66. impl Cache {
  67. fn file_path(&self, file: FileId) -> PathBuf {
  68. let name = file.to_base16();
  69. self.audio_root
  70. .join("files")
  71. .join(&name[0..2])
  72. .join(&name[2..])
  73. }
  74. pub fn file(&self, file: FileId) -> Option<File> {
  75. File::open(self.file_path(file)).ok()
  76. }
  77. pub fn save_file(&self, file: FileId, contents: &mut dyn Read) {
  78. if self.use_audio_cache {
  79. let path = self.file_path(file);
  80. mkdir_existing(path.parent().unwrap()).unwrap();
  81. let mut cache_file = File::create(path).unwrap_or_else(|_e| {
  82. ::std::fs::remove_dir_all(&self.audio_root.join("files")).unwrap();
  83. mkdir_existing(&self.audio_root.join("files")).unwrap();
  84. let path = self.file_path(file);
  85. mkdir_existing(path.parent().unwrap()).unwrap();
  86. File::create(path).unwrap()
  87. });
  88. ::std::io::copy(contents, &mut cache_file).unwrap_or_else(|_e| {
  89. ::std::fs::remove_dir_all(&self.audio_root.join("files")).unwrap();
  90. mkdir_existing(&self.audio_root.join("files")).unwrap();
  91. let path = self.file_path(file);
  92. mkdir_existing(path.parent().unwrap()).unwrap();
  93. let mut file = File::create(path).unwrap();
  94. ::std::io::copy(contents, &mut file).unwrap()
  95. });
  96. }
  97. }
  98. }