prost_types/type_url.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
use super::*;
/// URL/resource name that uniquely identifies the type of the serialized protocol buffer message,
/// e.g. `type.googleapis.com/google.protobuf.Duration`.
///
/// This string must contain at least one "/" character.
///
/// The last segment of the URL's path must represent the fully qualified name of the type (as in
/// `path/google.protobuf.Duration`). The name should be in a canonical form (e.g., leading "." is
/// not accepted).
///
/// If no scheme is provided, `https` is assumed.
///
/// Schemes other than `http`, `https` (or the empty scheme) might be used with implementation
/// specific semantics.
#[derive(Debug, Eq, PartialEq)]
pub(crate) struct TypeUrl<'a> {
/// Fully qualified name of the type, e.g. `google.protobuf.Duration`
pub(crate) full_name: &'a str,
}
impl<'a> TypeUrl<'a> {
pub(crate) fn new(s: &'a str) -> core::option::Option<Self> {
// Must contain at least one "/" character.
let slash_pos = s.rfind('/')?;
// The last segment of the URL's path must represent the fully qualified name
// of the type (as in `path/google.protobuf.Duration`)
let full_name = s.get((slash_pos + 1)..)?;
// The name should be in a canonical form (e.g., leading "." is not accepted).
if full_name.starts_with('.') {
return None;
}
Some(Self { full_name })
}
}
/// Compute the type URL for the given `google.protobuf` type, using `type.googleapis.com` as the
/// authority for the URL.
pub(crate) fn type_url_for<T: Name>() -> String {
format!("type.googleapis.com/{}.{}", T::PACKAGE, T::NAME)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_type_url_parsing() {
let example_type_name = "google.protobuf.Duration";
let url = TypeUrl::new("type.googleapis.com/google.protobuf.Duration").unwrap();
assert_eq!(url.full_name, example_type_name);
let full_url =
TypeUrl::new("https://type.googleapis.com/google.protobuf.Duration").unwrap();
assert_eq!(full_url.full_name, example_type_name);
let relative_url = TypeUrl::new("/google.protobuf.Duration").unwrap();
assert_eq!(relative_url.full_name, example_type_name);
// The name should be in a canonical form (e.g., leading "." is not accepted).
assert_eq!(TypeUrl::new("/.google.protobuf.Duration"), None);
// Must contain at least one "/" character.
assert_eq!(TypeUrl::new("google.protobuf.Duration"), None);
}
}