#![deny(missing_debug_implementations)]
#![deny(missing_docs)]
use serde::{de, Serialize};
mod auth;
mod error;
mod onedrive;
pub mod option;
pub mod resource;
mod util;
pub use self::{
auth::{Auth, ClientCredential, Permission, Tenant, TokenResponse},
error::{Error, Result},
onedrive::{
CopyProgressMonitor, ListChildrenFetcher, OneDrive, TrackChangeFetcher, UploadSession,
UploadSessionMeta,
},
resource::{DriveId, ItemId, Tag},
util::{DriveLocation, FileName, ItemLocation},
};
#[cfg(feature = "beta")]
pub use self::onedrive::{CopyProgress, CopyStatus};
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum ConflictBehavior {
Fail,
Replace,
Rename,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ExpectRange {
pub start: u64,
pub end: Option<u64>,
}
impl<'de> de::Deserialize<'de> for ExpectRange {
fn deserialize<D: de::Deserializer<'de>>(
deserializer: D,
) -> std::result::Result<Self, D::Error> {
struct Visitor;
impl de::Visitor<'_> for Visitor {
type Value = ExpectRange;
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Expect Range")
}
fn visit_str<E: de::Error>(self, v: &str) -> std::result::Result<Self::Value, E> {
let parse = || -> Option<ExpectRange> {
let mut it = v.split('-');
let start = it.next()?.parse().ok()?;
let end = match it.next()? {
"" => None,
s => {
let end = s.parse::<u64>().ok()?.checked_add(1)?; if end <= start {
return None;
}
Some(end)
}
};
if it.next().is_some() {
return None;
}
Some(ExpectRange { start, end })
};
match parse() {
Some(v) => Ok(v),
None => Err(E::invalid_value(
de::Unexpected::Str(v),
&"`{lower}-` or `{lower}-{upper}`",
)),
}
}
}
deserializer.deserialize_str(Visitor)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_range_parsing() {
let max = format!("0-{}", u64::MAX - 1);
let overflow = format!("0-{}", u64::MAX);
let cases = [
(
"42-196",
Some(ExpectRange {
start: 42,
end: Some(197),
}),
), (
"418-",
Some(ExpectRange {
start: 418,
end: None,
}),
),
("", None),
("42-4", None),
("-9", None),
("-", None),
("1-2-3", None),
("0--2", None),
("-1-2", None),
(
&max,
Some(ExpectRange {
start: 0,
end: Some(u64::MAX),
}),
),
(&overflow, None),
];
for &(s, ref expect) in &cases {
let ret = serde_json::from_str(&serde_json::to_string(s).unwrap());
assert_eq!(
ret.as_ref().ok(),
expect.as_ref(),
"Failed: Got {ret:?} on {s:?}",
);
}
}
}