aboutsummaryrefslogtreecommitdiff
path: root/2.27.1/src/protobuf_name.rs
diff options
context:
space:
mode:
Diffstat (limited to '2.27.1/src/protobuf_name.rs')
-rw-r--r--2.27.1/src/protobuf_name.rs374
1 files changed, 374 insertions, 0 deletions
diff --git a/2.27.1/src/protobuf_name.rs b/2.27.1/src/protobuf_name.rs
new file mode 100644
index 0000000..c40a69c
--- /dev/null
+++ b/2.27.1/src/protobuf_name.rs
@@ -0,0 +1,374 @@
+use std::fmt;
+
+/// Identifier in `.proto` file
+#[derive(Eq, PartialEq, Debug, Clone)]
+pub struct ProtobufIdent(String);
+
+impl ProtobufIdent {
+ /// New ident from a string.
+ #[allow(dead_code)]
+ pub fn new(s: &str) -> ProtobufIdent {
+ assert!(!s.is_empty());
+ assert!(!s.contains("/"));
+ assert!(!s.contains("."));
+ assert!(!s.contains(":"));
+ ProtobufIdent(s.to_owned())
+ }
+
+ /// Get as a string.
+ pub fn get(&self) -> &str {
+ &self.0
+ }
+}
+
+impl From<&'_ str> for ProtobufIdent {
+ fn from(s: &str) -> Self {
+ ProtobufIdent::new(s)
+ }
+}
+
+impl From<String> for ProtobufIdent {
+ fn from(s: String) -> Self {
+ ProtobufIdent::new(&s)
+ }
+}
+
+impl fmt::Display for ProtobufIdent {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&self.get(), f)
+ }
+}
+
+/// Relative protobuf identifier path.
+#[derive(Debug, Eq, PartialEq, Clone)]
+pub struct ProtobufRelativePath {
+ /// The path
+ pub path: String,
+}
+
+#[allow(dead_code)]
+impl ProtobufRelativePath {
+ /// Empty relative path.
+ pub fn empty() -> ProtobufRelativePath {
+ ProtobufRelativePath::new(String::new())
+ }
+
+ /// New path from a string.
+ pub fn new(path: String) -> ProtobufRelativePath {
+ assert!(!path.starts_with("."));
+
+ ProtobufRelativePath { path }
+ }
+
+ /// From path components.
+ pub fn from_components<I: IntoIterator<Item = ProtobufIdent>>(i: I) -> ProtobufRelativePath {
+ let v: Vec<String> = i.into_iter().map(|c| c.get().to_owned()).collect();
+ ProtobufRelativePath::from(v.join("."))
+ }
+
+ /// Get the string.
+ pub fn get(&self) -> &str {
+ &self.path
+ }
+
+ /// The path is empty.
+ pub fn is_empty(&self) -> bool {
+ self.path.is_empty()
+ }
+
+ /// As absolute path from root namespace.
+ pub fn into_absolute(self) -> ProtobufAbsolutePath {
+ if self.is_empty() {
+ ProtobufAbsolutePath::root()
+ } else {
+ ProtobufAbsolutePath::from(format!(".{}", self))
+ }
+ }
+
+ fn _last_part(&self) -> Option<&str> {
+ match self.path.rfind('.') {
+ Some(pos) => Some(&self.path[pos + 1..]),
+ None => {
+ if self.path.is_empty() {
+ None
+ } else {
+ Some(&self.path)
+ }
+ }
+ }
+ }
+
+ fn parent(&self) -> Option<ProtobufRelativePath> {
+ match self.path.rfind('.') {
+ Some(pos) => Some(ProtobufRelativePath::new(self.path[..pos].to_owned())),
+ None => {
+ if self.path.is_empty() {
+ None
+ } else {
+ Some(ProtobufRelativePath::empty())
+ }
+ }
+ }
+ }
+
+ /// Self path and parent paths.
+ pub fn self_and_parents(&self) -> Vec<ProtobufRelativePath> {
+ let mut tmp = self.clone();
+
+ let mut r = Vec::new();
+
+ r.push(self.clone());
+
+ while let Some(parent) = tmp.parent() {
+ r.push(parent.clone());
+ tmp = parent;
+ }
+
+ r
+ }
+
+ /// Append path component.
+ pub fn append(&self, simple: &ProtobufRelativePath) -> ProtobufRelativePath {
+ if self.path.is_empty() {
+ ProtobufRelativePath::from(simple.get())
+ } else {
+ ProtobufRelativePath::new(format!("{}.{}", self.path, simple))
+ }
+ }
+
+ /// Append identifier to the path.
+ pub fn append_ident(&self, simple: &ProtobufIdent) -> ProtobufRelativePath {
+ self.append(&ProtobufRelativePath::from(simple.clone()))
+ }
+
+ /// Get first component path and remaining.
+ pub fn split_first_rem(&self) -> Option<(ProtobufIdent, ProtobufRelativePath)> {
+ if self.is_empty() {
+ None
+ } else {
+ Some(match self.path.find('.') {
+ Some(dot) => (
+ ProtobufIdent::from(&self.path[..dot]),
+ ProtobufRelativePath::new(self.path[dot + 1..].to_owned()),
+ ),
+ None => (
+ ProtobufIdent::from(self.path.clone()),
+ ProtobufRelativePath::empty(),
+ ),
+ })
+ }
+ }
+}
+
+impl From<&'_ str> for ProtobufRelativePath {
+ fn from(s: &str) -> ProtobufRelativePath {
+ ProtobufRelativePath::from(s.to_owned())
+ }
+}
+
+impl From<String> for ProtobufRelativePath {
+ fn from(s: String) -> ProtobufRelativePath {
+ ProtobufRelativePath::new(s)
+ }
+}
+
+impl From<ProtobufIdent> for ProtobufRelativePath {
+ fn from(s: ProtobufIdent) -> ProtobufRelativePath {
+ ProtobufRelativePath::from(s.get())
+ }
+}
+
+impl From<Vec<ProtobufIdent>> for ProtobufRelativePath {
+ fn from(s: Vec<ProtobufIdent>) -> ProtobufRelativePath {
+ ProtobufRelativePath::from_components(s.into_iter())
+ }
+}
+
+impl fmt::Display for ProtobufRelativePath {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&self.path, f)
+ }
+}
+
+#[cfg(test)]
+mod relative_path_test {
+ use super::*;
+
+ #[test]
+ fn parent() {
+ assert_eq!(None, ProtobufRelativePath::empty().parent());
+ assert_eq!(
+ Some(ProtobufRelativePath::empty()),
+ ProtobufRelativePath::new("aaa".to_owned()).parent()
+ );
+ assert_eq!(
+ Some(ProtobufRelativePath::new("abc".to_owned())),
+ ProtobufRelativePath::new("abc.def".to_owned()).parent()
+ );
+ assert_eq!(
+ Some(ProtobufRelativePath::new("abc.def".to_owned())),
+ ProtobufRelativePath::new("abc.def.gh".to_owned()).parent()
+ );
+ }
+
+ #[test]
+ fn last_part() {
+ assert_eq!(None, ProtobufRelativePath::empty()._last_part());
+ assert_eq!(
+ Some("aaa"),
+ ProtobufRelativePath::new("aaa".to_owned())._last_part()
+ );
+ assert_eq!(
+ Some("def"),
+ ProtobufRelativePath::new("abc.def".to_owned())._last_part()
+ );
+ assert_eq!(
+ Some("gh"),
+ ProtobufRelativePath::new("abc.def.gh".to_owned())._last_part()
+ );
+ }
+}
+
+/// Absolute protobuf path (e. g. package).
+///
+/// This is not filesystem path.
+#[derive(Clone, Eq, PartialEq, Debug, Hash)]
+pub struct ProtobufAbsolutePath {
+ /// The path.
+ pub path: String,
+}
+
+impl ProtobufAbsolutePath {
+ fn root() -> ProtobufAbsolutePath {
+ ProtobufAbsolutePath::new(String::new())
+ }
+
+ /// From string.
+ pub fn new(path: String) -> ProtobufAbsolutePath {
+ assert!(path.is_empty() || path.starts_with("."), "{}", path);
+ assert!(!path.ends_with("."), "{}", path);
+ ProtobufAbsolutePath { path }
+ }
+
+ /// The path is empty.
+ pub fn is_empty(&self) -> bool {
+ self.path.is_empty()
+ }
+
+ /// From a path without leading dot.
+ ///
+ /// (Protobuf paths start with dot).
+ pub fn from_path_without_dot(path: &str) -> ProtobufAbsolutePath {
+ if path.is_empty() {
+ ProtobufAbsolutePath::root()
+ } else {
+ assert!(!path.starts_with("."));
+ assert!(!path.ends_with("."));
+ ProtobufAbsolutePath::new(format!(".{}", path))
+ }
+ }
+
+ /// Parse absolute path.
+ #[allow(dead_code)]
+ pub fn from_package_path(path: Option<&str>) -> ProtobufAbsolutePath {
+ match path {
+ None => ProtobufAbsolutePath::root(),
+ Some(path) => ProtobufAbsolutePath::from_path_without_dot(path),
+ }
+ }
+
+ /// Construct abs path from a string which may start with a dot.
+ pub fn from_path_maybe_dot(path: &str) -> ProtobufAbsolutePath {
+ if path.starts_with(".") {
+ ProtobufAbsolutePath::new(path.to_owned())
+ } else {
+ ProtobufAbsolutePath::from_path_without_dot(path)
+ }
+ }
+
+ /// Push identifier to the path.
+ pub fn push_simple(&mut self, simple: ProtobufIdent) {
+ self.path.push('.');
+ self.path.push_str(simple.get());
+ }
+
+ /// Push relative path.
+ pub fn push_relative(&mut self, relative: &ProtobufRelativePath) {
+ if !relative.is_empty() {
+ self.path.push('.');
+ self.path.push_str(&relative.path);
+ }
+ }
+
+ /// Try remove a prefix.
+ pub fn remove_prefix(&self, prefix: &ProtobufAbsolutePath) -> Option<ProtobufRelativePath> {
+ if self.path.starts_with(&prefix.path) {
+ let rem = &self.path[prefix.path.len()..];
+ if rem.is_empty() {
+ return Some(ProtobufRelativePath::empty());
+ }
+ if rem.starts_with('.') {
+ return Some(ProtobufRelativePath::new(rem[1..].to_owned()));
+ }
+ }
+ None
+ }
+}
+
+impl From<&'_ str> for ProtobufAbsolutePath {
+ fn from(s: &str) -> Self {
+ ProtobufAbsolutePath::new(s.to_owned())
+ }
+}
+
+impl From<String> for ProtobufAbsolutePath {
+ fn from(s: String) -> Self {
+ ProtobufAbsolutePath::new(s)
+ }
+}
+
+impl fmt::Display for ProtobufAbsolutePath {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(&self.path, f)
+ }
+}
+
+#[cfg(test)]
+mod absolute_path_test {
+ use super::*;
+
+ #[test]
+ fn absolute_path_push_simple() {
+ let mut foo = ProtobufAbsolutePath::new(".foo".to_owned());
+ foo.push_simple(ProtobufIdent::from("bar"));
+ assert_eq!(ProtobufAbsolutePath::new(".foo.bar".to_owned()), foo);
+
+ let mut foo = ProtobufAbsolutePath::root();
+ foo.push_simple(ProtobufIdent::from("bar"));
+ assert_eq!(ProtobufAbsolutePath::new(".bar".to_owned()), foo);
+ }
+
+ #[test]
+ fn absolute_path_remove_prefix() {
+ assert_eq!(
+ Some(ProtobufRelativePath::empty()),
+ ProtobufAbsolutePath::new(".foo".to_owned())
+ .remove_prefix(&ProtobufAbsolutePath::new(".foo".to_owned()))
+ );
+ assert_eq!(
+ Some(ProtobufRelativePath::new("bar".to_owned())),
+ ProtobufAbsolutePath::new(".foo.bar".to_owned())
+ .remove_prefix(&ProtobufAbsolutePath::new(".foo".to_owned()))
+ );
+ assert_eq!(
+ Some(ProtobufRelativePath::new("baz.qux".to_owned())),
+ ProtobufAbsolutePath::new(".foo.bar.baz.qux".to_owned())
+ .remove_prefix(&ProtobufAbsolutePath::new(".foo.bar".to_owned()))
+ );
+ assert_eq!(
+ None,
+ ProtobufAbsolutePath::new(".foo.barbaz".to_owned())
+ .remove_prefix(&ProtobufAbsolutePath::new(".foo.bar".to_owned()))
+ );
+ }
+}