cache.rs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. root: PathBuf,
  13. use_audio_cache: bool,
  14. }
  15. fn mkdir_existing(path: &Path) -> io::Result<()> {
  16. fs::create_dir(path).or_else(|err| {
  17. if err.kind() == io::ErrorKind::AlreadyExists {
  18. Ok(())
  19. } else {
  20. Err(err)
  21. }
  22. })
  23. }
  24. impl Cache {
  25. pub fn new(location: PathBuf, use_audio_cache: bool) -> Cache {
  26. mkdir_existing(&location).unwrap();
  27. mkdir_existing(&location.join("files")).unwrap();
  28. Cache {
  29. root: location,
  30. use_audio_cache: use_audio_cache,
  31. }
  32. }
  33. }
  34. impl Cache {
  35. fn credentials_path(&self) -> PathBuf {
  36. self.root.join("credentials.json")
  37. }
  38. pub fn credentials(&self) -> Option<Credentials> {
  39. let path = self.credentials_path();
  40. Credentials::from_file(path)
  41. }
  42. pub fn save_credentials(&self, cred: &Credentials) {
  43. let path = self.credentials_path();
  44. cred.save_to_file(&path);
  45. }
  46. }
  47. // cache volume to root/volume
  48. impl Cache {
  49. fn volume_path(&self) -> PathBuf {
  50. self.root.join("volume")
  51. }
  52. pub fn volume(&self) -> Option<u16> {
  53. let path = self.volume_path();
  54. Volume::from_file(path)
  55. }
  56. pub fn save_volume(&self, volume: Volume) {
  57. let path = self.volume_path();
  58. volume.save_to_file(&path);
  59. }
  60. }
  61. impl Cache {
  62. fn file_path(&self, file: FileId) -> PathBuf {
  63. let name = file.to_base16();
  64. self.root.join("files").join(&name[0..2]).join(&name[2..])
  65. }
  66. pub fn file(&self, file: FileId) -> Option<File> {
  67. File::open(self.file_path(file)).ok()
  68. }
  69. pub fn save_file(&self, file: FileId, contents: &mut dyn Read) {
  70. if self.use_audio_cache {
  71. let path = self.file_path(file);
  72. mkdir_existing(path.parent().unwrap()).unwrap();
  73. let mut cache_file = File::create(path).unwrap();
  74. ::std::io::copy(contents, &mut cache_file).unwrap();
  75. }
  76. }
  77. }