use super::pb::v3lockpb;
use crate::auth::AuthService;
use crate::channel::Channel;
use crate::error::Result;
use crate::rpc::ResponseHeader;
use http::HeaderValue;
use std::sync::{Arc, RwLock};
use tonic::{IntoRequest, Request};
use v3lockpb::lock_client::LockClient as PbLockClient;
use v3lockpb::{
LockRequest as PbLockRequest, LockResponse as PbLockResponse, UnlockRequest as PbUnlockRequest,
UnlockResponse as PbUnlockResponse,
};
#[repr(transparent)]
#[derive(Clone)]
pub struct LockClient {
inner: PbLockClient<AuthService<Channel>>,
}
impl LockClient {
#[inline]
pub(crate) fn new(channel: Channel, auth_token: Arc<RwLock<Option<HeaderValue>>>) -> Self {
let inner = PbLockClient::new(AuthService::new(channel, auth_token));
Self { inner }
}
#[inline]
pub async fn lock(
&mut self,
name: impl Into<Vec<u8>>,
options: Option<LockOptions>,
) -> Result<LockResponse> {
let resp = self
.inner
.lock(options.unwrap_or_default().with_name(name))
.await?
.into_inner();
Ok(LockResponse::new(resp))
}
#[inline]
pub async fn unlock(&mut self, key: impl Into<Vec<u8>>) -> Result<UnlockResponse> {
let resp = self
.inner
.unlock(UnlockOptions::new().with_key(key))
.await?
.into_inner();
Ok(UnlockResponse::new(resp))
}
}
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct LockOptions(PbLockRequest);
impl LockOptions {
#[inline]
fn with_name(mut self, name: impl Into<Vec<u8>>) -> Self {
self.0.name = name.into();
self
}
#[inline]
pub const fn new() -> Self {
Self(PbLockRequest {
name: Vec::new(),
lease: 0,
})
}
#[inline]
pub const fn with_lease(mut self, lease: i64) -> Self {
self.0.lease = lease;
self
}
}
impl From<LockOptions> for PbLockRequest {
#[inline]
fn from(options: LockOptions) -> Self {
options.0
}
}
impl IntoRequest<PbLockRequest> for LockOptions {
#[inline]
fn into_request(self) -> Request<PbLockRequest> {
Request::new(self.into())
}
}
#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct LockResponse(PbLockResponse);
impl LockResponse {
#[inline]
const fn new(resp: PbLockResponse) -> Self {
Self(resp)
}
#[inline]
pub fn header(&self) -> Option<&ResponseHeader> {
self.0.header.as_ref().map(From::from)
}
#[inline]
pub fn take_header(&mut self) -> Option<ResponseHeader> {
self.0.header.take().map(ResponseHeader::new)
}
#[inline]
pub fn key(&self) -> &[u8] {
&self.0.key
}
}
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct UnlockOptions(PbUnlockRequest);
impl UnlockOptions {
#[inline]
fn with_key(mut self, key: impl Into<Vec<u8>>) -> Self {
self.0.key = key.into();
self
}
#[inline]
pub const fn new() -> Self {
Self(PbUnlockRequest { key: Vec::new() })
}
}
impl From<UnlockOptions> for PbUnlockRequest {
#[inline]
fn from(options: UnlockOptions) -> Self {
options.0
}
}
impl IntoRequest<PbUnlockRequest> for UnlockOptions {
#[inline]
fn into_request(self) -> Request<PbUnlockRequest> {
Request::new(self.into())
}
}
#[cfg_attr(feature = "pub-response-field", visible::StructFields(pub))]
#[derive(Debug, Default, Clone)]
#[repr(transparent)]
pub struct UnlockResponse(PbUnlockResponse);
impl UnlockResponse {
#[inline]
const fn new(resp: PbUnlockResponse) -> Self {
Self(resp)
}
#[inline]
pub fn header(&self) -> Option<&ResponseHeader> {
self.0.header.as_ref().map(From::from)
}
#[inline]
pub fn take_header(&mut self) -> Option<ResponseHeader> {
self.0.header.take().map(ResponseHeader::new)
}
}