Atproto, add bound string
This commit is contained in:
parent
5bc903b2fa
commit
ee99f119f0
4 changed files with 62 additions and 0 deletions
|
|
@ -13,6 +13,7 @@ time = { version = "0.3.41", features = ["parsing", "formatting"] }
|
||||||
tracing-subscriber.workspace = true
|
tracing-subscriber.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
thiserror.workspace = true
|
thiserror.workspace = true
|
||||||
|
unicode-segmentation = "1.9.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ pub enum ParseError {
|
||||||
Serde(#[from] serde_json::error::Error),
|
Serde(#[from] serde_json::error::Error),
|
||||||
#[error("Length of parsed object too long, max: {max:?}, got: {got:?}.")]
|
#[error("Length of parsed object too long, max: {max:?}, got: {got:?}.")]
|
||||||
Length { max: usize, got: usize },
|
Length { max: usize, got: usize },
|
||||||
|
#[error("Length of parsed object too short, min: {min:?}, got: {got:?}.")]
|
||||||
|
MinLength { min: usize, got: usize },
|
||||||
#[error("Currently Did is enforced, cannot use handle, {handle:?}")]
|
#[error("Currently Did is enforced, cannot use handle, {handle:?}")]
|
||||||
ForceDid { handle: String },
|
ForceDid { handle: String },
|
||||||
#[error("Incorrectly formatted")]
|
#[error("Incorrectly formatted")]
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ macro_rules! basic_string_type {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod authority;
|
mod authority;
|
||||||
|
mod bound_string;
|
||||||
mod cid;
|
mod cid;
|
||||||
mod datetime;
|
mod datetime;
|
||||||
mod did;
|
mod did;
|
||||||
|
|
@ -63,6 +64,7 @@ mod record_key;
|
||||||
mod strong_ref;
|
mod strong_ref;
|
||||||
mod uri;
|
mod uri;
|
||||||
pub use authority::Authority;
|
pub use authority::Authority;
|
||||||
|
pub use bound_string::BoundString;
|
||||||
pub use cid::Cid;
|
pub use cid::Cid;
|
||||||
pub use datetime::Datetime;
|
pub use datetime::Datetime;
|
||||||
pub use did::Did;
|
pub use did::Did;
|
||||||
|
|
|
||||||
57
atproto/src/types/bound_string.rs
Normal file
57
atproto/src/types/bound_string.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
use crate::error::{Error, ParseError};
|
||||||
|
use std::{
|
||||||
|
fmt::{Display, Formatter, Result as FmtResult},
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct BoundString<
|
||||||
|
const MIN: usize, const MAX: usize>
|
||||||
|
{
|
||||||
|
value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const MIN: usize, const MAX: usize> BoundString<MIN, MAX> {
|
||||||
|
fn check_length(s: &str) -> Result<(), Error> {
|
||||||
|
let grapheme_count: usize = s.graphemes(true).take(MAX + 1).count();
|
||||||
|
if grapheme_count > MAX {
|
||||||
|
return Err(Error::Parse {
|
||||||
|
err: ParseError::Length { max: MAX, got: grapheme_count },
|
||||||
|
object: "String".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if grapheme_count < MIN {
|
||||||
|
return Err(Error::Parse {
|
||||||
|
err: ParseError::MinLength { min: MIN, got: grapheme_count },
|
||||||
|
object: "String".to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const MIN: usize, const MAX: usize> Display for BoundString<MIN, MAX> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||||
|
write!(f, "{}", self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const MIN: usize, const MAX: usize> FromStr for BoundString<MIN, MAX> {
|
||||||
|
type Err = Error;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Self::check_length(s)?;
|
||||||
|
|
||||||
|
Ok(BoundString { value: s.to_string() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, const MIN: usize, const MAX: usize> serde::de::Deserialize<'de>
|
||||||
|
for BoundString<MIN, MAX> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::de::Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let value: String = serde::de::Deserialize::deserialize(deserializer)?;
|
||||||
|
value.parse::<BoundString<MIN,MAX>>().map_err(<D::Error as serde::de::Error>::custom)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue