Skip to content
This repository was archived by the owner on Feb 16, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/batching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ mod tests {
.map(|_| test_record.clone())
.collect::<Vec<_>>();

let expected_fencing_token = types::FencingToken::new("hello").unwrap();
let expected_fencing_token: types::FencingToken = "hello".parse().unwrap();
let mut expected_match_seq_num = 10;

let num_batch_records = 3;
Expand Down
84 changes: 46 additions & 38 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -973,29 +973,14 @@ pub struct FencingToken(String);
impl FencingToken {
const MAX_BYTES: usize = 36;

/// Try creating a new fencing token from bytes.
pub fn new(s: impl Into<String>) -> Result<Self, ConvertError> {
let s = s.into();
if s.len() > Self::MAX_BYTES {
Err(format!(
"Size of a fencing token cannot exceed {} bytes",
Self::MAX_BYTES
)
.into())
} else {
Ok(Self(s))
}
}

/// Generate a random alphanumeric fencing token of `n` bytes.
pub fn generate(n: usize) -> Result<Self, ConvertError> {
Self::new(
rand::rng()
.sample_iter(&rand::distr::Alphanumeric)
.take(n)
.map(char::from)
.collect::<String>(),
)
rand::rng()
.sample_iter(&rand::distr::Alphanumeric)
.take(n)
.map(char::from)
.collect::<String>()
.parse()
}
}

Expand All @@ -1007,11 +992,35 @@ impl Deref for FencingToken {
}
}

impl TryFrom<&str> for FencingToken {
impl std::fmt::Display for FencingToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}

impl FromStr for FencingToken {
type Err = ConvertError;

fn from_str(value: &str) -> Result<Self, Self::Err> {
value.to_string().try_into()
}
}

impl TryFrom<String> for FencingToken {
type Error = ConvertError;

fn try_from(value: &str) -> Result<Self, Self::Error> {
Self::new(value)
fn try_from(value: String) -> Result<Self, Self::Error> {
if value.len() > Self::MAX_BYTES {
Err(format!("Fencing token cannot exceed {} bytes", Self::MAX_BYTES).into())
} else {
Ok(Self(value))
}
}
}

impl From<FencingToken> for String {
fn from(value: FencingToken) -> Self {
value.0
}
}

Expand Down Expand Up @@ -1705,8 +1714,7 @@ impl SequencedRecord {

match header.value.as_ref() {
CommandRecord::FENCE => {
let fencing_token =
FencingToken::new(std::str::from_utf8(&self.body).ok()?).ok()?;
let fencing_token = std::str::from_utf8(&self.body).ok()?.parse().ok()?;
Some(CommandRecord {
command: Command::Fence { fencing_token },
timestamp: Some(self.timestamp),
Expand Down Expand Up @@ -1831,12 +1839,6 @@ impl TryFrom<api::ReadSessionResponse> for ReadOutput {
#[derive(Debug, Clone)]
pub struct BasinName(String);

impl AsRef<str> for BasinName {
fn as_ref(&self) -> &str {
&self.0
}
}

impl Deref for BasinName {
type Target = str;
fn deref(&self) -> &Self::Target {
Expand Down Expand Up @@ -1884,17 +1886,17 @@ impl std::fmt::Display for BasinName {
}
}

impl From<BasinName> for String {
fn from(value: BasinName) -> Self {
value.0
}
}

/// Access token ID.
/// Must be between 1 and 96 characters.
#[derive(Debug, Clone)]
pub struct AccessTokenId(String);

impl AsRef<str> for AccessTokenId {
fn as_ref(&self) -> &str {
&self.0
}
}

impl Deref for AccessTokenId {
type Target = str;

Expand Down Expand Up @@ -1933,6 +1935,12 @@ impl FromStr for AccessTokenId {
}
}

impl std::fmt::Display for AccessTokenId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}

impl From<AccessTokenInfo> for api::IssueAccessTokenRequest {
fn from(value: AccessTokenInfo) -> Self {
Self {
Expand Down
Loading