spotify_id.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. use std;
  2. use std::fmt;
  3. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
  4. pub struct SpotifyId(u128);
  5. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
  6. pub struct SpotifyIdError;
  7. const BASE62_DIGITS: &'static [u8] = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  8. const BASE16_DIGITS: &'static [u8] = b"0123456789abcdef";
  9. impl SpotifyId {
  10. pub fn from_base16(id: &str) -> Result<SpotifyId, SpotifyIdError> {
  11. let data = id.as_bytes();
  12. let mut n = 0u128;
  13. for c in data {
  14. let d = match BASE16_DIGITS.iter().position(|e| e == c) {
  15. None => return Err(SpotifyIdError),
  16. Some(x) => x as u128,
  17. };
  18. n = n * 16;
  19. n = n + d;
  20. }
  21. Ok(SpotifyId(n))
  22. }
  23. pub fn from_base62(id: &str) -> Result<SpotifyId, SpotifyIdError> {
  24. let data = id.as_bytes();
  25. let mut n = 0u128;
  26. for c in data {
  27. let d = match BASE62_DIGITS.iter().position(|e| e == c) {
  28. None => return Err(SpotifyIdError),
  29. Some(x) => x as u128,
  30. };
  31. n = n * 62;
  32. n = n + d;
  33. }
  34. Ok(SpotifyId(n))
  35. }
  36. pub fn from_raw(data: &[u8]) -> Result<SpotifyId, SpotifyIdError> {
  37. if data.len() != 16 {
  38. return Err(SpotifyIdError);
  39. };
  40. let mut arr: [u8; 16] = Default::default();
  41. arr.copy_from_slice(&data[0..16]);
  42. Ok(SpotifyId(u128::from_be_bytes(arr)))
  43. }
  44. pub fn to_base16(&self) -> String {
  45. format!("{:032x}", self.0)
  46. }
  47. pub fn to_base62(&self) -> String {
  48. let &SpotifyId(mut n) = self;
  49. let mut data = [0u8; 22];
  50. for i in 0..22 {
  51. data[21 - i] = BASE62_DIGITS[(n % 62) as usize];
  52. n /= 62;
  53. }
  54. std::str::from_utf8(&data).unwrap().to_owned()
  55. }
  56. pub fn to_raw(&self) -> [u8; 16] {
  57. self.0.to_be_bytes()
  58. }
  59. }
  60. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
  61. pub struct FileId(pub [u8; 20]);
  62. impl FileId {
  63. pub fn to_base16(&self) -> String {
  64. self.0
  65. .iter()
  66. .map(|b| format!("{:02x}", b))
  67. .collect::<Vec<String>>()
  68. .concat()
  69. }
  70. }
  71. impl fmt::Debug for FileId {
  72. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  73. f.debug_tuple("FileId").field(&self.to_base16()).finish()
  74. }
  75. }
  76. impl fmt::Display for FileId {
  77. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  78. f.write_str(&self.to_base16())
  79. }
  80. }