Allow constructing Scopes from a string
This commit is contained in:
+127
-4
@@ -3,10 +3,13 @@ use std::{
|
||||
collections::HashSet,
|
||||
fmt,
|
||||
ops::BitOr,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use serde::ser::{Serialize, Serializer};
|
||||
|
||||
use errors::Error;
|
||||
|
||||
/// Represents a set of OAuth scopes
|
||||
///
|
||||
/// # Example
|
||||
@@ -24,6 +27,21 @@ pub struct Scopes {
|
||||
scopes: HashSet<Scope>,
|
||||
}
|
||||
|
||||
impl FromStr for Scopes {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Scopes, Self::Err> {
|
||||
let mut set = HashSet::new();
|
||||
for scope in s.split_whitespace() {
|
||||
let scope = Scope::from_str(&scope)?;
|
||||
set.insert(scope);
|
||||
}
|
||||
Ok(Scopes {
|
||||
scopes: set,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Scopes {
|
||||
fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
@@ -250,7 +268,7 @@ impl fmt::Display for Scopes {
|
||||
/// Permission scope of the application.
|
||||
/// [Details on what each permission provides][1]
|
||||
/// [1]: https://github.com/tootsuite/documentation/blob/master/Using-the-API/OAuth-details.md)
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Hash, Serialize)]
|
||||
enum Scope {
|
||||
/// Read only permissions.
|
||||
#[serde(rename = "read")]
|
||||
@@ -266,9 +284,25 @@ enum Scope {
|
||||
Push,
|
||||
}
|
||||
|
||||
impl PartialOrd for Scope {
|
||||
fn partial_cmp(&self, other: &Scope) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
impl FromStr for Scope {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Scope, Self::Err> {
|
||||
Ok(match s {
|
||||
"read" => Scope::Read(None),
|
||||
"write" => Scope::Write(None),
|
||||
"follow" => Scope::Follow,
|
||||
"push" => Scope::Push,
|
||||
read if read.starts_with("read:") => {
|
||||
let r: Read = Read::from_str(&read[5..])?;
|
||||
Scope::Read(Some(r))
|
||||
},
|
||||
write if write.starts_with("write:") => {
|
||||
let w: Write = Write::from_str(&write[6..])?;
|
||||
Scope::Write(Some(w))
|
||||
},
|
||||
_ => return Err(Error::Other("Unknown scope".to_string())),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,6 +397,27 @@ pub enum Read {
|
||||
Statuses,
|
||||
}
|
||||
|
||||
impl FromStr for Read {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Read, Self::Err> {
|
||||
Ok(match s {
|
||||
"accounts" => Read::Accounts,
|
||||
"blocks" => Read::Blocks,
|
||||
"favourites" => Read::Favourites,
|
||||
"filters" => Read::Filters,
|
||||
"follows" => Read::Follows,
|
||||
"lists" => Read::Lists,
|
||||
"mutes" => Read::Mutes,
|
||||
"notifications" => Read::Notifications,
|
||||
"reports" => Read::Reports,
|
||||
"search" => Read::Search,
|
||||
"statuses" => Read::Statuses,
|
||||
_ => return Err(Error::Other("Unknown 'read' subcategory".to_string())),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Read {
|
||||
fn partial_cmp(&self, other: &Read) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
@@ -437,6 +492,27 @@ pub enum Write {
|
||||
Statuses,
|
||||
}
|
||||
|
||||
impl FromStr for Write {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Write, Self::Err> {
|
||||
Ok(match s {
|
||||
"accounts" => Write::Accounts,
|
||||
"blocks" => Write::Blocks,
|
||||
"favourites" => Write::Favourites,
|
||||
"filters" => Write::Filters,
|
||||
"follows" => Write::Follows,
|
||||
"lists" => Write::Lists,
|
||||
"media" => Write::Media,
|
||||
"mutes" => Write::Mutes,
|
||||
"notifications" => Write::Notifications,
|
||||
"reports" => Write::Reports,
|
||||
"statuses" => Write::Statuses,
|
||||
_ => return Err(Error::Other("Unknown 'write' subcategory".to_string())),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Write {
|
||||
fn partial_cmp(&self, other: &Write) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
@@ -664,4 +740,51 @@ mod tests {
|
||||
assert_eq!(&ser, &expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scope_from_str() {
|
||||
let tests = [
|
||||
("read", Scope::Read(None)),
|
||||
("read:accounts", Scope::Read(Some(Read::Accounts))),
|
||||
("read:blocks", Scope::Read(Some(Read::Blocks))),
|
||||
("read:favourites", Scope::Read(Some(Read::Favourites))),
|
||||
("read:filters", Scope::Read(Some(Read::Filters))),
|
||||
("read:follows", Scope::Read(Some(Read::Follows))),
|
||||
("read:lists", Scope::Read(Some(Read::Lists))),
|
||||
("read:mutes", Scope::Read(Some(Read::Mutes))),
|
||||
("read:notifications", Scope::Read(Some(Read::Notifications))),
|
||||
("read:reports", Scope::Read(Some(Read::Reports))),
|
||||
("read:search", Scope::Read(Some(Read::Search))),
|
||||
("read:statuses", Scope::Read(Some(Read::Statuses))),
|
||||
("write", Scope::Write(None)),
|
||||
("write:accounts", Scope::Write(Some(Write::Accounts))),
|
||||
("write:blocks", Scope::Write(Some(Write::Blocks))),
|
||||
("write:favourites", Scope::Write(Some(Write::Favourites))),
|
||||
("write:filters", Scope::Write(Some(Write::Filters))),
|
||||
("write:follows", Scope::Write(Some(Write::Follows))),
|
||||
("write:lists", Scope::Write(Some(Write::Lists))),
|
||||
("write:media", Scope::Write(Some(Write::Media))),
|
||||
("write:mutes", Scope::Write(Some(Write::Mutes))),
|
||||
(
|
||||
"write:notifications",
|
||||
Scope::Write(Some(Write::Notifications)),
|
||||
),
|
||||
("write:reports", Scope::Write(Some(Write::Reports))),
|
||||
("write:statuses", Scope::Write(Some(Write::Statuses))),
|
||||
("follow", Scope::Follow),
|
||||
("push", Scope::Push),
|
||||
];
|
||||
for (source, expected) in &tests {
|
||||
let result = Scope::from_str(source).expect(&format!("Couldn't parse '{}'", &source));
|
||||
assert_eq!(result, *expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scopes_str_round_trip() {
|
||||
let original = "read write follow push";
|
||||
let scopes = Scopes::from_str(original).expect("Couldn't convert to Scopes");
|
||||
let result = format!("{}", scopes);
|
||||
assert_eq!(original, result);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user