use std::fmt; use std::iter; /// Valid Rust identifier #[derive(Eq, PartialEq, Debug, Clone)] pub(crate) struct RustIdent(String); #[allow(dead_code)] impl RustIdent { pub fn new(s: &str) -> RustIdent { assert!(!s.is_empty()); assert!(!s.contains("/"), "{}", s); assert!(!s.contains("."), "{}", s); assert!(!s.contains(":"), "{}", s); RustIdent(s.to_owned()) } pub fn super_ident() -> RustIdent { RustIdent::new("super") } pub fn get(&self) -> &str { &self.0 } pub fn into_string(self) -> String { self.0 } pub fn to_path(&self) -> RustIdentWithPath { RustIdentWithPath::from(&self.0) } } impl fmt::Display for RustIdent { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.get(), f) } } impl From<&'_ str> for RustIdent { fn from(s: &str) -> Self { RustIdent::new(s) } } impl From for RustIdent { fn from(s: String) -> Self { RustIdent::new(&s) } } impl Into for RustIdent { fn into(self) -> String { self.0 } } #[derive(Default, Eq, PartialEq, Debug, Clone)] pub(crate) struct RustRelativePath { path: Vec, } #[allow(dead_code)] impl RustRelativePath { pub fn into_path(self) -> RustPath { RustPath { absolute: false, path: self, } } pub fn empty() -> RustRelativePath { RustRelativePath { path: Vec::new() } } pub fn from_components>(i: I) -> RustRelativePath { RustRelativePath { path: i.into_iter().collect(), } } pub fn is_empty(&self) -> bool { self.path.is_empty() } pub fn first(&self) -> Option { self.path.iter().cloned().next() } pub fn remove_first(&mut self) -> Option { if self.path.is_empty() { None } else { Some(self.path.remove(0)) } } pub fn prepend_ident(&mut self, ident: RustIdent) { self.path.insert(0, ident); } pub fn append(mut self, path: RustRelativePath) -> RustRelativePath { for c in path.path { self.path.push(c); } self } pub fn push_ident(&mut self, ident: RustIdent) { self.path.push(ident); } pub fn _append_ident(mut self, ident: RustIdent) -> RustRelativePath { self.push_ident(ident); self } pub fn to_reverse(&self) -> RustRelativePath { RustRelativePath::from_components( iter::repeat(RustIdent::super_ident()).take(self.path.len()), ) } } #[derive(Default, Eq, PartialEq, Debug, Clone)] pub(crate) struct RustPath { absolute: bool, path: RustRelativePath, } impl fmt::Display for RustRelativePath { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { for (i, c) in self.path.iter().enumerate() { if i != 0 { write!(f, "::")?; } write!(f, "{}", c)?; } Ok(()) } } impl From<&'_ str> for RustRelativePath { fn from(s: &str) -> Self { RustRelativePath { path: s.split("::").map(RustIdent::from).collect(), } } } #[allow(dead_code)] impl RustPath { pub fn is_absolute(&self) -> bool { self.absolute } pub fn is_empty(&self) -> bool { assert!(!self.absolute); self.path.is_empty() } pub fn with_ident(self, ident: RustIdent) -> RustIdentWithPath { RustIdentWithPath { path: self, ident } } pub fn first(&self) -> Option { assert!(!self.absolute); self.path.first() } pub fn remove_first(&mut self) -> Option { assert!(!self.absolute); self.path.remove_first() } pub fn to_reverse(&self) -> RustPath { assert!(!self.absolute); RustPath { absolute: false, path: self.path.to_reverse(), } } pub fn prepend_ident(&mut self, ident: RustIdent) { assert!(!self.absolute); self.path.prepend_ident(ident); } pub fn append(self, path: RustPath) -> RustPath { if path.absolute { path } else { RustPath { absolute: self.absolute, path: self.path.append(path.path), } } } pub fn append_ident(mut self, ident: RustIdent) -> RustPath { self.path.path.push(ident); self } pub fn append_with_ident(self, path: RustIdentWithPath) -> RustIdentWithPath { self.append(path.path).with_ident(path.ident) } } impl From<&'_ str> for RustPath { fn from(s: &str) -> Self { let (s, absolute) = if s.starts_with("::") { (&s[2..], true) } else { (s, false) }; RustPath { absolute, path: RustRelativePath::from(s), } } } impl From for RustPath { fn from(s: String) -> Self { RustPath::from(&s[..]) } } impl fmt::Display for RustPath { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.absolute { write!(f, "::")?; } write!(f, "{}", self.path) } } #[derive(Eq, PartialEq, Debug, Clone)] pub(crate) struct RustIdentWithPath { pub path: RustPath, pub ident: RustIdent, } #[allow(dead_code)] impl RustIdentWithPath { pub fn new(s: String) -> RustIdentWithPath { let mut path = RustPath::from(s); let ident = path.path.path.pop().unwrap(); RustIdentWithPath { path, ident } } pub fn prepend_ident(&mut self, ident: RustIdent) { self.path.prepend_ident(ident) } pub fn to_path(&self) -> RustPath { self.path.clone().append_ident(self.ident.clone()) } } impl> From for RustIdentWithPath { fn from(s: S) -> Self { RustIdentWithPath::new(s.into()) } } impl fmt::Display for RustIdentWithPath { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.to_path(), f) } }