1 use super::L64;
2 /// A unique identifier for files or directories in the actual
3 /// file system, to map "files from the graph" to real files.
4 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
5 pub struct Inode(pub super::L64);
6 use byteorder::{BigEndian, ByteOrder};
7 use std::str::FromStr;
8 
9 impl std::fmt::Debug for Inode {
fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result10     fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
11         let mut b = [0; 8];
12         BigEndian::write_u64(&mut b, (self.0).0);
13         write!(fmt, "Inode({})", data_encoding::BASE32_NOPAD.encode(&b))
14     }
15 }
16 
17 impl Inode {
18     pub const ROOT: Inode = Inode(L64(0u64));
is_root(&self) -> bool19     pub fn is_root(&self) -> bool {
20         *self == Inode::ROOT
21     }
22 }
23 
24 impl FromStr for Inode {
25     type Err = <u64 as FromStr>::Err;
from_str(x: &str) -> Result<Self, Self::Err>26     fn from_str(x: &str) -> Result<Self, Self::Err> {
27         Ok(x.parse::<u64>()?.into())
28     }
29 }
30 
31 impl From<u64> for Inode {
from(x: u64) -> Inode32     fn from(x: u64) -> Inode {
33         Inode(x.into())
34     }
35 }
36 
37 impl From<Inode> for u64 {
from(x: Inode) -> u6438     fn from(x: Inode) -> u64 {
39         x.0.into()
40     }
41 }
42 
43 use super::Base32;
44 
45 impl Base32 for Inode {
to_base32(&self) -> String46     fn to_base32(&self) -> String {
47         let inode: u64 = self.0.into();
48         let mut b = [0; 8];
49         BigEndian::write_u64(&mut b, inode);
50         let mut bb = [0; 13];
51         data_encoding::BASE32_NOPAD.encode_mut(&b, &mut bb);
52         let b = std::str::from_utf8(&bb).unwrap();
53         b.to_string()
54     }
from_base32(s: &[u8]) -> Option<Self>55     fn from_base32(s: &[u8]) -> Option<Self> {
56         let mut b = [0; 8];
57         if data_encoding::BASE32_NOPAD.decode_mut(s, &mut b).is_ok() {
58             Some(Inode(BigEndian::read_u64(&b).into()))
59         } else {
60             None
61         }
62     }
63 }
64 
65 pub mod inode_base32_serde {
66     use super::*;
67     use serde::*;
68 
69     pub struct InodeDe {}
70 
71     impl<'de> serde::de::Visitor<'de> for InodeDe {
72         type Value = Inode;
73 
expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result74         fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
75             write!(formatter, "a base32-encoded string")
76         }
77 
visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: de::Error,78         fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
79         where
80             E: de::Error,
81         {
82             let mut b = [0; 8];
83             if data_encoding::BASE32_NOPAD
84                 .decode_mut(s.as_bytes(), &mut b)
85                 .is_ok()
86             {
87                 let b: u64 = BigEndian::read_u64(&b);
88                 Ok(Inode(b.into()))
89             } else {
90                 Err(de::Error::invalid_value(
91                     serde::de::Unexpected::Str(s),
92                     &self,
93                 ))
94             }
95         }
96     }
97 
deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Inode, D::Error>98     pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Inode, D::Error> {
99         d.deserialize_str(InodeDe {})
100     }
101 
serialize<S: Serializer>(inode: &Inode, s: S) -> Result<S::Ok, S::Error>102     pub fn serialize<S: Serializer>(inode: &Inode, s: S) -> Result<S::Ok, S::Error> {
103         let inode: u64 = inode.0.into();
104         let mut b = [0; 8];
105         BigEndian::write_u64(&mut b, inode);
106         let mut bb = [0; 13];
107         data_encoding::BASE32_NOPAD.encode_mut(&b, &mut bb);
108         let b = std::str::from_utf8(&bb).unwrap();
109         s.serialize_str(b)
110     }
111 }
112